Error Messages
Every revert string in the protocol, grouped by contract, with the condition that produces it. All are plain assert strings — there are no custom errors to decode.
Factory
| Message | Cause |
|---|---|
Protocol token not yet deployed | deploy_pair before the one-shot protocol deploy has run |
Not system deployer | deploy_protocol_token from any other address |
Protocol already deployed | Second call to deploy_protocol_token |
Incorrect fee | msg.value is not exactly deployment_fee |
Invalid name/symbol | Either string is empty |
Invalid salt | Anchor block field is zero |
Anchor not mined | Anchor is the current block or later |
Too late | Past anchor_block + INCLUSION_WINDOW |
Blockhash unavailable | Anchor more than 256 blocks back |
Blockhash mismatch | Salt bytes [8:16] do not match the anchor's hash prefix |
Vanity miss | Resulting address does not begin 0x24 — usually mining against the raw salt instead of keccak256(salt ‖ msg.sender) |
Only hook | moveDeployerToken from anything but the hook |
Index OOB | getDeployerTokenAt past the end |
BondingCurveTemplate
| Message | Cause |
|---|---|
Already initialized | Second initialize |
Unauthorized | initialize from anything but the factory |
Invalid token / Invalid deployer | Zero address passed |
Protocol path sends no fee | is_protocol=True with non-zero value |
Incorrect fee | User path value is not DEPLOYER_INITIAL_PAYMENT |
Below minimum | Fewer than 1 lot |
Not initialized | FLAG_INITIALIZED unset |
Invalid state | Already graduated or in refund mode |
Supply exceeded | Buy would push past 800,000 lots |
User limit exceeded | Post-trade balance above 36,000 lots |
Incorrect payment | msg.value does not match the quote — re-quote and retry |
Insufficient native for graduation | Curve balance below FIXED_LIQUIDITY_NATIVE at graduation |
Deployer locked | Deployer attempted to sell |
Insufficient tokens | Balance below the requested lots |
Cannot sell at floor | Supply is at 60,000 lots |
Insufficient contract balance | Curve cannot cover the sell proceeds |
Protocol curve cannot refund | initiate_refund on $LP24's curve |
Period not over | Less than 259,200 s (3 days) since deployment |
No refunds | Zero balance or no eligible lots |
Not refund mode | Claiming or sweeping outside refund mode |
Refund window closed | Past the 604,800 s (7 days) deadline |
Deployer cannot refund | Deployer attempted to claim |
Insufficient balance | Curve cannot cover the refund |
Refund window still open | Sweeping before the deadline |
Already swept | Terminal state already reached |
TokenTemplate
| Message | Cause |
|---|---|
Trading not enabled | Transfer while locked, and neither side is the minter |
Transfer to zero address | Zero recipient |
Insufficient balance / Insufficient allowance | Standard ERC-20 |
Approve to zero address | Zero spender |
Decreased allowance below zero | decreaseAllowance underflow |
Only minter | mint, burnFrom or enableTrading from a non-minter |
Exceeds max supply | Mint past 1,200,000,000 × 10⁹ (1.2B) |
Burn exceeds balance | Burn more than held |
Already initialized / Unauthorized | Re-init, or init from a non-factory |
Invalid minter / Invalid deployer / Invalid mint recipient | Zero address in initialize |
PrimaryHook & GraduationManager
| Message | Cause |
|---|---|
Only a factory curve may graduate | Factory.is_curve(msg.sender) is false |
Already registered | Token has already graduated |
Invalid deployer | Zero deployer at graduation |
Insufficient graduation funds | msg.value < GRADUATION_NATIVE |
Secondary native push failed | The SecondaryHook rejected the earmark push |
Pool sqrtPrice mismatch | Gnosis — the V3 pool was re-initialized at a different price |
Pool init not permitted | beforeInitialize without the transient gate set — a front-run attempt |
Unauthorized | A hook callback invoked by anything but the pool manager |
Exact-output buys disabled | Buy swap with amountSpecified > 0 |
Use processProtocolFees | distributeFees called on $LP24 |
No position | Token has not graduated |
No fees / Nothing to distribute | Pending balance at or below dust |
Nothing to process | Protocol balance at or below 1,000,000 wei |
No protocol token | $LP24 constant unset |
Pool not initialized | $LP24 pool has no price |
Pool too thin for any safe swap | The MEV cap leaves no room for any swap — wait for liquidity |
No deployer fees for protocol token | Withdrawal attempted on $LP24 |
Not deployer | Caller is not the current registered deployer |
CTO not enabled | Vote template not configured |
Protocol token cannot be CTO'd | Takeover attempted on $LP24 |
Send exact CTO fee | Fee is not exact — no overage refund |
Token not registered | Token has not graduated |
CTO vote already active | Clear the previous one with cancel_failed_cto |
Stake transfer failed | Insufficient allowance or balance for the stake |
No active vote / Not vote contract | Finalization from the wrong caller |
Invalid new deployer | Zero address would lock fees permanently |
Vote still active / Vote was finalized / Vote passed - must finalize | cancel_failed_cto preconditions |
SecondaryHook
| Message | Cause |
|---|---|
Only PRIMARY_HOOK | notifyReserved from any other address |
Wrong native amount | Earmark value is not exactly SECONDARY_NATIVE_RAW |
No secondary for PROTOCOL_TOKEN | $LP24 cannot pair with itself |
Token not registered in PrimaryHook | Token has not graduated |
Secondary exists | Pool already created |
Token funds not received | Contract holds less than 40,000,000 × 10⁹ (40M) |
No native earmark for token | Never funded by the PrimaryHook, or already consumed. Sending tokens yourself does not create an earmark. |
Exact-output disabled | Exact-output swap on a secondary pool |
amount0 zero | Degenerate initial price calculation |
CTOVoteTemplate
| Message | Cause |
|---|---|
Already initialized / Only hook | Re-init, or init from a non-hook |
Invalid token / Invalid hook / Invalid initiator | Zero address |
Initiator needs 5% of supply | Stake below 60,000,000 × 10⁹ (60M, 5% of supply) |
Not initialized | Acting on an uninitialized vote |
Voting ended / Vote period expired | Voting after close |
Amount must be > 0 | Zero-value vote |
Already voted | Use add_votes instead |
Must vote first | add_votes with no existing position |
Transfer failed | Insufficient allowance or balance |
Already ended / Vote still active | end_vote timing |
Too early to end early | Less than 3,600 s (1 hour) since opening |
Quorum not met / Majority not achieved | end_vote_early preconditions unmet |
Vote not ended / Already finalized / Vote did not pass | Finalization preconditions |
Withdraw next block | Flash-loan guard — withdrawal is locked to a block after close |
No tokens to withdraw | Nothing deposited, or already withdrawn |
TokenSocials & TokenVesting
| Message | Cause |
|---|---|
Not owner | set_socials or transfer_owner from a non-owner |
Not registered | Token has no socials record |
Unauthorized | register_token from anything but the factory |
nothing to release | Still within the cliff, or everything vested so far is already released |
token cannot be zero / beneficiary cannot be zero | Vesting constructor validation |
Two reverts worth recognising
Incorrect payment on a buy almost always means someone else's buy landed first and moved the price — re-quote and resubmit, it is not a bug. Pool too thin for any safe swap means the MEV cap has left no headroom on a nearly-empty pool; it resolves as liquidity returns and is not a permanent failure.