Nothing to integrate
No permission from Pons, no listing, no partnership, no change to their contracts. A fee recipient is an address. We are just an address that does something with what it receives.
Pons already charges a creator fee on every trade. Payd is what you point it at: a contract instead of a wallet, which turns that fee into real tokenised equities and delivers them to your token’s holders. No staking, no sign-up, nothing to approve. This page is the whole mechanism, and every contract it names is on the explorer at the foot of it.
What it is
Pons v2 lets a launch name its creator-fee recipient. That is the entire
integration surface: you launch your own token, on Pons, exactly as you would have, and give the
address of a vault the factory clones instead of your own wallet. This code is the Pons
deployer of nothing and holds no standing power over any launch.
No permission from Pons, no listing, no partnership, no change to their contracts. A fee recipient is an address. We are just an address that does something with what it receives.
Holders never sign anything — not once. The token never leaves their wallet, there is no pool to stake into and nothing to lock. Shares are pushed to them.
The vault is an EIP-1167 clone of an immutable implementation: no owner, no
proxy, no storage slot anyone can rewrite. The share promised to holders can only be
raised, never lowered. The single door out is migrate, and it is
described below.
The money
The fee crosses exactly two contracts, and they do not play by the same rules. Every percentage below is a constant in the code, not a policy we apply.
Pons v2 — the creator fees of one launch
│
▼
FeeVault — one per launched token
├─ rewardsBps ≥ 50 % ─► buys the basket ─► Distributor ─► holders
├─ the residue ─► CREATOR — the creator’s own address, immutable
└─ PLATFORM_BPS 10 % ─► Treasury (hard cap 15 %, stamped at birth)
│
▼
Treasury — one, shared by the whole platform
├─ 33.33 % the dev wallet — immutable, and it can only ever fall
├─ 33.33 % the $PAYD vault — paid out to $PAYD holders as stock
├─ 16.67 % buy back and burn — to 0x…dEaD
└─ 16.67 % liquidity — held by the Treasury itself, Uniswap v4
The Treasury’s _split measures the contract’s balance, not a
parameter, so an unexpected payment or a donation is split like everything else. The dev share is
a ratchet: setSplit refuses any value above the current one, so 33.33 % is a
ceiling for the life of the contract, never a starting point. The liquidity position is held by
the Treasury directly against the Uniswap v4 PoolManager — no NFT, nothing to approve, and
no function that withdraws it. Nor the pocket on its way there: the hatch that used to send
it to a Safe before graduation was deleted, so the LP share has exactly one exit and it
leads into the position.
$PAYD taxes itself at zero. The platform’s own token runs through the same
pair of contracts as anyone else’s launch, but its vault is born at
PLATFORM_BPS = 0 — it would otherwise be paying itself. Its numbers:
86.49 % to holders, 13.51 % creator residue to the Safe, which against traded volume
is 3.20 % and 0.50 %.
The cycle
One turn of the cycle, in the order the code runs it. On an ETH-quoted vault
each open step refunds its own gas at the real cost, priced at block.basefee —
which the caller does not choose — and capped hard: MAX_REFUND is 0.01 ETH per call
on the vault, 0.02 on the distributor. publishRoot is the single exception, and the
only privileged call in the loop.
harvest() anyone — pull the creator fees out of Pons and split them │ platform (fixed at birth) · rewards (rewardsBps, │ raisable only) · creator (the residue) ▼ buyBasket(minOuts[]) anyone — buy the WHOLE basket for every epoch since the last │ purchase: one shared hop into the pivot currency, then one leg │ per stock, each above its own price floor, delivered straight │ to the Distributor ▼ publishRoot(...)keeper only— commit the cumulative Merkle root, immediately │ in force. Preceded by five preflight checks, including a full │ recomputation from a second node. ▼ distribute(holder, ...) anyone — push a holder’s shares to them. Or the holder calls claim(...) and pays their own gas — or collect(...) and settles every launch they hold in one transaction.
An epoch nobody buys for simply carries over: the money stays in the vault and the next purchase covers every epoch that went by. Nothing is lost and nothing is stuck.
The contracts
Two are minted fresh per launch; six exist once for the platform. There is no
withdraw for any privileged address anywhere. The only withdraw() that
exists pays the caller a payment that had already failed to reach that same caller, takes no
address argument, and can move nobody else’s balance.
Payd weighed 54,635 bytes of initcode, now 20,371platform$PAYD is a tenant of the registry rather than its landlord: it runs through
the same pair of contracts as anyone else’s launch and holds no standing power over any other.
Its vault is not even in the registry — Bootstrap deploys it outside — which is
why Collector carries no allowlist of targets: one would lock the platform’s own
token out, and buy nothing, since a router that holds nothing has nothing to take.
The payout
The holder side has no interface and no decision in it. These four facts are the whole of it, and every one of them is a constant or a public view on the Distributor.
Roots are cumulative: one claim settles the entire history, one transfer per stock. A share once credited stays claimable for ever — there is no window, no expiry and no forfeiture anywhere in the contracts.
A share is delivered automatically once it is worth roughly $10, and at most once
every 24 h. Below that it keeps adding up. A transfer costs gas whatever it carries:
delivering a $0.20 share would burn half of it, waiting keeps 99 % of it. Nothing is withheld,
only batched — and claim() is always open to a holder willing to pay their own
gas.
payoutBps starts at 400 and the bytecode refuses anything outside
10–1 000 (0.1 %–10 %). Paying a slice rather than the lot smooths the quiet stretches, with a
floor so a young vault is never stranded. Only the 48-hour timelock moves it.
The Uniswap pool, the Pons bonding curve, the vault, the Distributor, address 0, the burn
address 0xdead, and a timelocked excluded[] list of CEXs and contracts. Holders below the value
threshold are out too, and their weight is redistributed to the others — the threshold
is the value of the share, not a percentage of supply, which would be too permissive at launch
and too restrictive later.
And the pot only ever fills: fundRewards() lets anyone put money
straight into the reserve the epochs buy from — no dev share taken, no gas cut, and no function
that takes it back out. It is the same one-way street the fees take; it just does not have to come
from a trade.
On your own site
A vault is public state, so the card that reads it needs nothing from us. Drop the element on your page and it talks to the chain from your visitor’s browser — there is no server in between, nothing to host, and nothing that can go down and take the card with it.
<script type="module" src="https://paydprotocol.eth.limo/sdk/payd.js"></script> <payd-vault vault="0xYourVaultAddress"></payd-vault>
The vault address is the only thing you have to know. The Distributor, the token, the basket and the fee split are all read from it — copying a second address into a third-party page is how one of the two ends up stale. The card shows what your token pays, the countdown to the next buy, the basket and its weights, and a button that lets a holder collect without leaving your site.
economics() returns the split as shares of traded volume — what a trader
actually pays, and the only figure comparable from one launch to the next. It is computed live
from Pons’ own parameters, so nothing is transcribed and nothing goes stale.
The card lives in a shadow root, so your stylesheet cannot reach into it and it cannot leak out. Colours, radius and fonts come in through CSS custom properties, which do cross that boundary.
There is a headless API under the element, and docs/SDK.md lists every call it
makes, in order, so the same card can be rebuilt in viem, ethers, wagmi, web3.py, a Go backend
or a Dune query. None of it needs a key, a server, or our permission.
The engineering
None of these is a preference. Each one is a measurement, taken against the live chain — not one test in the suite passes thanks to a stand-in for Pons or Uniswap.
An earlier design bought one stock per epoch and honoured the weights by rotation. The value was fair; the composition was noise. A purchase now covers a window — every epoch not yet funded — and buys every leg by its weight. The window shares the hop into the pivot (139,625 gas), the TWAP read of that same pool (69,389 gas), the price feed, the base transaction and the refund.
A paused stock, a dry pool, a floor the market will not meet: that leg is skipped.
Its pivot currency stays in pivotReserve, the contract emits
LegSkipped, and the next purchase spends it. A stock Robinhood pauses costs a
delay, never a loss — and never the other legs.
Pons keeps one escrow ledger per currency. Measured over seven days of credits: 40.9 % of Pons volume is quoted in ETH, 22.0 % in USDG, 37.2 % in stock tokens. A vault that reads only the ETH ledger leaves three fifths of the market unreachable.
Everything routes through one pivot currency, USDG, because that is where the equities’
liquidity is. A quote with no pivot pool is reached by QUOTE → WETH → PIVOT,
whose second hop is the pool every ETH-quoted vault already uses. The route is declared at
birth from a measurement, never probed at swap time.
A USDG line is transferred as is — there is no pool of a token against itself, so no floor to compute. A line that is the vault’s own quote is held back before the hop rather than bought back after it: the round trip cost 0.10 % measured on NVDA/USDG at tier 500, to end up exactly where it started.
minOut = 0Every swap carries a floor derived from an oracle — Chainlink where a feed exists, a 30-minute Uniswap v3 TWAP otherwise. Equity feeds go stale at the weekend; the floor then comes from the on-chain TWAP alone, which is the primary source anyway.
A share is the balance averaged over the whole epoch — the area under the curve,
∫ balance dt / L, not a sample of blocks. Buy a minute before the payout and you
are paid for a minute. No seed, no anchor, no reveal: the window is two immutables and a
subtraction.
Roots are cumulative, so one claim settles the whole history in one transfer per stock.
Pushes take an explicit list capped at MAX_BATCH (64) — there is no unbounded
loop over holders anywhere, and no gas ceiling anyone can walk the contract into.
The trust surface
The token is minted by the Pons factory and has no transfer hook, so no contract can know a past balance. Without staking — and staking is a click, a lock-up, and a contract holding your tokens — the split has to be computed off the chain and committed to it. That is the whole trust surface, and it is worth stating plainly rather than burying.
The contracts never pay out more than they took in, never pay the same share twice, and never take back what was already paid.
There is no withdrawal to any privileged address, on any contract. Those functions do not exist — this is a property of the bytecode, not a promise.
Deliveries run continuously, so at any moment roughly one epoch of rewards sits in the
contract. That exact figure is public and readable on chain:
Distributor.quoteAtRisk().
The timelock is an OpenZeppelin TimelockController deployed with
no administrator. Its only proposer is the Safe; its executor is
address(0), which OpenZeppelin reads as anyone — the Safe decides, the
public executes, 48 h later, and every proposal emits a CallScheduled the moment
it is filed.
migrate can point a vault’s future flow at a successor, and only the
timelock opens it. The destination must satisfy Payd.isVault, which is written by
one internal function and that nobody can steer — then it must be the same launcher, the
same token, the same currency, pay holders at least as well and take no more for the platform.
Not one stock leaves the Distributor: what was already credited stays claimable where it
is, and the vault’s undelivered reserve follows the stream into the successor’s rewards
pool, which is a one-way pocket there too.
The repository ships a tool that redoes the allocation from the chain alone. It takes no input from us, needs no key and signs nothing. A divergence is a reproducible proof anyone else can reproduce too.
Three privileged actors, and that is the list. The keeper, which publishes
roots and can do nothing else. The timelock, 48 h, which reweights and lists and moves no value. And
a generation key — cold, immutable, holding nothing — whose only power is to
approve a candidate vault factory, revocably, so that the timelock may then adopt it.
It cannot name anything by itself; it turns one compromise into two independent ones, which is worth
something only because it is not kept with the Safe.
Verify, don’t trust
The five platform contracts, each one deployed once and verified, and below them
$PAYD’s own vault. The per-launch contracts have no fixed address — a
FeeVault/Distributor pair is cloned for every token, and the app names
both on the page of the launch that owns them. $PAYD’s is listed here only because it is
the first the registry built.
The implementations hang off DistributionFactory, not off the registry:
Payd stamps and indexes, the factory clones. Adopting a new factory takes the
generation key and the 48-hour timelock, and it changes nothing for a vault already
cloned — migrate is per vault, and per vault it is the timelock’s call.