prepare_curve_swap
Build an unsigned Curve swap on Ethereum for stETH/ETH or stable_ng plain pools. Handles coin index resolution and automatic approval, with mandatory slippage protection.
Instructions
Build an unsigned Curve swap on Ethereum. Issue #615. Supports the canonical legacy stETH/ETH pool (0xDC24316b9AE028F1497c275EB9192a3Ea0f67022 — historically the tightest-spread venue for stETH↔ETH) and any plain pool registered with the stable_ng factory (covers crvUSD/USDC, USDe/USDC, etc.). Pass pool + fromToken + toToken; the tool resolves coin indices from the pool's coins array. Use fromToken: "native" for the ETH leg of the stETH/ETH pool (the only currently-supported pool whose coins(i) returns the ETH sentinel). Slippage gate REQUIRED: slippageBps (server reads get_dy and applies the cap) or minOut (explicit decimal-string uint256). The pool's exchange() accepts min_dy=0 silently — defaulting to that would let MEV extract the entire output. ERC-20 inputs chain an approval to the pool automatically. Rejected: meta pools (use exchange_underlying — different ABI), cryptoswap / tricrypto / older legacy stable pools (uint256 indices, use_eth flag — different selectors). For unsupported Curve pairs, fall back to prepare_swap (LiFi).
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| wallet | Yes | 0x EVM wallet address that will sign the tx. | |
| pool | Yes | Curve pool address. Must be the canonical legacy stETH/ETH pool (0xDC24316b9AE028F1497c275EB9192a3Ea0f67022) or a stable_ng factory plain pool. Meta pools, cryptoswap, tricrypto, and older legacy stable pools are rejected with a clear error. | |
| fromToken | Yes | Token to spend. Pass `"native"` only for pools whose `coins(i)` returns the ETH sentinel (0xeeee...eeee) at some index — currently the legacy stETH/ETH pool. For ERC-20 inputs the tool chains an approval to the pool automatically. | |
| toToken | Yes | Token to receive. Same rules as `fromToken`. Must differ from `fromToken` and both must appear in the pool's `coins` array. | |
| amount | Yes | Human-readable decimal input amount in the from-token (e.g. "1.5"). Decimals are read from the from-token contract; native = 18. | |
| slippageBps | No | Slippage tolerance in basis points (50 = 0.5%). When set, `min_dy = get_dy(i,j,dx) * (1 - slippageBps/10000)`. Either `slippageBps` or `minOut` is required — the pool's exchange() accepts `min_dy=0` silently and defaulting to that would let MEV extract the entire output. Capped at 5% (500 bps). | |
| minOut | No | Explicit minimum output in the to-token's wei (decimal-string uint256). Takes precedence over `slippageBps` when both are provided. | |
| acknowledgeHighSlippage | No | Required when `slippageBps > 100` (1%). Same gate as `prepare_swap` — sandwich-MEV bots target wide-slippage txs. | |
| acknowledgeNonAllowlistedSpender | No | AFFIRMATIVE GATE — required whenever `fromToken` is an ERC-20 (the approve leg targets the Curve pool, which is NOT in the global protocol approve-allowlist: Aave Pool, Compound Comet, Morpho Blue, Lido Queue, EigenLayer, Uniswap NPM, Uniswap SwapRouter02, LiFi Diamond). The allowlist is a security recommendation, not a hard requirement: it limits approvals to a small set of well-known spenders to keep prompt-injection drains from sliding through. Setting this flag is the user's affirmative ack that they understand the approval target sits outside that curated set — the on-device clear-sign of `approve(<curve-pool>, <amount>)` and the prepare-receipt warning advisory are the verification anchors. Do NOT default this to true silently; surface the trade-off to the user first. Ignored when `fromToken: "native"` (no approval; native ETH is sent as msg.value). | |
| approvalCap | No | Cap on the ERC-20 approval preceding this action. Omit for "unlimited" (standard DeFi UX — fewer follow-up approvals). Pass "exact" to approve only what this action pulls. Pass a decimal string (e.g. "500") for a specific ceiling in the asset's human units; must be ≥ the action amount, otherwise the transaction would revert. |