A treasury-backed price floor with burn.
The operator funds a paymentToken reserve; holders can then always sell the projectToken to the
contract at a fixed floor price, and every token bought is immediately forwarded to the burn address
(0x…dEaD), removing it from circulation. This puts a hard, reserve-backed floor under the token — you can
never get less than floorPrice for it while the reserve lasts — and every sale permanently shrinks the
circulating supply.
constructor(projectToken, paymentToken, floorPrice, owner)—floorPriceispaymentTokenper1e18projectToken.sell(amount)— sell project tokens at the floor: they are burned and you receiveamount · floorPrice / 1e18ofpaymentToken. Reverts if the reserve can't cover it.fundReserve(amount)/withdrawReserve(amount)— operator tops up or reclaims the reserve.- Views:
quote(amount),buyableAtFloor(),reserve(),totalBurned().
ReentrancyGuard+SafeERC20+ checks-effects-interactions; the project-token pull credits the actual amount received (fee-on-transfer safe).- Tokens are burned by forwarding to
0x…dEaD— portable across any ERC-20 (noburn()hook required) and provably out of circulation. - Fully tested: unit tests for floor payout, burning, reserve exhaustion, quote/buyable views, withdrawal, and
every guard, plus two stateful invariants (
fail_on_revert = true):- reserve conservation — the payment-token balance always equals the tracked reserve;
- no project held / all burned — the contract never retains any project token, and the burn-address
balance always equals lifetime
totalBurned.
forge test
FOUNDRY_INVARIANT_FAIL_ON_REVERT=true forge test --match-path "test/BuybackBurner.invariant.t.sol"PROJECT_TOKEN=0x... PAYMENT_TOKEN=0x... FLOOR_PRICE=2000000000000000000 \
forge script script/Deploy.s.sol --rpc-url "$RPC_URL" --broadcastNot audited. Reference implementation — review before any real deployment.