Recomputed from chain at most once an hour. Base block 50,010,468, read 2026-08-15T16:11:23.971Z
First money.
A first institutional ticket of 1,000,000 dollars would be 901 times every claim that exists on this protocol, and 989 times the book that actually earns. Every cap, breaker and operating rule on the live system was chosen against a book of 1,109.71 dollars. Anyone can compute that from two public calls, so this is us writing it down first.
1. The multiple, against three different denominators.
There is no single honest denominator, so all three are here. They differ from one another by a few percent, and none of them changes the answer. Each is a live read, so each multiple falls as the book grows.
| Denominator | Live figure | 1,000,000 dollars is |
|---|---|---|
| kUSD outstanding, every claim anybody holds | 1,109.707154 | 901 times |
| skUSD staked assets, the only leg exposed to the strategy | 1,011.582169 | 989 times |
| USDC reserve across all three modules | 1,110.888006 | 900 times |
Raw kUSD supply is 1,144.707154. The difference against outstanding is kUSD the PSM contracts custody after a redemption rather than burn, which is a claim on nobody. The denominator to use is outstanding, and it is the one the signed attestation uses.
These are live reads, not a dated snapshot, and they will get smaller as multiples the moment anybody deposits. That is the point of deriving them rather than typing them. The dated, executed version of the same question, with a fork test that mints a million dollars through the deployed bytecode, is at /dossier/capacity.
2. Three modules. All three say minting is enabled. One can mint.
This is the second thing a reviewer finds, and it is the one that ends diligence conversations without a follow-up question, because it looks exactly like an undisclosed second mint path. Run a state dump across the three Peg Stability Modules and every one of them returns mintingEnabled() == true and paused() == false. Most of the reserve is not in the one the mint path points at.
| Module | USDC | kUSD held | Can it mint kUSD |
|---|---|---|---|
Live mint module 0xaBDE1138aa1Ce88d1dF06422C0c3b05D70569803 | 30.000000 | 0.000000 | Yes. kUSD grants it MINTER_ROLE, read live. |
Retired mint module 0x07eBb486e11BD217e6085eb5ab663e4517595993 | 995.003000 | 3.000000 | No. Superseded July 10, 2026 and its minting role revoked on the token. It still redeems from its own reserve. |
Redeem reserve module 0xFf3025ec18e301855aB0f36Ec6ECa115a29A5Fbc | 85.885006 | 32.000000 | No. Earlier module, redeem only, minting role revoked in the June 16, 2026 ceremony. |
So 2.70% of the reserve sits in the module a new mint enters, and 97.30% of it sits in the two that the mint path does not point at, 89.57% of the whole in the retired one alone. All three are true and they answer different questions, which is why all three are printed rather than whichever one reads best.
Why the retired module still says minting is enabled, and what actually stops it
mintingEnabled and paused are flags stored on the module. Neither is the authority. The authority lives on the token, as MINTER_ROLE on kUSD, and a mint attempted by a contract that does not hold it reverts inside the same transaction. That is a one-line check per module and it is printed in section 6. Three reads: kUSD accepts the live module and refuses both retired ones.
Kerne has until now stopped exactly there, and said so, because three reads do not establish that nothing else in the world holds the role. kUSD is plain AccessControl, getRoleMemberCount reverts on it, and the honest version of the stronger claim needs the token's whole role history rather than three calls. So here is the history. Every role event kUSD has emitted since creation block 44,448,090, 16 of them, replayed to block 49,986,217 and netted, leaves one holder of MINTER_ROLE and one holder of DEFAULT_ADMIN_ROLE. The minter is the live module. The admin is the timelock. Five other addresses have held the minting role at some point, both retired modules and both KerneVaults and the deploying wallet, and every one of those grants has a matching revocation in the same log. Nothing that holds a role on kUSD today is a wallet.
The part that is not obvious, and that we would rather state than have inferred: on the retired module, the flag being true is what makes a swap there fail. The mint path branches on it. With the flag true, the module calls mint on the token, kUSD refuses it, and the whole transaction reverts, so the depositor keeps their USDC. With the flag false, the same function takes its other branch and pays the caller out of the module's own kUSD inventory, which needs no role at all. That inventory is 3.000000 kUSD today. Switching the flag off would open a small live path rather than close one, so it stays on, and it stays on deliberately.
The reserve stays there because a module can only fund redemptions from its own balance. Moving it is not a governance decision anyone is declining to take: the deployed bytecode has no administrative withdrawal, so USDC leaves a module only through a redemption or a fee skim. That is why the retired module is still summed into published backing, and why it is still a live redemption target in the interface.
Everything that can act on any of the three, enumerated
Not a spot check on addresses we chose to name. Every RoleGranted and RoleRevoked event each module has ever emitted was replayed and netted, which is a complete answer because those events are the only way a role can move under this contract. Creation block 48,469,020 for the live module, 47,425,902 for the retired one and 44,792,319 for the redeem reserve, each replayed to block 49,986,217 on August 15, 2026. All three give the same result, and each has emitted exactly 11 role events in its life.
- Administration is the timelock 0x36A14976980B7Dd33136f6613545EB0A2C0a0D72 and nothing else, on all three. Minimum delay 172800 seconds.
- The manager role, which is what
pause()requires, is the timelock plus one dedicated guardian contract at 0xC47adaf51907bB1871D07E18eA21dc75Ae93Cc8E. Itssafe()returns the operator Safe, and simulatingpause(module)against live state succeeds from the Safe and reverts from any other address. So a module can be halted in one transaction with no delay, while restarting it is an administrative action and takes the full 48 hours. That asymmetry is deliberate. - No externally owned account holds anything. Two ever did, for a matter of minutes each at deployment: the deploying wallet on the oldest module, and a founder-custodied wallet on the two newer ones. Both were revoked in the same deployment session, each by its own transaction in the module's event log, and no wallet has held a role on any module since. Everything that holds one today is a contract.
- No proxy. All three EIP-1967 slots read zero on every one of these contracts, so there is no implementation to swap and no route around the delay.
3. What was sized against a book this size, and what a million would need.
None of these are hypothetical. Each is a live value, each is linked to where it was already published, and each row states what would have to change before the same setting is a deliberate choice at a thousand times the size rather than an inherited default.
| Parameter | Live value | At 1,000,000 dollars |
|---|---|---|
| Per stable mint cap stableCaps(USDC) | 10,000,000 USDC | Unchanged, and this is the one parameter that was never sized against the current book. Headroom is 9,999,970 USDC against a tracked exposure of 30. A million dollar ticket would use 10.00% of that. This is why the answer to "will it take it" is yes. |
| Vault solvency breaker solvencyCheckDisabled, minSolvencyThreshold | true, 10100 | A 101 percent threshold behind a bypassed gate. It reads the vault's solvency ratio, and that vault has zero share supply, so clearing the flag today measures nothing: the check would pass on a sentinel constant. At a million it would need a source that reads the module's own reserve against its own minted liability. Published at /risk on July 24, 2026. |
| Flash lending flashFeeBps, maxFlashLoan(USDC) | 0 bps, full balance | All three modules lend their entire USDC balance atomically at no fee. Today the largest such loan any module can write is 995.00 dollars, because the largest lendable balance and the deepest redeemable reserve are the same number. At a million it is a million, at zero cost, inside one transaction. It is repaid in that same transaction or the whole thing reverts, so it is not a solvency question, but a zero rate on a four figure balance and a zero rate on a seven figure one are not the same decision. Published at /api/por on August 1, 2026. |
| Instant exit depth deepest single module reserve | 995.003 USDC | One swap hits exactly one module, so instant capacity is the deepest leg and never the sum. Today that leg is 0x07eBb486e11BD217e6085eb5ab663e4517595993, the retired mint module. A million minted into the live module makes the live module the deepest leg. The published exit figure is a property of where the reserve sits, and it moves on the first deposit. |
| Staking vault deposit cap skUSD.maxDeposit(address) | 2^256 - 1 | There is no cap. A staked million would be 99.90% of the staking vault, so one depositor would own effectively all of the only leg that earns, and every distribution and share price move would be theirs. Nothing on chain prevents that, and nothing about it is hidden: it is one call. |
| Time to change any of the above TimelockController.getMinDelay() | 172800 seconds | Every setter above sits behind a 48 hour delay, so none of them can be retuned in response to an event. The exception is the stop: pause() requires the manager role, which the guardian contract holds alongside the timelock, so the Safe halts a module in one transaction while restarting it takes the full delay. Read the queue live at /timelock. The delay is public notice rather than an independent veto: the Safe is proposer, executor and canceller on the timelock, so nobody outside it can cancel a queued operation. |
| The deployable side the delta neutral book | pilot scale, one venue | This is the real constraint and it is not a parameter. The strategy is sized one for one against a disclosed founder custodied float on a single venue. Minting is not deploying: USDC in a module earns nothing and there is no function on that contract that puts it to work. A million would mint, stake, and then sit while the book behind it was built. Live figures at /api/por. |
4. What a million dollars actually does, in order.
- It is accepted, permissionlessly, today. No onboarding, no signature from us, no allowlist. The fee at that size is 5 bps, so 1,000,000 USDC returns 999,500 kUSD. The fee ladder steps down at 50,000, 250,000 and 1,000,000, so read
getFee(USDC, amount)for your own size rather than assuming a flat rate. - The round trip is 12 basis points, not the entry tier doubled. A million goes in at 5 bps. What comes back out is 999,500, which is under the million threshold, so the exit prices on the tier below at 7 bps. The arithmetic is the tier boundary, not a spread we charge, and it is reproducible with two
getFeecalls. - Headroom falls by the gross deposit, fee included. The exposure counter is gross of the fee, so a million dollar mint takes a million and change out of the 9,999,970 USDC above.
- The published exit figure moves to the live module. Instant single-transaction depth is the deepest single reserve. After the deposit that is the module holding the deposit.
- Nothing earns until it is staked, and staking it makes the depositor the vault. kUSD sitting in a wallet earns nothing by construction. Staked, a million is 99.90% of skUSD.
- The strategy behind it does not exist at that size yet. That is the honest end of this list. The mint clears; the deployment is the part that would have to be built against the deposit rather than waiting for it.
5. The argument against, in our own words.
Publishing this is publishing the strongest available argument for not depositing, on our own domain, under our own name. We think that is the correct trade and it is worth saying why rather than leaving it as a pose.
A reviewer who derives this themselves concludes that Kerne either did not know or chose not to say. Both readings are worse than the number. The number is not a defect; being small is the ordinary condition of something that has not been chosen yet, and it is fixed by being chosen. Being the protocol that would not print it is not fixed by anything.
The two questions this page answers are also the two Kerne would rather be asked early than late. If the answer to either one disqualifies us for you, it does so on the second page you read rather than after a call, which is a better outcome for both sides. What is on offer here is not scale. It is a reserve you recompute rather than one you are told about. The rest of the ledger of what Kerne measured and then declined is at /refused, and what it switched off is at /removed.
6. Reproduce every number on this page.
No key, no account, no permission. A public Base endpoint is enough. Note that DEFAULT_ADMIN_ROLE is a run of 64 zeroes and not the hash of its name, and that the cap getter is stableCaps and takes the stable's address.
RPC=https://mainnet.base.org
USDC=0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
KUSD=0x5C2EfdF0D8D286959b42308966bc2B97f5680AA3
SKUSD=0x96F5102C15b839757f811A98CEc3725Ac21DfA14
MINT=0xaBDE1138aa1Ce88d1dF06422C0c3b05D70569803
RETIRED=0x07eBb486e11BD217e6085eb5ab663e4517595993
REDEEM=0xFf3025ec18e301855aB0f36Ec6ECa115a29A5Fbc
TIMELOCK=0x36A14976980B7Dd33136f6613545EB0A2C0a0D72
GUARDIAN=0xC47adaf51907bB1871D07E18eA21dc75Ae93Cc8E
MINTER=$(cast keccak "MINTER_ROLE")
MANAGER=$(cast keccak "MANAGER_ROLE")
ADMIN=0x0000000000000000000000000000000000000000000000000000000000000000
# the three reserves, and the concentration
for M in $MINT $RETIRED $REDEEM; do
cast call $USDC "balanceOf(address)(uint256)" $M --rpc-url $RPC
done
# who can actually mint. expect true, false, false
for M in $MINT $RETIRED $REDEEM; do
cast call $KUSD "hasRole(bytes32,address)(bool)" $MINTER $M --rpc-url $RPC
done
# the flags that look like a second mint path. expect true, true, true
for M in $MINT $RETIRED $REDEEM; do
cast call $M "mintingEnabled()(bool)" --rpc-url $RPC
done
# who administers each module, and who can stop it. expect true and true, six times
for M in $MINT $RETIRED $REDEEM; do
cast call $M "hasRole(bytes32,address)(bool)" $ADMIN $TIMELOCK --rpc-url $RPC
cast call $M "hasRole(bytes32,address)(bool)" $MANAGER $GUARDIAN --rpc-url $RPC
done
# the book, and the staking vault that has no deposit cap
cast call $KUSD "totalSupply()(uint256)" --rpc-url $RPC
cast call $SKUSD "totalAssets()(uint256)" --rpc-url $RPC
cast call $SKUSD "maxDeposit(address)(uint256)" 0x000000000000000000000000000000000000dEaD --rpc-url $RPC
# capacity and price at your size
cast call $MINT "stableCaps(address)(uint256)" $USDC --rpc-url $RPC
cast call $MINT "currentExposure(address)(uint256)" $USDC --rpc-url $RPC
cast call $MINT "getFee(address,uint256)(uint256)" $USDC 1000000000000 --rpc-url $RPC
# the round trip: the way in, then the way back out on what is left
cast call $MINT "getFee(address,uint256)(uint256)" $USDC 999500000000 --rpc-url $RPCUSDC carries 6 decimals, so 1000000000000 is one million dollars. kUSD carries 18 and skUSD carries 24. The same figures as JSON are at /api/por, app.kerne.fi/api/psm-status and /facts.json under first_money. The governance addresses referenced above are the timelock 0x36A14976980B7Dd33136f6613545EB0A2C0a0D72 and the pause guardian 0xC47adaf51907bB1871D07E18eA21dc75Ae93Cc8E.
One method note, stated rather than glossed. KUSDPSM uses OpenZeppelin AccessControl without the enumerable extension, so getRoleMemberCount reverts and no single call lists the holders. The enumeration in section 2 is therefore an event replay: RoleGranted and RoleRevoked from each module's creation block to head, netted. It is complete only if the log scan is complete, which is a real dependency on the provider and is why the block range is published with it. Reproduce it with cast logs against an endpoint that will serve the full range, or read the same shape for the governance contract itself at /api/timelock.
Every figure on this page is a live read taken when the page was last generated, at Base block 50,010,468, read 2026-08-15T16:11:23.971Z. Nothing on it is a demand signal: capacity describes what a contract will accept, not what anyone has deposited, and Kerne has not been chosen by a large depositor. If any number here disagrees with /api/por, that endpoint is the one that is true and the disagreement is a defect worth reporting to liam@kerne.fi.