Skip to content

fix: close the audit's informational items in one pass - #15

Merged
Zena-park merged 1 commit into
mainfrom
fix/audit-info-items
Aug 21, 2026
Merged

fix: close the audit's informational items in one pass#15
Zena-park merged 1 commit into
mainfrom
fix/audit-info-items

Conversation

@Zena-park

Copy link
Copy Markdown
Owner

Why

Security audit Info items I-1 … I-8 and the listed test gaps, bundled as agreed.

What

Code

  • I-3 · MinterControl — an address is a Controller or a Minter, never both, in any pairing. The indirect form of self-management (A manages B, B manages A) let each key refill the budget the other spends; now refused as AddressAlreadyPaired at scheduling and at execution. Chains (A→B→C) are refused too — simpler than a graph walk, and a chain still concentrates authority. Cost: two cold SLOADs per schedule/execute.
  • I-1 · UpgradeControlupgradeToAndCall refuses ether with ValueNotAccepted. It is payable only because the overridden function is; the proxy could never return value.
  • I-8 · MockSmartAccount — answers a bad signature with 0xffffffff via tryRecover instead of reverting, as a real ERC-1271 account does.

Docs

  • I-4removeController leaving pending appointments in place: documented in the module, ADR-003 and docs/deploying.md, with the reason (a by-Minter index would be a set with removal on every schedule/execute/cancel, for a case that is not inconsistent state) and the procedure (scan ControllerScheduled for the freed Minter — pendingController is keyed by Controller).
  • I-2Eip2612 header: the standard permit front-run property and the integrator's try/catch.
  • I-5/I-6/I-7 were already documented; no change.
  • docs/security-review.md: MinterControl invariant restated, residual risks 4 (pending revival) and 5 (permit front-run), counts updated.

Tests (+15 forge, +2 Halmos)
ERC-1271 rejections (disowning account, non-ERC-1271 code) for both permit and EIP-3009 · zero permit owner · EIP-3009 window endpoints excluded · permit under a pause (raise blocked, lowering allowed, nonce untouched) · seizure against a shrunk balance keeps its schedule · lapsed seizure still cancellable · Minter re-activation · revived appointment after removeController · bare implementation refuses an upgrade · ether refused · unknown upgrade cancel reverts · role-conflict refusals both directions · symbolic: only raises are gated under a pause / a listing.

Checks

  • npm run check — 136 tests (8 suites) · Slither 0 findings · Halmos runs in CI (21 properties)

🤖 Generated with Claude Code

MinterControl: an address is a Controller or a Minter, never both, in
any pairing. The direct form (a key over itself) was already refused;
the indirect form -- A manages B while B manages A -- let each key
refill the budget the other spends, the same failure as one key holding
both ends. Refused as AddressAlreadyPaired at scheduling and again at
execution. Chains are refused too: simpler than a graph walk, and a
chain still concentrates authority. removeController leaving pending
appointments in place is documented with its reason (a by-Minter index
would be a set, for a case that is not inconsistent state) and the
operating procedure (scan ControllerScheduled for the freed Minter).

UpgradeControl.upgradeToAndCall refuses ether: it is payable only
because the function it overrides is, and the proxy has no way to send
value back out.

Eip2612 documents the standard permit front-run property and the
try/catch an integrator should use.

Tests added for the gaps the audit listed -- ERC-1271 rejections, zero
permit owner, EIP-3009 window endpoints, permit under a pause, seizure
against a shrunk balance, cancelling a lapsed seizure, Minter
re-activation, the revived-appointment case, the bare implementation
refusing an upgrade -- plus two symbolic properties for the
allowance-raise boundary. The ERC-1271 mock now answers a bad signature
with the failure value instead of reverting.

docs/security-review.md gains residual risks 4 and 5 and the new counts.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings August 21, 2026 15:05

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@Zena-park
Zena-park merged commit a0bcad0 into main Aug 21, 2026
3 checks passed
@Zena-park
Zena-park deleted the fix/audit-info-items branch August 21, 2026 15:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants