Test results
Summary
| Suite | Tests | Result |
|---|---|---|
| Unit and fuzz (Foundry) | 99 | Pass |
| Invariant (Foundry) | 9 | Pass |
| Mainnet fork (Foundry) | 14 | Pass |
| Frontend (Vitest) | 57 | Pass |
| Total | 179 | Pass |
Plus forge fmt, forge build, pnpm lint, pnpm typecheck and pnpm build, all clean.
Coverage by contract
- PloutoRegistry — 13 tests
One-time initialization; rejection of unknown tokens, mismatched curves, wrong launcher, wrong fee recipient and non-native quote; missing bytecode; double wiring; non-owner access.
- GravityStaking — 26 tests
Weight calculation for all three locks; multiple positions per wallet; accumulator correctness; new stakers cannot claim historical rewards; claiming does not unlock; maturity enforcement; zero-staker rollover; emergency behaviour; pause behaviour; fee-on-transfer rejection; a live reentrancy attempt.
- PloutoRevenueRouter — 18 tests
Split constants sum to 10,000 bps; claiming by measured delta; an over-reporting escrow cannot inflate revenue; donations excluded from the split; claiming allowed pre-launch but routing blocked; pause behaviour; balance classification.
- BuybackExecutor — 28 tests
Budget accounting; every safety bound; price-impact rejection; a failed route preserving funds; untradeable phases; PoolKey reconstruction; unauthorised keeper and admin calls; wrong chain; the dead-address fallback for a non-burnable token.
- PloutoReserve — 14 tests
Timelock enforcement; expiry; guardian veto; unauthorised propose and cancel; double execution; insufficient balance; a recipient that rejects ETH; ERC-20 withdrawal; donation classification.
Invariants
Nine properties, each over 128 runs × 32 calls = 4,096 randomised calls:
invariant_splitReconciles allocations sum exactly to routed revenueinvariant_neverRoutesMoreThanClaimed claimed − routed == unallocatedinvariant_routerBalanceCoversObligations the router holds what it owesinvariant_stakingNeverOverpays claimed <= received, and always fundedinvariant_principalFullyBacked staking holds >= totalStakedinvariant_totalStakedMatchesPositions totals equal the sum of open positionsinvariant_buybackBudgetSolvent received − spent == budgetinvariant_retirementAccounting burned + toDead == totalRetiredinvariant_executorHoldsNoTokens executor never retains PLOUTOFork tests
Run against live Robinhood Chain state:
ROBINHOOD_RPC_URL=https://rpc.mainnet.chain.robinhood.com forge test --match-path 'test/fork/*' -vvConfirmed live: chain ID 4663; bytecode at all ten Pons addresses; factory self-consistency; the live launch config; previewLaunchEconomics; escrow credit and claim; launch-record decoding; the token being fixed-supply and burnable with no reachable mint; the curve interface; a real pre-graduation buyback; PoolKey reconstruction resolving to an initialized pool; a real post-graduation swap; phase handling.
Two executions observed on forked state:
| Route | Spent | Retired | Real burn |
|---|---|---|---|
| Bonding curve (phase 0) | 0.01 ETH | 5,858,334 tokens | Yes — totalSupply() decreased |
| Uniswap v4 pool (phase 2) | 0.005 ETH | 74,014 tokens | — |
Frontend tests
57 tests over wallet connection, network switching, prelaunch gating, the complete transaction-state machine, stake approval and deposit, reward claim, mature withdrawal, transaction failure, accessibility, and — importantly — that missing data never renders as a fabricated figure.
Running them
forge test -vvvpnpm testWhat this does not prove
A passing suite demonstrates the properties the author thought to check, under conditions the author thought to create. It cannot demonstrate the absence of a property nobody considered. It is not an audit.