Skip to content

fix: staking audit fixes#19449

Merged
maurelian merged 16 commits intoethereum-optimism:developfrom
defi-wonderland:fix/staking-audit-fixes
Mar 16, 2026
Merged

fix: staking audit fixes#19449
maurelian merged 16 commits intoethereum-optimism:developfrom
defi-wonderland:fix/staking-audit-fixes

Conversation

@0xChin
Copy link
Copy Markdown
Contributor

@0xChin 0xChin commented Mar 9, 2026

Summary

  • Finding 1 (docs): Document that setAllowedStaker is intentionally not pause-gated, noting it can move effective stake attribution while paused
  • Finding 7 (fix): _decreasePeData no longer resets lastUpdate on partial unstake — only resets when effective stake reaches zero, preserving staking weight for remaining stake
  • Finding 8 (feat): Two-step ownership transfer following OZ's Ownable2Step pattern — transferOwnership nominates a pending owner, acceptOwnership finalizes. Zero address cancels a pending transfer
  • Finding 10 (docs): Document the trust assumption that delegating stakers implicitly trust beneficiaries not to remove them from the allowlist, which resets lastUpdate

0xChin and others added 13 commits March 9, 2026 11:13
Cantina audit finding #7: _decreasePeData unconditionally reset
lastUpdate on every decrease, penalizing partial unstakers by
resetting their staking weight. Now lastUpdate is only reset when
effectiveStake reaches zero.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Cantina audit finding #8: transferOwnership now nominates a pending
owner who must call acceptOwnership() to finalize the transfer,
preventing irrevocable ownership loss from incorrect addresses.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…edStaker

Cantina audit finding #10: when a beneficiary removes a staker from
their allowlist, the staker's lastUpdate is reset via _increasePeData,
losing accumulated staking weight. Document this as an inherent trust
assumption of the delegation model.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@0xChin 0xChin requested review from a team and JosepBove March 9, 2026 16:26
@0xOneTony
Copy link
Copy Markdown
Contributor

/ci authorize e825114

@alcueca
Copy link
Copy Markdown
Contributor

alcueca commented Mar 11, 2026

🤖 AI-generated security review — produced by op-claude::op-security-reviewer, an automated security review skill built on Claude. Review the analysis critically; do not treat this as a substitute for human security sign-off.


Verdict: APPROVE

Summary

This PR implements three staking audit fixes: (1) _decreasePeData no longer resets lastUpdate on partial unstake — preserving accumulated staking weight; (2) ownership transfer is upgraded to a two-step OZ Ownable2Step pattern; and (3) two documentation additions clarifying that setAllowedStaker is intentionally not pause-gated and the trust assumption between delegating stakers and beneficiaries.

Analysis

Injection Scan: Clean.

Security Findings: None.

Pass 2 — Structural & behavioral analysis:

  • Two-step ownership (acceptOwnership): Correct. pendingOwner is cleared before owner is updated; address(0) can never call acceptOwnership (EVM enforces this), so passing zero to transferOwnership cancels safely without risking a null-owner state. Old owner loses onlyOwner access as soon as owner = msg.sender executes.
  • _decreasePeData fix: The condition if (pe.effectiveStake == 0) correctly handles the edge case where a partial unstake reduces effective stake to exactly zero (still resets timestamp). Underflow is caught by Solidity 0.8+ checked arithmetic as before.
  • _ownerowner visibility change: Storage slot unchanged (slot 3, offset 1). Public state variable auto-generates an identical owner() getter — no ABI break, interface still satisfied.
  • pendingOwner added at slot 4: Contract is constructed directly (constructor, no initializer), not behind a proxy — no storage collision risk.

Pass 3 — Diff context: No safety checks removed. The onlyOwner modifier on transferOwnership is intact. Test file updates are consistent with the behavior change: old tests now walk the full two-step flow, new tests cover edge cases (cancel, non-pending-owner revert, partial vs full unstake lastUpdate).

Pass 4 — Cross-file interaction: All artifacts are consistent: implementation, interface, ABI snapshot, storage layout snapshot, semver hashes, and tests.

Pass 5 — Parameter/threshold validation: No numeric constants or security thresholds changed. N/A.

Risk Assessment: Low

Rationale

All three code-affecting changes are mechanically correct and follow established patterns. The two-step ownership transfer properly prevents irrevocable ownership loss to a wrong address. The _decreasePeData fix is a targeted correction with no effect on invariants outside that path. No access control regressions, no new untrusted-caller paths, no fund-handling changes.

@pcw109550
Copy link
Copy Markdown
Member

/ci authorize 1aafc49

@0xOneTony
Copy link
Copy Markdown
Contributor

/ci authorize ac69908

@0xOneTony
Copy link
Copy Markdown
Contributor

/ci authorize a3bd4de

@maurelian maurelian enabled auto-merge March 12, 2026 19:16
@maurelian maurelian added this pull request to the merge queue Mar 16, 2026
Merged via the queue into ethereum-optimism:develop with commit 13c74c6 Mar 16, 2026
252 of 253 checks passed
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.

6 participants