Security, guardian, pausing
This page explains:
- roles (admin vs guardian)
- pause surfaces
- what happens when paused
- how clients and bots should behave
Roles (high level)
Admin (owner):
- config wiring before freezeConfig
- timelock-controlled in production
- cannot use pause surfaces as a substitute for governance
Guardian:
- fast incident response
- pause-only or disable-only capabilities
- in production, expected to be a multisig with strict op policy
Canonical reference:
- docs/security/roles-and-permissions-matrix-v1.0.0.md
freezeConfig
Most core contracts have:
configFrozenflag (public, readable onchain)freezeConfig()onlyOwner (one-way, irreversible)
Two-phase launch model
The protocol launches before freezeConfig(). This is intentional:
- Pre-freeze (launch through external audit): The protocol is live and playable. The admin retains the ability to re-wire contract addresses so that fixes from the external security audit can be applied before locking the protocol permanently.
- Post-freeze (permanent): The admin calls
freezeConfig()on each core contract. After this, wiring cannot be changed. The protocol runs on code alone.
This is a one-way transition. There is no unfreezeConfig().
After configFrozen:
- wiring cannot be changed (ex: registry address, router pointers, reward vault pointers)
- guardian pausing still works
setGuardian()remains callable (required for guardian key rotation)
What agents and integrators should do:
- Check
configFrozenon core contracts to detect the current phase - Pre-freeze: monitor for
ConfigFrozenevents and re-read contract addresses from the deployment manifest after any wiring change - Post-freeze: contract addresses are permanent; no further monitoring needed
Pause surfaces
MineCore: takeoversPaused
Controlled by:
- MineCore.guardian
Effect when true:
- takeover() reverts with Errors.TakeoversPaused
- takeoverWithToken(…) reverts with Errors.TakeoversPaused
- getTakeoverPrice still works
Mining safety (important):
- On pause transitions, MineCore clamps currentReignLastAccrualTime to block.timestamp.
- This means paused time is never mined later.
Furnace: lockingPaused
Controlled by:
- Furnace.guardian
Effect when true:
- enterWithEth / enterWithClaim / enterWithToken reverts with Errors.LockingPaused
- quoteEnterWithEth / quoteEnterWithClaim / quoteEnterWithToken also reverts (same modifier)
- ShareholderRoyalties claim mode=lock continues to work only when locking is enabled
Optional single-switch wiring:
- MineCore.setLockingPaused(bool) forwards to Furnace
- if using forwarding, Furnace.guardian is set to MineCore before freezeConfig
MarketRouter: tradingPaused
Controlled by:
- MarketRouter.guardian
Effect when true:
- listLock / listing settlement / bonus target escrow execution reverts with Errors.TradingPaused
- exits still work:
- delistLock(tokenId)
- cancelBonusTargetEscrow(escrowId)
- emergencyDelist(tokenId) (after 7 days)
EntryTokenRegistry: disable tokens
Controlled by:
- owner can enable and disable
- guardian can disable only
Effect:
- disabled tokens cannot be used for:
- Furnace.enterWithToken
- MineCore.takeoverWithToken
WETH is not allowlisted and is always supported via the WETH special-case.
Guardian activation criteria (practical)
The guardian should pause only for clear protocol safety reasons. Common triggers:
- takeover pricing anomalies (unexpected getTakeoverPrice outputs, reference price corruption)
- unexpected revert spikes on core paths (takeover, enter, offer acceptance)
- swap routing anomalies (registry routes mismatching router.poolFor validation)
- reserve accounting inconsistencies (reserve underflow attempts, abnormal bonus quotes)
- suspected exploit paths or dependency failures (DEX router issues, pool hijack risk)
What clients should do when paused
UI behavior:
- detect pause flags and display a clear banner
- disable affected CTAs
- keep exit paths available (delist, cancel offer, withdraw balances)
Bot behavior:
- stop calling:
- takeovers when takeoversPaused
- Furnace entry when lockingPaused
- executeAutoFurnace when tradingPaused
- keep calling MaintenanceHub.poke() only if the swap paths are safe
User funds safety (important)
- Pausing does not seize funds.
- Pausing only prevents new state transitions on the paused surfaces.
- Pull-based withdrawals remain available:
- MineCore.withdrawKingBalance
- MineCore.withdrawRefundBalance
- MarketRouter.delistLock / cancelBonusTargetEscrow
FAQ for integrators: what happens when guardian pauses?
Takeovers paused (MineCore.takeoversPaused = true):
- New takeovers revert.
- The current reign cannot end.
- Crown emission accrual is clamped at the pause boundary.
- There is no “backpay” when unpaused.
- UI should:
- hide/disable takeover buttons
- keep price display, history, and Crown ETH withdrawal UX
Locking paused (Furnace.lockingPaused = true):
- New Furnace entries revert.
- All Furnace quoteEnterWith* helpers revert.
- Barons ETH collection still works in mode 0 (Collect ETH).
- Auto-compound paths behave safely:
- ShareholderRoyalties auto-compound uses a best-effort call and restores the user’s ETH available to Collect (claimableEth) on revert.
- LP vault auto-compound keeps rewards intact on revert.
- UI should:
- disable lock actions and compounding CTAs
- keep Collect ETH CTA available
Trading paused (MarketRouter.tradingPaused = true):
- Market actions revert (listings, listing settlement, bonus target escrow execution).
- Exits stay open:
- delistLock, cancelBonusTargetEscrow, emergencyDelist (after 7d)
- UI should:
- disable new listings and bonus target escrow actions
- keep cancel/delist buttons available
Token disabled (EntryTokenRegistry token enabled=false):
- enterWithToken and/or takeoverWithToken revert for that token.
- ETH entry remains available.
- UI should:
- gray out the token in token pickers
- explain that it was disabled for safety