Docs

How Posy works

Posy is one small contract, PosyPots, and these pages. A pot collects USDG from anyone who wants to chip in; when it closes, the contract buys up to 6 tokenized stocks through Uniswap's SwapRouter02 on Robinhood Chain and the shares go straight to the recipient. If it is cancelled instead, everyone takes back exactly what they put in.

A pot's life

1 · open

open(recipient, deadline, goal, slippageBps, stems[], title). Each stem is a stock, the fee tier of its USDG pool on Uniswap and its share of the pot in basis points; the shares must add up to exactly 100%. The contract refuses a pool that does not exist, a repeated stock, a deadline in the past or more than a year out, and a slippage limit above 15%. The goal is only for the progress bar.

2 · chip in

contribute(id, amount, note) after approving USDG. Allowed until the deadline second. The note (64 bytes at most) is emitted in the Chipped event and shown on the pot's page.

3 · close

close(id, minOut[]). The organiser may close at any time; after the deadline, anyone may. The pot's USDG is split by weight — each stock gets floor(raised × weight / 10,000) and the last takes the remainder — and each part is swapped with exactInputSingle, recipient fixed to the pot's recipient. Each leg must return at least its minimum, and each minimum must clear the price guard below.

4 · or cancel, and refund

cancel(id) by the organiser while the pot is open, or by anyone once 30 days have passed after the deadline without a close. Then refund(id) pays each contributor exactly their total, once.

The contract

Reading Robinhood Chain…

PosyPots0xDc17e535370512Ea8d47CDFF0927B3e67be98788
Init code hash0xae8508b90c6e15f8aff88864af98c9e55689005f7a5cee7dd9cae4ef5ce2feb8
Runtime hash0x2c17f9046d2cee1bd5b9ee5a13602ff6dc7c1e3972a77d0a4c1984498881c0e4
Size10,884 bytes of runtime · source (GPL-2.0-or-later)
Compilersolc 0.8.26, optimizer 200 runs, EVM cancun
Deployed through0x4e59b44847b379578588920cA78FbF26c0B4956C (the deterministic-deployment proxy), salt 0x74151c72c6899cbaacc80d06476d2eefa15aaf6e3c3251d4291e859358153950
Uniswap SwapRouter020xCaf681a66D020601342297493863E78C959E5cb2
Uniswap QuoterV2 (quotes)0x33e885eD0Ec9bF04EcfB19341582aADCb4c8A9E7
Uniswap v3 factory0x1f7d7550B1b028f7571E69A784071F0205FD2EfA
USDG (what a pot collects)0x5fc5360D0400a0Fd4f2af552ADD042D716F1d168

PosyPots has no owner, no fee, no upgrade and no pause. Its only state-changing functions are open, contribute, close, cancel and refund. Every address it calls is a constant in its code, so it has no constructor arguments.

Check it is this code

Nobody holds a key to PosyPots, including us, so it is deployed by its first user: the Start a pot page sends salt ++ initcode to the deterministic-deployment proxy, which creates it at keccak256(0xff ++ proxy ++ salt ++ keccak256(initcode)). Anyone can repeat that arithmetic and compile the source themselves:

solc 0.8.26 · optimizer on, 200 runs · evmVersion cancun
keccak256(initcode)            = 0xae8508b90c6e15f8aff88864af98c9e55689005f7a5cee7dd9cae4ef5ce2feb8
address                        = 0xDc17e535370512Ea8d47CDFF0927B3e67be98788
keccak256(eth_getCode(address)) must be 0x2c17f9046d2cee1bd5b9ee5a13602ff6dc7c1e3972a77d0a4c1984498881c0e4

The pages check the last line before they read anything: an address holding different code counts as "not deployed". The build refuses to publish if a fresh compile of the source moves any of the three.

The price guard

Whoever closes a pot chooses the minimum each stock must deliver — the page takes Uniswap's live QuoterV2 quote and asks for at least 99% of it. On its own that would let a closer set minimums of zero and trade against the pot in the same transaction. So the contract also computes each leg's value at the pool's 30-minute time-weighted average price (Uniswap's own observe()) and refuses any minimum below that value less the pot's slippage limit. A price pushed around inside the closing transaction does not move a 30-minute average.

What the limit means in the worst case: someone entitled to close could push the pool against the pot and fill it right at the floor — the 30-minute price less the limit — so the limit is the most a pot can lose to its closer, and the pool's own fee comes out of the same margin. Keep it small: the page suggests 3% and refuses a limit that a pool's fee alone would use up.

Measured at block 71,647,327, the gap between each giftable pool's current price and its 30-minute average had a median of 4 basis points (largest 38). The suggested limit is 3%.

A pool needs 30 minutes of recorded prices for this. 3 pools with a USDG pair keep too few observations today (TSLA, NU, RIVN), so the pages do not offer those stocks. What the guard does not do: it cannot tell whether the pool's price itself is fair compared with the stock market — it protects the pot from the person closing it, not from the market.

Refusals

Every refusal is a named error, and the pages translate it before your wallet opens.

ErrorMeans
BadRecipientThat recipient address cannot receive a pot.
BadStocksEach stock can appear once, and a pot holds one to six of them.
BadWeightsThe shares of the pot must add up to 100%, and none can be zero.
BadFeeThat Uniswap fee tier does not exist.
NoPoolUniswap has no USDG pool for that stock at that fee.
BadDeadlineThe deadline must be in the future and within a year.
BadSlippageSlippage must be between 0.01% and 15%.
TextTooLongThat text is too long: 64 characters at most.
NotOpenThis pot is not open any more.
NotOrganiserOnly the organiser can cancel this pot before its deadline (or anyone, 30 days after it).
TooEarlyOnly the organiser can close this pot before its deadline. Anyone can after it.
DeadlinePassedThis pot's deadline has passed, so it no longer takes contributions.
ZeroAmountEnter an amount.
TooMuchThat amount is larger than any USDG balance could be.
EmptyNobody has chipped in yet, so there is nothing to buy.
BadMinimumsThe close was built for a different pot. Reload and try again.
MinimumTooLowThat minimum is below what the pool's 30-minute price allows. Reload for a fresh quote.
TwapUnavailableOne of the pools has less than 30 minutes of price history, so the pot cannot price it safely yet.
NotCancelledRefunds open only if the pot is cancelled.
NothingToRefundThis wallet has nothing to take back from this pot.
TransferFailedThe USDG transfer failed: check your balance, and approve the pot first.
ReentrantRefused a re-entrant call.

Stocks a pot can buy

39 of the 42 Robinhood stock tokens with a USDG pool on Uniswap, scanned at block 71,647,327. Prices are the pool's, per share.

StockPricePool feeUSDG in pool
NVDANVIDIA
$224.390.05%$3,634,978
USOUnited States Oil Fund
$152.910.3%$1,197,698
CRCLCircle Internet Group
$92.660.3%$1,189,490
SPCXSpace Exploration Technologies Corp. Class A Common Stock
$147.920.05%$1,078,047
QQQInvesco QQQ
$740.590.05%$580,507
MUMicron Technology
$1078.910.3%$577,312
HIMSHims & Hers Health
$29.270.3%$546,475
RDDTReddit
$152.041%$532,725
GOOGLAlphabet Class A
$342.240.05%$477,273
METAMeta Platforms
$776.370.3%$388,114
GLDSPDR Gold Trust
$391.570.05%$380,075
MSFTMicrosoft
$497.360.3%$374,998
MSTRStrategy Inc.
$161.911%$362,450
AMCAMC Entertainment
$2.870.3%$321,576
AMZNAmazon
$249.510.3%$303,912
GMEGameStop
$24.930.05%$300,430
COSTCostco
$899.200.3%$281,754
LLYEli Lilly
$1184.070.05%$214,945
SPYSPDR S&P 500 ETF Trust
$767.240.05%$209,323
AAPLApple
$336.070.05%$190,143
INTCIntel
$127.140.3%$183,562
SGOViShares 0-3 Month Treasury Bond
$100.570.05%$154,544
DJTTrump Media & Technology Group
$9.031%$153,893
AMDAMD
$630.250.3%$141,103
DELLDell
$541.181%$140,550
RBLXRoblox
$48.341%$116,466
SLViShares Silver Trust
$57.710.3%$111,649
AVGOBroadcom
$350.240.3%$108,235
QUBTQuantum Computing
$9.140.3%$93,182
TSMTaiwan Semiconductor Manufacturing
$447.701%$89,880
PLTRPalantir Technologies
$192.320.3%$87,391
NETCloudflare, Inc. Class A common stock
$358.960.3%$84,094
MRNAModerna
$195.120.3%$60,498
NFLXNetflix
$71.910.3%$41,119
JNJJohnson & Johnson
$272.260.3%$32,961
SNDKSandisk Corporation
$1744.161%$32,314
TTWOTake-Two Interactive Software
$203.280.3%$25,298
ASMLASML Holding NV
$1718.251%$20,822
USARUSA Rare Earth
$15.400.3%$18,934

Tests

Everything below ran against Robinhood Chain's live state — the real USDG, the real stock tokens and the real Uniswap pools — through the node's eth_simulateV1, with PosyPots deployed through the real proxy inside the simulation. Nothing was broadcast.

  • Properties: 10/10 pass, 525 checks. Each refusal must be the specific named error; each amount is checked to the unit against numbers computed in the test from what the people in it typed. The re-entrancy lock, which no real sequence can reach (USDG makes no callbacks), is tested with one eth_call that installs the runtime by state override and sets the lock's slot, found by name in solc's storage layout.
  • Fuzz: 8 seeds, 126 operations (79 landed), each held against an independent model after every step (what the contract holds is tracked from USDG's own Transfer logs) and every pot and every person's record read back at the end. Each seed ends with one of four fixed scenarios — several friends chip in and the organiser closes; refused refunds and cancels, then exact refunds; a stranger refused before the deadline and closing after it; a minimum one unit under the floor refused by name, then cancel and refund — and the run fails unless all four ran and every operation landed.
  • Sabotage: 31 deliberate bugs planted in the contract and the page's transaction builder; 31/31 were caught by the property named for them. None was missed.
  • In a browser: 7/7 journeys, 37 checks — a first user deploys the contract from the page, an organiser opens a pot, two friends chip in from separate wallets, the pot closes and the recipient's balances rise; and a pot is cancelled and refunded.

Risks, plainly

  • Not audited. The contract is small and tested, and it holds contributors' USDG until a pot closes or is cancelled.
  • The recipient's address is final. A mistyped address receives the shares and nobody can take them back.
  • Robinhood controls the stock tokens. They can pause a token or block an address; a pot whose purchase or delivery is blocked cannot close, and can be cancelled and refunded.
  • Prices move. The pot holds dollars until it closes; the recipient gets what those dollars buy then.
  • A pot nobody closes can be closed by anyone after its deadline, and cancelled by anyone 30 days later.

Older gift links

Before 25 September 2026 Posy sent single gifts as links holding a key. Those links still open at /claim; nothing about them depends on PosyPots.