Skip to content

phase 0 — cover the redeem downside branch [BS-4845] - #674

Open
iamsahu wants to merge 2 commits into
feat/cl-recovery-pathfrom
chore/redemption-rewards-p0-unblock
Open

phase 0 — cover the redeem downside branch [BS-4845]#674
iamsahu wants to merge 2 commits into
feat/cl-recovery-pathfrom
chore/redemption-rewards-p0-unblock

Conversation

@iamsahu

@iamsahu iamsahu commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Description

This pull request introduces automated checks to ensure that all deployable production contracts remain within the EIP-170 runtime bytecode size limit, both in local development and continuous integration (CI). It adds a new script and CI step for Foundry builds, strengthens Hardhat configuration for stricter enforcement, and documents the rationale and usage of these safeguards. Additionally, it introduces new tests and documentation for contract behavior and formal verification coverage.

Contract Size Enforcement:

  • Added a new script, scripts/check_contract_sizes.sh, which checks all deployable production contracts against the EIP-170 runtime bytecode limit during Foundry builds. This script is scoped to production contracts and allows for a configurable minimum margin.
  • Integrated the new size check into the CI pipeline by adding a "Check contract sizes" step to .github/workflows/Tests.yaml, ensuring that oversized contracts are caught before deployment.
  • Updated the Makefile to include a size target that runs the new size-check script, and marked it as a phony target. [1] [2]

Hardhat Configuration Improvements:

  • Modified hardhat.config.ts to set contractSizer.strict to true for local and CI builds (except during coverage runs), causing Hardhat compilation to fail if any contract exceeds the EIP-170 limit. This ensures that the Hardhat build, which produces larger bytecode than Foundry, is also gated. [1] [2]

Testing and Documentation:

  • Added two new tests to RedeemManager.1.t.sol to verify correct handling of redemption requests when the settlement rate falls below the request rate, and to ensure the cap logic behaves as intended in edge cases.
  • Added a detailed README.md to certora/ explaining the current state of formal verification, documenting known breakages, and outlining steps for future repairs.

Notice

  • Have you checked to ensure there aren't other open Pull Requests for the same update/change?
  • Have you assigned this PR to yourself?
  • Have you added at least 1 reviewer?
  • Have you updated the official documentation?
  • Have you added sufficient documentation in your code?
  • Have you added relevant tests to the official test suite?

Pull Request Type

  • 💫 New Feature (Breaking Change)
  • 💫 New Feature (Non-breaking Change)
  • 🛠️ Bug fix (Non-breaking Change: Fixes an issue)
  • 🕹️ Chore (Non-breaking Change: Doc updates, pkg upgrades, typos, etc..)

Breaking changes (if applicable)

Testing

  • Have you tested this code with the official test suite?
  • Have you tested this code manually?

Manual tests (if applicable)

Additional comments

…, gate contract sizes, diagnose Certora

Groundwork for the "LsETH Rewards while Redeeming" work. No production code changes.

Redeem downside coverage. Today's redeem payout is min(rate_at_settlement,
rate_at_request): maxRedeemableEth is recorded at request time and the claim path only
ever clamps the payout DOWN to it (RedeemManager.1.sol:430-436), with no symmetric
branch. So a redeemer bears the full loss when the pool rate falls between request and
settlement. testClaimMultiRate only ever settles at rates >= the request rates, so that
branch had zero coverage. Adds two tests:

- testClaimSettlementRateBelowRequestRateChargesFullLossToRedeemer: pins that the
  request-time value is a cap and never a floor.
- testPartialClaimBelowRequestRateDriftsImpliedCapRate: pins that maxRedeemableEth is a
  decrementing ETH budget, not a rate — after a partial claim below the request rate the
  implied per-LsETH cap ratchets from 1.0 to 50.5. Anything that later reads
  maxRedeemableEth / amount as "the rate at request time" would over-credit.

Contract size gate. RiverV1 is at 22,970 runtime bytes — 1,606 free — and every cheap
lever is already spent (foundry.toml: optimizer_runs = 3, via_ir, bytecode_hash = none).
Plain `forge build --sizes` cannot be used as a gate because it exits non-zero on
AccountingRiverV1 and RiverV1ForceCommittable, two test harnesses that are over the limit
by design. Adds scripts/check_contract_sizes.sh, scoped to contracts declared under
contracts/src, plus a `make size` target and a CI step. Also sets contractSizer.strict in
hardhat.config.ts: hardhat compiles only contracts/src, with looser settings than
foundry.toml (runs 100 vs 3, default ipfs bytecodeHash), so it produces larger bytecode
than forge — a green forge build is not evidence that a change deploys. strict is disabled
for `hh coverage`, since solidity-coverage instruments past EIP-170.

Certora diagnosis. Every conf except AllowlistV1 fails at the solc stage, so the workflow
has been verifying nothing for those contracts since before a3bb388 (2026-06-04).
Because certoraRun fails on compilation rather than on a rule, it does not look like a
verification failure. certora/README.md records the exact breakage and splits it into two
independent repairs: RiverV1Harness is coupled to the pre-extraction architecture (and has
drifted behaviourally — it still calls the one-arg _commitBalanceToDeposit, missing the
slashing-containment parameter), and OperatorsRegistryV1Harness uses OperatorAllocation,
which the V3 ETH-based refactor removed. No conf change here: repointing
RedeemManagerV1.conf at production River/OperatorsRegistry is very likely the fix, but it
cannot be validated without CERTORAKEY and a prover run.
@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8143df6f-dd68-458f-90b7-f2512da8b806

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Comment @coderabbitai help to get the list of available commands.

@iamsahu iamsahu changed the title phase 0 — cover the redeem downside branch… phase 0 — cover the redeem downside branch [BS-4845] Aug 17, 2026
@iamsahu
iamsahu marked this pull request as ready for review August 17, 2026 12:33
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.

1 participant