Repository navigation
Conversation
Adds contrib/snapshot/export_snapshot.py and a `make snapshot-export` target to produce a `zetacored export` genesis JSON for testnet or mainnet. Reuses download_snapshot.py for the snapshot fetch and skips the node sync that the devnet fork needs, since export reads committed state straight from the data dir. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U888hFEu3YMDT9dnpcQ3MS
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Want higher recall? High effort reviews run extra passes and find more bugs. A team admin can switch effort levels in the Cursor dashboard.
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 8edf120. Configure here.
Stage 2 of the migration snapshot: a pure, deterministic pass over a `zetacored export` that attributes each account's native ZETA (liquid + slashing-aware staked + unbonding) and routes module accounts, pinned contracts, and the zero address into a remainder that mints to the migration multisig. Emits a Postgres-ready CSV, schema, and a human-readable audit copy, with supply invariants enforced. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U888hFEu3YMDT9dnpcQ3MS
|
!!!WARNING!!! Be very careful about using Only suppress a single rule (or a specific set of rules) within a section of code, while continuing to scan for other problems. To do this, you can list the rule(s) to be suppressed within the #nosec annotation, e.g: /* #nosec G401 */ or //#nosec G201 G202 G203 Pay extra attention to the way |
Two-stage design, exact export + compute commands for testnet/mainnet, flags, output exploration, and the contract-vs-EOA detection approach so the team can run the snapshot and try attribution ideas. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U888hFEu3YMDT9dnpcQ3MS
…ch pin Contracts hold native ZETA that no keypair can claim on Solana, so their balances have to route to the remainder instead of being attributed. The addresses were already pinnable one at a time; passing sixteen of them on the command line was not something you want to get right by hand. - --pin-file reads them from a file: # comments, blank lines skipped, first whitespace field per line is the address, so a TSV works as-is. - The mainnet list is committed as contrib/snapshot/pins_mainnet.txt: the 16 contracts from the top-500 eth_getCode scan at height 17619782, 9,351,261 ZETA. Mainnet only; a testnet run passes no pins. - Report what each pin actually caught. The summary now prints per-pin azeta plus a subtotal, and a pin that matched no holder fails the run. That last part is the point. An unmatched pin used to be silently ignored, so a typo in one of sixteen addresses left that contract's ZETA marked claimable and all three supply checks still balanced. Nothing signalled it. The check is governed by the existing --supply-check, so it downgrades to a warning with the rest. Not yet run: the end-to-end mainnet snapshot with this pin file. The README says so and labels the expected numbers a prediction. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CBYPC9DZYnjZoEhJD1K6zK
|
can you pls check the cursor + greptile comments? the stale-cache one especially — download_snapshot.py exits 0 when a cache already exists, so a rerun without --force silently exports the old height. |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
CI runs golangci-lint v2.1.6 and flagged `var pins []string`. Local was on v2.8.0, which does not. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CBYPC9DZYnjZoEhJD1K6zK
usmaneth
left a comment
There was a problem hiding this comment.
core compute is solid - tried to double-count a validator's self-delegation via the valoper form and the pinned-delegator path, both hold, and the module list matches maccPerms exactly. the real gap is that nothing enforces a zero-height export, so a plain one ships every pending reward to the multisig with all checks green - inline. the open threads on the stale snapshot cache, mainnet-without-pin-file, and the rm -rf on --home are the other things i'd want answered before this produces a real migration snapshot.
…apshot (#4647) * fix(zetatool): refuse incomplete staking and distribution input in snapshot The snapshot now reads distribution and refuses, as hard errors that --supply-check=false cannot skip: - unpaid rewards or commission, or a distribution module balance other than the community pool - staking records that do not add up: share sums, duplicates, unknown validators, invalid status, negative values, excess share dust - staking pools that do not exactly match validator tokens and unbonding entries - a pin on a staking pool, or a remainder its categories do not explain The summary prints the remainder by category and the 18->9 conversion dust. Attribution and the CSV output are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(snapshot): document the snapshot acceptance guarantees --for-zero-height and the distribution module are now required by zetatool snapshot, so the README and the export script say so. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(zetatool): name a supply mismatch and pin the remainder category precedence - Compute refuses a bank supply that differs from the sum of bank balances with its own message. The remainder identity check is now a backstop, tested through finalize directly. - A test pins the zero address and a module account, and checks the pin wins over both categories. - The summary's non-std line says its amount is liquid only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(zetatool): list the bank/supply mismatch as a hard refusal --supply-check=false now downgrades only three output checks. The bank sum vs supply check fails in Compute before anything is written, so the README, the command help and the flag help say so. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: add changelog entry for #4647 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
usmaneth
left a comment
There was a problem hiding this comment.
the distribution check closes the zero-height gap properly - a plain export now fails before anything is written, and the pool/share reconciliation in validateStaking means stake can't quietly leak into the remainder either. good to go from my side.
…de homes - Pass --force to the downloader unless --skip-download is set, so a normal run always exports a fresh snapshot instead of a stale cache. - Quote every interpolated path with shlex.quote in the init, rm, cp and export commands, including the redirect targets. - Refuse a --home that has data/ but no .zeta-snapshot-export marker, and write the marker after init, so the script never overwrites a real node home. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Mainnet without pins attributes contract-held ZETA (WZETA and friends) to claimable rows. Refuse --chain-id 7000 with no pins before reading the export. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@ws4charlie the cursor and greptile comments are all addressed: stale cache and path quoting in c9a1fc0, zero-height in b9b0ea5 (#4647, zetatool now refuses a non-zero-height export). On the |

Summary
contrib/snapshot/export_snapshot.py+make snapshot-export): produces azetacored exportgenesis JSON for testnet or mainnet. Reusesdownload_snapshot.pyfor the fetch and skips the node sync a devnet fork needs, sinceexportreads committed state straight from the data dir. Strips the logger preamble so the output is valid JSON.zetatool snapshot): a pure, deterministic function over that export. Attributesliquid + staked + unbondingper address (slashing-aware viaTokensFromShares), routes module accounts, the zero address and pinned contracts to a single remainder, and emits Postgres-ready CSV +schema.sql.remainder = supply - attributed, so nothing is dropped and the books balance by construction.--pin-filereads them from a file, andcontrib/snapshot/pins_mainnet.txtcarries the 16 mainnet contracts found by aneth_getCodescan of the top-500 holders (9,351,261 ZETA). A pin that matches no holder now fails the run, which is what catches a typo or a wrong-network pin file.contrib/snapshot/README.mdhas the exact commands for both stages, the flags, and a Verification status section listing what is and is not proven yet.Generated with Claude Code