Why every quote you sign is simulated on chain first
Before a Tirio quote reaches you, the complete swap runs against the latest block. What that simulation checks, what it catches and what it guarantees.
A DEX aggregator can compute a route with perfect math and still hand you a quote that fails. Pools change between blocks. A hooked pool can price a real swap differently from what it reports. A token can take a tax on a pool nobody measured. Integer rounding across several hops can add up. None of that shows up until the transaction actually runs.
So before Tirio returns the quote you sign, it runs that transaction. Not an approximation of it: the complete call your wallet will send, against the latest block, without broadcasting anything. This post explains how that works, what it catches, and where its guarantee ends.
What "simulating" means here
Every Ethereum-compatible node can execute a call without turning it into a transaction. The JSON-RPC method is eth_call, which the Geth documentation describes as executing "a new message call immediately, without creating a transaction on the block chain." The node runs the code on top of the chosen block's state, returns the result and throws the state changes away. Nothing is signed, nothing is mined and no gas is paid.
What Tirio simulates
When you press Review on tirio.io, or call /quote on the API, the engine does three things in order:
- Routes the order with its own copy of each pool's math, splitting it across paths where that pays more after gas.
- Builds the exact transaction: the call to Tirio's Router with your tokens, amounts, recipient, minimum output and deadline, and the route the Executor will run.
- Runs that transaction with
eth_callat the latest block. The route itself is tested even before your wallet has approved or holds the input, so you see a real result before you approve anything.
The numbers you see come from that run. The output in the quote is the simulated output, and the gas estimate is the simulated gas. The response marks this with simulated: true, and the app shows a Simulated badge.
What happens when a simulation disagrees
Most of the time the simulated output matches the plan closely. When it does not, the engine treats the simulation as the truth and the plan as the hypothesis.
- If the transaction reverts, that route is never returned as a quote.
- If it succeeds but pays clearly less than planned, it is not returned either. A venue can legitimately charge a real swap more than it reports when asked for a price, and this is how such a venue is caught.
- What reaches you is a route that worked, with the output and gas it actually produced at the latest block.
What this catches in practice
The point of simulating is that it catches problems no model can see in advance:
- State that moved. A pool traded between the moment it was read and the latest block.
- Venue behaviour. A hooked pool, a market maker or a launchpad curve that pays differently for the actual caller and amount than its quote function said.
- Token behaviour. A transfer tax that applies only on certain pools, or a token that blocks transfers.
- Settlement details. Rounding and the exact integer amounts that flow between hops, which a floating-point estimate would gloss over.
A second simulation, in your browser
The API's simulation is not the last one. When you press Swap on tirio.io, the app runs the exact transaction once more with eth_call, from your own account, before your wallet opens. If it would revert, the Router's error is decoded into a plain message, such as an output below your minimum or an expired deadline, nothing is sent and a fresh quote is requested.
Before that, the app also checks the quote itself: that the transaction targets Tirio's Router, and that the decoded calldata carries exactly the tokens, amounts, recipient, minimum and deadline you asked for. Our security documentation lists every check.
What a simulation guarantees, and what it does not
A successful simulation proves one thing precisely: this exact transaction worked against the state of the latest block. That is a strong statement. It means the route is valid, the venues accept it, the token transfers go through and the output was what the quote shows.
It cannot promise that the next block will look the same. Your transaction lands a few blocks later, and other trades may land first. That gap is covered by two values written into the transaction itself:
- Minimum received. The Router measures what actually reached your address and reverts the whole swap if it is less than your minimum. Your slippage setting decides that minimum.
- Deadline. A transaction mined after it reverts.
So the guarantee is layered. Simulation makes sure the quote is real at the moment it is made. The minimum and the deadline make sure that, whatever happens afterwards, you either get at least what you accepted or nothing happens and you pay only gas.
Two honest details
- The price you see while typing is not simulated. It is routed the same way, refreshed as you type and marked Indicative price. Simulation happens when you review, because that is when there is a transaction to run. Our guide to reading a swap quote shows how the two can differ by a few cents.
- If a simulation cannot run, which is rare, the quote comes back with
simulated: falseand the app marks it Not simulated with a warning. The browser-side simulation still runs before your wallet opens.
Why we built it this way
Simulating every signed quote costs time and node capacity, and a router could skip it and still be right most of the time. We think "most of the time" is the wrong standard for something you sign. A quote should describe a transaction that has actually worked, and when the world disagrees with our model, the world should win.
If you build on the API, the same applies to you: every /quote response tells you whether it was simulated, and its tx is the exact transaction that ran.