A fee plugin
for Pons.

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.

46 equities listed · 30-minute epochs · Robinhood Chain 4663 · no owner, no pause, no admin withdrawal

What it is

Pons collects the fee. The contracts do the rest.

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.

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.

Nothing to approve

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.

Nothing we can take back

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

Two storeys, and no third one.

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

Four calls. Three of them are anyone’s.

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

Eight contracts. No owner in any of them.

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.

FeeVaultreceives the creator fees, splits them three ways, buys the basket — holds no stock, everper launch
Distributorholds the stocks, pays them out against a Merkle proof, remembers what each holder was already paidper launch
Paydholds the registry, the stock allowlist and the platform rate — it launches nothing itselfplatform
DistributionFactorymakes the pairs of one payout mode, and only that — split off because Payd weighed 54,635 bytes of initcode, now 20,371platform
Treasurysplits the platform share four ways — dev 33.33 %, $PAYD rewards 33.33 %, buy-and-burn 16.67 %, liquidity 16.67 %platform
Collectorsettles N launches in one transaction — a router that holds nothingplatform
Timelock48 h, OpenZeppelin, deployed with no admin — the Safe proposes, anyone executes once the delay is upplatform
Bootstrapdeploys a pair in one transaction — the two reference each other, so neither can be deployed firstplatform

$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

What a holder actually gets, and when.

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.

Cumulative, so nothing expires

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.

Pushed at about $10, at most daily

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.

4 % of the reserve per window

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.

Who is not in the tree

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

Two lines of HTML. No backend, no key.

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.

Your number, not a marketing one

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.

It cannot break your CSS

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.

Or rebuild it yourself

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

The eight decisions that make it work.

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.

One purchase buys the whole basket

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 failed leg blocks nothing

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.

One quote per vault, stamped at birth

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.

The pivot is a crossroads, not a wall

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.

Two legs skip the pool entirely

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.

Never minOut = 0

Every 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.

There is no snapshot to snipe

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.

Cumulative roots, bounded pushes

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

One key publishes. Here is what it cannot do.

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.

It cannot invent money

The contracts never pay out more than they took in, never pay the same share twice, and never take back what was already paid.

It cannot touch the funds

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.

It cannot drain the protocol

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 one privileged key moves no value

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.

The one door out is guarded

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.

Anyone can recompute it

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.

And what can still go wrong

  • The tokenised equities belong to Robinhood. They can pause them, block an address or burn holdings. This protocol is exposed to that like everyone else.
  • Pons can redirect the fee stream. The registry’s owner can point creator fees at another address, with three days’ notice and no veto on our side. Stocks already in the contracts stay claimable; it is the future flow that would stop.
  • A compromised publishing key can misallocate what is not yet delivered — about one epoch, because delivery is continuous.
  • If the publishing service stops, fees pile up and nothing is distributed until it comes back. Nothing is lost meanwhile.
  • The smallest shares fall below the delivery threshold. They stay claimable rather than being delivered at a loss.
  • No external audit has been done to date.

Verify, don’t trust

Every address, on the explorer.

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.

Payd0x54c90f5DbBE310F71bc3B10dd87efF284ac63B03verified
DistributionFactory0x1228E61aba98260dC8b5eAf3D40A899bA766753b · holds the FeeVault and Distributor implementations every launch clonesverified
Treasury0x943Cb95441B26622a1c3c606E20cB60b2Dc94694verified
Collector0xf3102FfE59DC2147bC0DF7e5b64d40E6b8Fed9f7verified
Timelock0x1e9389CF4B42527f6EB1e107E99B9F5Da15c7291 · 48 h delay · deployed with no adminverified
$PAYD vault0x4DBA57f2E1b9AFE02cA091916F98dd7B4A248A64verified

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.

Hold the token. That is the whole job.