Activation notice: block 45,811,287
This page records what changed on chain 114514 at block 45,811,287.
In effect since block 45,811,287. Node 0.9.21 swapped in at block 45,811,286 (2026-10-31 04:30 UTC), and the rules below turned on one block later. Rust SDK 0.28.0 and TypeScript SDK 0.32.0 were published in the same window. No gateway or indexer release rode it.
{"type":"account_state","address":"0x…"} returns the current height. Use it to check where the chain is.
The pin is one block above the swap. The outgoing node commits block 45,811,286 and then halts, so that block still ran the old rules. The new rules apply from the first block after it.
A stalled validator oracle keeps the mark
Before the height the node treated a core market whose validator oracle is older than the staleness window (60 s unless voted) as a market with no price: liquidation, ADL, triggers and the health check waited, and one such position held the whole account's liquidation back on every market. That is the posture of an oracle-only venue. MetaFlux has a book, so it follows Hyperliquid: the oracle component freezes at its last value and the mark keeps pricing.
| Case | Before the height | Now |
|---|---|---|
| The risk mark of a core market whose validator oracle is stale | absent: liquidation, ADL, TP/SL triggers and TWAP slices wait | the committed mark, clamped into last oracle × (1 ± band) (5 % unless voted). Everything that reads the mark runs |
| An account with one position on such a market | the whole account's liquidation waits, on every market | judged as a whole, on that clamped mark |
account_state health_deferred | present while any position is on a stale market | present only while a position is on a stale self-priced market, or on a market with no oracle at all |
| A self-priced market (MTF) whose index is stale | reduce-only; liquidation waits | unchanged. Its index is its own book, so a band around it protects nothing |
| The mark of a spot-margin position whose base oracle is stale | absent: the forced close and the collateral withdraw wait | the last committed oracle price. A base whose price is its own book still waits |
| A portfolio-margin collateral token whose price perpetual has a stale oracle | no credit and no seizure | credited and seized at the price perpetual's risk mark: its book, clamped into last oracle × (1 ± band), the same mark its positions liquidate on. A token whose oracle has never sourced a price still counts for nothing |
| A spot-margin enable vote on a pair whose base oracle is stale | refused | unchanged: a pair is not enabled against a feed nobody pushes |
| A delisting with no voted price on a stale market | refused | unchanged: a settlement closes every position for good, so it still waits for a fresh index or a voted price |
| The funding premium sample on a stale market | omitted | unchanged. The interest term still accrues |
Spot tokens stay in an account at negative equity
Every exit that moves a spot token out of an account is refused while the account's equity, after the losses it has not realized yet, is negative. The tokens are what the waterfall can still reach once the account is flat. A fully margined account with positive equity is not affected: held initial margin does not count.
| Action | Refusal |
|---|---|
send_asset (any token, either direction), core_evm_transfer, send_to_evm_with_data, the legacy withdraw3, sub_account_spot_transfer, an Earn deposit of a non-USDC token, a staking delegation | PRECONDITION_FAILED: negative cross account value: spot tokens stay |
Equity here is cross_account_value plus the loss side of unrealized PnL and of pending funding,
with no gain counted: the same figure as free collateral before held initial margin comes off.
An Earn deposit and a staking delegation keep the owner's title, but the liquidation waterfall reads only the spot ledger, so they are gated too. bridge_withdraw moves USDC only and keeps its free-collateral refusal.
An agent signs the owner into the digest
Before the height the typed digest of submit_order, cancel_order, schedule_cancel, twap_order,
update_leverage, update_isolated_margin, top_up_isolated_only_margin and
set_position_mode did not carry the owner the action names. A relay that held a signature an
agent made for one account could send the same bytes under another account that approved the same
agent. The copy ran in the second account, at its own cost. No funds moved between the two
accounts, but the chain recorded an agent link the first owner never made.
Since the height, each of those actions has two type strings, the same shape every other
owner-bound action already has: the string as printed today, and a twin with address owner right
after metafluxChain.
| Who signs | Which string | Result |
|---|---|---|
| The owner, for its own account | either string | admitted |
| An approved agent, for its master | the twin with owner | admitted |
An approved agent, the string without owner | refused: signer is neither the owner nor an approved agent |
So an agent signature now names the account it was made for, and it verifies under no other.
submit_order and cancel_order carry owner on the wire always, so a client signs the twin for
them whoever the signer is. The other six carry owner only when an agent acts for a master; a
self-signed call without owner keeps the string it has today.
The twins:
action.type | encodeType with owner |
|---|---|
submit_order | MetaFluxTransaction:SubmitOrder(string metafluxChain,address owner,uint32 market,string side,string kind,uint64 size,uint64 limitPx,string tif,string stpMode,bool reduceOnly,string cloid,uint16 builderFee,address builderUser,string positionSide,uint64 triggerPx,bool triggerIsMarket,string triggerTpsl,uint64 nonce) |
submit_order with trail_px | the same, with uint64 trailPx before uint64 nonce |
cancel_order | MetaFluxTransaction:CancelOrder(string metafluxChain,address owner,uint32 market,uint64 oid,uint64 nonce) |
schedule_cancel | MetaFluxTransaction:ScheduleCancel(string metafluxChain,address owner,uint64 cancelAtBlock,uint64 nonce) |
twap_order | MetaFluxTransaction:TwapOrder(string metafluxChain,address owner,uint32 market,string side,uint64 totalSize,uint32 sliceCount,uint64 delayMs,bool reduceOnly,uint64 nonce) |
twap_order with position_side | the same, with string positionSide after bool reduceOnly |
twap_order with randomize: true | the same, with string positionSide,bool randomize after bool reduceOnly |
update_leverage | MetaFluxTransaction:UpdateLeverage(string metafluxChain,address owner,uint32 asset,uint32 leverage,bool isIsolated,uint64 nonce) |
update_isolated_margin | MetaFluxTransaction:UpdateIsolatedMargin(string metafluxChain,address owner,uint32 asset,string delta,uint64 nonce) |
top_up_isolated_only_margin | MetaFluxTransaction:TopUpIsolatedOnlyMargin(string metafluxChain,address owner,uint32 asset,string amount,uint64 nonce) |
set_position_mode | MetaFluxTransaction:SetPositionMode(string metafluxChain,address owner,bool hedge,uint64 nonce) |
The owner word is the address, left-padded to 32 bytes, at index 1 of the message. The Rust SDK
0.28.0 and the TypeScript SDK 0.32.0 sign the twins. An agent that keeps an
older SDK is refused on these eight actions from the height on. Its master's own signatures are not
affected.