exchange.IO("lp.simulate", ...)
Runs a plan's add-liquidity transaction with eth_call (nothing is signed, broadcast or paid) to confirm it executes and see the amounts it uses.
exchange.IO(k, plan)
exchange.IO(k, plan, stateOverride)Examples
-
Give the wallet a temporary 100 ETH and simulate a range above the price that uses only ETH.
javascriptfunction main() { var plan = exchange.IO("lp.plan", {symbol: "ETH_USDC", budget: 100, range: {pct: [2, 10]}}) var ov = {} ov[exchange.IO("address")] = {balance: "0x56bc75e2d63100000"} var r = exchange.IO("lp.simulate", plan, ov) if (!r) { Log("Simulation failed:", GetLastError()) return } Log("Pool:", r.pool, "ETH sent (wei):", r.value) r.positions.forEach(function (p) { Log("Liquidity:", p.liquidity, "uses:", p.amountBase, "ETH +", p.amountQuote, "USDC") }) } -
Aerodrome and Velodrome: a basic-pool plan simulates without any balance.
javascriptfunction main() { var plan = exchange.IO("lp.plan", {symbol: "ETH_USDC", budget: 100, stable: false}) var r = exchange.IO("lp.simulate", plan) Log(r.protocol, "LP tokens:", r.lpTokens) Log("Deposit:", r.amountBase, "ETH +", r.amountQuote, "USDC") }
Returns
| Type | Description |
object / null value |
|
Arguments
| Name | Type | Required | Description |
k | string | Yes | Set to |
plan | object | Yes | A plan returned by |
stateOverride | object | No | State override for the node's |
See Also
Uniswap / PancakeSwap Aerodrome / Velodrome exchange.IO exchange.IO("lp.plan") exchange.IO("lp.add") exchange.IO("simulate")
Remarks
Fields: positions gives each position's minted liquidity and the token amounts used; value is the native coin sent with the transaction (decimal string in the smallest unit, non-zero when paying in the native coin); swapNeeded true means the plan needs a swap first, so the post-swap amounts are simulated and the token the wallet does not hold yet must be supplied with stateOverride, or the call reverts on the transfer (an error such as execution reverted: STF).
Allowances: the transaction pulls tokens from the wallet, so a short allowance for the PositionManager (Permit2 for V4/Infinity CL) also reverts; a real lp.add approves automatically, while a simulation either pays in the native coin (no approval needed) or supplies the allowance in stateOverride. A plan that needs only the native coin (such as a range above the price on a native pair) simulates with just a balance for the wallet.
V4/Infinity CL pools on Uniswap and PancakeSwap pay tokens through Permit2, so supply the token's approval of Permit2 and the PositionManager allowance inside Permit2 (the Permit2 address is v4.permit2 in exchange.IO("contracts")); their PositionManager returns no amounts, so the result shows the planned amounts plus tickLower and tickUpper, and note says so (no revert means the amounts fit).
Basic pools on Aerodrome and Velodrome are simulated with the Router's quoteAddLiquidity, which needs no balances or approvals, returning {pool, protocol, lpTokens, amountBase, amountQuote, swapNeeded, note}.