Hot Potato post-mortem: the floor held, the token didn't matter
Four days of TATER on mainnet, every trade on one chart. The proven floor did exactly what it promised and was irrelevant to the price the whole time. What went wrong, what held, and how I would build the next one.
- FROM
- Dax the Dev <[email protected]>
- SOURCE
- https://blog.skill-issue.dev/blog/hot_potato_postmortem/
- FILED
- 2026-10-29 21:00 UTC
- TIME
- 11 min read
- SERIES
- ZERA cryptography
- TAGS
Four days ago I launched a token with a hidden, proven floor on Solana mainnet with 0.5 SOL behind it. Today I closed it: pulled the liquidity, redeemed my own TATER through the vault at the floor, and closed the program. This post is the whole run on one chart, what each move on it was, a straight answer to “did it fail”, and the design I’d ship instead.
Short version. The cryptographic part did not fail once. The floor never dropped, every redemption paid out at the committed price, the reserve covered the supply at every epoch, and the last thing the program ever did was pay me 0.5634 SOL for 246.85 TATER under a proof. The token failed, in the ordinary way tokens fail: the market traded at 5× to 50× the floor from minute eight onward, so the only thing I had actually proven was irrelevant to anyone’s decision, and the parts that would have mattered (who gets the premium, who gets sniped, who provides liquidity) were either missing or were me.
The chart
Every transaction that touched the pool, reconstructed from the chain (the pool’s two token vault balances after each transaction; price is SOL in the pool over TATER in the pool). The green step is the vault’s backing ceiling, reserve over supply, which is the most the hidden floor could be. Log scale, because the run spans two orders of magnitude and a linear axis just shows a hairline floor and a spike.
- 1 launch snipes
- 2 operator issuance sells
- 3 retail ladder
- 4 sniper dump
- 5 top: 1.7 SOL buy
- 6 liquidity pulled
All 90 pool transactions as a table
| time (UTC) | side | TATER | SOL | price after | wallet |
|---|---|---|---|---|---|
| 10-25 19:38 | lp | 100.000 | 0.1500 | 0.00150 | operator |
| 10-25 19:39 | sell | 10.000 | 0.0136 | 0.00124 | operator |
| 10-25 19:39 | sell | 10.000 | 0.0113 | 0.00104 | operator |
| 10-25 19:39 | sell | 5.000 | 0.0050 | 0.00096 | operator |
| 10-25 19:39 | buy | 13.847 | 0.0150 | 0.00122 | operator |
| 10-25 19:40 | buy | 1.617 | 0.0020 | 0.00125 | ARFa…6ST2 |
| 10-25 19:40 | buy | 7.426 | 0.0100 | 0.00144 | ARFa…6ST2 |
| 10-25 19:43 | buy | 25.821 | 0.0500 | 0.00258 | operator |
| 10-25 19:46 | buy | 9.945 | 0.0297 | 0.00342 | FBfC…A8xc |
| 10-25 19:47 | sell | 3.043 | 0.0099 | 0.00313 | ARFa…6ST2 |
| 10-25 19:48 | buy | 7.072 | 0.0248 | 0.00388 | FMNq…SBqb |
| 10-25 19:49 | buy | 10.535 | 0.0495 | 0.00562 | DPs5…exBB |
| 10-25 19:49 | buy | 6.157 | 0.0396 | 0.00725 | 7qqe…iTkD |
| 10-25 19:53 | sell | 2.000 | 0.0139 | 0.00665 | ARFa…6ST2 |
| 10-25 20:03 | buy | 11.251 | 0.0990 | 0.01143 | HtbX…o9So |
| 10-25 20:10 | buy | 0.428 | 0.0050 | 0.01171 | He75…SEEP |
| 10-25 20:15 | buy | 6.829 | 0.1000 | 0.01789 | operator |
| 10-25 20:15 | buy | 2.049 | 0.0400 | 0.02072 | FLHg…Mtbk |
| 10-25 20:15 | sell | 1.320 | 0.0263 | 0.01883 | ARFa…6ST2 |
| 10-25 20:23 | lp | 26.801 | 0.5100 | 0.01893 | operator |
| 10-25 20:37 | sell | 11.037 | 0.1743 | 0.01314 | operator |
| 10-25 20:38 | sell | 13.245 | 0.1450 | 0.00912 | operator |
| 10-25 20:42 | sell | 0.428 | 0.0039 | 0.00903 | He75…SEEP |
| 10-25 20:45 | buy | 23.336 | 0.3000 | 0.01806 | operator |
| 10-25 20:45 | lp | 16.853 | 0.3060 | 0.01808 | operator |
| 10-25 20:47 | lp | 0.100 | 0.0018 | 0.01808 | operator |
| 10-25 20:47 | sell | 0.100 | 0.0018 | 0.01803 | operator |
| 10-25 21:12 | buy | 5.096 | 0.0995 | 0.02082 | EMXx…abLF |
| 10-25 21:27 | sell | 0.268 | 0.0056 | 0.02066 | ARFa…6ST2 |
| 10-25 21:37 | lp | 1.990 | 0.0413 | 0.02066 | EMXx…abLF |
| 10-25 21:39 | lp | 1.990 | 0.0413 | 0.02067 | EMXx…abLF |
| 10-25 21:43 | buy | 1.238 | 0.0262 | 0.02139 | EMXx…abLF |
| 10-25 21:53 | sell | 0.603 | 0.0128 | 0.02104 | ARFa…6ST2 |
| 10-25 22:00 | buy | 2.283 | 0.0500 | 0.02244 | E3rM…djAi |
| 10-25 22:01 | buy | 2.142 | 0.0500 | 0.02389 | E3rM…djAi |
| 10-25 22:01 | buy | 2.014 | 0.0500 | 0.02538 | E3rM…djAi |
| 10-25 22:01 | buy | 1.896 | 0.0500 | 0.02692 | E3rM…djAi |
| 10-25 22:01 | buy | 1.789 | 0.0500 | 0.02850 | E3rM…djAi |
| 10-25 22:06 | buy | 11.337 | 0.4000 | 0.04277 | 27Q8…mmh2 |
| 10-25 22:06 | buy | 2.209 | 0.1000 | 0.04679 | E3rM…djAi |
| 10-25 22:12 | buy | 2.022 | 0.1000 | 0.05098 | FTWM…Eyog |
| 10-25 22:19 | buy | 7.994 | 0.5000 | 0.07459 | DPQ6…D7JB |
| 10-25 22:33 | buy | 0.132 | 0.0100 | 0.07510 | DPQ6…D7JB |
| 10-25 22:33 | buy | 0.131 | 0.0100 | 0.07562 | DPQ6…D7JB |
| 10-25 22:33 | buy | 1.258 | 0.1000 | 0.08091 | DPQ6…D7JB |
| 10-25 22:41 | buy | 0.121 | 0.0100 | 0.08144 | He75…SEEP |
| 10-25 22:57 | sell | 0.061 | 0.0050 | 0.08118 | He75…SEEP |
| 10-25 23:02 | sell | 0.452 | 0.0366 | 0.07921 | ARFa…6ST2 |
| 10-25 23:16 | sell | 0.350 | 0.0277 | 0.07774 | EMXx…abLF |
| 10-25 23:35 | lp | 2.048 | 0.1610 | 0.07769 | EMXx…abLF |
| 10-25 23:43 | sell | 0.339 | 0.0264 | 0.07622 | ARFa…6ST2 |
| 10-25 23:43 | sell | 0.254 | 0.0195 | 0.07515 | ARFa…6ST2 |
| 10-25 23:44 | buy | 2.874 | 0.2388 | 0.08879 | EMXx…abLF |
| 10-26 01:40 | buy | 3.270 | 0.3283 | 0.10937 | 2Kb6…KUVZ |
| 10-26 03:31 | sell | 23.174 | 1.4405 | 0.03471 | FBfC…A8xc |
| 10-26 03:33 | buy | 1.389 | 0.0500 | 0.03660 | 27Q8…mmh2 |
| 10-26 03:34 | buy | 1.318 | 0.0500 | 0.03854 | E3rM…djAi |
| 10-26 03:41 | lp | 3.980 | 0.1546 | 0.03856 | EMXx…abLF |
| 10-26 03:42 | buy | 4.037 | 0.1700 | 0.04502 | EMXx…abLF |
| 10-26 04:28 | buy | 4.000 | 0.1980 | 0.05315 | FHpc…7wCT |
| 10-26 04:43 | buy | 0.148 | 0.0080 | 0.05350 | 4EHH…rsQf |
| 10-26 04:49 | buy | 1.172 | 0.0651 | 0.05633 | 8y69…d8vQ |
| 10-26 04:58 | buy | 0.060 | 0.0034 | 0.05648 | EMXx…abLF |
| 10-26 05:03 | buy | 0.890 | 0.0520 | 0.05879 | 4EHH…rsQf |
| 10-26 09:09 | buy | 1.589 | 0.0983 | 0.06329 | 5iD7…ggmT |
| 10-26 09:24 | sell | 10.535 | 0.5376 | 0.04063 | DPs5…exBB |
| 10-26 09:24 | sell | 2.049 | 0.0805 | 0.03766 | FLHg…Mtbk |
| 10-26 11:08 | buy | 24.554 | 1.7000 | 0.12331 | 8oUU…JMWQ |
| 10-26 15:20 | sell | 0.076 | 0.0095 | 0.12270 | ARFa…6ST2 |
| 10-26 15:21 | sell | 0.069 | 0.0085 | 0.12214 | ARFa…6ST2 |
| 10-26 15:21 | sell | 0.062 | 0.0077 | 0.12165 | ARFa…6ST2 |
| 10-26 15:22 | sell | 0.056 | 0.0069 | 0.12121 | ARFa…6ST2 |
| 10-26 18:47 | sell | 0.061 | 0.0074 | 0.12073 | He75…SEEP |
| 10-26 19:36 | sell | 0.125 | 0.0153 | 0.11976 | ARFa…6ST2 |
| 10-26 19:48 | sell | 0.094 | 0.0114 | 0.11903 | ARFa…6ST2 |
| 10-26 19:48 | sell | 0.070 | 0.0085 | 0.11849 | ARFa…6ST2 |
| 10-26 20:30 | sell | 0.039 | 0.0046 | 0.11819 | 4EHH…rsQf |
| 10-26 20:50 | sell | 3.270 | 0.3546 | 0.09676 | 2Kb6…KUVZ |
| 10-26 21:51 | sell | 0.211 | 0.0206 | 0.09558 | ARFa…6ST2 |
| 10-26 22:34 | sell | 5.172 | 0.4348 | 0.07232 | 8y69…d8vQ |
| 10-27 04:31 | buy | 0.099 | 0.0073 | 0.07268 | EMXx…abLF |
| 10-27 04:59 | buy | 0.401 | 0.0299 | 0.07418 | EMXx…abLF |
| 10-28 03:05 | lp | 2.868 | 0.2153 | 0.07411 | EMXx…abLF |
| 10-28 03:07 | sell | 10.411 | 0.6048 | 0.04482 | EMXx…abLF |
| 10-29 19:56 | lp | 0.355 | 0.0040 | 0.04508 | operator |
| 10-29 19:56 | lp | 0.102 | 0.0036 | 0.04510 | operator |
| 10-29 19:56 | lp | 0.046 | 0.0020 | 0.04510 | operator |
| 10-29 20:08 | lp | 17.394 | 0.7858 | 0.04506 | operator |
| 10-29 20:08 | lp | 10.684 | 0.4827 | 0.04499 | operator |
| 10-29 20:08 | lp | 18.284 | 0.8261 | 0.01779 | operator |
The six numbered moments:
- Launch snipes, 19:46 to 20:03 UTC on day one. Five wallets bought a combined 45 TATER within 25 minutes of pool creation, for 0.24 SOL total, through a sniping program (not Jupiter, not the widget). Prices 0.0034 to 0.0114 SOL per TATER, so already 2× to 7× the floor. I missed these in the chart on the launch post; more on that below.
- My issuance sells, 20:37 and 20:38. I ran the issuance script twice, selling 24.3 freshly minted TATER into a pool that held 55 TATER, and halved the price from 0.0189 to 0.0091. Disclosed at the time. Still the single dumbest operator action of the run, and the point where “the vault only sells when the market runs ahead” became something I had to put in code rather than in myself.
- The retail ladder, 22:00 day one to 01:40 day two. Fifteen buys from seven wallets, mostly 0.05 to 0.5 SOL each, walked the price from 0.021 to 0.109. The pool held under 3.3 SOL the entire time, so every 0.1 SOL buy moved it 4% to 8%.
- The sniper dump, 03:31 day two. The wallet from event 1 consolidated 23.17 TATER (its own 9.9 plus two other snipes) and sold in one transaction for 1.44 SOL. Cost basis under 0.1 SOL for all of it. The pool dropped from 0.109 to 0.035. A second sniper took 0.54 SOL out six hours later.
- The top, 11:08 day two. One wallet bought 24.55 TATER for 1.70 SOL at 0.123, 49× the backing ceiling. It still holds all of it.
- Liquidity pulled, today 20:08. I removed all three of my positions. I was the only liquidity provider of consequence; the pool went from 2.1 SOL to 0.002 SOL in three transactions, and the price line stops meaning anything.
Over the whole run the backing ceiling moved from 0.00167 to 0.00254 SOL per TATER. The market never came within 3× of it after the first ten minutes. That gap is the story.
Did it fail?
Split the question, because the two halves have opposite answers.
The vault and the proofs: no. Five ratchets, each with a Groth16 proof that the
new floor commitment is at least the old one and that the live reserve covers the live
supply. Two shielded redemptions (1 TATER on launch day as a check, 246.85 today),
each one a proof opening the floor commitment without revealing it, each one paid
exactly x × F. Light’s compressed notes, the nullifier set, the owner binding added
on launch night: all of it ran on mainnet without an incident. If you want the
sentence from the first post, “the floor’s value stays secret and everyone can still
verify it never went down and the reserve covers everyone,” that sentence was true at
every block for four days, and the final redemption transaction is the receipt.
The token: yes, and in a way the proofs could never have prevented. A floor at 0.0025 under a market at 0.05 to 0.12 is a promise about a world nobody was trading in. Three things followed from that gap, and all three were visible by hour three:
- The premium went to whoever was fastest, not to the reserve. The pool collected
9.5 SOL of swap volume at 30 bps, so about 0.03 SOL in fees, which came to me as
the LP. The two snipers who exited took 1.9 SOL of realized profit out, and five
other wallets that flipped took another 0.7 SOL. The vault, the thing that
is supposed to grow, received exactly the 0.32 SOL I put in from my own two
issuance sells, and nothing else, ever.
mint_at_premium, the mechanism that was meant to route a running premium into the reserve, never went live on mainnet: the config transaction failed withInstructionFallbackNotFound(I built it against a stale discriminator) and I let the launch post say “live when the widget shows a mint price” instead of fixing it that night. On devnet it works. On mainnet it was a paragraph. - The only liquidity was mine. Three positions, 100% of the pool. Which means the price chart above is not a picture of what TATER was worth; it is a picture of what a 2 SOL constant-product pool does when 0.1 SOL arrives. When I left, the market left with me. A token whose market exists at the operator’s pleasure is not a market, whatever its floor is proven to be.
- Hidden F bought nothing. The argument for hiding the floor is that a public one lets people size trades against it. That matters when the market is near the floor. At 20× above it, the hidden number was a curiosity. I spent most of the engineering time on the part of the design that mattered least for this run.
So: a correct cryptographic mechanism bolted to an uncorrected market. The mechanism proved the floor. Nothing made the floor relevant.
How the closure went, and what it cost whom
I want the numbers in one place, because “the vault always takes it back” was the pitch and the closure is where that gets tested.
| SOL | |
|---|---|
| Deposited into the vault (0.5 at launch, 0.32 from issuance proceeds) | 0.8224 |
| Paid out by the vault to me, under proof, at F = 0.002282 | 0.5657 |
| Left in the vault’s reserve account | 0.2567 |
| Floor refunds to remaining holders, paid by hand from the authority wallet (in progress) | 0.172 |
| Added to the pool as liquidity over the run | 0.9678 |
| Withdrawn from the pool today | 2.0946 |
| Program rent reclaimed on close | 2.5239 |
Everyone who still holds TATER: 75.4 tokens, 74.3 of them across seven wallets that
paid 3.5 SOL for them (mostly in events 3 and 5), plus 1 TATER someone shielded into
a private note on day two and never redeemed. At the floor they were owed 0.172 SOL, and the
reserve had 0.257 SOL, so the solvency invariant held to the end. Then I closed the
program, and a closed Solana program cannot be redeployed under the same id, so the
0.257 SOL in the reserve is now locked in an account nobody can sign for. The holders
can no longer redeem through the vault, and neither can whoever holds that shielded
note. That is the one place in this story where the promise was broken, it was broken
by the shutdown rather than by the market, and it was my decision. So I’m making good
on it by hand: every wallet still holding TATER is being paid its floor value, 0.002282
SOL per token, directly from the authority wallet 6SnLV…Ljkz. That is 0.172 SOL
across the seven holding wallets. The transfers are being processed now and each one
will show in the authority wallet’s history. If you are the one who shielded 1 TATER
into a note on day two, there is no wallet to match it to; reach out and I’ll settle
it the same way. The honest accounting is still that the floor never paid out through
the vault to anyone but me, and the refunds exist because the shutdown took that exit
away.
The chart in the launch post was missing the five snipes and the dump. The RPC returned those transactions as “version 1” and my parser asked for version 0, so my own analytics quietly skipped the only trades that mattered. Fixed, and the chart above has all 90.
What I’d build instead
Each of these is a direct answer to one of the failures above.
The pool is the reserve. Don’t run a vault beside a pool. Run a single-sided
concentrated position owned by the vault PDA, with the quote side set at the floor:
the vault’s SOL is the bid at F, visible on every DEX aggregator, and every buy
above F deposits straight into the position the vault controls. The premium then
accrues to the reserve by construction, which is what mint_at_premium was trying to
do with a rate limiter and a second account. DAMM v2 supports exactly this shape.
Launch at the floor, not above it. Seed the first liquidity at 1× to 1.5× backing with depth proportional to the reserve, not 100 TATER and 0.15 SOL. The whole reason a floor is interesting is that the market occasionally touches it; a launch that opens 8× above the floor has decided in advance that it won’t.
Make sniping expensive. DAMM v2 has a fee scheduler: open at a 50% fee decaying to 30 bps over the first hour, with fees routed to the vault position. The five launch buys that cost 0.24 SOL would have put most of that in the reserve instead of in the sniper’s cost basis. Alpha vaults exist for the same reason. I used neither because I was “keeping it simple,” and simple cost 1.9 SOL in sniper profits.
No operator sells, ever. The authority should not be able to hold or sell the token. Issuance is the permissionless mint and nothing else, and the mint must be live and tested on mainnet before the pool is created, with the config transaction in the same deploy script as the pool creation so one cannot exist without the other.
Design the exit before the entry. The program needed a wind_down instruction:
authority pauses issuance, publishes the floor opening (hiding it no longer serves
anyone), opens a redemption window of N days during which redeem needs no operator,
and only after the window can the authority sweep what’s left and close. I had no
such path, so closing meant choosing between leaving 2.5 SOL of rent locked up
indefinitely or stranding 0.26 SOL of other people’s exit. Neither should have been a
choice. Write the shutdown first.
Hide the floor only when it matters. Keep the commitment scheme, it works, but make the opening public whenever spot is more than some multiple above backing. Below that multiple the hidden value protects the reserve from being sized against; above it, it only protects me from questions.
Analytics that can’t miss a trade. Ask the RPC for the newest transaction version it supports, cross-check reconstructed trades against the pool’s actual vault balances, and alarm on any gap. A dashboard that silently drops the sniper transactions is worse than no dashboard.
Still outstanding from the first post: a real multi-party ceremony for the circuits, an audit, and a note-transfer circuit. None of that changed. None of it would have changed this chart either.
What I’m keeping
The shielded-note stack held under real money with strangers poking at it, including a sniping bot and at least one person who worked out how to shield micro-amounts to probe the note tree. Owner-bound redemptions, the operator-proved redeem path, the in-browser claim, the Light v2 CPI shape, the event parser: all of that moves straight into Zera and Vanta as intended. The devnet playground at /tater/devnet stays up with the full system, including the mint that mainnet never got.
What I’m dropping is the idea that a proof about the floor is a product. It’s a component. The product is the market around it, and this run had none of its own.
Addresses for anyone who wants to check the above: program
4d3CvyKeyH42e1HECTpLeKYyRUP376zYuZ1QBUnTPZnh (closed), vault
G81nMdxMiiDpKGkn2CqSXfnXHGoBErCy6cBZinBS6ZTK, pool
CPycDZCCtHnBKtkuEx4naBVKfGxT37BFYpJQac74KxgU, authority
6SnLVaudzicobvWrDeEvTaJhuaJ8RgNigb2JEMRcLjkz. The final redemption is
56yj8A…CxrH
and the claim is
TSmuiG…Vh2j.