Operators
Launch prerequisites, deployment invariants, sequencing and automation operations.
Production runbook
Required external inputs
- Two distinct canonical Safe 1.4.1 proxies deployed on Robinhood Chain: genesis and guardian, each threshold >= 2, no enabled modules, no guard, and either no fallback handler or the pinned canonical Safe 1.4.1 compatibility handler.
- SafeProxy, singleton, and any permitted fallback-handler runtime code hashes matching the values pinned in
Deploy.s.sol. Deployment verifiesmasterCopy()against the hardcoded canonical Safe 1.4.1 and SafeL2 1.4.1 singleton addresses and runtime code hashes. - The signed STK-001 risk acceptance and
ACCEPT_UNPROTECTED_SEQUENCER_RISK=true. Do not infer or substitute a sequencer feed while no canonical Robinhood Chain feed exists. - A funded, one-use deployer account.
- Two independent Robinhood Chain RPC endpoints for automation, one production RPC for deployment, and a separate RPC for final-state verification.
- Privy application ID and production origins for wallet UX.
- Monitoring for chain RPC, automation health, gas balance, disabled sequencer protection, Chainlink feed freshness, Robinhood
oraclePaused(), pending epochs, emergency state, and governance events.
Preflight
- Pin the release commit and reproduce all validation commands in the root README.
- Run the deployment on a current Robinhood mainnet fork with
FORK_MAINNET=true. - Confirm every token and feed in
config/chains.jsonagainst Robinhood and Chainlink official registries. - Confirm that no canonical sequencer feed is available, review STK-001's scenario exposure and expiry, and collect the two named risk approvals before funding any market. Contract deployment alone does not authorize deposits.
- Review risk parameters, especially feed heartbeat, USDG cap, volatile haircuts, aggregate active unsold capacity, per-market capacity, payout limits, zero launch emission rate, voting parameters, and Timelock delay. The values in
config/mainnet.jsonare proposed templates, not economic approval. - Have an independent Solidity audit. Resolve every Critical and either fix each High or satisfy the signed, bounded exception policy. STK-003 and STK-004 are currently open.
- Simulate the exact production broadcast and review every transaction.
- Build the frontend with the reviewed
deployments/4663.json, production browser RPC, Privy application ID, and allowed origin; exercise wallet login and one non-critical transaction in a production-origin browser smoke test. - Install and fire-test the Prometheus alerts.
/readyzremains unavailable until one complete automation and monitoring cycle succeeds and then reports the failure threshold; oracle invalidity, emergency state, low gas, and partial RPC failure are metric-driven alerts.
Deployment invariants
After deployment, verify onchain:
- Kernel executor, Authority governor/policy, and RolesAdmin admin equal the Timelock.
- Authority guardian equals the guardian Safe and vault equals MINTR.
- No deployer role remains in ROLES or the Timelock.
- No external account has Timelock
DEFAULT_ADMIN_ROLE. - Governor is proposer/canceller, the genesis Safe is proposer-only, and executor role is open.
- Guardian Safe has
emergency_shutdownand TimelockCANCELLER_ROLE, but no proposer/executor/restart authority. - Timelock holds all other administrative and restart roles.
- Every PRICE asset points to the expected Chainlink proxy with correct decimals, heartbeat, cap, haircut, category, and pause check.
- Every protocol contract's live runtime code hash matches the reviewed deployment manifest.
- Manifest mode is exactly
ACCEPTED_UNPROTECTED, deployed PRICE isStonkPriceUnprotected,sequencerProtectionEnabled()is false, and feed/grace are zero. Any other unprotected production state is invalid. getPrice()equals the corresponding current feed answer after scaling/cap.- No bond market exists immediately after
Deploy.s.sol, and Distributor rate is zero.
Launch sequence
- Deploy and verify source code with explicit STK-001 acknowledgement. Do not create a market during deployment.
- Run
make verify-deploymentfrom a clean checkout againstINDEPENDENT_RPC_MAINNETand archive the output. - Publish the deployment manifest and frontend build from the same commit.
- Start two independent permissionless automation instances and monitoring.
- Complete the independent audit, close STK-003/STK-004, sign the STK-001 capacity limit, and publish the approved loss budget.
- Through the genesis Safe and Timelock, create only the tightly capped bootstrap market or markets covered by that approval.
- Distribute and delegate gSTONK sufficiently for quorum.
- Exercise a non-critical governance proposal end to end.
- Exercise guardian shutdown on testnet/fork and governance-only restart.
- Revoke the genesis Safe proposer role through governance.
Do not fund production bond capacity or invite users before the audit, economic/counterparty approvals, signed STK-001 exposure ceiling, fork rehearsal, source verification, production wallet/transaction smoke, alert fire test, and control-plane invariant checks are complete. Aggregate active unsold capacity is the sum of remaining STONK payout capacity across all live markets; it is the maximum additional STONK those markets can mint, not a stock-token sale target.
Strict PRICE upgrade
When Chainlink publishes a canonical Robinhood Chain sequencer uptime feed:
- Verify the address through two official sources and directly inspect bytecode,
decimals() == 0, answer semantics, current status,startedAt, and operating history. - On a current fork, deploy
StonkPrice(kernel, feed, gracePeriod, currentPriceModule). The constructor accepts migration only from the currently installed PRICE module and validates/copies its complete bounded registry. - Compare every asset configuration and strict price to the old module. Rehearse outage, recovery-grace, stale-round, and policy-reconfiguration paths.
- Prepare a Timelock proposal executing the Kernel
UpgradeModuleaction for the new PRICE module. Decode and simulate the exact calldata; the Kernel reconfigures dependent policies as part of the upgrade. - Execute after the governance delay, then run the independent deployment verifier against a separate RPC and confirm every policy points to the new module.
- Update the committed manifest, keeper and frontend artifacts. Remove the public warning and retire STK-001 only after
sequencerProtectionEnabled()is true and a live recovery-grace test passes.
If verification or migration differs at any step, cancel the proposal. Do not install a guessed feed, proxy shim, or module with an empty asset registry.
Automation deployment
keeper/Dockerfile and railway.json package the roleless automation service with a /healthz deployment check and restart-on-failure policy. Build from the repository root so config/ and the committed production deployment manifest are included. Set CHAIN=mainnet, a sealed KEEPER_PRIVATE_KEY, and at least two comma-separated KEEPER_RPC_URLS. Run a second replica in another provider/region with a different key and RPC ordering. Alert from /metrics on RPC divergence/down state, low gas, disabled sequencer protection, pending epochs, inactive MINTR/TRSRY, invalid/stale/paused oracles, unexpected Timelock delay, and Governor/Timelock event activity. Disabled protection is an expected persistent High-risk state under STK-001, not a healthy uptime signal.