Donations — fueling the pot
Anyone funds the machine: native or ERC20, measured on arrival, irreversible by design.
The pot has exactly one inflow besides the harvest's buyback share: donate — permissionless, secondary-only, measured on arrival, and one-way. This chapter is the full funding guide: the mechanics, the safety checks before you fund a pool you don't control, and the strategies that fit how the pot actually spends.
The mechanics
| rule | why |
|---|---|
the pot must be configured first (PotNotReady) | before initPot there is no "secondary" to credit — a donation to an undeclared pot would be a guess about roles that don't exist yet |
value XOR allowance, never both (BadDonation) | a native pot is funded with attached value, an ERC20 pot through an allowance — mixing them is always a caller bug, so it reverts loudly |
| the credit is the measured balance delta | a fee-on-transfer secondary credits exactly what arrived; a donation that nets to zero reverts instead of emitting a lie |
| only secondary can ever be donated | the pot is a war chest denominated in the buyback currency — main enters the pot only by being bought or absorbed, never deposited |
Every donation emits Donated(poolId, donor, amount) with the credited amount, and the credit immediately joins the hook's obligationOf(secondary) accounting — custody covers every donated wei from the moment it lands until the market spends it.
Before you donate — the two checks
potOf(poolId).recipient is where every pump's and shield's main is delivered. address(0) means burn — the trustless shape. A live address means you are trusting whoever the admin points it at, including future re-pointing.Donation strategy — the pot spends on the market's clock
Because of the spending curve, a donation is never a market order: a 100 ETH donation on a 0.30% pool with 1,000 ETH of tangent depth can spend at most 2.4 ETH per buy, and only against ≥ 125 ETH of genuine buy demand. That changes what "good funding" looks like:
| strategy | when it fits |
|---|---|
| lump-sum | simplest, and safe by construction — the pacing laws stream it into the market for you. One transaction, one thing for the community to verify. |
| scheduled tranches | when you want the POT's balance (which is public) to signal sustained commitment rather than a one-off — a vesting contract or a Sablier-style stream calling donate() on a schedule |
| revenue routing | the deepest shape: a protocol sends a slice of its actual revenue to donate every period, making the buyback proportional to real usage — Integrate buybacks is the dozen-line version |
| self-fueling | zero external funding at all: a non-zero buybackShare makes every harvest donate the pool's own secondary-side fees to its own pot — the machine feeds itself from traffic |
One-way means one-way: no donor refund, no admin sweep, no governance override — the design deliberately gives donors zero residual claim, because any claim path would be a rug path. A donation is a market commitment, not a deposit.
Reading a pot's funding history
A community can audit a project's buyback promise entirely on-chain: sum the Donated events, watch the balance, and compare against the pump volume — no trust in reported numbers, ever.
FAQ
Who can donate, and to which pools?+
Anyone can donate to any hooked pool — a community member, a partner protocol, another contract. It's a permissionless public-goods action; no role or allowlist is involved.
Can I get a donation back?+
No. Donations are irreversible by design — the pot has no withdrawal path for anyone. Treat a donation like burning value into the pool's defense budget.
What exactly do I donate — MAIN or SECONDARY?+
Always the SECONDARY currency (native ETH via msg.value when secondary is native, an ERC20 pull otherwise). The pot spends secondary to buy or defend MAIN.
How are fee-on-transfer tokens handled?+
The pot credits what actually arrived, not what you asked to send — the balance is measured on arrival. A tax token simply donates its post-tax amount.
Can a smart contract donate programmatically?+
Yes — one call: hook.donate{value: amt}(key, amt). That's the whole integration; pair it with quotePump/quoteShield to size donations against the defense you want.