Skip to content
Protocol contracts not yet configured for this build
Enter app

Introduction

Build status

What runs, what passes, and — more usefully — what that does and does not prove.

The suite

SuiteCountWhat it exercises
Unit99Every contract, in isolation, against mock Pons infrastructure.
Fuzz4Randomised amounts and lock terms across staking and routing.
Invariant9Protocol-wide properties over 4,096 randomised calls each.
Mainnet fork14The real Pons contracts, on forked mainnet state.
Frontend57Wallet 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 PoolKey reconstructed 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:

  1. totalSentToBuybacks + totalSentToStakers + totalSentToReserve == totalRevenueRouted, exactly.
  2. totalRewardsClaimed <= totalRewardsReceived, and the staking contract always holds enough ETH to cover what it owes.
  3. The PLOUTO balance of the staking contract is always at least totalStaked.
  4. totalRevenueClaimed - totalRevenueRouted == unallocatedRevenue.
  5. totalBudgetReceived - totalEthSpent == buybackBudget.
  6. totalPloutoBurned + totalPloutoSentToDead == totalPloutoRetiredByProtocol.
  7. The executor never holds PLOUTO between executions.
  8. totalStaked and totalWeight always 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 when msg.sender is 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.