Docs

How Meed pays

Meed turns "pay these people these amounts" into one transaction that sells exactly enough of your tokenized stocks on Robinhood Chain (chain id 4663) and pays each person in USDG. This page is the whole mechanism, the checks, the numbers and what is not built. The code is plain JavaScript that the page loads as-is.

The transaction

Every payment is one call to execute() on Uniswap's Universal Router, in this order:

CommandWhat it does
PERMIT2_PERMIT_BATCHYour one signature: for each token, exactly the amount this payment may pull, for the router only, expiring in 30 minutes. Left out when an allowance already covers it.
PERMIT2_TRANSFER_FROMPer stock: the ceiling — the planned shares plus your price allowance — pulled into the router once.
V3_SWAP_EXACT_OUT / V4_SWAPPer pool: "give me exactly this many dollars", paid for out of the shares the router holds. Up to 4 pools per stock.
PERMIT2_TRANSFER_FROMYour own USDG, if you chose to spend it first.
TRANSFER ×nEach person, their exact amount, in USDG.
SWEEP per stockEvery share the pools did not need, back to you.
SWEEP USDGAny dollar left in the router, back to you. There should be none.

Because every sale is exact-output, what each person receives is fixed by construction; what varies is the number of shares sold, and that is capped by the ceiling. If any sale falls short, a TRANSFER fails and the whole transaction is undone. Meed deploys no contract of its own.

The layouts are the ones the router deployed on this chain actually uses, read from its verified source: V3_SWAP_EXACT_OUT takes a trailing uint256[] minHopPriceX36, and v4's ExactOutputSingleParams carry a minHopPriceX36 before hookData. The five-field layout in Uniswap's public docs reverts on this router.

The split

With Keep my mix, the payment is divided across the stocks you ticked in proportion to what each holding is worth at Robinhood's price, so a payment worth a tenth of those holdings sells a tenth of each. A stock is capped at what it can actually raise — Meed prices the sale, and if the shares needed plus your allowance would exceed what you hold, or the pools cannot raise that much, it lowers that stock's cap and divides the rest again. A stock asked for less than $1.00 is dropped and its share divided among the others. With Cheapest, Meed prices the whole payment against each ticked stock alone and sells only the one that costs least (falling back to the mix if none can raise it alone). With Choose amounts, you type the dollars per stock and they must add up. The division is exact to the last unit of USDG (six decimals): the parts always add to the total.

Exact-dollar sales across pools

Most stocks trade in several Uniswap v3 and v4 pools. To raise a fixed number of dollars as cheaply as possible, every pool used should finish at the same marginal price — the next share would fetch the same wherever it went — so Meed searches for that one price and reads off how far each pool must move. It reads each pool's price, liquidity and the tick bitmap around the price, walks the pool word by word exactly as TickBitmap does, and prices every sale to the unit without asking the chain. A sale that would need tick data it has not read is reported as unknown rather than guessed. Splitting is used only when it is cheaper than the best single pool; a pool that would take under 1.5% of the sale is dropped. This engine was built for KERF, a sibling site, and is reused unchanged.

How it is checked: tools/test-sim.mjs prices 800 sales — every listed stock, every pool, four sizes — and compares each with Uniswap's own QuoterV2 and V4Quoter at the same block. 604 agreed to the unit, 0 disagreed, and 196 were beyond the tick data read and were not guessed. Two controls must disagree: the same pool with its liquidity nudged by one part in a million, and the same sale in the wrong direction.

What the page checks before your wallet sees anything

The page decodes its own transaction (assertPay in js/route.js) and refuses to hand it to your wallet unless:

  • it calls the Universal Router and uses only the seven commands above, none of them allowed to fail;
  • every TRANSFER pays USDG to an address on your list, for exactly the amount you typed, once — and everyone on the list is paid;
  • every stock is pulled once, for exactly its planned ceiling, into the router, and swept back to you once;
  • every swap is a single pool, sells a stock you ticked for USDG, keeps its dollars in the router, uses no hook and may spend no more than that stock's ceiling;
  • each stock's pools raise exactly the dollars planned for it, and the order is permit, pulls and sales, payments, change;
  • the signature covers only tokens this payment spends, for at least what it pulls, for the router.

Then it simulates the transaction from your address. A refusal there becomes a sentence — "prices moved past your limit" — instead of a failed transaction.

Approvals

The first time you pay from a stock, your wallet asks you to let Permit2 — Uniswap's approval contract — move it. That is an unlimited approval to Permit2, which is how Uniswap's own apps work: Permit2 still moves nothing without a signature that names the spender, the token, the exact amount and an expiry. Every payment after that is one signature and one transaction. You can revoke an approval at any time from your wallet or the explorer.

Limits, and why

These are decisions, not measurements, and each is written down with its reason in js/config.js.

People in one payment10
Stocks in one payment8
Most in one payment$25,000
Least on one line$1.00
Default price allowance0.5%
Signature and transaction lifetime30 and 20 minutes
Highest pool fee used5%
A stock is listed if $1,000 sells within3%

A stock is listed only when a Morpho market lends the real USDG against it, which is where Meed reads Robinhood's price for it. At the last scan 10 other tokens were left out, each with its reason: CLSK (a $1,000 sale costs 97.80% against Robinhood's price); CRWV (a $1,000 sale costs 5.09% against Robinhood's price); IONQ (no pool can sell $1,000 of it); RGTI (no pool can sell $1,000 of it); AVGO (no Robinhood price feed through a USDG market); JNJ (no Robinhood price feed through a USDG market); NET (no Robinhood price feed through a USDG market); NU (no Robinhood price feed through a USDG market); QUBT (no Robinhood price feed through a USDG market); SOUN (no Robinhood price feed through a USDG market).

What it costs

Measured at block 64,910,289 by tools/probe-pay.mjs, against Robinhood's price for each of the 45 stocks. Medians across stocks; the three parts are medians of their own, so they need not add up.

PaymentCostPool feePrice movePool vs Robinhood
$1000.26%0.24%0.01%0.02%
$1,0000.27%0.28%0.05%−0.00%
$5,0000.36%0.29%0.13%0.00%

Gas, measured on a fork of the chain: 460,499 gas for two people paid from two stocks (about $0.06), and 874,180 for ten people from three stocks (about $0.11), at a gas price of 0.0509 gwei and ETH at $2,416.

Tests

Nothing here has been audited by anybody. These are the checks we ran ourselves, what each one does, and how it last came out.

  • 19/19 properties on Robinhood Chain itself (tools/props.mjs, block 64,938,280). The page's planner and builder make the payment; a contract run inside an eth_call with no deployment sends it through the real Universal Router and pools, funded by a state override, and measures balances itself: every person paid exactly, the router keeps nothing, every share sold arrives in a pool, the change comes back. Four refusals — a payee owed one unit too many, a ceiling one share short, an expired deadline, a missing approval — are each classified by their revert reason and paired with a control that goes through. Six ABI-surface checks require the page's own reader to accept every payment it built and refuse tampered copies. A control proves a wrong storage slot funds nothing.
  • 30/30 on a fork of this chain (tools/test-tx.mjs): real Permit2 signatures, real transactions, and every payment read back two ways — from the tokens' own transfer logs and from balances. Two people from two stocks; a replayed signature refused (InvalidNonce); a signature for another spender refused (InvalidSigner); cash spent first; a payment made stale by an $8,000 sale ahead of it, refused and then re-planned; ten people in one transaction; a sale through Uniswap v4 alone; a wallet that no longer holds the shares.
  • 604 of 800 sales priced exactly, 0 off (tools/test-sim.mjs): every stock, every pool, four sizes, against QuoterV2 and V4Quoter at one block; 196 were past the tick data read and were reported as unknown, not guessed. Two controls must disagree.
  • 45/45 offline checks over 500 random draws (tools/test-plan.mjs): the split's invariants after every draw (the parts add to the total to the unit, no stock past its cap, the mix kept, an honest refusal), every refusal the payee form promises, and the transaction reader fuzzed with twelve kinds of tamper.
  • 2/2 fuzz seeds clean, 10/10 deliberate breaks caught (tools/fuzz.mjs): random sequences of operations on a fork, every invariant checked after every step, and each break caught by the invariant named for it.
  • 27/27 deliberate breaks caught (tools/sabotage.mjs): the transaction builder broken one line at a time and run through the real chain, the split and the payee form broken and run through the offline checks, and the simulator broken and compared with Uniswap's quoters — each caught by the check named for it; 3 cannot be seen on chain (the router sweeps the difference straight back) and are caught by the page's own reader instead, with the reason written down. The sweep found a real bug: the loop that divides a payment could spin forever once a cap was wrong upstream. It is bounded now.
  • 23/23 through the real pages in a real browser (tools/e2e.mjs): a request link made, opened in the app, paid by clicking, and the receipt page reading it back — against a fork, under the deployed Content-Security-Policy.

The case against it

Put fairly: if all you want is dollars for a stock, a brokerage selling at the market usually costs less than a Uniswap pool's fee, and Meed's median cost of 0.27% on $1,000 is mostly that fee. Pools on this chain are also thinner than the stock market, so large payments cost more — 0.36% at $5,000 — and above $25,000 Meed will not try. Keeping your mix costs more than it has to, as well: the landing page's $1,200 example cost −$1.75 spread over four stocks and −$3.58 from AAPL alone, a difference of $1.83. PLUCK, a sibling site built at the same time, measured the same thing first; it is why Meed has a Cheapest mode. What Meed is for is the payment itself: an exact amount, to anyone on chain, in one step, with nothing left sitting in between.

Before this, the first idea for this site was a way to bet against a stock by borrowing it. It died in ten minutes of measurement: every Morpho market on this chain that lends a stock — NVDA, SPY, AAPL, GOOGL and TSLA among them — held zero shares to borrow.

Addresses

Every address the site uses, read back on chain by tools/verify-addresses.mjs.

Uniswap Universal Router0x8876789976dEcBfCbBbe364623C63652db8C0904
Permit20x000000000022D473030F116dDEE9F6B43aC78BA3
Uniswap v3 factory0x1f7d7550B1b028f7571E69A784071F0205FD2EfA
Uniswap v4 PoolManager0x8366a39CC670B4001A1121B8F6A443A643e40951
Uniswap v4 StateView0xF3334192D15450CdD385c8B70e03f9A6bD9E673b
QuoterV2 (v3)0x33e885eD0Ec9bF04EcfB19341582aADCb4c8A9E7
Quoter (v4)0x8Dc178eFB8111BB0973Dd9d722ebeFF267c98F94
Morpho Blue (price feeds)0x9D53d5E3bd5E8d4Cbfa6DB1ca238AEA02E651010
USDG — Global Dollar0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168
Multicall30xcA11bde05977b3631167028862bE2a173976CA11

Not built

  • No ETH as a source. Payments come from stocks and USDG only.
  • Payees receive USDG only, not stocks and not ETH.
  • No schedule. Meed cannot pay rent every month by itself; there is no contract to hold a standing order.
  • No history of your own. Receipts are read from the chain one hash at a time; nothing is stored.
  • No stock without a Robinhood price feed on a Morpho market, even if it trades in a pool.
  • Cheapest picks one stock. It does not search for the cheapest division across several stocks; when no single stock can raise the payment it falls back to keeping your mix.