Severity: Critical (as filed) · Area: Contract (contracts/token-factory/src/lib.rs) · Status: ✅ Resolved — re-verified against the tree on 2026-08-19
Description
Original defect. transfer_admin and update_admin were independently written copies of the same state transition, and they had drifted: only update_admin emitted adm_upd. Any monitoring built on that event — a reasonable thing to build for admin-key rotation — would silently miss a rotation performed through transfer_admin, giving an attacker holding a compromised admin key a documented way to rotate to their own key without tripping event-based alerting.
Why this is now closed. Both entrypoints are now thin delegates over one implementation:
rotate_admin (lib.rs:1610-1626) holds the single copy of the auth check, the self-transfer guard, the state write, and the adm_upd emission. transfer_admin (lib.rs:1629) and update_admin (lib.rs:1634) each call it and do nothing else, so no rotation path can be silent and the two cannot drift again.
- The duplication itself is retained deliberately rather than accidentally:
transfer_admin is kept as an ABI alias for callers built against the older signature, documented as such at lib.rs:1627-1628 and docs/contract-abi.md:348-352, which also records the original divergence and directs new integrations to update_admin.
- Tests pin the equivalence:
test_transfer_admin_and_update_admin_share_guards (test.rs:3788) and test_transfer_admin_and_update_admin_produce_same_state (test.rs:3807), alongside the pre-existing rotation tests at test.rs:1549-1590 and test.rs:3771.
- The event table at
docs/contract-abi.md:436 lists adm_upd with its (current_admin, new_admin) payload.
Note that the other half of what a reviewer might expect here — that admin rotation is still single-step, so a typo'd address permanently bricks the factory — is a separate, still-open defect tracked in #1012.
Tasks
Acceptance Criteria
Re-verified on 2026-08-19 during the 30-issue codebase audit tracked in ISSUES.md.
Severity: Critical (as filed) · Area: Contract (
contracts/token-factory/src/lib.rs) · Status: ✅ Resolved — re-verified against the tree on 2026-08-19Description
Original defect.
transfer_adminandupdate_adminwere independently written copies of the same state transition, and they had drifted: onlyupdate_adminemittedadm_upd. Any monitoring built on that event — a reasonable thing to build for admin-key rotation — would silently miss a rotation performed throughtransfer_admin, giving an attacker holding a compromised admin key a documented way to rotate to their own key without tripping event-based alerting.Why this is now closed. Both entrypoints are now thin delegates over one implementation:
rotate_admin(lib.rs:1610-1626) holds the single copy of the auth check, the self-transfer guard, the state write, and theadm_updemission.transfer_admin(lib.rs:1629) andupdate_admin(lib.rs:1634) each call it and do nothing else, so no rotation path can be silent and the two cannot drift again.transfer_adminis kept as an ABI alias for callers built against the older signature, documented as such atlib.rs:1627-1628anddocs/contract-abi.md:348-352, which also records the original divergence and directs new integrations toupdate_admin.test_transfer_admin_and_update_admin_share_guards(test.rs:3788) andtest_transfer_admin_and_update_admin_produce_same_state(test.rs:3807), alongside the pre-existing rotation tests attest.rs:1549-1590andtest.rs:3771.docs/contract-abi.md:436listsadm_updwith its(current_admin, new_admin)payload.Note that the other half of what a reviewer might expect here — that admin rotation is still single-step, so a typo'd address permanently bricks the factory — is a separate, still-open defect tracked in #1012.
Tasks
Acceptance Criteria
FactoryState.adminemitsadm_upd, verified by test.Re-verified on 2026-08-19 during the 30-issue codebase audit tracked in
ISSUES.md.