Pre-auditThree days of senior audit time for $1,500, credited in full toward your Zealynx audit.3 audit days, credited toward your auditSee how →
L-07·audit-finding

Retirement reports success before permission changes are durable on Base

Fixednfterc-1155marketplace
TL;DR

Retirement reports success before permission changes are durable on Base. Final disposition: Fixed.

Severity
LOW
Method
MManual review
CAT.

Tracker: issue #33 · Status: Fixed · Verified at: audit-v3-rereview-handoff

02Section · Affected files

Affected files

script/retire_superseded.sh#L45-L59

03Section · Description

Description

Both retirement transactions use --confirmations 1, discard the transaction output, and are followed by an unconditional done. message. The script preserves no transaction hash, does not wait for a safe or finalized block, and does not re-read the permissions after the selected safety level is reached.

Base exposes distinct latest, safe, and finalized block tags, while OP Stack finality distinguishes unsafe, safe, and finalized blocks. One sequencer confirmation is therefore not proof that a privileged retirement is durable. If its block is reorganized, the superseded market's permissions return without a new grant transaction, but the operator has no saved hashes with which to reconcile the run. See the Base RPC block-tag documentation and OP Stack finality documentation.

The source-level behavior is:

code
50: ... --confirmations 1 >/dev/null
55: ... --confirmations 1 >/dev/null
59: echo "done."

The script is idempotent and re-reads both permissions on a later run, so the state is recoverable by rerunning it. The issue is that no step requires that rerun after finality, while the first run reports completion.

04Section · Recommendations

Recommendations

At minimum, document and enforce a second idempotent run after the relevant Base head is finalized. Capture each transaction hash so the operator can reconcile the first run.

For stronger automation, wait until each successful receipt is at or behind the chosen safe or finalized head, confirm its block remains canonical, then re-read every target's class mask and relayer role at that head. Exit nonzero unless all targets are fully retired.

05Section · Remediation

Remediation

Fixed. done. now requires a finality phase after the send tail, defaulting to RETIRE_FINALITY=safe, and the run record carries the finality head. The script no longer reports success while its permission changes are still revertible.

06Section · Verification provenance

Verification provenance

Final disposition: Fixed. Verified at audit-v3-rereview-handoff, commit f020448976eb7c4895e1626ef3228876cff2b7d2. This earlier remediation disposition is carried forward from the prior re-review, not independently re-verified in the generation-d pass. The report-wide scope and evidence limitations remain applicable; see the final report overview.

Status
Fixed
L-07