Build status
What runs, what passes, and — more usefully — what that does and does not prove.
The suite
| Suite | Count | What it exercises |
|---|---|---|
| Unit | 99 | Every contract, in isolation, against mock Pons infrastructure. |
| Fuzz | 4 | Randomised amounts and lock terms across staking and routing. |
| Invariant | 9 | Protocol-wide properties over 4,096 randomised calls each. |
| Mainnet fork | 14 | The real Pons contracts, on forked mainnet state. |
| Frontend | 57 | Wallet flows, launch gating, transaction states, formatting. |
All of them pass. That is a statement about the tests, not a statement about safety — see audit status.
What the fork tests actually prove
This is the part worth reading, because it is the difference between "the mocks agree with each other" and "this works against the real thing".
The fork suite runs against live Robinhood Chain state and confirms:
- Chain ID is
4663. - Every Pons address has deployed bytecode.
- The factory's own getters agree with the addresses this repository hardcodes.
- The live launch config, launch fee and creator-tax ceiling read correctly.
- The Fee Escrow accepts a credit and pays out exactly that amount on
claim(). - A pre-graduation buyback executes against real curve liquidity, and the acquired tokens are retired.
- The canonical Uniswap v4
PoolKeyreconstructed from a factory record resolves to an initialized pool. - A post-graduation buyback executes through that real pool.
Every external integration point has been exercised against the contract it will actually talk to, not against a stand-in.
The invariants
Properties the invariant suite asserts hold no matter what call sequence it generates:
totalSentToBuybacks + totalSentToStakers + totalSentToReserve == totalRevenueRouted, exactly.totalRewardsClaimed <= totalRewardsReceived, and the staking contract always holds enough ETH to cover what it owes.- The PLOUTO balance of the staking contract is always at least
totalStaked. totalRevenueClaimed - totalRevenueRouted == unallocatedRevenue.totalBudgetReceived - totalEthSpent == buybackBudget.totalPloutoBurned + totalPloutoSentToDead == totalPloutoRetiredByProtocol.- The executor never holds PLOUTO between executions.
totalStakedandtotalWeightalways equal the sum of the open positions.
Two real bugs this found
Worth recording, because a suite that never caught anything is not evidence of much.
- Escrow double-counting. ETH arriving from the Fee Escrow was triggering the Revenue Router's
receive()and being booked as a donation and as claimed revenue. Fixed by falling through whenmsg.senderis the escrow, since the claim already accounts for it by measured balance delta. - Stranded rollover. Rewards received while nothing was staked were held correctly, but the flush ran before the new position was counted — so the first staker to arrive received nothing. Fixed by snapshotting the accumulator, counting the new weight, then flushing.
Tooling
forge fmt, forge build, forge test, pnpm lint, pnpm typecheck, pnpm test and pnpm build all run clean. Remaining compiler warnings are limited to block.timestamp comparisons — intentional, since locks and timelocks are measured in days — and mock-only ERC-20 return-value warnings in test fixtures.
What none of this proves
A passing suite is not an audit. It demonstrates that the properties the author thought to check hold under the conditions the author thought to create. It cannot demonstrate the absence of a property nobody considered.
Plouto has not been audited. Treat it as experimental software.