Block Conditions
Deposits
Your deposit is blocked if:
-
it would reach or exceed
max_depositsfor that spot asset -
the spot market is in reduce-only mode and your deposit does not pay off a borrow
-
the spot market’s deposits are paused
-
the spot market is still in the
Initializedstatus (not yet opened for trading) -
your
pool_iddoes not match the spot market’spool_id -
it would exceed the spot market’s daily deposit cap
Withdraws
Your withdrawal or borrow is blocked if:
-
you have outstanding liabilities and any oracle on an asset or liability you hold is invalid (“invalid” per the
MarginCalcaction) -
it would increase your number of liabilities above 1 while one of them has the isolated asset tier (you can only hold one outstanding liability when that liability has the isolated asset tier)
-
it would put your total collateral (weighted collateral value) below your initial margin requirement
-
it would put that asset’s protocol liquidity below the rolling limits (these limits differ based on whether the withdraw would open a borrow)
Placing Orders
You cannot place an order if:
-
it is risk-increasing and would put your initial margin requirement above your total collateral
-
it would increase your number of outstanding liabilities above 1 while one of them has the isolated asset tier
Order placement applies to perpetual markets only. Spot order placement is removed on Velocity (there is no spot order book). Borrows are instead opened through withdrawals and swaps, which are governed by the withdrawal conditions above.
Filling Orders
Your order won’t fill if it would send you under the margin requirement plus buffer (you’d hit InsufficientCollateral). Within a match, if either side hits this condition, the match won’t go through.
Settle Perp PnL
You can’t settle perp PnL if:
-
the market’s oracle is deemed invalid
-
you have negative unrealized PnL and your account value is below the maintenance margin requirement (this check does not apply when you’re settling positive unrealized PnL)
-
the market’s oracle price diverges too far from its 5-minute TWAP (
validate_market_within_price_band) -
a third party (not your authority or delegate) tries to settle your negative PnL against a margin-invalid oracle
-
the
SettlePnl(or, if you have an open position,SettlePnlWithPosition) operation is paused for the market -
the market has an open position and its status is not
Active, or has no open position and its status is neitherActivenorReduceOnly
Pause and market-status gating
Every condition above is a rule about your account or your action. Pauses are different: they are switches an admin flips, and they block an action for everyone. There are three independent layers, and your action must clear all three.
Layer 1: the exchange-wide breaker (State.exchangeStatus)
State.exchangeStatus is a u8 bitmask (ExchangeStatus, state/state.rs). 0 means fully active; each bit halts one class of action across every market.
| Bit | Value | What it blocks | Error |
|---|---|---|---|
DepositPaused | 0b0000_0001 | all deposits | ExchangePaused |
WithdrawPaused | 0b0000_0010 | all withdrawals, borrows, and pool transfers | ExchangePaused |
AmmPaused | 0b0000_0100 | AMM as a counterparty (the AMM stops being available in a fill) | ExchangePaused |
FillPaused | 0b0000_1000 | order fills, order triggering, revert_fill, and liquidate_perp_with_fill | ExchangePaused |
LiqPaused | 0b0001_0000 | liquidations | ExchangePaused |
FundingPaused | 0b0010_0000 | funding-rate updates and spot interest accrual | ExchangePaused |
SettlePnlPaused | 0b0100_0000 | PnL settlement | ExchangePaused |
AmmImmediateFillPaused | 0b1000_0000 | auction-skipping immediate AMM fills (auctions must run their full duration) | no error, the fill just waits |
Two of these have effects worth calling out:
FillPausedalso blocks triggering.trigger_orderstarts an order’s auction and pays the keeper reward, so it is part of the fill lifecycle and carries the same gate asfill_perp_order. A stop or take-profit order will not be triggered while fills are paused.- A full halt is its own condition. Some instructions (signed-message taker order placement, spot interest refresh, several keeper cranks) are gated on
exchange_not_paused, which fails only when every bit is set. Those instructions keep working during a partial pause and stop only in a complete halt.
Layer 2: per-market pause bits (paused_operations)
Each market carries its own bitmask, so one market can be frozen while the rest of the exchange trades normally.
Perp markets (PerpMarket.pausedOperations, PerpOperation):
| Bit | Value | What it blocks | Error |
|---|---|---|---|
UpdateFunding | 0b0000_0001 | funding-rate updates for this market | no error, the crank returns without updating |
AmmFill | 0b0000_0010 | the AMM filling orders in this market | no error, the AMM is skipped as a counterparty |
Fill | 0b0000_0100 | fills and triggering in this market | MarketFillOrderPaused |
SettlePnl | 0b0000_1000 | settling PnL, including expired-position settlement | InvalidMarketStatusToSettlePnl |
SettlePnlWithPosition | 0b0001_0000 | settling PnL while an open base position remains | InvalidMarketStatusToSettlePnl |
Liquidation | 0b0010_0000 | liquidating this perp position | InvalidLiquidation |
AmmImmediateFill | 0b0100_0000 | auction-skipping immediate AMM fills in this market | no error, the auction runs its full duration |
SettleRevPool | 0b1000_0000 | sweeping this market’s revenue share to the revenue pool | no error, the sweep returns early |
Spot markets (SpotMarket.pausedOperations, SpotOperation):
| Bit | Value | What it blocks | Error |
|---|---|---|---|
UpdateCumulativeInterest | 0b0000_0001 | interest accrual for this market | no error, accrual is skipped |
Fill | 0b0000_0010 | fills against this spot market | MarketFillOrderPaused |
Deposit | 0b0000_0100 | deposits, including the deposit leg of a transfer_pools and any credit into the revenue pool | MarketActionPaused |
Withdraw | 0b0000_1000 | withdrawals and borrows | MarketWithdrawPaused |
Liquidation | 0b0001_0000 | liquidating a position in this market | InvalidLiquidation |
Insurance funds (SpotMarket.insuranceFund.pausedOperations, InsuranceFundOperation): Init, Add, RequestRemove, and Remove each gate the matching staking instruction and reject with InsuranceFundOperationPaused. See Insurance Fund Staking.
A warm admin may only flip UpdateFunding and SettleRevPool on a perp market (PerpOperation::WARM_EDITABLE). Every other bit is reserved for the cold or pause admin, and a warm update preserves the bits it is not allowed to touch.
Layer 3: market status
Status is a single value, not a bitmask, and it gates actions on its own:
| Action | Statuses that allow it | Error otherwise |
|---|---|---|
| Place a perp order | not Settlement (an order placed while the market is ReduceOnly is forced reduce-only) | MarketPlaceOrderPaused |
| Fill a perp order | Active or ReduceOnly, and not in settlement | MarketFillOrderPaused |
| Spot deposit | not Initialized; must be Active if the resulting position is a positive deposit balance | MarketBeingInitialized, MarketActionPaused |
| Spot withdraw or borrow | Active, ReduceOnly, or Settlement | MarketWithdrawPaused |
| Settle perp PnL | Active with an open position, Active or ReduceOnly with none | see Settle Perp PnL above |
A ReduceOnly perp market forces every fill to be risk-reducing, including fills of orders placed earlier. Order placement stamps reduce_only from the market status at the time the order was created, so an order placed while the market was Active still carries reduce_only = false after the market flips. The fill path therefore re-derives reduce-only from the live market status and stamps it onto the order, for the taker and every maker in the match. A resting maker quote that would increase exposure is then size-clamped to the position it can close, or cancelled outright. If you keep quotes on a market that is being delisted, expect them to stop adding exposure the moment the status changes, not the moment you replace them.
Telling a pause apart from a bug
ExchangePaused(error6024) is always exchange-wide. ReadState.exchangeStatusto see which bit is set.MarketActionPaused(6146),MarketPlaceOrderPaused(6147),MarketFillOrderPaused(6148), andMarketWithdrawPaused(6149) are always scoped to one market. Read that market’sstatusandpausedOperations.- The program logs every set bit by name (
"<Operation> is paused") when it rejects, so the transaction logs name the exact bit. - A silent no-op (no error, the action simply does not happen) is the expected shape for the funding, interest-accrual, AMM-fill, and revenue-sweep bits. Do not treat an unchanged funding rate or a skipped AMM fill as a failed transaction.