Skip to main content
In short: you want to swap a large amount without getting a bad price, and need to know which limit to set. Set a limit price if you have a price in mind, an impact cap if you do not want to move the market, or a cost limit if you want the largest trade that fits cheaply. Only the limit price is enforced on the network. An order with a limit price is also spread across every pool that will fill it at your price, so more of it fills. Swaps here go through our own router rather than an outside aggregator. It prices swaps on Ethereum, Base and Arbitrum. HyperEVM has no swaps. So a plan can ask two questions an aggregator cannot answer. How much will the market take at a price you name? And how much of a resting order fills right now?

Which limit do you want?

A swap step takes three optional limits. Most of the skill is choosing between them, because each one does a different job.
Only limit_price is a promise. It becomes the minimum output in the signed form and is enforced on the network. A fill below it fails.The two size limits are not signed and do not need to be. They can only make a trade smaller, and spending less than you approved is what a partial fill already is.

Buy at a price you named

You want cbBTC, but only at 80,000 or better. You care about the price, and take whatever size the market gives you there.
That says 1,000 USDC must buy at least 0.0125 cbBTC. With partial set to true it rests and takes what clears, then comes back for the rest. With it false, the trade either fills at that price or does not happen. Use this whenever a person said a number.
A limit price is two whole numbers, written out units/in units. Never a decimal. A decimal has to be converted against two different token scales somewhere, and every place that happens is a place a limit can be multiplied by a million by mistake.

Move a large amount without moving the market

A treasury shifting 2,000,000 USDC into WETH cares less about a specific price than about the trade not printing a candle.
Offer the two million. The router shrinks it until the impact is at most 0.05%, then prices that smaller trade. The answer tells you it shrank the offer and that this limit is why. Use this when somebody says “do not move the market”. No price is named, so you take the market rate for whatever size fits.

Trade whatever fits cheaply, when nobody knows what fits

An agent told to convert “as much as is sensible” has no size to offer. Ask the market first.
This returns the largest trade that fills within 5 basis points, and the price floor for that trade. Both are signed together. On one measurement of Base the size was 58,360 USDC, and 12,264 20 minutes later, because trades in between had moved the pool. Use this when the size is the unknown. It is the only limit that answers how much.
Both numbers come from one call on purpose. The floor is worked out from the amount being quoted. Choose a size first and sign a floor for the original amount, and the smaller trade can never clear it, so the swap fails.

They combine

Any combination is allowed except a limit price together with a separate minimum output. Those two can disagree, and picking a winner would trade at a price nobody chose. A resting order that uses all three says: fill no worse than this price, take no more than the market offers at 5 basis points, and do not move the pool more than 10 getting there.
Zero is refused for both size limits. Zero impact and zero cost each describe a trade nothing fills, so a plan carrying one would look bounded while being unfillable. Leave the setting out to mean “no limit”.

Spreading across pools happens for you

At a given price, the amount available is the sum across every pool, not only the best one’s depth, because pools are independent and each one stops at your price on its own. DeFiLoops asks for this on every order with a price limit. You do not set it in the plan: at a fixed price, filling more of your own order is what you asked for. Measured on Base, 2,000,000 USDC with a price limit 25 basis points below spot: That is twice the fillable size, for about 1.5 basis points of price.
This buys capacity, not a better price. It is worth nothing to an order the best single pool could already absorb. Below roughly $45,000 it changes nothing at any limit. It helps where you asked for a good price on a large order, by turning a partial fill into a complete one.
Spreading across pools is free. Spreading across time is a trade-off. Four back-to-back swaps on one pool give exactly the same result as one swap of the total, because the second starts wherever the first left the price.Splitting over time only pays if the price recovers in between. → Splitting a big trade

How big a bite is

A resting order on a network takes bites: it fills a piece when the price allows and comes back for the rest. Every bite is sized before it is signed. The router is asked once, with the order’s price and its impact cap. The answer is the bite. The agent signs for exactly that amount, with the price floor that fits it. If nothing fits under the cap, the order rests and tries again when the price moves. An order that states no cap gets a default. You can change either number. A card refuses a cap above 5%. A market order in bites has no price to wait for. Each pass takes what clears under the cap, and the order ends when it is filled, expires or is cancelled.

Partial fills, and amounts that shrink with them

A resting order fills in bites. Each bite runs the whole rest of the plan at a fraction of full size, so every amount in the plan has to shrink with it. Amounts that reference an earlier step shrink on their own. A step spending “what the swap produced” is automatically a tenth when the swap was a tenth. Fixed amounts do not, so the system refuses the plan rather than running one step at the number the document wrote while the money around it moved. A bite of a tenth executing the whole trade is not an error anybody would catch by reading the plan. Sometimes there is nothing to reference. Repaying WETH bought with USDC and then taking back cbBTC collateral has no step producing cbBTC to point at, and pointing at the WETH would withdraw a WETH-shaped number of a different token. So a fixed amount can name a step whose size it follows. You state the amount for the whole order and say what it scales with. At full size it is the amount you wrote, and at a tenth it is a tenth of that.
0.2 cbBTC is the take-back at full order size. ScalesWith: "buy" makes a bite that filled a tenth withdraw a tenth.

Under the hood

The measurements behind the numbers above, and the mistake that costs people money. Not needed to write a plan.

The cap is part of what you approve

The impact cap and the market flag are part of the order you approve. Change either afterwards and the approval reads as stale, so you approve again. That check runs on our servers. The hardware enclave does not recompute it, so it guards against drift in our software and not against a hostile server.

The question is inverted on purpose

A trader does not ask what the impact of $500k is. They ask how much they can trade, and the answer depends on what they are willing to pay. So the sizing service takes a cost and returns a size. That inversion is also what makes it cheap to compute. “What does size S cost” needs a quote per size, and finding the largest size under a cost is then a search. “What size costs C” is one probe: the pool is given a price limit, stops itself when it reaches it, and reports what it moved. Measured on Base, USDC to WETH, across 11 pools:
A cost limit is where the last unit trades, not what the whole trade pays. This is the most misread number here, and it is misread in the direction that makes execution look about twice as expensive as it is.The right-hand column above is the number to compare against a quote. Do not estimate it by halving the limit. On this pair that would have been wrong by 25% to 100% at every level.

A cost limit and an impact limit are not the same setting

Both take a number in basis points and both hand back a size, which is why people substitute one for the other. Because one is marginal and the other is an average, the same number is not the same request. A cost limit of 25 admits a trade whose average footprint is about 10, so max_cost_bps: 25 is roughly max_impact_bps: 10. Confirmed from opposite directions on the same pair. A 1,000,000 USDC offer capped at an average of 10 came back at 803,244 USDC. A cost limit of 25 came back at 818,992. The two agree within 2% on size and within 2 pips on cost.
An impact limit cannot make a trade bigger. It only shrinks what you offered, so it needs you to have picked a size first. A cost limit has no offer to shrink and answers the sizing question outright. The capped size does not depend on how much you offer. Offer more than fits, and you get the same size back for the same market and the same cap.

What spreading across pools does and does not reach

The sizing service reports how much depth sits in the direct pools at a given price. That figure is a lower bound, because it ignores routes that hop through an intermediate asset. The same test on two frozen copies from the same day landed on both sides of it. Where the best single route was direct, the spread won by 235 pips. Where the best single route hopped twice, the single route won by 150. Compare against a real quote before assuming the spread is better.
An early version of this work claimed a spread can never price worse than the best single pool. That holds only at equal volume. A spread that fills twice as much is necessarily deeper into the market. The guarantee is the price limit, and every pool stops at it. Filling more costs price, and that is the trade-off.

What is built, and what is not