feat(lib): LibCorporateActionsPause reader helper (RAI-319)#22
feat(lib): LibCorporateActionsPause reader helper (RAI-319)#22hardyjosh wants to merge 1 commit into
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Warning This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
This stack of pull requests is managed by Graphite. Learn more about stacking. |
0540e39 to
581a552
Compare
ac0cecc to
b9aca8c
Compare
b9aca8c to
6c0d395
Compare
6c0d395 to
8116e4f
Compare
581a552 to
6af8c8f
Compare
8116e4f to
74112b9
Compare
Stateless library that wraps ICorporateActionsV1 and tells callers whether the current block is inside any pre- or post-window of a matching scheduled or completed action.
Algorithm (from SPEC § 16.3):
* Pending side: query earliestActionOfType(mask, PENDING). If now + pauseTimeBefore >= effectiveTime, return paused=true.
* Completed side: query latestActionOfType(mask, COMPLETED). If now <= effectiveTime + pauseTimeAfter, return paused=true.
* When both windows are open simultaneously, return the pending action's effectiveTime — integrators see the next event coming, not the last one done.
Short-circuits cleanly when corporateActionsVault == address(0) or mask == 0 — no external call, no state. Cancelled action nodes are unlinked from the linked list by st0x.deploy and unreachable from the traversal API, so no explicit filter is needed.
No-match detection uses the NODE_NONE = type(uint256).max sentinel
documented by ICorporateActionsV1.{earliest,latest}ActionOfType — cursor
0 is the bootstrap INIT node (a real walkable node) and must not be
treated as "no match". The pending and completed sides each treat
cursor == NODE_NONE as the unambiguous "no matching action" signal.
Adds three regression tests in `LibCorporateActionsPause.t.sol`:
- testNodeNoneSentinelOnBothSidesDoesNotPause — explicit no-match path
- testWildcardMaskAcceptsBootstrapCursorZero — bootstrap cursor-0 must
be accepted as a real match under wildcard mask
- testFuzzPausedFalseImpliesEffectiveTimeZero — SPEC 16.3 invariant
(paused=false iff effectiveTime=0)
Plus defensive boundary fuzz coverage (audit #72):
- testPendingEffectiveAtNowStillPausesDefensive — pins the documented
"upstream filter is authoritative" behaviour when PENDING returns
effectiveTime <= now
- testMaxPauseTimeAfterDoesNotOverflow — confirms uint256-space addition
in post-window check tolerates type(uint64).max
- additional defensive fuzz tests
14+ unit tests against a shared MockCorporateActions stub
(`test/mocks/MockCorporateActions.sol`) cover:
* both short-circuits (zero vault, zero mask)
* no actions, pending only, completed only, both
* NODE_NONE no-match on both sides
* exact-edge inclusivity at both window boundaries
* mask filtering (matching and non-matching action types, wildcard)
* zero-width window edges (pauseTimeBefore=0, pauseTimeAfter=0)
* pending-takes-precedence-when-both-windows-open
The mock is intentionally shared from the start so the three test files
that will need it across the corporate-action stack (this one,
PythOracleAdapter.autoPause.t.sol, AutoPausePropagation.t.sol) cannot
drift on the ICorporateActionsV1 signature.
Adds the rain.tofu.erc20-decimals foundry remapping needed by the transitive import chain ICorporateActionsV1 → LibCorporateActionNode → LibCorporateAction → LibStockSplit → LibTOFUTokenDecimals.
Also gitignores `audit/` and `.fixes/` so the audit skill's local
artifacts don't pollute commits or REUSE compliance.
Found by /audit Pass 1 (Security) A15-1, Pass 5 (Correctness) A15p5-1,
and Pass 6 (Hazard Surface) H1 against ST0x-Technology/st0x.oracle at
3a24b5d..f45f652.
Closes #72, #207, #221.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
74112b9 to
fd0d3ec
Compare
6af8c8f to
e9cc087
Compare

Stateless library that wraps ICorporateActionsV1 and tells callers whether the current block is inside any pre- or post-window of a matching scheduled or completed action.
Algorithm (from SPEC § 16.3):
Short-circuits cleanly when corporateActionsVault == address(0) or mask == 0 — no external call, no state. Cancelled action nodes are unlinked from the linked list by st0x.deploy and unreachable from the traversal API, so no explicit filter is needed.
14 unit tests against a minimal MockCorporateActions stub cover:
Adds the rain.tofu.erc20-decimals foundry remapping needed by the transitive import chain ICorporateActionsV1 → LibCorporateActionNode → LibCorporateAction → LibStockSplit → LibTOFUTokenDecimals.