Standing orders
Limit, take profit, stop loss, DCA and counter-flow. You sign an order rather than sending a trade, and a keeper executes it when the trigger fires. This page is what each one does and, more usefully, how each one fails.
The order types
| Type | Fires when | Available on |
|---|---|---|
| Limit | The price reaches your trigger | Pro and Custom |
| Take profit | A limit sell above the market | Pro and Custom |
| Stop loss | The price falls to your trigger | Pro only |
| DCA | On a schedule — n fills, paced by an interval | Pro only |
| Counter | Somebody else trades — you take the other side | Pro and Custom |
How an order is placed
- You approve Permit2An allowance to the standing-order router for the token being sold.
- You sign an EIP-712 orderNo transaction is sent. The signature is the order.
- A digest gate runs before you signThe locally computed EIP-712 digest is compared against the router's own
hashOrder. A mismatch refuses to sign rather than producing an order that can never fill. - The keeper watchesWhen the trigger fires it submits your signed order to the router, which pulls the tokens through Permit2 and swaps.
BNB Chain carries two Permit2 deployments — the canonical one and PancakeSwap's — and different standing routers there were deployed against different ones. Signing against the wrong Permit2 changes the EIP-712 domain, the router recovers a different signer, and the fill reverts with InvalidSigner().
Nothing surfaces to the user. The order is accepted, it rests, and it never fills — indistinguishable from a price that never arrived. The fix is to read PERMIT2() from the router you are signing for, never from a per-chain constant.
Limit and take profit
A limit order carries a price as limitPriceX96, and one detail about it causes more confusion than anything else on this page:
It is a minimum output per unit of input, not an absolute coin price. On a buy that reads naturally. On a sell it is inverted, and encoding the coin's price directly produces an order that never fills. If you are constructing orders yourself, derive the value from the side.
The trigger is evaluated against the pool, not against an indexer's last recorded trade. An indexer running behind the head would fire triggers against hours-old prices.
Slippage and the oracle
Setting a non-zero slippage on a standing order forces the router to consult its price oracle, which enforces a freshness window (450 seconds). This is a protection — an order filled against a stale price is worse than an order that did not fill — but it does mean an order can decline to execute on a quiet pool with no recent oracle update.
Stop loss
Sells when the price falls to your trigger. Every guard on it fails closed:
- Available on Pro (V3) only. V4 spot is unavailable to the guard upstream, so a Custom stop is refused with a reason rather than accepted and silently ignored.
- The trigger may sit at most 50% below the market, slippage included. A stop further down is refused.
DCA
A ladder of n fills paced by an interval. Available on Pro (V3) coins only — the V4 standing router rejects the order type outright.
A DCA of n fills at interval i does not reach its final fill until n × i has elapsed. If the order's expiry is shorter than that, the tail of the ladder can never execute. The order form refuses a window shorter than the ladder needs rather than accepting a schedule it cannot complete.
DCA also needs a pool with enough activity for each rung to fill sensibly. On a cold pool a ladder will execute against thin depth and the fills will be poor.
Counter-flow
The most unusual type. Instead of a price trigger, you take the other side of someone else's trade:
| Direction | Behaviour |
|---|---|
| Counter-buy | Buys into other people's sells |
| Counter-sell | Sells into other people's buys |
The policy specifies which trades qualify and how much of each to counter. It is validated at signing time rather than trusted from the form, so a malformed policy is named there instead of reverting on chain.
A counter order without per-trigger sizing will spend its entire budget on the first qualifying trade. Set the per-trigger portion deliberately.
Why an order might not fill
This is the useful list, in rough order of how often each one is the answer:
| Cause | Symptom | Check |
|---|---|---|
| The price never reached the trigger | Order rests | The pool's actual range since you signed |
| Sell-side limit price encoded as an absolute price | Rests forever | Whether the value is output-per-input |
| Wrong Permit2 for that router | Rests forever, no error anywhere | PERMIT2() on the router you signed for |
| Order type not supported on that venue | Refused at signing | DCA and stop loss are Pro-only |
| DCA ladder longer than the expiry | Tail fills never happen | n × interval against the window |
| Oracle staleness | Fill skipped on a quiet pool | Whether slippage is non-zero |
| Keeper not running for that chain | Nothing fills at all, for anyone | The status page |
| Indexer far behind the chain head | Triggers evaluated late | The indexer's lag on the status page |
Unlike a market swap, which you send yourself, a standing order needs something off-chain to notice and submit it. That is a real dependency and it is worth being explicit about: if the keeper for your chain is not running, your order will not fill regardless of price. Your funds are never at risk — nothing has moved and the approval can be revoked — but the order is inert.
Cancelling
Every resting order can be cancelled from the Your orders panel. Cancelling invalidates the signature on chain, so the order cannot be filled afterwards even by someone holding a copy of it. Revoking the Permit2 allowance separately is also worth doing when you are finished with a token.
Placing an order grants the router an unlimited, non-expiring allowance for the token being sold. That is how a keeper can fill later without another prompt. If you would rather not leave one standing, revoke it after your orders are done.