Skip to content

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:

  1. Add a Sign Message rule so you can sign in (Textile uses SIWE — no gas, no on-chain tx).
  2. Add each Textile contract you interact with to your Address Book.
  3. Add an EVM contract call rule to your Transaction Policy for each contract.
  4. 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.

  1. In the Utila console, go to Vault Settings > Transaction Policy, then click Manage policy.
  2. Click Add New Rule.
  3. Set Rule type = Sign Message.
  4. 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)
  5. 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.

  1. Open the Utila console.
  2. Go to your workspace's Address Book.
  3. Add each contract from the Address Book page that's relevant to what you plan to do (see Per-role allowlists below).
  4. Tag them with a label like Textile Pool Factory so 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:

  1. Go to Vault Settings > Transaction Policy, then click Manage policy.
  2. Click Add New Rule.
  3. Set Rule type = EVM contract call.
  4. 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 Textile ABE group) from Step 2
    • Blockchain = the network the contract is deployed on (Ethereum, Base, Celo, or Celo Sepolia)
  5. Configure Rule action: if approvals are required, select the approver user group and the number of approvers needed.
  6. Click Create rule.
  7. Repeat for other contracts.
  8. 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:

ContractFunctions used by the app
Pool FactorydeployPool

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:

ContractFunctions used by the app
Your Pooldrawdown, repayInterest, repay (principal), approveRedeemRequest (approve a lender's withdrawal request), proposeCreditLineSettingsChange, proposeTrancheSettingsChange, proposeUnderwriter, revokeUnderwriterProposal
Stablecoinapprove (authorizes the Pool to pull tokens for interest/principal repayment)

Lenders (staking into a pool)

ContractFunctions used by the app
Pooldeposit, reserve (reserve a deposit slot), requestWithdraw, withdraw, redeem, claimReservedInterest, setAutoInterestCompounding
Stablecoinapprove (authorizes the Pool to pull your deposit)

Underwriters

ContractFunctions used by the app
Underwriter RegistryregisterUnderwriter, updateProfile, updateFees, deactivate, reactivate
PoolacceptUnderwriter (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

ContractEthereumBaseCelo
Pool Factory0xfA0EE507Dd3b71dC7Ef810713B84DFF4e98c94530x23647722680C4A45FCa2ff18E572E7d43Bae1aa50xd22bFBACD29a48A4b68A5BC490FabCF18B07a3E2
Registry0xf2bd1C6cD5fCF619df3c2542A19F128728561ec60x059725Ded2e07176C03554056109e9741CC2F7820xe3400D36697e2C0E3904DfF63Bdcf5F21f11673c
Underwriter Registry0x4b6f0D66e5426067178cce5E38B9a117AcFfCF7F0xc3E1f6e34a633a37d1C8e73A0f3eb1003d0699fE0xA51B0018A3F4DD03723da2E3a3936917a939c6ce
Withdrawal Registry0x511caA407e30D94D790D23A6212738794f893Ecd0x4F29844b3163E0f77ea05C884614Ab20fF1b8aF60x54753101A5285e72813d0d126b1c387Acd6a390d

Testnet

ContractCelo Sepolia
Pool Factory0xffce297C9bFb8664C3A26C5f94555d54c69A47aE
Registry0x4F2319AF61e40BdAF8eD06876b66808F67C12074
Underwriter Registry0x528ce3917a598d6705624FCb8A50cB155212aabD
Withdrawal Registry0x0b9311Ad840D1321Cb7756d27A1145CFEeFB1b6d

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