Skip to main content

Priority fees

A priority bid is a rate you pay to move your next order toward the front of a block. You send it as its own action, priority_bid, before the order it applies to.

info

Status: live. priority_bid has an EIP-712 type string, /exchange accepts it, and no height gate holds it back. The block-ordering step and the settlement charge both run today.

One part is NOT enabled: governance control of the cap. The vote kind set_priority_bid_max_bps exists and a quorum can enact it, but the read side still returns the built-in cap. The cap is 8 bps and nothing can change it today. See The cap.

TL;DR

  1. You send priority_bid for ONE asset, with a rate in whole basis points.
  2. You wait for that bid to commit. An uncommitted bid does nothing.
  3. Your next order on that asset is placed nearer the front of the block.
  4. That order consumes the bid, and pays filled notional × rate.
  5. The payment goes to the protocol fee pools, not to the validator that ordered you.

A priority bid buys position in the block. It does not buy position in the order book. See Priority fee vs broker fee — that is the confusion this page exists to prevent.

What the bid buys

A block carries a list of actions. Every node applies that list in order. The node that proposes the block sorts the user part of the list, and your bid is one term of the sort key. A higher bid moves your order earlier in that list.

That is the whole effect. In particular:

The bid does NOTWhy
Change how your order matchesThe book is price-time priority. The engine never reads the bid.
Reserve a priceYou are earlier in the queue of actions, not entitled to a fill.
Skip a risk checkMargin, tick, lot and open-interest checks run unchanged.
Pass a system writeOracle prices, deposits and the other writes a node injects are drained ahead of the whole user segment. A bid cannot reach them.
Pass another account's standalone cancelCancels sort into a class ahead of every other action, whatever anybody bid. This is deliberate: a paid lift must never trap a maker who is trying to pull a quote.
Reach across blocksThe sort runs inside one proposed block only. It cannot pull you into an earlier block.

A liquidation is an ordinary user action for this sort. It carries no bid, so a paying order can precede another account's liquidation inside the same block.

info

One exception to the cancel rule. An account keeps its own actions in the order it sent them. So a cancel that follows that same account's earlier action in the same block inherits that earlier action's rank, and a paying order from another account can precede it. A cancel sent on its own is always ahead.

Only a plain single order is lifted. The sort reads the bid for a submit_order and for nothing else. A batch_order, a modify, a scale ladder or a chase order ranks as if it had no bid — and it still consumes the bid. See When the bid is consumed.

warning

A bid is a preference, not a guarantee. The sort is applied by the node that proposes the block, over the actions that node holds at that moment. Your order and a competing order can land in different blocks, or reach different nodes at different times. Nothing here promises you beat a specific counterparty.

Send the bid first, and let it commit

The sort reads committed state. A bid that has not yet committed is not in that state, so it ranks as 0 and lifts nothing.

The safe sequence:

  1. Send priority_bid. Wait for the response that confirms it committed.
  2. Send the order.

Sending both together is the common mistake. The bid may commit in the same block as the order or later, and in both cases the order is sorted with no bid — yet the order still consumes the bid once the bid is committed.

Who is paid

Not the validator. The charge is debited from the taker and credited to the protocol fee pools, split by the standard schedule — see Where fees go.

This is a design decision, not an accident of routing. The party that orders your action is never the party that receives your bid, so a bid is not a payment to any individual proposer.

The charge is:

charge = filled notional × bid_bps / 10000 (truncated toward zero)

It is additional to your normal taker fee, and it is charged on the taker side only.

The cap

Value
Cap today8 bps
Minimum accepted bid1 bps
Bounds a governance vote may set1 – 100 bps

A bid of 0 is rejected. A bid above the cap is rejected. Neither stores anything and neither costs anything.

Why the vote floor is 1 and not 0. A cap of 0 would reject every bid, which removes the whole lane by vote. The floor keeps that off the table: the lane can be made narrow, not deleted.

The cap is enforced twice, by one reader. Admission checks your bid against the cap, and settlement clamps the stored bid to the cap again before charging. Both read the same value, so they can never disagree — and a cap lowered after you bid applies to the charge, not just to new bids.

The governance vote set_priority_bid_max_bps is built but its read side is not yet enabled. Until it is, the cap is the built-in 8 bps for every account and every asset.

When the bid is consumed

One bid per account per asset. A second priority_bid on the same asset replaces the first. Bids on different assets are independent.

Your next accepted perpetual order on that asset consumes it. The bid is removed at that point, whatever happens next:

SituationBid consumed?Charged?
Order fillsyesyes, on the filled notional
Order rests, no fillyesno
Order fills a tiny size, charge truncates to 0yesno
Order is rejected before it reaches the booknono
A batch_order leg on that asset is acceptedyesyes, on that leg's fills
A spot order on that assetnono

The rule behind the table: the bid is consumed because the front-of-block slot was already spent, not because the order worked out. A resting order that never fills therefore burns the bid for nothing. If you want priority for a later order, send a new bid.

Spot orders never consume a priority bid, and never pay one. The bid applies to the perpetual order path only.

The asset is not validated. A bid names an asset id and the handler stores it without checking that a market exists. A bid on an id with no market is accepted and sits there, because no order will ever consume it.

Priority fee vs broker fee

Both are extra money attached to an order. They buy different things, and neither substitutes for the other.

Priority feeBroker fee
What it buysOrdering — position in the blockRouting — it pays the front end or bot that sent the order
Who is paidThe protocol fee poolsThe broker, in full
How it is sentIts own priority_bid action, before the orderA builder block on the order
Approval neededNone. You bid for yourself.The trader must approve the broker first
Cap8 bps8 bps protocol cap, plus the trader's own lower cap
Effect on matchingNoneNone
warning

Paying a broker does not move you up the queue. A broker fee is compensation for routing. It is invisible to the block sort and to the matching engine. If you want ordering, you send a priority_bid — there is no other lever.

The reverse also holds: a priority bid pays nobody who routed for you, so it cannot replace a broker agreement.

What a rejected bid looks like

priority_bid is validated on-chain, not at admission. The endpoint accepts the signed action, the chain commits it, and the handler then rejects it.

When that happens inside the endpoint's wait window you get the failure envelope:

{
"error": {
"code": "INVALID_REQUEST",
"message": "invalid parameters: bid 9 exceeds cap 8"
}
}

The message column below is prose, listed so you can read a log. Match on code.

Biderror.message
bid_bps above the capinvalid parameters: bid <n> exceeds cap <cap>
bid_bps of 0invalid parameters: zero bid

If the action has not committed before the wait window closes, you get 202 Accepted instead. That is not a success: the action is still in flight, and it may still be rejected when it commits.

warning

A rejected bid still consumes its nonce. The replay window advances when the action commits, before the handler runs. Re-sending the corrected bid needs a new nonce. Nothing else is charged or stored.

Who may sign it

Master key only. An approved agent wallet cannot send priority_bid. Agent authority is trading-only, and a priority bid commits the owner's funds to a charge, so it sits outside that authority with the transfer and staking actions.

A multi-sig account can execute priority_bid through its normal M-of-N path.

Reading your bid back

There is no query that returns a pending priority bid. Track what you sent and when it committed. The charge itself appears with the fill it was taken on.

See also

  • Broker codes — the other extra fee on an order, and what it really buys
  • Fees — the base maker/taker schedule and the protocol split the charge joins
  • Order types — the order the bid applies to
  • POST /exchange — the wire shape and field table