The coin
Every Keel coin is a clone (EIP-1167) of one contract, KeelCoin. It is an ordinary ERC-20 with 18 decimals and a fixed supply of 1,000,000,000, all of which starts inside the coin itself, in its market. The launcher picks one stock token, the stock the whole market is held in. Nothing about a coin can change after launch.
The curve
The coin is its own market: a constant-product curve between the coins it still holds and a reserve of one stock, measured in the token’s raw units. The reserve starts with a virtual amount, set at launch from the starting value the launcher picks ($1,000 to $30,000 of the stock at that moment). Nobody paid for those shares and nobody can take them out; they set where the price starts and how fast it moves.
A buy of net shares after the fee receives coins × net ÷ (shares + net) coins, rounded down, where shares is virtual plus real. A sale of c coins pays shares × c ÷ (coins + c), rounded down, less the fee. The price of a coin is therefore a number of shares; the page shows it in dollars at the stock’s live price in its Uniswap pool. The page computes every quote with the contract’s own integer formulas.
The coins the market holds are counted separately from the coin’s ERC-20 balance at its own address, so coins (or shares) sent to a coin by mistake can never move its price.
Paying and being paid
buy(path, amountIn, minCoinsOut, to) accepts three kinds of payment:
- ETH: sent as value, with a Uniswap v3 path from WETH to the stock. The page uses ETH → USDG in Uniswap’s WETH/USDG 0.01% pool, then USDG → the stock in its deepest pool.
- The stock itself: an empty path. No swap, no Uniswap fee.
- Any other token (the page offers USDG): a path from that token to the stock. The coin pulls exactly
amountInand swaps it.
sell(coins, path, minOut, to) is the mirror: an empty path pays out the stock; a path from the stock to WETH pays out ETH (the WETH is unwrapped); a path to any other token pays that token.
The contract checks that every path starts at what is paid and ends at the stock (or the reverse), and never touches the coin itself. The router is approved for exactly the amount being swapped and the approval is cleared afterwards. What arrives is measured as a balance change, never taken from the router’s say-so. The one price check the buyer needs is minCoinsOut: it bounds the swap and the curve together, because more shares always buy more coins. The page sets it from Uniswap’s own quote (QuoterV2) and the limit you pick, 0.5%, 1% or 3%.
On the pools the page routes through, a round trip ETH → stock → ETH costs about the pools’ fees: 0.12% for a stock with a 0.05% pool, 0.62% for one with a 0.3% pool, at $50 or at $2,000 (measured 1 Oct 2026). Paying and being paid in the stock costs nothing beyond the coin’s own fee.
The fee
1% of every buy and sell, taken in the stock, the same for every coin. Half (0.5% of the trade) stays in the market as real shares, without minting coins for it, so it nudges the price up for everyone holding. Half builds up for the coin’s creator. claim() pays it in the stock; anyone may call it, and it always pays the creator. The creator can hand future fees and what is waiting to another address with setCreator. Keel takes nothing.
Always fully held
The market keeps every real share buyers paid in, less what sellers took out. Can it run short? No. On a constant-product curve, selling every coin back walks the reserve down to exactly where it started, the virtual amount, plus whatever the fee left behind. So the real shares never go below zero, and a sale is also capped at the real shares held. At every moment the coin holds exactly reserve + creator’s fees in the stock, to the unit; the tests check that after every trade.
That does not mean a coin cannot fall. Late buyers pay more shares per coin than early ones, and selling walks the price back down the same curve. What it means is that the market never owes more stock than it has, and that what it has is the stock, not ETH.
The picture and links
At launch, the picture, description and up to three links are ABI-encoded and stored as the code of a tiny contract (SSTORE2), 24 KB at most. Your browser crops the picture square and shrinks it to under 16 KB first. meta() returns them byte for byte, and nothing depends on a server.
The contracts
| What | Address |
|---|---|
| KeelFactory | 0x11AF7E0d65d4613587138d5ff0450C00a34F0023 |
| KeelCoin implementation | 0x5CEffA39f5b119A6516d4971C8b968eadB51daFD |
| CREATE2 deployer (Arachnid’s, deterministic) | 0x4e59b44847b379578588920ca78fbf26c0b4956c |
| Uniswap v3 factory | 0x1f7d7550B1b028f7571E69A784071F0205FD2EfA |
| Uniswap SwapRouter02 | 0xCaf681a66D020601342297493863E78C959E5cb2 |
| Uniswap QuoterV2 (quotes only) | 0x33e885eD0Ec9bF04EcfB19341582aADCb4c8A9E7 |
| WETH / USDG 0.01% pool | 0x52e65B17fB6E5BA00Ed806f37Afcd2DaA50271Ca |
The factory’s address is keccak256(0xff ++ deployer ++ salt ++ keccak256(initCode)), with salt 0xcd981a9d15367d1195b6d88642ba07ad941149c31cffb6ffc7c1dc7fb38b2d4f and init-code hash 0x465adadad4c4a48f518137673deaa814b0fe6e1f07fd8661379743f4f31b8f8f. So the address is the code: anyone can deploy it, and whoever does puts exactly this code there. The first launch does it automatically. The factory refuses a launch whose stock has no live USDG pool at the fee tier given, a starting amount outside its bounds, or another Keel coin as the stock. Source: KeelFactory.sol and KeelCoin.sol; solc 0.8.26, optimizer 1000 runs, via-IR, Cancun. Status right now: checking…
How it was tested
Every property below runs on a private fork of live Robinhood Chain (anvil, started fresh at the newest block for each property). The real CREATE2 deployer deploys the factory, coins launch on real stock tokens, and every buy and sell routes through the real Uniswap pools, in the state the chain is in right now. Nothing is broadcast and nothing is mocked. Expected numbers are computed in the test from the formulas written out there, never by asking the contract, and every swap is held to the unit against Uniswap’s own quoter asked in the same state.
The last run: 14/14 properties and 347 checks passed against live state (01 Oct 2026), for the factory at 0x11AF7E0d65d4613587138d5ff0450C00a34F0023.
| # | Property | Checks |
|---|---|---|
| P1 | The factory lands at the address its code fixes, and nobody can initialise the implementation | 7 |
| P2 | A launch checks what it is given, and a good one starts the curve exactly as written NVDA has a live pool at every tier; the dead-tier refusal is covered by the multicall address | 22 |
| P3 | Buying with the stock itself: coins and shares to the unit, and the limit holds | 34 |
| P4 | Buying with ETH: the swap pays exactly what Uniswap quotes, the curve does the rest, nothing stays behind | 55 |
| P5 | Selling for the stock: shares to the unit, the reserve can always pay, the limit holds | 20 |
| P6 | Selling for ETH and for USDG: paid exactly what Uniswap quotes for the shares, nothing stays behind | 29 |
| P7 | Buying with USDG: the route is pulled, swapped and measured; allowances are cleared | 9 |
| P8 | A route must run from what is paid to the stock (or back), and amounts must be real | 16 |
| P9 | Random trading by three people, then everyone sells out: the books balance after every trade and the reserve always pays 18 buys, 9 sells; 0.295928700121382592 shares left as kept fees | 91 |
| P10 | The creator's half is paid to the creator, by anyone, once; only the creator can hand it on | 16 |
| P11 | Coins or shares sent to a coin by mistake cannot move its price | 7 |
| P12 | Rounding never pays out more than was paid in: buy-then-sell at every size, including one unit | 24 |
| P13 | A launch with a first buy: the launcher gets the coins in the same transaction; the factory keeps nothing | 8 |
| P14 | Gas: what each action costs on the real pools launchWithBuy 3525819, buyEth 336686, buyStock 127980, sellEth 335130, sellStock 120004, claim 95792 | 9 |
Then a sabotage sweep plants 23 bugs, one at a time, in copies of the contracts. Among them: the fee not taken, the creator paid from the reserve, a sale not capped at the reserve, a route checked at only one end, the router left with an allowance, a coin balance that moves the price. Each run requires the property named for its bug to fail. 23/23 were caught by the property named for them.
And in a real browser: headless Chrome drove these pages with a test wallet against a private copy of the live chain. It launched the first coin from the launch page (deploying the factory on the way), bought with ETH, USDG and the stock, sold for each of them, and claimed the creator’s fees. 10/10 journeys and 63 checks passed, and the harness read each outcome back from the chain itself (01 Oct 2026).
Risks
- Unaudited. The contracts are tested, not audited.
- Coins can lose almost all their value. The market always holds the stock it owes, but the price of a coin can fall a long way down its curve as people sell.
- Stocks fall. A coin is priced in shares, so the stock’s own moves carry straight through to its dollar price.
- Robinhood controls its stock tokens. Robinhood can pause, block or burn its tokenized stocks. While a stock is paused, every coin held in it can be neither bought nor sold. If it blocked a coin’s address, that coin’s market would be frozen.
- Thin pools cost more. Buying with ETH or USDG goes through the stock’s Uniswap pool. In a thin one, a big buy moves the price; paying in the stock itself avoids it.