security: HIGH-1 — defer commit_pool_ordinal allocation to threshold-… - #147
Merged
Conversation
…cross `COMMIT_POOL_COUNTER` was bumped inside `execute_create_creator_pool` and the resulting ordinal pinned onto `PoolDetails.commit_pool_ordinal` at create time. The bluechip mint-decay formula in `calculate_and_mint_bluechip` then read this ordinal as its `x` input. Effect: paid commit-pool creation spam (junk pools that never cross threshold) permanently inflates `x` for every future legitimate threshold-crossing pool, decaying the protocol's bluechip mint schedule toward zero without the attacker ever crossing a threshold themselves. At a $1 launch creation fee, ~$33k in fees + gas (plus rotation across ~33k addresses to bypass the 1h per-address rate limit) suppresses the mint to zero permanently. Fix: allocate the ordinal at threshold-cross time inside `execute_notify_threshold_crossed`, immediately after the `POOL_THRESHOLD_MINTED` idempotency gate. Junk pools that never cross no longer consume an ordinal slot, so the decay input tracks real protocol activity (threshold crossings) instead of paid creation volume. Atomicity is preserved across failure paths: `POOL_THRESHOLD_MINTED` flips, `COMMIT_POOL_COUNTER` bumps, and `POOLS_BY_ID` updates ride in the same tx as the mint dispatch. A failed mint reverts all three; `RetryFactoryNotify` then re-allocates from the same prior counter value, so no slot is ever consumed by a failed cross. The existing zero-guard at the consumer in `calculate_and_mint_bluechip` becomes load-bearing — any future path that bypasses the new allocation site fails closed instead of inflating the mint to the base 500e6 amount. Migration: not required for fresh launch. If any deployment already has commit pools with non-zero `commit_pool_ordinal` from the pre-fix code, the notify handler will overwrite the field with the freshly allocated value at threshold-cross — since `POOL_THRESHOLD_MINTED` gates uncrossed pools, the overwrite is correct. https://claude.ai/code/session_019mxdB2vwswjgipCUq2x4Fu
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
…cross
COMMIT_POOL_COUNTERwas bumped insideexecute_create_creator_pooland the resulting ordinal pinned ontoPoolDetails.commit_pool_ordinalat create time. The bluechip mint-decay formula incalculate_and_mint_bluechipthen read this ordinal as itsxinput.Effect: paid commit-pool creation spam (junk pools that never cross threshold) permanently inflates
xfor every future legitimate threshold-crossing pool, decaying the protocol's bluechip mint schedule toward zero without the attacker ever crossing a threshold themselves. At a $1 launch creation fee, ~$33k in fees + gas (plus rotation across ~33k addresses to bypass the 1h per-address rate limit) suppresses the mint to zero permanently.Fix: allocate the ordinal at threshold-cross time inside
execute_notify_threshold_crossed, immediately after thePOOL_THRESHOLD_MINTEDidempotency gate. Junk pools that never cross no longer consume an ordinal slot, so the decay input tracks real protocol activity (threshold crossings) instead of paid creation volume.Atomicity is preserved across failure paths:
POOL_THRESHOLD_MINTEDflips,COMMIT_POOL_COUNTERbumps, andPOOLS_BY_IDupdates ride in the same tx as the mint dispatch. A failed mint reverts all three;RetryFactoryNotifythen re-allocates from the same prior counter value, so no slot is ever consumed by a failed cross. The existing zero-guard at the consumer incalculate_and_mint_bluechipbecomes load-bearing — any future path that bypasses the new allocation site fails closed instead of inflating the mint to the base 500e6 amount.Migration: not required for fresh launch. If any deployment already has commit pools with non-zero
commit_pool_ordinalfrom the pre-fix code, the notify handler will overwrite the field with the freshly allocated value at threshold-cross — sincePOOL_THRESHOLD_MINTEDgates uncrossed pools, the overwrite is correct.https://claude.ai/code/session_019mxdB2vwswjgipCUq2x4Fu