Nordstern

Simulate Swap

Simulates an arbitrary swap transaction via eth_call and returns the received output amount, gas usage and raw return data — without holding funds or sending anything on-chain.

POST/simulate/{chain_id}

Simulates any swap transaction — yours or another aggregator's — against live chain state and reports what it would actually return. Use it to re-validate quotes before execution, to compare aggregators on equal terms, or to debug reverting calldata. The input can be an ERC-20 (the approval-based flow: the wallet approves the router, the router pulls the tokens) or the chain's native token, sent as the transaction's value.

No funds are needed: the simulation runs entirely inside an eth_call with state overrides. A minimal proxy contract is placed at the from address and from is given amountIn of the input token: for an ERC-20, its balance and its allowance towards to are overridden to amountIn; for the native token, its native balance is, and amountIn is sent along as the call's value. The proxy then calls to with the given calldata — measuring the received output tokens, the gas the call consumed and its raw return data. The block environment is realistic by default: tx.gasprice is the current network gas price, block.coinbase is the latest block's validator and the gas limit is derived from the block gas limit — so gas- and validator-dependent code paths behave as they would on-chain.

GET is also supported with the same fields as query parameters.

Parameters

chain_idreqinteger

EVM-compatible chain ID (path parameter).

fromreqstring

Wallet address the transaction would be sent from. Output tokens are measured at this address. It does not need to hold any funds or approvals — both are provided via state overrides.

toreqstring

Contract address the transaction calls (typically an aggregator router). Must differ from from.

datareqstring

Transaction calldata as a 0x-prefixed hex string. Submit exactly what you would send on-chain.

tokenInreqstring

Contract address of the input token. Use 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE for the chain's native token: the transaction is then simulated with amountIn as its value, the way a swap that starts with ETH, BNB, etc. is sent on-chain.

amountInreqstring

Input amount in the token's base units. For an ERC-20, the sender's balance and allowance are overridden to exactly this value; for the native token, it is the value sent with the transaction. Decimal or 0x-hex.

tokenOutreqstring

Contract address of the output token to measure. Use 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE for the chain's native token.

gasPricestring

Gas price in wei, reflected by tx.gasprice during the simulation; the sender is automatically funded to cover it. Default: the current network gas price. Pass 0 to simulate without a gas price.

gasstring

Gas limit for the simulation. Default: 50% of the current block gas limit.

blockstring

Block to simulate at: a block number (decimal or 0x-hex) or a tag such as latest or pending. Default: latest.

spenderstring

Address the allowance override is granted to, when the router pulls tokens through a separate contract (e.g. Permit2-style flows). Default: to. Not used for a native tokenIn.

coinbasestring

Address to use as block.coinbase during the simulation. Default: the validator of the most recent block, so validator-dependent logic behaves as it would on-chain.

balanceSlotstring

ERC-20 base storage slot of the token's balance mapping. Resolved automatically for tokens known to the aggregator; required only for exotic tokens. Omit for a native tokenIn.

allowanceSlotstring

ERC-20 base storage slot of the token's allowance mapping. Resolved automatically for tokens known to the aggregator; required only for exotic tokens. Omit for a native tokenIn.

Request

curl 'https://api.nordstern.finance/simulate/8453' \
  -H "Content-Type: application/json" \
  -H "Referer: https://yourdomain.com" \
  -d '{
    "from": "0xYourWalletAddress",
    "to": "0xC87De04e2EC1F4282dFF2933A2D58199f688fC3d",
    "data": "0x3f0bde25...",
    "tokenIn": "0x4200000000000000000000000000000000000006",
    "amountIn": "1000000000000000000",
    "tokenOut": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
  }'
// Re-validate a quote: pass the quote's tx fields straight through.
const response = await fetch("https://api.nordstern.finance/simulate/8453", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Referer": "https://yourdomain.com",
  },
  body: JSON.stringify({
    from: "0xYourWalletAddress",
    to: quote.tx.to,
    data: quote.tx.data,
    tokenIn: "0x4200000000000000000000000000000000000006",
    amountIn: "1000000000000000000",
    tokenOut: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
  }),
});
const result = await response.json();
console.log(result);
import requests

url = "https://api.nordstern.finance/simulate/8453"
body = {
    "from": "0xYourWalletAddress",
    "to": "0xC87De04e2EC1F4282dFF2933A2D58199f688fC3d",
    "data": "0x3f0bde25...",
    "tokenIn": "0x4200000000000000000000000000000000000006",
    "amountIn": "1000000000000000000",
    "tokenOut": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
}
headers = {"Referer": "https://yourdomain.com"}
response = requests.post(url, json=body, headers=headers)
print(response.json())

Response

successboolean

Whether the simulated call succeeded. false means the transaction would revert on-chain; the simulation itself still ran and returns 200.

amountOutstring

Amount of tokenOut received by from, in base units. "0" when success is false.

gasUsedinteger

Gas consumed by the call to to. Excludes the 21,000 intrinsic transaction gas and calldata gas, so it is directly comparable across quotes but slightly below the full on-chain total.

returnDatastring

Raw return data of the call as 0x-prefixed hex. Carries the revert payload when success is false.

revertReasonstring

Human-readable decoded revert reason. Only present when success is false.

blockstring

The block parameter the simulation ran at (echoes the request, default latest).

{
  "success": true,
  "amountOut": "2120362157",
  "gasUsed": 431202,
  "returnData": "0x000000000000000000000000000000000000000000000000000000007e63c92d",
  "block": "latest"
}

A reverting transaction still returns 200, with the decoded reason:

{
  "success": false,
  "amountOut": "0",
  "gasUsed": 54210,
  "returnData": "0x08c379a0...",
  "revertReason": "Insufficient output",
  "block": "latest"
}
Note:

amountOut is measured as a real balance delta at from, so transfer taxes, rebases and router fees are all reflected — it is the amount the wallet would actually receive.

Errors

CodeMeaning
400Missing or invalid parameter, unknown storage slots for an untracked ERC-20 tokenIn (provide balanceSlot/allowanceSlot), storage slots sent with a native tokenIn, or a simulation setup revert (e.g. tokenOut is not an ERC-20). The JSON response body describes the issue.
404Chain ID not supported.
502The RPC node backing the simulation failed. Safe to retry.

See Errors for the full error format.

On this page