Kerne Logo

Live risk surface.

Every wired risk threshold in the protocol, side by side with its current on-chain value and the exact Solidity identifier you can grep yourself. Refreshed every 15 minutes from /api/risk-status. If a value here disagrees with what is on-chain, the on-chain value wins and this page is wrong.

Loading risk surface from /api/risk-status...

A safety gate that is switched off, and why.

solvencyCheckDisabled returns true on both mint Peg Stability Modules. With it set, the PSM does not ask the vault whether the vault is solvent before minting or redeeming. We are publishing this because nobody had found it, and a protocol whose whole claim is that its numbers survive being checked does not get to hold back the state of a safety gate on the contract that takes deposits.

It was set deliberately, as transaction 7 of the 13-step July 10, 2026 deploy ceremony, while the vault it reads was being remediated. The contract's own documentation says to flip it back once that vault returns a meaningful number. The window opened on July 10 and has not closed. Nothing tracked the flag back to zero and nothing published it, so nothing forced the question. That is the real failure here, and it is a process one.

Two reasons it is off, and the second is the uncomfortable one. The gate couples two books that do not fund each other: kUSD minted through the PSM is backed 1:1 by the USDC sitting in that same PSM, while the vault is the delta-neutral WETH book, so a vault reading can block a mint whose backing it says nothing about. And if we cleared the flag today the gate would measure nothing anyway: getSolvencyRatio() returns a hardcoded 200% sentinel whenever the vault has zero liabilities, which it does, so the check would pass on a constant. We would rather publish the flag as true than publish a green light that means nothing.

What still protects a minter, all of it live and readable: the depeg gate IS enforced, with the Chainlink USDC/USD feed wired and a fail-closed posture on an unset oracle; backing is published hourly and signature-bound as psm_solvency_ratio at /api/por/signed; the retired PSM had its mint authority revoked on July 10, 2026, so its copy of the flag cannot mint anything; the concentration and mint caps still revert; and the flag is DEFAULT_ADMIN only, which since 2026-08-06 means it is behind a 48 hour timelock rather than two instant signatures, and emits an event, so its full history is reconstructable from logs by anyone.

A delay is only a control if somebody is watching it. Since 2026-08-09 a daemon polls that timelock every 60 seconds, decodes anything scheduled against it and pages the operator channel, and the live queue plus that daemon's own heartbeat are public at /timelock and /api/timelock, which answers 503 rather than an empty queue when the chain cannot be read. It pages us, not you, and it does not create anybody independent who can cancel.

# Check it yourself, no signature from us required
cast call 0xaBDE1138aa1Ce88d1dF06422C0c3b05D70569803 \
"solvencyCheckDisabled()(bool)" \
--rpc-url https://mainnet.base.org
# expected: true
# and the gate that IS enforced
cast call 0xaBDE1138aa1Ce88d1dF06422C0c3b05D70569803 \
"depegCheckDisabled()(bool)" \
--rpc-url https://mainnet.base.org
# expected: false

The full writeup, including what would have to change for the flag to be worth clearing and why clearing it is not itself the fix, is in the security notes as KRN-26-PSM-SOLVENCY-GATE-DISCLOSURE. It stays true, and stays published, until it changes.

Two contracts we cannot prove the source of.

Everything else on this site is built so you do not have to take our word for it. On two contracts there is one thing you cannot check: that the bytecode running on Base was compiled from the source we publish. We cannot reproduce it either. They are named here, in words, because a reader who finds this on their own reads it as something we hid, and because "check it yourself" is worth less if the exceptions are only ever a cell in a table.

KerneStaking 0x032Af163 was deployed before a January 7, 2026 repository reset wiped the history that contained its source. The contract was built from a working tree that was never committed, so the exact source no longer exists anywhere. The closest surviving commit compiles to within four characters of the deployed size and then diverges at character 142. We tried again on June 11, 2026 and the current source still compiles to a different code body. Verifying it would require migrating every stake to a fresh contract. Nothing is staked: totalStaked() returns zero and the contract holds no ether, so the migration would move nothing and we have not spent the deploy on it.

KerneFlashArbBot 0x57e73919 is a different failure. It was deployed on January 15, 2026 at 22:22 UTC, four hours and fourteen minutes after the last commit that touched it, and the working tree changed in between. The deployed bytecode diverges from that commit at character 87, in the function dispatch table. One known difference: current source carries a Maverick router the deployed contract does not have. This one is fixable by redeploying from source, and that redeploy is written and waiting rather than done.

What bounds the second one today. The bot executes triangular arbitrage and can flash borrow from the vault, so an unverifiable version of it is worth being specific about. Its two operational roles were revoked from the old operational key on April 17, 2026, and neither the 2-of-3 Safe nor the current operations signer holds EXECUTOR_ROLE today, so no Kerne key can drive it. Granting that role back is a Safe transaction that lands on chain in public. It holds no ether. Neither contract holds user deposits, and neither sits in the mint or redeem path: kUSD, the live mint PSM, and skUSD are all source-verified, and those are the three that stand between a holder and their dollar.

# Nothing is staked in the unverifiable staking contract
cast call 0x032Af1631671126A689614c0c957De774b45D582 \
"totalStaked()(uint256)" \
--rpc-url https://mainnet.base.org
# expected: 0
# No Kerne key can execute the arb bot
cast call 0x57e73919Efc8a70B40a0bFc562C4DC9e58c4D76F \
"hasRole(bytes32,address)(bool)" \
$(cast keccak "EXECUTOR_ROLE") \
0x09a2780ac8Be6D5d2d1F85A8D92b09D40C9CA37e
# expected: false (also false for the Safe)
# Its admin is the 2-of-3 Safe, so a re-grant is public
cast call 0x57e73919Efc8a70B40a0bFc562C4DC9e58c4D76F \
"hasRole(bytes32,address)(bool)" \
0x0000000000000000000000000000000000000000000000000000000000000000 \
0x52d3E450bA6c299B1B07298F1E87DD74732D4877
# expected: true
# The sizes we publish are the sizes on chain
cast codesize 0x032Af1631671126A689614c0c957De774b45D582
# expected: 6372
cast codesize 0x57e73919Efc8a70B40a0bFc562C4DC9e58c4D76F
# expected: 22618

Per-contract verification status for the whole registry, including these two, is on the audit and verification page. Places where deployed bytecode differs from a source we do still hold are a separate list, on deployed versus source. These two stay here until a redeploy makes them checkable.

Verify yourself.

This page is a rendering of the JSON at /api/risk-status. Four commands against Base mainnet reproduce the most load-bearing claims independently:

# Mint authority on kUSD v2 sits with the live KUSDPSM
cast call 0x5C2EfdF0D8D286959b42308966bc2B97f5680AA3 \
"hasRole(bytes32,address)(bool)" \
$(cast keccak "MINTER_ROLE") \
0xaBDE1138aa1Ce88d1dF06422C0c3b05D70569803
# expected: true
# Key rotation proof: the retired mint PSM no longer holds it
cast call 0x5C2EfdF0D8D286959b42308966bc2B97f5680AA3 \
"hasRole(bytes32,address)(bool)" \
$(cast keccak "MINTER_ROLE") \
0x07eBb486e11BD217e6085eb5ab663e4517595993
# expected: false (revoked in the July 10, 2026 redeploy)
# Mint surface on the live PSM is currently active
cast call 0xaBDE1138aa1Ce88d1dF06422C0c3b05D70569803 \
"mintingEnabled()(bool)"
# expected: true
# Default admin role gated by the 2-of-3 Safe
# DEFAULT_ADMIN_ROLE is bytes32(0) in OpenZeppelin AccessControl, not a keccak of the name
cast call 0x5C2EfdF0D8D286959b42308966bc2B97f5680AA3 \
"hasRole(bytes32,address)(bool)" \
0x0000000000000000000000000000000000000000000000000000000000000000 \
0x52d3E450bA6c299B1B07298F1E87DD74732D4877
# expected: true

These are read on every request by /api/risk-status, which is what the panel above and the homepage banner render. They are checked when someone asks, not on a schedule.