test: add mock unit tests for LibOpSLFRCurrentExchangeRate run() and integrity() - #163
thedavidmeister wants to merge 10 commits into
Conversation
…integrity() Closes #59 Co-Authored-By: Claude <noreply@anthropic.com>
|
Warning Review limit reached
Next review available in: 48 minutes You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
WalkthroughAdds Forge tests for ChangesSFLR Exchange Rate Unit Tests
Estimated code review effort: 2 (Simple) | ~10 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ 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 |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@test/src/lib/op/LibOpSFlrCurrentExchangeRate.t.sol`:
- Around line 23-25: The boundary coverage for the testRunMappingMocked function
is incomplete because the current assumption excludes the zero case and lacks
explicit tests for edge conditions. Remove the vm.assume constraint that
excludes zero from testRunMappingMocked, then add separate dedicated test
functions to explicitly cover the boundary cases: a test for rate18 equal to 0,
a test for rate18 equal to 1e18 (standard decimal), and a test for
type(uint256).max that verifies the overflow/revert behavior. This ensures the
test suite comprehensively covers all required boundary conditions as stated in
issue `#59`.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 0b8b35b1-d359-4424-b6c6-b71719f9b9b5
📒 Files selected for processing (1)
test/src/lib/op/LibOpSFlrCurrentExchangeRate.t.sol
|
Rework note (human reject, 2026-07-04): (a) mapping fuzz and (c) integrity fuzz are good and stay as-is. Missing is #59's leg (b): EXPLICIT boundary pins — add named tests for rate18 = 0 and rate18 = 1e18 (parity), both ruling-neutral (exactly representable, lossy/lossless agree). Do NOT add the type(uint256).max boundary test yet: that input's semantics (revert vs floor) are gated on the org revert-vs-floor design ruling at rainlanguage/rain.erc4626.words#70 — pinning it now would enshrine one side. Relink Closes #59 → Refs #59 (the max leg stays open on the issue until the ruling), and note the deferral on #59. |
|
Update to the rework note: the org REVERT ruling landed (rain.erc4626.words#70, closed premise-corrected) — the deferred type(uint256).max boundary leg is now UNBLOCKED and should be included: assert the exact CoefficientOverflow-class revert for a mocked rate exceeding the int224 coefficient bound (~1.35e67), alongside the 0 and 1e18 explicit pins. Then Closes #59 in full. |
…efficient overflow
|
🤖 ai:producer |
The rework note's overflow leg is named for type(uint256).max; what landed pinned 2**223, the smallest overflowing rate. Those are not the same test: type(uint256).max is the only input that reaches the int224 coefficient bound through a uint256 -> int256 conversion that wraps to -1, so an implementation that checks the bound after converting would accept it and emit a negative rate. Pins the CoefficientOverflow class for that input alongside the existing boundary pin. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Merging main in changed the premise under this test. getSFLRPerFLR18 now rejects a zero exchange rate with ZeroSFLRRate, so the op no longer encodes zero as FLOAT_ZERO the way the rework note assumed when it asked for an explicit rate18 = 0 pin. The pin stays and its expectation moves to the current behaviour: the op propagates the guard rather than swallowing it, which the lib-level pin on main cannot observe from its side of the call. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
CI answered what the boundary pin could not: type(uint256).max does not take the CoefficientOverflow path 2**223 takes. It is far enough above the coefficient bound that the packing first normalises one decimal place down, and that shift drops a non-zero digit, so a lossless conversion refuses it as LossyConversionToFloat(type(uint256).max / 10, -17). Two different errors from the two ends of the overflow region is exactly why the rework note asked for this input by name and why the boundary test cannot stand in for it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The legal job failed installing nix, not on anything in this branch: the nix-quick-install tarball came down corrupt (zstd: unsupported format) while static and test installed the same version fine on the same run. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Closes #59
The only existing test for the sFLR exchange-rate opcode was a single fork snapshot at a fixed block. That test pins one magic value but cannot catch regressions in the coefficient-to-Float mapping for arbitrary rates.
This PR adds a lib-level test file
test/src/lib/op/LibOpSFlrCurrentExchangeRate.t.solwith:testIntegrity: fuzz-verifies thatintegrity()always returns(0, 1)regardless of operand/input/output arguments.testRunMappingMocked: fuzz-verifies thatrun()maps an arbitrary mocked sFLR rate throughLibDecimalFloat.fromFixedDecimalLosslessPacked(rate18, 18)correctly, usingvm.mockCallonSFLR_CONTRACT. Constrained torate18 < 2^223(the int224 coefficient limit of the Float format).Co-Authored-By: Claude noreply@anthropic.com
Summary by CodeRabbit