write.pool.redeem
Burns tranche shares to withdraw underlying asset and accrued interest from an Arcadia lending tranche. Builds an unsigned redeem transaction for the specified owner and receiver.
Instructions
Build an unsigned redeem transaction to withdraw from an Arcadia lending tranche (ERC-4626). Burns tranche shares and returns the corresponding amount of underlying asset, including accrued interest. The owner must be the shares holder; receiver is where the underlying asset is sent.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| tranche_address | Yes | Tranche contract address (ERC-4626 vault). Get this from read.pool.list — each pool's `tranches[0].address`. | |
| shares | Yes | Amount of tranche shares to burn, in raw units. To redeem everything, use the owner's full share balance. | |
| receiver | Yes | Address that receives the underlying asset. Usually the owner's own wallet. | |
| owner | Yes | Address that owns the tranche shares being burned. Normally the signer's own wallet. | |
| chain_id | No | Chain ID: 8453 (Base), 130 (Unichain), or 10 (Optimism) |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| description | Yes | ||
| transaction | Yes | ||
| predicted_account_address | No |
Implementation Reference
- src/tools/write/pool/redeem.ts:10-91 (handler)Handler function that registers the write.pool.redeem tool. Validates addresses, encodes the ERC-4626 redeem() call using tranche ABI, appends an ERC-8021 attribution suffix, and returns an unsigned transaction object (to, data, value, chainId).
export function registerPoolRedeemTool(server: McpServer, _chains: Record<ChainId, ChainConfig>) { server.registerTool( "write.pool.redeem", { annotations: { title: "Build Pool Redeem Transaction", readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false, }, outputSchema: SimpleTransactionOutput, description: "Build an unsigned redeem transaction to withdraw from an Arcadia lending tranche (ERC-4626). Burns tranche shares and returns the corresponding amount of underlying asset, including accrued interest. The owner must be the shares holder; receiver is where the underlying asset is sent.", inputSchema: { tranche_address: z .string() .describe( "Tranche contract address (ERC-4626 vault). Get this from read.pool.list — each pool's `tranches[0].address`.", ), shares: z .string() .describe( "Amount of tranche shares to burn, in raw units. To redeem everything, use the owner's full share balance.", ), receiver: z .string() .describe("Address that receives the underlying asset. Usually the owner's own wallet."), owner: z .string() .describe( "Address that owns the tranche shares being burned. Normally the signer's own wallet.", ), chain_id: z.number().default(8453).describe(CHAIN_ID_DESCRIPTION), }, }, async (params) => { try { const validTranche = validateAddress(params.tranche_address, "tranche_address"); const validReceiver = validateAddress(params.receiver, "receiver"); const validOwner = validateAddress(params.owner, "owner"); const shares = BigInt(params.shares); let data = encodeFunctionData({ abi: trancheAbi, functionName: "redeem", args: [shares, validReceiver, validOwner], }); data = appendDataSuffix(data) as `0x${string}`; const result = { description: `Redeem ${params.shares} shares of tranche ${params.tranche_address}, sending the underlying asset to ${params.receiver}`, transaction: { to: validTranche, data, value: "0", chainId: params.chain_id, }, }; return { content: [ { type: "text" as const, text: JSON.stringify(result, null, 2), }, ], structuredContent: result, }; } catch (err) { return { content: [ { type: "text" as const, text: `Error: ${err instanceof Error ? err.message : String(err)}`, }, ], isError: true, }; } }, ); } - src/tools/write/pool/redeem.ts:24-44 (schema)Input schema definition for write.pool.redeem: tranche_address, shares, receiver, owner (all strings), and chain_id (number, default 8453).
inputSchema: { tranche_address: z .string() .describe( "Tranche contract address (ERC-4626 vault). Get this from read.pool.list — each pool's `tranches[0].address`.", ), shares: z .string() .describe( "Amount of tranche shares to burn, in raw units. To redeem everything, use the owner's full share balance.", ), receiver: z .string() .describe("Address that receives the underlying asset. Usually the owner's own wallet."), owner: z .string() .describe( "Address that owns the tranche shares being burned. Normally the signer's own wallet.", ), chain_id: z.number().default(8453).describe(CHAIN_ID_DESCRIPTION), }, - src/tools/output-schemas.ts:10-14 (schema)Output schema (SimpleTransactionOutput) used by write.pool.redeem: contains description string and transaction object (to, data, value, chainId).
export const SimpleTransactionOutput = z.object({ description: z.string(), transaction: Transaction, predicted_account_address: z.string().optional(), }); - src/tools/index.ts:67-67 (registration)Registration call in registerAllTools() that wires up the write.pool.redeem tool under the 'Write tools — pool' section.
registerPoolRedeemTool(server, chains); - src/utils/attribution.ts:19-22 (helper)Helper that appends an ERC-8021 attribution suffix to the encoded redeem calldata for on-chain attribution.
export function appendDataSuffix(calldata: string): string { if (!DATA_SUFFIX) return calldata; return calldata + DATA_SUFFIX.slice(2); }