Documentation
How a dead bonding curve gets brought back, and who gets what when it does.
This page describes the whole system: the curve mathematics, every contract call, the exact settlement arithmetic, the fees, and the things that can go wrong. It is written to be checkable — every number here is either read from a contract or derived from one, and where something is assumed rather than verified, it says so.
What Necropolis is
Necropolis is two things: a register of every Pons V2 bonding curve on Robinhood Chain that stopped trading before it graduated, and an escrow that lets people pool the ETH needed to finish one.
It is not a launchpad. The protocol never mints a token and never starts a curve. Its entire inventory is produced, for free, by the launchpads it sits downstream of — and that inventory grows every day the chain runs.
The project has one token, $NECRO, launched on Pons like everything else it indexes. The protocol's contracts never touch it. See The token.
A crypt is a single-purpose escrow contract deployed over one abandoned curve. People send ETH to it. If enough arrives to close that curve's gap, anyone can trigger the purchase that forces graduation, and the crypt distributes what comes back. If not enough arrives before the deadline, every wei is refundable. There is no third outcome.
Dying on a curve
A Pons V2 launch mints a fixed supply of 1,000,000,000 tokens straight into its own bonding curve contract. Traders buy and sell against that curve — not against any AMM — until the curve has collected its graduation threshold of the quote asset. For native ETH-quoted launches that threshold is 4.2 ETH.
When the threshold is reached, the curve is swept: the collected ETH and the reserved token supply seed a Uniswap v4 pool whose liquidity position is permanently locked, behind the Pons hook. That is graduation, and it is the moment the token acquires a market.
Before that moment there is no pool at all. The only venue is the curve's own sell side. On a launch nobody is watching any more, that is not a market — it is a formality.
So a curve that stops trading at, say, 3.90 of its 4.2 ETH leaves behind three things:
- Locked ETH. The 3.90 ETH sits in the curve contract. It does not move until someone pushes the curve past the threshold.
- Trapped holders. Everyone who bought holds a token with nowhere to sell it. Not because they are down — because there is no venue.
- Unsold supply. The remaining slice of the curve, which nobody bought.
Across every Pons launch to 4 September 2026: 207,893 launched, 3,228 graduated. That is 1.55%. The other 204,665 are in the state described above.
The two sides
Two groups are stranded on opposite sides of the same dead contract, and neither can act alone.
| Has | Wants | Puts in | Gets out | |
|---|---|---|---|---|
| Trapped holder | Tokens, no venue | An exit that does not exist | ETH bounty | A permanently liquid pool to sell into |
| Reviver | ETH, no position | The unsold slice of the curve | ETH pledge | Recovered tokens + the bounty, pro-rata |
The bounty is the part people find surprising, so it is worth stating plainly: a bounty poster buys an exit, not a position. They get no claim on the recovered tokens. What they get is that their existing bag acquires a market for the first time. Whether that is worth paying for is their judgement, and nothing in the contract makes it for them.
The curve
Everything Necropolis ranks and prices comes from one relation. A Pons curve books collected
reserve R against tokens sold s as:
R(s) = k · s² / 2 with R(CURVE_SUPPLY) = THRESHOLD
which inverts to
s(R) = CURVE_SUPPLY · √(R / THRESHOLD)
With CURVE_SUPPLY = 800,000,000, POOL_SUPPLY = 200,000,000 and
THRESHOLD = 4.2 ETH. From this, three quantities follow.
Gap
What the curve still has to collect. Read straight off the contract, no assumptions:
gap = THRESHOLD − reserveCollected
Required in
What a reviver must actually send. The curve books reserve net of its 1% trade fee, so the input is grossed up:
requiredIn = ceil( gap × 10000 / (10000 − tradeFeeBps) ) // tradeFeeBps = 100
// the factory adds a small buffer on top when it opens a crypt,
// so a sell landing mid-flight does not strand it one wei short
targetIn = requiredIn × (1 + bufferBps / 10000) // bufferBps = 50
Any pledged ETH the buy does not consume is returned pro-rata at claim time, so over-padding costs nothing but gas.
Recovered tokens
Closing the gap buys the entire remaining curve supply:
revivalTokens = CURVE_SUPPLY − s(reserveCollected)
Worked examples
| Reserve | Gap | Required in | Tokens recovered | Avg price / token |
|---|---|---|---|---|
| 4.10 ETH | 0.10 | 0.1010 | 9.6M | 1.05 × 10⁻⁸ |
| 3.90 ETH | 0.30 | 0.3030 | 29.1M | 1.04 × 10⁻⁸ |
| 3.00 ETH | 1.20 | 1.2121 | 123.6M | 9.81 × 10⁻⁹ |
| 2.50 ETH | 1.70 | 1.7172 | 182.8M | 9.39 × 10⁻⁹ |
Note the direction: a wider gap buys tokens at a lower average price, because you are buying further down the curve — but it is more capital at risk on a token that already failed once. That tradeoff is the whole product, and Necropolis does not pick a side of it.
The 800M / 200M supply split is inferred from published figures, not read from a deployed contract. The gap and the required-in figures above do not depend on it — they come from the threshold and the fee, both readable on-chain. But anything comparing the reviver's entry price to the pool's opening price does, and a different split moves that comparison a long way.
Until the split is confirmed against a sample of graduated curves, Necropolis publishes the gap and declines to publish a spread multiple. If you see one quoted anywhere, it is not from us.
Lifecycle
Five stages. Every one of them is a call anyone can make — there is no privileged operator anywhere in the path.
Entomb
Anyonefunction openCrypt(address ponsFactory, address curve, uint64 lastTradeAt)
external returns (address crypt)
Deploys a CREATE2 clone that exists only for this one curve. The salt is the curve address, so the crypt address is derivable off-chain before it exists.
The factory refuses unless all of these hold: the curve came from a
recognised Pons factory; it is quoted in native ETH; it has not graduated; its gap is at or
under maxGap; and it has had no trade for at least
dormancyPeriod.
That last gate is deliberate. A curve that is still trading does not need reviving, and a
contract that let anyone open a crypt over a live launch would be a coordination tool for
front-running other people's launches. lastTradeAt is supplied by the caller
because Pons curves do not expose it as a view; the check is written in the conservative
direction, so overstating recency can only make a crypt harder to open.
Bounty
Trapped holdersfunction postBounty() external payable
Adds ETH to the pot paid out to whoever closes the gap. Tracked in
bountyOf[msg.sender], on a ledger entirely separate from pledges.
A bounty poster has no claim on the recovered tokens and cannot take a pledger's share. If the crypt collapses, the full bounty is refundable.
Pledge
Reviversfunction pledge() external payable // min 0.001 ETH
Puts up the ETH that actually closes the gap. Pledgers own the recovered tokens and split
the bounty. Tracked in pledgeOf[msg.sender].
Pledging past targetIn is allowed and is not wasted — the surplus comes back
pro-rata at claim time. It also raises the odds the buy clears the threshold if someone
sells into the curve first.
Exhume
Anyonefunction exhume(uint256 minTokensOut) external
The crypt re-reads the live requirement rather than trusting the
targetIn it opened with, because a sell into the curve since then can have
widened the gap. If pledges no longer cover it, this reverts and the crypt stays open for
more pledges.
Otherwise it buys the remainder of the curve in one transaction, and then:
if (!curve.graduated()) revert GraduationDidNotFire();
This is the load-bearing line of the whole protocol. A stale gap, a sell landing in the same block, a Pons accounting difference — any of them and the entire transaction unwinds and the escrowed ETH is untouched. The crypt cannot half-spend.
Permissionless on purpose: revival must never depend on the crypt's opener still being around.
Settle
Pledgersfunction claim() external // after a successful exhume
function collapse() external // mark a crypt dead after its deadline
function refund() external // take your ETH back from a collapsed crypt
Graduation has fired, so liquidity is now locked in a Uniswap v4 pool behind the Pons hook
and the trapped holders have a venue. Pledgers call claim() to take their
tokens, bounty share and any unspent pledge.
If the deadline passes without a revival, anyone calls collapse(), and both
pledgers and bounty posters call refund() for the full amount they put in.
Settlement arithmetic
Exactly what claim() pays, in the order the contract computes it.
// at exhume, once graduation is confirmed
recovered = tokens the curve actually sent
tokensNet = recovered − recovered × protocolFeeBps / 10000
bountyNet = totalBounty − totalBounty × protocolFeeBps / 10000
unspentPledge = totalPledged − amountSpent
// at claim, for a pledger p
tokenShare = tokensNet × pledgeOf[p] / totalPledged
bountyShare = bountyNet × pledgeOf[p] / totalPledged
refundShare = unspentPledge × pledgeOf[p] / totalPledged
A full example
A curve sitting at 3.90 ETH. Gap 0.30, required in 0.3030. One holder posts a 0.40 ETH bounty. Alice pledges 0.20, Bob pledges 0.15 — 0.35 total, which covers it.
| Pledged | Share | Tokens | Bounty | Unspent back | |
|---|---|---|---|---|---|
| Alice | 0.2000 | 57.1% | 16.2M | 0.2229 | 0.0269 |
| Bob | 0.1500 | 42.9% | 12.2M | 0.1671 | 0.0201 |
| Treasury | — | 2.5% | 0.73M | 0.0100 | — |
| Holder | — | — | — | — | a liquid pool |
Figures are rounded for readability; the contract works in wei and integer division, and the only thing that can remain in a crypt after everyone has settled is a couple of wei of rounding dust. There is a fuzz test that asserts exactly that.
Fees
| Fee | Rate | Taken from | Charged by |
|---|---|---|---|
| Curve trade fee | 1.00% | The quote leg of the revival buy | Pons, not Necropolis |
| Protocol fee | 2.50% | Recovered tokens and bounty | Necropolis |
| Buffer | 0.50% | Padding on the buy — returned if unused | Nobody |
| Opening a crypt | 0 | — | Gas only |
| Pledging, bounty, refund | 0 | — | Gas only |
The protocol fee is hard-capped in the contract at MAX_PROTOCOL_FEE_BPS = 500
(5%). That ceiling is a constant, not a setting — no owner call can exceed it.
A crypt keeps the terms it opened on. Changing a parameter affects crypts opened after the change and nothing already live, so nobody's fee can be raised while their ETH is escrowed.
Parameters
- Graduation threshold
- 4.2 ETH Pons constant for native-quoted launches
- Max gap
- 2.0 ETH Wider than this is a launch, not a revival
- Dormancy
- 7 days Zero curve trades before a crypt may open
- Crypt duration
- 14 days Then it can be collapsed and refunded
- Protocol fee
- 250 bps Hard cap 500 bps
- Minimum pledge
- 0.001 ETH Contract constant, keeps the ledger clean
Safety model
- The buy is all-or-nothing.
exhume()assertscurve.graduated()after the purchase. If graduation did not fire, the whole transaction reverts and nothing was spent. This is a revert, not a policy. - Two ledgers, two refund paths, no overlap. A bounty poster can never take a pledger's tokens; a pledger can never take another pledger's refund.
- Settlement is pull-based and there is no loop over contributors anywhere. No number of pledgers can make a payout run out of gas or brick the contract.
- No admin key over user funds. The factory owner can recognise Pons factories and set parameters for future crypts. There is no function, anywhere, that lets anyone move escrowed ETH or claimed tokens.
- Reentrancy guarded on every function that moves value, with state written before any external call.
- The ABI seam is one file. Every read Necropolis performs on a foreign Pons
contract goes through a single
PonsAdapterlibrary, so upstream ABI drift is a one-file patch rather than an audit-wide change. - Crypt addresses are CREATE2-derived from the curve address, so you can compute and verify a crypt's address independently of any front end — including this one.
The two functions that move your money are exhume() and claim(), and
together they are about sixty lines. Read them on the explorer before you send anything —
here or anywhere else on this chain.
What can go wrong
Listed because they are real, not because the list is required.
- The holders you just freed. Graduation hands every trapped bag its first venue. Some of those holders have been waiting months to sell, and they can sell into the pool you created.
- Snipe tax. Pons applies a decaying tax on buys immediately after graduation. It does not touch the reviver's entry, which happened on the curve — but it does affect what trading around that moment costs.
- The gap can widen. A sell into the curve between your pledge and the exhume pushes the reserve back down. The contract handles this by reverting rather than half-spending, but it means a crypt can sit covered and then stop being covered.
- The token already failed once. Reviving a curve creates a market. It does not create demand, and nothing about graduation makes a dead project alive.
- Capital is locked until settlement. Pledged ETH cannot be withdrawn while a crypt is open — only after a successful exhume, or after the deadline and a collapse.
- Unaudited. See below.
Open unknowns
Things that are not settled yet, stated here rather than buried.
| Item | Status | What it affects |
|---|---|---|
| Pons V2 ABI | Unconfirmed | Every selector is a compile-time assumption until probed against a live curve. This is the single largest unknown in the system. |
| Curve supply split | Inferred | 800M / 200M is derived from published figures. Gap and required-in do not depend on it; any entry-vs-pool price comparison does. |
| Audit | None yet | Foundry suite covers the happy path, collapse-and-refund, the gap-widens-mid-flight revert, and a fuzz test asserting the crypt drains to dust. That is testing, not an audit. |
| Snipe tax model | Not modelled | Known to exist, not yet quantified in the interface. |
Architecture
Four layers. There is no custody anywhere in the path: the only component that ever holds funds is the crypt contract for a given curve, and the only way out of it is settlement.
| Layer | What it does | Why it is built that way |
|---|---|---|
ContractsNecropolisFactoryNecropolisCryptPonsAdapter |
One EIP-1167 clone per grave, deployed with CREATE2. Pledge, bounty, exhume and settlement all happen here. | Pull-based settlement with no loop over contributors, so no number of pledgers can brick a payout. Every Pons read goes through one adapter library, so upstream ABI drift is a one-file patch. |
| Indexer | Backfills the Pons launch log, then re-reads live curve state on a loop and reclassifies every grave into warm, cooling or cold. | Curve reads batch through multicall3 in chunks of 400, and trade recency comes from one windowed log scan across every curve at once. A full refresh of 30,000 curves is roughly 75 round trips rather than 90,000. |
| Storage & API | SQLite behind a read-only HTTP API that serves the register, a grave's detail and the payoff for a given pledge. | One covering index for the register's only hot query. Wei is stored as text and converted to integers at the boundary, so no amount ever passes through a float. The API holds no key and relays no transaction. |
| Web | The register, the plot map and the crypt panel. | The payoff figures use the same arithmetic as claim(), so the number shown
before signing is the number the contract pays. |
If this site went offline, nothing would be lost: every grave, crypt and contribution is recoverable from the chain alone, and every contract call above can be made directly from a block explorer.
Contract reference
NecropolisFactory
| Function | Who | Does |
|---|---|---|
openCrypt(factory, curve, lastTradeAt) | Anyone | Deploys a crypt over a dormant curve |
cryptOf(curve) | View | The crypt for a curve, or zero |
page(offset, limit) | View | Paginated crypt list |
recogniseFactory(factory, ok) | Owner | Allow-lists a Pons factory |
setParams(...) | Owner | Terms for future crypts only |
NecropolisCrypt
| Function | Who | Does |
|---|---|---|
pledge() | Anyone | Fund the gap; owns recovered tokens |
postBounty() | Anyone | Pay for the exit; no token claim |
exhume(minTokensOut) | Anyone | Buy the remainder, assert graduation |
claim() | Pledgers | Tokens + bounty + unspent, pro-rata |
collapse() | Anyone | Mark an expired crypt dead |
refund() | Contributors | Full refund from a collapsed crypt |
remaining() | View | ETH still needed, live |
revivable() | View | Whether exhume() would pass now |
Phases
| Phase | Meaning | What works |
|---|---|---|
Open | Accepting contributions | pledge, postBounty, exhume, collapse after deadline |
Exhumed | Graduation fired | claim |
Collapsed | Deadline passed, no revival | refund |
The token
$NECRO is launched on Pons, on the same bonding curve as every token in the register: fixed supply of 1,000,000,000, graduating to a permanently locked Uniswap v4 pool at 4.2 ETH. If it never graduates, it becomes grave #1 — and the first crypt the protocol opens.
| Contract | posted here at launch |
| Supply | 1,000,000,000 — fixed by Pons, no mint function |
| Distribution | The Pons curve. No presale, no private round, no allocation outside the curve. |
| Dev wallet | Disclosed at launch, with whatever it bought on the curve |
What holding it does and doesn't do
- It is not a claim on escrowed funds. ETH in a crypt belongs to that crypt's
pledgers and bounty posters, and only
claim()orrefund()can move it. No token balance changes that. - It is not a share of protocol fees. The 2.5% protocol fee goes to the treasury. Nothing in the contracts routes any of it to token holders.
- It is not required to use the protocol. Anyone can pledge, post a bounty or exhume without ever holding it.
- It is a token on an open curve, with every risk that implies. It can go to zero. Nothing on this site is a reason to buy it.
Planned
What the token is being built toward. None of it is live, and none of it is a promise of value — each piece ships in verified contracts before this page calls it live.
| Piece | What it would do | Status |
|---|---|---|
| Resurrection Fund | Part of treasury revenue posts bounties on the graves that staked $NECRO votes for. Votes use staked, time-locked tokens — not balance snapshots, which a flash loan could fake. | Planned |
| Buyback | Part of treasury revenue buys $NECRO on the open market. Early on, most treasury revenue will be the token's own trading fees, not revival fees — it is stated here so nobody has to work that out. | Planned |
| Lower revival fee | Staked $NECRO reduces the protocol fee on a pledger's claim. | Planned |
| Grave alerts | Near-miss curves and filling crypts, pushed to stakers. | Planned |
If any of this changes — a fee share, governance, anything — it will be in the contracts first, verified on Blockscout, and written here before it is announced anywhere else.
The only valid $NECRO contract is the one on this page and pinned on @necropolisfund. Copycat tokens with the same name and ticker appear within minutes of every launch on this chain. If an address is not here, it is not ours.
How to buy
Four steps. The only one that can go wrong in an expensive way is the last.
- Add Robinhood Chain to your wallet. The button on the
register page does it in one click. Manually:
Network name Robinhood ChainRPC URL https://rpc.mainnet.chain.robinhood.comChain ID 4663Currency ETHExplorer https://robinhoodchain.blockscout.com - Bridge ETH in. The canonical route is the Arbitrum bridge — about ten minutes in, about seven days out. Third-party bridges such as Relay and Across are faster in both directions.
- Buy on Pons using the contract address from this site — not from a search result, a reply, or a DM.
- Check the address matches, character by character, against the one on this page and pinned on @necropolisfund. Copycats with the same name and ticker appear within minutes of every launch.
Addresses
| Contract | Chain | Address | Status |
|---|---|---|---|
| NecropolisFactory | Robinhood Chain · 4663 | not deployed | Pending |
| NecropolisCrypt (impl) | Robinhood Chain · 4663 | not deployed | Pending |
| $NECRO token | Robinhood Chain · 4663 | not launched | Pending |
| Pons V2 meme hook | Robinhood Chain · 4663 | 0xe5e7…e044 | Pons |
Contracts will be verified on Blockscout before this table is filled in. On a chain with a documented scam wave, an unverified escrow contract is one nobody should send ETH to — and that includes this one. If this table still says "not deployed", nothing is live, and any address claiming to be Necropolis is not.
Glossary
| Bonding curve | The contract a Pons launch trades against before it has an AMM pool. Price rises as supply sells. |
| Graduation | The moment a curve reaches its threshold, is swept, and seeds a permanently-locked Uniswap v4 pool. |
| Gap | Threshold minus reserve collected. What is still missing. |
| Grave | A curve in the register: dormant, ungraduated, ETH-quoted. |
| Crypt | The escrow contract deployed over one grave. |
| Pledge | ETH put up to close the gap. Owns recovered tokens. |
| Bounty | ETH put up by a trapped holder to make revival worth triggering. No token claim. |
| Exhume | The transaction that buys the remaining curve and forces graduation. |
| Collapse | Marking an expired crypt dead so refunds can be taken. |
| Warm / Cooling / Cold | Register heat tiers by gap: ≤ 0.5 ETH, ≤ 2 ETH, beyond. |
FAQ
Does Necropolis hold my funds?
Your ETH sits in the crypt contract for that specific curve, not in any account controlled
by us. There is no function that lets anyone withdraw it other than the settlement paths:
claim() after a successful revival, or refund() after a collapse.
The API is read-only, holds no key and relays no transactions.
What happens if the gap never closes?
After cryptDuration (14 days by default) anyone calls collapse(),
and every pledger and bounty poster can call refund() for the full amount they
put in. No fee is taken on a collapse.
Can a crypt be opened over a token that is still trading?
No. The factory requires zero curve trades for at least dormancyPeriod. This is
enforced in openCrypt(), not by policy.
Why would a trapped holder pay a bounty instead of just waiting?
Because waiting has no mechanism behind it. Pre-graduation there is no pool, so there is no price at which they can exit at size. A bounty converts a stuck bag into a bag with a venue. Whether that trade is worth it depends entirely on the size of their position against the size of the bounty, and that is their call to make.
Do I get a discount on the tokens?
You buy the unsold slice of the curve at the curve's own prices — there is no discount mechanism and no special access. Whether that slice is cheap relative to where the pool opens depends on the supply split, which is not yet verified. See the note in The curve.
What stops someone front-running the exhume?
Nothing stops a third party from buying the remaining curve themselves — and if they do,
graduation fires anyway and the crypt's pledgers simply get a full refund on collapse. The
contract's job is to make sure that outcome is clean, not to prevent it. The
minTokensOut parameter on exhume() is a slippage floor for the
caller.
Does holding $NECRO give me anything from the protocol?
No. It is not a claim on any crypt's escrowed ETH, not a share of protocol fees, and not needed to use the protocol. See The token.
Is Necropolis affiliated with Pons, Uniswap or Robinhood?
No. It reads their public contracts and is unaffiliated with all three. Nothing on this site is endorsed by any of them.