Exit Triggers & Emergency Runbook
Most yield protocols publish their APY. Far fewer publish what specifically would force them to protect principal. We publish both, and we publish them at the level of detail an auditor needs: every wired threshold below has a code source citation. If the doc says a threshold is enforced by the contract, you can read the line in KerneVault.sol that enforces it. If the doc says a bot rule fires, you can read the line in the Sentinel risk engine that fires it.
Trust is symmetric: we ask you to trust us with capital, so we owe you the rules we operate under in writing. Our position is simple: a stablecoin product earning double digit APY needs to answer the question "what would force you to exit?" before users deposit, not after.
Severity Levels
Every trigger below maps to one of four severity levels. The level determines response time, who is paged, and which automated actions fire first.
- P0 (Critical): Funds are actively at risk. Vault is paused within 30 minutes, all founders paged, 24/7 response.
- P1 (High): Protocol degraded with elevated risk but no immediate fund loss. Response within 1 hour.
- P2 (Medium): Monitoring alert with non urgent degradation. Response within 4 hours.
- P3 (Low): Informational. Addressed in the next operational session.
On Chain Solvency Circuit Breaker
The vault computes a solvency ratio of total assets divided by total share supply, expressed in basis points. The contract enforces three thresholds directly, with no off chain dependency.
- Solvency below 99% (Red Halt): Triggers the on chain circuit breaker. After a 4 hour grace period of continuous insolvency, the vault auto pauses. The grace period exists so a brief mark to market dip does not pause the vault unnecessarily; sustained insolvency does. Source:
KerneVault.solconstantsCRITICAL_CR_THRESHOLD = 9900andGRACE_PERIOD = 4 hours. - Solvency below 100% (Yellow Alert): Triggers a soft alert flag and notifies operators. Source:
WARNING_CR_THRESHOLD = 10000. - Solvency at or above 101% (Safe Recovery): Required to clear an active circuit breaker after the 4 hour cooldown. Source:
SAFE_CR_THRESHOLD = 10100. - Liquidation rate cap: A maximum of 5% of TVL may be liquidated in any one hour, enforced by
maxLiquidationPerHourBps = 500. This stops cascading forced exits.
Off Chain Risk Engine Breakers
The Sentinel risk engine continuously evaluates the live position. When any of the following thresholds is breached, the engine executes an Emergency Unwind: it closes hedge positions on the exchange and broadcasts a transaction to pause the vault. Every threshold is a constant in bot/sentinel/risk_engine.py.
- Health Score below 60: The engine computes a multi factor health score (delta exposure, liquidation distance, volatility, drawdown). A score under
critical_health_score = 60triggers Emergency Unwind. - Daily loss exceeds 0.1% of NAV (floor $50,000): Hard daily stop, computed as
max($50,000, 0.1% * NAV). The TVL scaling means a $500M vault stops at $500K daily loss, not at the $50K floor. - Hourly loss exceeds 0.02% of NAV (floor $10,000):
max($10,000, 0.02% * NAV), which scales identically. Designed to catch fast crises before the daily limit fires. - Daily drawdown exceeds 2%: A separate breaker measuring drawdown as a percentage of starting equity.
max_drawdown_pct = 0.02. - Net delta exceeds 2% (volatility adjusted): The base delta limit is 2%, tightened during high volatility. Source:
delta_limit = 0.02. - Liquidation distance under 30%: Penalizes the health score, accelerating the path to the score 60 breaker.
min_liquidation_distance = 0.30.
LST Depeg
The Sentinel monitors the ratio of the deposited liquid staking token against ETH. A sustained deviation indicates the LST has decoupled, which threatens the delta neutrality of the position.
- Single cycle deviation above 2%: Logs a warning and increments the breach counter.
DEPEG_THRESHOLD = 0.02insentinel_monitor.py. - Three consecutive cycles above 2%: Triggers Emergency Unwind: shorts close on the exchange, vault is paused. The three cycle requirement filters out single tick noise; sustained depeg fires the breaker.
- Recovery: Requires the LST ratio to return above 0.998 sustained for 48 hours before the vault is unpaused.
Oracle Integrity
Pricing flows through KerneOracleRouter.sol using a Pyth primary feed and Chainlink anchor. The router enforces three thresholds:
- Pyth and Chainlink agree within 2%: Pyth is used (more precise).
toleranceBps = 200. - Pyth and Chainlink diverge between 2% and 5%: Chainlink is used as the conservative anchor (Pyth may be temporarily deformed).
- Pyth and Chainlink diverge above 5%: The full circuit breaker fires; all priced operations revert. Both feeds are deformed and no safe price exists.
circuitBreakerBps = 500. - Pyth max age 60 seconds: If Pyth has not updated within 60 seconds, the router falls back to Chainlink.
pythMaxAge = 60. - Chainlink max age 1 hour: If Chainlink is also stale beyond its heartbeat, the call reverts entirely.
chainlinkMaxAge = 3600. - PSM Chainlink staleness 1 hour: The PSM has its own 1 hour staleness check on its USDC oracle. PSM operations revert with
OraclePriceStaleabove this. Source:KUSDPSM.sol.
Hedge Drift & Funding
The Sentinel monitors the running hedge for drift from delta neutral and for adverse funding rates.
- Delta deviation above 5%: Flagged for rebalance.
REBALANCE_THRESHOLD = 0.05insentinel_monitor.py. - Hourly funding below minus 1bps: Logs a warning and notifies operators.
NEGATIVE_FUNDING_THRESHOLD = -0.0001. Negative funding does not by itself trigger an unwind; the daily and hourly loss breakers handle that path if losses materialize. - Allocator concentration cap 60% per venue: The neural allocator caps any single venue at 60% of total weight.
DEFAULT_MAX_VENUE_CONCENTRATION = 0.60inbot/neural/constraint_projection.py.
Operational & Custody Triggers
Operational scenarios are governed by written runbooks rehearsed internally and stored in docs/runbooks/.
- Suspected smart contract exploit (P0): Any holder of the on chain
PAUSER_ROLEexecutespause()within 15 minutes of detection. Bot trading halts within 5 additional minutes. Full team call within 10 minutes. - Off chain asset reporting cooldown 10 minutes: A compromised Strategist key cannot drain perceived TVL by spamming reports;
offChainUpdateCooldown = 10 minutesenforces the floor between updates. - Withdrawal cooldown 7 days: Withdrawals follow request-then-claim;
withdrawalCooldown = 7 daysgives the hedging engine time to unwind in an orderly manner. - Frontend compromise: kerne.fi is taken offline. The site is restored from a known good commit only after dependency, deployment, and DNS verification.
- Multi signature key compromise: The compromised key is rotated using the remaining keys. All recent multi signature actions are audited for unauthorized transactions.
What Each Protective State Means for Your Funds
- Vault paused: Deposits and withdrawals are halted. Principal continues to accrue staking yield. On chain balances are unchanged. The 7 day withdrawal claim window pauses with the vault.
- Emergency Unwind: The Sentinel closes hedge positions on the exchange and broadcasts a transaction to pause the vault. Confirmation of the on chain pause is awaited explicitly; if the pause transaction fails or reverts, operators receive a CRITICAL alert and escalate to a manual Safe pause.
- Settlement Mode: In a catastrophic scenario, hedges close in an orderly sequence. The vault reopens for withdrawals only, paying pro rata shares of remaining assets at final NAV. The Insurance Fund covers any shortfall before user redemptions are processed.
- kUSD throughout all states: kUSD remains backed by on chain collateral. The PSM and Insurance Fund are the dollar redemption paths even during emergency unwind, subject to the oracle and capacity constraints described above.
Spec, Not Yet Wired
The following thresholds appear in our internal risk policy or backtests but are not yet enforced by code. We list them here because honesty about the gap is the entire point of this chapter. Each item is on our roadmap and will be moved into the wired section as it ships.
- Layered 130%/115%/105% collateral buffer: Our internal risk spec calls for a target collateral ratio of 130% with action at 115% (partial unwind) and 105% (halt). The contract today enforces only the 99/100/101% solvency band described above. The deeper buffer is aspirational, not enforced.
- Staged hedge reduction on extended negative funding: The roadmap calls for 75% of nominal hedge after 72 consecutive hours of negative funding and 50% after 120 hours. Today the bot only logs and alerts on negative funding; the loss breakers (daily and hourly limits) are what actually constrain exposure.
- Per venue dollar margin cap: Internal policy calls for a maximum of $5 million in hedge margin per CEX account. The current allocator uses a 60% concentration cap (relative weighting), not a hard dollar ceiling.
- On chain liquidity buffer (10% of TVL): Internal policy calls for 10% of TVL held as liquid collateral on Base for instant withdrawals. Implementation is partial; this number is not yet a hard contract constraint.
- Time based hedge venue health monitor: A hard "venue unreachable for over 5 minutes triggers automated alert and trade halt" rule is on the roadmap. Today the bot retries on connection errors and surfaces failures via existing alert channels.
Where to Verify
Every wired threshold on this page can be verified independently. We do not ask anyone to trust the runbook on faith.
- Live solvency: kerne.fi/transparency shows current collateral, kUSD supply, and ratio.
- Daily Proof of Reserves: kerne.fi/api/por publishes a signed and timestamped attestation.
- Live trigger state: kerne.fi/api/risk-status returns the current value of every wired threshold against its limit, so anyone can audit in real time whether the protocol is operating inside its rules.
- Solidity sources:
KerneVault.sol,KerneOracleRouter.sol, andKUSDPSM.solare verified on BaseScan. The threshold constants cited above are public state and can be read directly from chain. - Bot sources: The Sentinel risk engine constants and decision points are in
bot/sentinel/risk_engine.pyandbot/sentinel_monitor.py. Each citation in this chapter names the constant by the same identifier the code uses, so a grep over the file will land on the rule. - Post incident transparency: Within 7 days of any P0 incident, we publish a public post mortem with timeline, root cause, impact, and changes made.
Verify These Numbers Yourself
Every on chain threshold cited above can be reproduced by any caller against a public Base RPC. The KerneVault is at 0x8005bc7A86AD904C20fd62788ABED7546c1cF2AC. The commands below use Foundry's cast against https://mainnet.base.org, but any RPC against chain id 8453 produces the same output.
Current solvency ratio
cast call 0x8005bc7A86AD904C20fd62788ABED7546c1cF2AC "getSolvencyRatio()(uint256)" --rpc-url https://mainnet.base.org
Returns a uint256 in basis points where 10000 = 100%. A return of 20000 means there are no outstanding liabilities (empty vault). Anything below 9900 with a sustained 4 hour breach pauses the vault.
Vault paused state
cast call 0x8005bc7A86AD904C20fd62788ABED7546c1cF2AC "paused()(bool)" --rpc-url https://mainnet.base.org
Returns false when the vault is operating normally and true when deposits and withdrawals are halted. The same flag is enforced by the OpenZeppelin Pausable mixin used by every protocol mutator.
On chain threshold constants
curl -s https://kerne.fi/api/risk-status | jq '.triggers.onChain[] | select(.name | test("threshold"))'Returns the Red Halt, Yellow Alert, and Safe Recovery thresholds at 9900, 10000, and 10100 basis points respectively. The deployed bytecode does not expose these as direct getters (the source declared them as private constants, optimized out by the compiler); the canonical values are mirrored at /api/risk-status under triggers.onChain and asserted against the contract source by the threshold constant test suite at bot/tests/test_threshold_constants.py. Source vs deployed drift is documented under the gaps array of the same API response.
Insolvency grace period
cast call 0x8005bc7A86AD904C20fd62788ABED7546c1cF2AC "GRACE_PERIOD()(uint256)" --rpc-url https://mainnet.base.org
Returns 14400 (= 4 hours in seconds). This is the continuous insolvency window before the auto pause fires.
Withdrawal cooldown
cast call 0x8005bc7A86AD904C20fd62788ABED7546c1cF2AC "withdrawalCooldown()(uint256)" --rpc-url https://mainnet.base.org
Returns 604800 (= 7 days in seconds). This is the time between requestWithdrawal and claimWithdrawal.
Live circuit breaker and alert flags
cast call 0x8005bc7A86AD904C20fd62788ABED7546c1cF2AC "lastReportedTimestamp()(uint256)" --rpc-url https://mainnet.base.org curl -s https://kerne.fi/api/risk-status | jq '.summary, .triggers.onChain[] | select(.name == "vault_paused" or .name == "time_since_last_offchain_report")'
The cast call returns the unix timestamp of the most recent strategist off chain asset report; subtract from block.timestamp to get seconds since last report. The crCircuitBreakerActive and crSoftAlertActive booleans are not exposed as direct getters by the deployed bytecode (source vs deployed drift listed in /api/risk-status under the gaps array); the live boolean state is published in the same API response under summary.circuitBreakerActive and summary.softAlertActive. The vault paused flag and the time since last off chain report are also surfaced there with their canonical limits.
Reserves backing kUSD
cast call 0x8005bc7A86AD904C20fd62788ABED7546c1cF2AC "totalAssets()(uint256)" --rpc-url https://mainnet.base.org cast call 0x5C2EfdF0D8D286959b42308966bc2B97f5680AA3 "totalSupply()(uint256)" --rpc-url https://mainnet.base.org
totalAssets is denominated in WETH (18 decimals). totalSupply on the kUSD contract is the total minted kUSD (18 decimals). Combined with an ETH/USD price these reproduce the solvency ratio shown on the transparency page.
If any of these returns disagree with what this chapter or the live status card shows, the chapter is wrong, not the chain. Open an issue at the Kerne repository or message the team and we will publish a correction.
Honest Limitations
This page is a commitment, not insurance. Pre committed triggers handle the most likely failure modes; they cannot anticipate every possible scenario. The Insurance Fund provides material protection but does not guarantee full recovery in every event. External audits are in progress at the time of writing. The items in the "Spec, Not Yet Wired" section above are a known gap, not a hidden one.
If a scenario falls outside the rules above, the Head of Protocol has authority to recommend additional protective action with multi signature consensus. The bias in every ambiguous case is to pause first and investigate, even at the cost of yield. Read the Risk Disclosures chapter for the full risk picture, including categories no exit trigger can fully neutralize.