Appearance
Using Textile with a Utila wallet
Utila is an MPC custody wallet with a rule-based Transaction Policy engine. Every outbound transaction is evaluated against the policy — if no rule allows it, Utila returns Rejected by Policy and the transaction never reaches the chain.
To use Textile from a Utila vault, you need to:
- Add a Sign Message rule so you can sign in (Textile uses SIWE — no gas, no on-chain tx).
- Add each Textile contract you interact with to your Address Book.
- Add an EVM contract call rule to your Transaction Policy for each contract.
- Save the policy (changes go through your vault's approval workflow).
IMPORTANT
Transaction Policy rules are evaluated top-to-bottom using a first-match rule. If a broad "deny" rule sits above your Textile rules, it will block them. Order Textile rules above any catch-all denies.
Step 1: Allow sign-in (Sign Message rule)
Textile authenticates with Sign-In with Ethereum (SIWE). When you click Connect wallet, the app asks your wallet to sign a short login message. Nothing is sent on-chain and no gas is spent — but Utila's policy engine treats this as a personal_sign request and blocks it unless a rule allows it.
- In the Utila console, go to Vault Settings > Transaction Policy, then click Manage policy.
- Click Add New Rule.
- Set Rule type =
Sign Message. - Configure the conditions:
- Initiator =
Member(pick yourself, or leave it broader if you want any member to be able to sign in) - From =
Wallet(pick the wallet you'll sign in with)
- Initiator =
- Click Create rule, then Save changes. A quorum on your vault must approve the policy change before it's live.
Once the rule is active, sign-in will work.
Step 2: Add Textile contracts to the Address Book
Utila requires the To address of any contract call rule to exist as an Address Book Entry (ABE) or belong to an ABE group.
- Open the Utila console.
- Go to your workspace's Address Book.
- Add each contract from the Address Book page that's relevant to what you plan to do (see Per-role allowlists below).
- Tag them with a label like
Textile Pool Factoryso they're easy to find later.
TIP
If you'll interact with multiple Textile contracts, create an ABE group named Textile and add all of them to it. You can then reference the group in a single policy rule instead of one rule per contract.
Step 3: Add EVM contract call rules
For each contract (or ABE group) from Step 2:
- Go to Vault Settings > Transaction Policy, then click Manage policy.
- Click Add New Rule.
- Set Rule type =
EVM contract call. - Configure the conditions:
- Initiator =
Member(pick yourself, or a member group if you want to scope who can call it) - From = the wallet, or wallet group, that will sign the transaction
- To = the Textile contract (or
TextileABE group) from Step 2 - Blockchain = the network the contract is deployed on (Ethereum, Base, Celo, or Celo Sepolia)
- Initiator =
- Configure Rule action: if approvals are required, select the approver user group and the number of approvers needed.
- Click Create rule.
- Repeat for other contracts.
- Click Save changes. The policy change enters your vault's approval workflow — a quorum on your vault must approve it before it takes effect.
NOTE
By default a rule allows any function on the target contract. To constrain a rule to specific functions, use Utila's function-signature feature on the rule (see Utila's help center for details). Unless you have a strong reason to lock down individual methods, allowing the whole contract is simpler and covers future protocol upgrades.
Per-role allowlists
Minimum contracts and functions to allowlist, by what you want to do on Textile. Every on-chain action in the Textile app goes through one of the contracts below, so if a call gets rejected it's because a rule is missing here.
NOTE
Rules default to "any function on the target contract". You only need per-function rules if you want to lock down specific methods. Listing the functions below just tells you which are actually called by the app.
Borrowers (opening and operating a credit pool)
Before deploying a pool:
| Contract | Functions used by the app |
|---|---|
| Pool Factory | deployPool |
After deploying, add the deployed Pool address to the Address Book and create a rule for it. The Pool contract is where draws, repayments, and settings updates happen:
| Contract | Functions used by the app |
|---|---|
| Your Pool | drawdown, repayInterest, repay (principal), approveRedeemRequest (approve a lender's withdrawal request), proposeCreditLineSettingsChange, proposeTrancheSettingsChange, proposeUnderwriter, revokeUnderwriterProposal |
| Stablecoin | approve (authorizes the Pool to pull tokens for interest/principal repayment) |
Lenders (staking into a pool)
| Contract | Functions used by the app |
|---|---|
| Pool | deposit, reserve (reserve a deposit slot), requestWithdraw, withdraw, redeem, claimReservedInterest, setAutoInterestCompounding |
| Stablecoin | approve (authorizes the Pool to pull your deposit) |
Underwriters
| Contract | Functions used by the app |
|---|---|
| Underwriter Registry | registerUnderwriter, updateProfile, updateFees, deactivate, reactivate |
| Pool | acceptUnderwriter (accept a borrower's proposal), withdrawAllInterest (claim earned fees) |
IMPORTANT
New pools can't be pre-allowlisted. Every pool deployed via the Pool Factory is a new contract at a new address. After deploying (or joining) a pool, add its address to the Address Book and create a rule for it before you try to interact with it.
Contract addresses
Use the addresses from the Address Book page. Summary of the main ones you'll need:
Mainnet
| Contract | Ethereum | Base | Celo |
|---|---|---|---|
| Pool Factory | 0xfA0EE507Dd3b71dC7Ef810713B84DFF4e98c9453 | 0x23647722680C4A45FCa2ff18E572E7d43Bae1aa5 | 0xd22bFBACD29a48A4b68A5BC490FabCF18B07a3E2 |
| Registry | 0xf2bd1C6cD5fCF619df3c2542A19F128728561ec6 | 0x059725Ded2e07176C03554056109e9741CC2F782 | 0xe3400D36697e2C0E3904DfF63Bdcf5F21f11673c |
| Underwriter Registry | 0x4b6f0D66e5426067178cce5E38B9a117AcFfCF7F | 0xc3E1f6e34a633a37d1C8e73A0f3eb1003d0699fE | 0xA51B0018A3F4DD03723da2E3a3936917a939c6ce |
| Withdrawal Registry | 0x511caA407e30D94D790D23A6212738794f893Ecd | 0x4F29844b3163E0f77ea05C884614Ab20fF1b8aF6 | 0x54753101A5285e72813d0d126b1c387Acd6a390d |
Testnet
| Contract | Celo Sepolia |
|---|---|
| Pool Factory | 0xffce297C9bFb8664C3A26C5f94555d54c69A47aE |
| Registry | 0x4F2319AF61e40BdAF8eD06876b66808F67C12074 |
| Underwriter Registry | 0x528ce3917a598d6705624FCb8A50cB155212aabD |
| Withdrawal Registry | 0x0b9311Ad840D1321Cb7756d27A1145CFEeFB1b6d |
For Pool Template, Tranche Template, and Protocol Configuration (rarely called directly, but included for completeness), see the full Address Book.
Troubleshooting
The transaction fails with Rejected by Policy. Utila blocked the call before it hit the chain. Either the To contract isn't in your Address Book yet, or there's no rule that matches this call. Add the contract and a rule, then retry.
The transaction is "pending approval" in Utila. Your rule requires quorum approvals. Ask the other approvers on your vault to approve the transaction in their Utila console.
I added a rule but it still gets rejected. Check the rule ordering. Rules are evaluated top-to-bottom and the first match wins — make sure your Textile rule sits above any broader deny rule.
The policy change is pending. Policy edits also go through the vault's approval workflow. A quorum needs to approve the policy change itself before your new rule is live.
References
- Utila help: Create an EVM contract call rule
- Utila help: Edit the transaction policy for a vault
- Utila help: Introduction to the transaction policy