feat(contracts): M002 legacy seller claims migration - #982
Open
alexanderludwig wants to merge 9 commits into
Open
feat(contracts): M002 legacy seller claims migration#982alexanderludwig wants to merge 9 commits into
alexanderludwig wants to merge 9 commits into
Conversation
Unfreezes the deployed AntseedSellerRewardsPool after M001 activates. Claims are blocked twice today: the pool has no sellerClaimPolicy, and ANTS transfers are disabled with the pool (the transfer sender) never whitelisted. - policies/AntseedLegacySellerClaimPolicy: stateless claim policy that re-derives each seller's cumulative locked ANTS from EmissionsV2/V1 state (epochs 0..lastEpoch, mirroring claimSellerEmissions), releases releaseBps (default 1538 ~ 10/65) with optional linear vesting, and returns zero for sellers the wash-trading registry has proven (or the owner flagged). - script/migrations/M002LegacySellerClaims/Install.s.sol: keyless, idempotent install. Token owner whitelists the pool on ANTSToken (skipped when transfers are enabled or already whitelisted); pool owner deploys the policy and installs it. Guards: M001 active, pool discovered via V2, lastEpoch = gate.effectiveEpoch() - 1 >= MIGRATION_EPOCH, wash registry required with code. - scripts/deployments/m002.mjs: single install phase, signers deployer + sellerRewardsPoolOwner, states ready/active/not-applicable/invalid, records 002-legacy-seller-claims and updates current.json, finalize recovery, fork test that rehearses M001 then applies M002 on top. - m001.mjs: extract rehearseM001OnFork so later migrations can layer on an activated M001 fork; ledger.mjs gains a canonicalRoot override and only regenerates chain config from the repository ledger. - Tests: policy unit tests, M002 migration tests (frozen-before proof, release payout, wash trader NothingToClaim, resume paths, no-op rerun), runner tests for M002 classification/baseline/records. - Docs: README section, M002 runbook, .env.example, CHANGELOG.
This reverts commit f1f1b43.
…/m002-legacy-seller-claims
…/m002-legacy-seller-claims
alexanderludwig
force-pushed
the
contracts-update-all
branch
from
September 5, 2026 08:55
a2f8027 to
91c67a4
Compare
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.
Summary
Adds M002, the migration that unfreezes the deployed
AntseedSellerRewardsPoolafter M001 activates. Follows up on Shahaf'sAntseedLegacySellerClaimPolicysketch and his ask to add a wash-trading check.Claims from the pool are blocked twice today, and M001 deliberately leaves both alone:
pool.sellerClaimPolicy == 0NoSellerClaimPolicyAntseedLegacySellerClaimPolicy(sellerRewardsPoolOwner)ANTSToken.transferWhitelistwhile transfers are disabledTransfersNotEnabledsetTransferWhitelist(pool, true)(deployer= token owner)What's in it
policies/AntseedLegacySellerClaimPolicy.sol— stateless (the pool callsclaimableSellerRewardsas a view, so noclaims[seller]counter is possible). Re-derives each seller's cumulative locked ANTS from EmissionsV2/V1 state mirroringclaimSellerEmissions, treatscumulative − lockedas already released, paysreleaseBps(default 1538 ≈ 10/65) with optional linear vesting. Proven wash traders (isProvenWashTraderon the wash-trading registry, or owner flag) get 0; their ANTS stays in the pool.script/migrations/M002LegacySellerClaims/Install.s.sol— keyless (vm.startBroadcast(address)), idempotent, both steps skip what's already on chain. Guards: M001 active, pool discovered via V2,lastEpoch = gate.effectiveEpoch() − 1 ≥ MIGRATION_EPOCH, wash registry required with code.scripts/deployments/m002.mjs— singleinstallphase; statesready/active/not-applicable(V1-only testnet) /invalid(incl. a claim policy this ledger didn't install). Reads V2 fromlegacyEmissionsEscrow.legacyEmissions(); defaultsWASH_TRADING_REGISTRYto what M001 pinned intoPositionInit. Records002-legacy-seller-claims+current.json;finalizerecovers a crash-after-broadcast.--fork-testrehearses M001 then applies M002 on top.rehearseM001OnForkfor reuse;canonicalRootoverride; chain config only regenerates from the repo ledger (never from a temp rehearsal root).M002LegacySellerClaims/README.mdrunbook,.env.example, CHANGELOG.Test plan
forge test— 796/796 (incl. 15 new M002 migration tests: frozen-before proof for both reverts, released-share payout, wash traderNothingToClaim, both half-applied resume paths, no-op rerun, guard rejections)node --test scripts/deploy-contracts.test.mjs— 37/37 (6 new M002 tests)node scripts/validate-contract-deployments.mjs— clean; no gas-snapshot driftpnpm contracts:deploy -- M002 --network base-mainnet --fork-test(M001 → M002 on a pinned Anvil fork) — was started locally; still in progress at PR timeUsage