- Simulating a swap previews its output and confirms it would succeed before you sign, spend gas, or broadcast anything — it is a read-only
eth_callagainst your Ethereum node. - For a price, call the Uniswap V2 router
getAmountsOutor the Uniswap V3QuoterV2quoteExactInputSingle— both return the expected output amount for your input. - To confirm the exact trade would go through,
eth_callthe router’sswapExactETHForTokenswith your realamountOutMinand deadline — a revert such asUniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNTmeans the real transaction would fail too. - To preview exact asset changes or simulate from an account that doesn’t hold the funds yet, use
eth_simulateV1with state overrides andtraceTransfers. - Every example uses ethers.js v6 and a Chainstack Ethereum node, and was verified live against Ethereum mainnet.
How swap simulation works
Simulating a swap runs the trade against the current chain state and returns what would happen — the output amount and whether it would revert — without a signature, without spending gas, and without broadcasting a transaction. You do it with a singleeth_call (or eth_simulateV1) to your node, so you can check a trade as often as you like at no cost and with no onchain footprint.
A swap simulation answers three separate questions, and each has its own tool:
- How many tokens will I receive — a quote from the Uniswap V2 router
getAmountsOutor the V3QuoterV2. - Will the exact swap succeed with my slippage limit and deadline — an
eth_callagainst the router’s swap function, which reverts with the same reason a real transaction would. - What exactly changes, and can I preview it from an account that doesn’t hold the funds yet —
eth_simulateV1with state overrides and asset-change tracing.
- WETH —
0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2(18 decimals) - USDC —
0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48(6 decimals) - Uniswap V2 router 02 —
0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D - Uniswap V3 QuoterV2 —
0x61fFE014bA17989E743c5F6cB21bF9697530B21e
The output amounts shown come from live mainnet runs. Pool reserves change with every block, so your exact numbers will differ.
Prerequisites
- Node.js 18 or later.
- The ethers.js v6 library — install it with
npm install ethers. - A Chainstack Ethereum node endpoint — deploy a node and copy the HTTPS endpoint from the node’s Access and credentials tab. See view node access and credentials for the exact location.
RPC_URL in each script below. Keep it private — treat it like a password.
Preview the output with the Uniswap V2 router
The fastest quote is the Uniswap V2 router’sgetAmountsOut — a view function that reads the pool reserves and returns the amount you would receive for a given input along a token path. Calling it is a read-only eth_call, so it needs no account, no funds, and no gas.
getAmountsOut returns an array of amounts, one per hop in the path. The first element is your input and the last is your output.
v2-quote.js
router.getAmountsOut(...) call is an eth_call under the hood. By default it runs against the latest block; pass a block tag to simulate against past state — for example router.getAmountsOut(amountIn, path, { blockTag: 25498586 }).
Preview the output with the Uniswap V3 QuoterV2
For Uniswap V3, theQuoterV2 contract simulates a swap through the pool’s concentrated-liquidity math and returns the output amount plus the resulting price. Unlike a V2 reserve formula, it walks the pool’s ticks, so it accounts for how your trade moves the price.
quoteExactInputSingle takes a single struct and returns four values — the output amount, the pool price after the swap (sqrtPriceX96After), how many initialized ticks the swap crossed, and a gas estimate. It is not a view function — it reverts internally to return its result — so call it with staticCall to run it through eth_call.
Uniswap V3 pools exist at several fee tiers — 100 (0.01%), 500 (0.05%), 3000 (0.3%), and 10000 (1%). WETH/USDC is deepest at 500. Try the tiers you care about and take the best quote.
v3-quote.js
Confirm the swap would succeed with eth_call
A quote tells you the price, but it does not run the swap you are about to send. To confirm the exact transaction would go through — with your slippage guard, deadline, and recipient — simulate the router’s swap function itself witheth_call. If the call returns, the real transaction would succeed and you get the exact output; if it reverts, the real transaction would revert with the same reason.
This example encodes swapExactETHForTokens and sends it through provider.call, which is eth_call. Because you buy with ETH, value carries the input and the path starts with WETH — the router wraps the ETH for you.
simulate-swap.js
amountOutMin above the quote — for example ethers.parseUnits("999999999", 6) — and the same call reverts with the reason the real transaction would return:
eth_call runs the swap logic against current state without moving any funds. Whether the value must be backed by a real balance depends on your node’s configuration, so setting from to a funded wallet is the reliable choice. To simulate from an account that does not hold the ETH, override its balance with eth_simulateV1.
Preview asset changes with eth_simulateV1
eth_simulateV1 runs a full transaction (or a sequence of them) and can override account state first — balances, code, storage — then report every asset movement. Use it to simulate a swap from any address without funding it, and to read the exact amounts that would move.
This example gives a chosen address 10 ETH with a state override, simulates the swap, and reads the USDC received from the transfer logs. traceTransfers: true surfaces every asset movement — including native ETH — as a Transfer log, so you can total the deltas directly.
simulate-v1.js
Choose the right method
| Method | Answers | Executes the swap? | Needs funds? |
|---|---|---|---|
V2 getAmountsOut | Expected output for a V2 route | No — reads reserves, applies the V2 formula | No |
V3 quoteExactInputSingle | Expected output and price impact for a V3 pool | Simulated — reverts internally to return the quote | No |
eth_call on the swap | Whether the exact swap would succeed, and its output | Yes | Only if your node enforces balances |
eth_simulateV1 | Output and every asset change, from any account | Yes | No — override balances and allowances |
eth_call to confirm it would succeed with your slippage and deadline. Reach for eth_simulateV1 when you need exact asset changes or want to simulate from an account without first funding it.
Wrapping up
You now have four ways to inspect a Uniswap trade before committing to it — a V2 quote, a V3 quote, a fulleth_call execution check, and an eth_simulateV1 asset-change preview — all read-only against your Chainstack Ethereum node. Compute amountOutMin from a fresh quote and your slippage tolerance, confirm the swap with a simulation, and only then sign and broadcast the real transaction.