Guardian Routines

The procedure side of the guardian key: the reads to do before and after a call, and when to hand over to the owner. The levers themselves, their arguments and their authority are Guardian.


1. Before you act

  • Chain. Confirm the wallet’s chain before signing. Pool salts carry no block.chainid, so one salt lands at the same address on every chain of the fleet: the right call on the wrong chain reaches a real pool, not a dead address.
  • Role. AccessControl.perms(you) carries bit 17 (guardian) on the AC the target reads: Admin.AC(), PoolFactory.AC(); the mark store answers to the same root. AccessControl.quorumPolicyArmed() reports whether the policy is armed; whether the live multisig configuration still satisfies it is not an on-chain view, read getOwners() / getThreshold() on the Safe directly against QuorumLib.
  • That something is actually pending, before any cancel. AccessControl.pendingRole(role) and UpgradeGate.pendingUpgrade have public getters. Admin.pendingOps and the mark store’s queued ops are internal: the ETA comes from the TimelockRequested or store OpQueued event, or the indexer. A cancel with nothing pending reverts NoPending on Admin and costs only gas.
  • The live implementation, before a store call. Store levers run on PoolFactory.implementation(); a call to a retired or pending implementation reverts.
  • The legs, before a halt. Discovery is PoolFactory.getOfficialPoolsForToken(token) → getPoolTokens(pool) (Access control). batchRiskOp takes the two arrays positionally; a length mismatch reverts InvalidInput.
  • The lane, before a store halt. PoolFactory.laneOf(feedId) minus one is the lane; pick the tiers with tierMask (1 primary, 2 reference, 3 both).

2. After you act

Read state, not the transaction. Halt and pause events are snapshot triggers rather than indexed topics, so the indexer will not answer “what is halted right now” (Observability).

You calledVerifyEvent
haltAsset / batchRiskOpPool.getAsset(token).flags carries your bitAssetHalted / RiskOpsBatched, BatchLegSkipped
haltAsset(pool, token, 0x0800) (coop kill)getAsset(token).flags bit 11 (COOP_ENABLED) clear; the leg still swapsAssetHalted with src 0x0800
collapseAnchorgetAsset(token).anchor is the new anchor and HALT_ANCHOR_BIT (0x0004) is setAnchorUpdated
Store halt(lane, tierMask)PoolFactory.feedOf(feedId, t) flags bit 0 set on each tier you halted; the mark reads 0, which is the lever working, not a failed writeLaneHalted
cancelOp / store cancel / cancel*The pending read from §1 is now zeroTimelockCancelled, OpCancelled, UpgradeCancelled, RoleCancelled
pause()paused() true on that singletonPaused(true)

Then check for side effects. A halt on the reference tier alone stops every spoke leg that bands against that lane. After a halt, the fraction of the book still tradable is feeds.tradable_ratio and bot_tradable_ratio (Observability).


3. Escalate

The guardian key cannot reverse its own actions. Hand over to the owner as soon as the lever has landed:

  • What you halted or paused, with the src bits, lanes and tier masks, so the release clears exactly those.
  • Why, with the read that triggered it.
  • What is now blocked that the incident did not require blocking.

Intake and contact are Access control and security@btr.markets. A suspected vulnerability rather than an operational fault goes through Audits.

Escalate rather than act when the remedy is a widen, an un-halt, a grant, a param write or a value movement. None of those are reachable from this key.

A coop kill carries no release clock and, on a seated pool, can be re-armed by the seat after TUNING; if the kill must hold there, use HALT_BIT and say so in the hand-over (Guardian §3).

Example: a lane wedged outside its band (dark past 10dmax). The remedy is the owner’s reanchor(lane, tierMask) at TUNING: it drops the dark lane’s anchor so the next push lands unbanded, which then has to be checked against the source. It acts per lane; hand over every wedged lane, not a sample. A lane’s bounds themselves (ttl, maxDev, σ floor) change only with a new class table at a fleet upgrade.

halt is the instant lever for any lane, and it is a guardian lever (Mark Relayer). The other remedies are not reachable from this key.

Releasing a lane halt is the owner’s action, not yours. unhalt is owner-only on the store; the lane returns dark, the first push after release is banded against the mark the halt kept over the whole gap since it was observed, and the lane reads markless until that push lands. Hand the halt over with the lanes and tier masks. The transaction is not the end of the incident.