Skip to content

fix(oracle): resolve top-up credentials through pod-or-node + regression test [re-review finding 1] - #491

Merged
0xpanicError merged 2 commits into
pankaj/feat/non-eigenpod-withdrawal-credentialsfrom
fix/oracle-approve-validators-resolver
Aug 13, 2026
Merged

fix(oracle): resolve top-up credentials through pod-or-node + regression test [re-review finding 1]#491
0xpanicError merged 2 commits into
pankaj/feat/non-eigenpod-withdrawal-credentialsfrom
fix/oracle-approve-validators-resolver

Conversation

@0xpanicError

@0xpanicError 0xpanicError commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Finding 1 (BLOCKER) — the production top-up builder stranded pod-less validators

The independent re-review at head 0101757 found that EtherFiAdmin._approveValidators — the production builder of the 31 ETH top-up deposit data, reached via executeValidatorApprovalTask — hardcoded getEigenPod(). For a pod-less node that is address(0), so it baked 0x02 + address(0) credentials whose deposit root can never match the node credentials fixed at creation. confirmAndFundBeaconValidators then reverts IncorrectBeaconRoot, and the validator is stranded at 1 ETH forever.

This is the only production path that funds a validator past 1 ETH, so the pod-less feature could not work as merged. EtherFiAdmin.sol was outside the original 15-file diff, which is why it was missed.

Fix (src/oracle/EtherFiAdmin.sol)

Resolve the credential target as pod-or-nodeIEtherFiNode(node).getEigenPod(), else the node — mirroring StakingManager.confirmAndFundBeaconValidators. Resolved raw (not via withdrawalCredentialTarget) so a top-up is not blocked if the pod was retired between creation and approval (consistent with the earlier finding-4 scoping). Pod-backed nodes are unaffected: getEigenPod() returns the pod, the else branch is never taken, and the built root is byte-identical to before.

Test (test/behaviour-tests/oracle-podless-funding.t.sol)

Drives the real path — executeValidatorApprovalTask → _approveValidators → confirmAndFundBeaconValidators — for a pod-less validator and asserts it funds to full validator size, stays linked, and stays pod-less. The existing pod-less tests hand-build the top-up DepositData and prank the admin, skipping _approveValidators; this one lets the builder build it.

Non-vacuous, verified both directions:

  • Passes against the fixed builder.
  • Fails IncorrectBeaconRoot() when the fix is reverted (confirmed with forge build --force to defeat the incremental-build cache).

Notes

  • Existing suites unaffected: lifecycle 54, prelude 42 green.
  • Out of scope / follow-up (oracle repo): the off-chain daemon has a second, independent gate — validator_scanner.py computes expected credentials through getEigenPod and rejects pod-less validators with "Withdrawal credentials mismatch." That must be fixed in the oracle repo before pod-less validators can be approved in production. This PR only fixes the on-chain builder.
  • Release ordering: oracle + EtherFiAdmin must land before/with the contract upgrade, never after.

Base: pankaj/feat/non-eigenpod-withdrawal-credentials (the #485 branch).

🤖 Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.


Note

Medium Risk
Touches the only on-chain path that builds validator top-up deposit data after oracle approval; incorrect credential logic would strand funds, but the change mirrors existing StakingManager behavior and is covered by a targeted regression test.

Overview
Fixes a blocker where pod-less validators could never complete oracle-driven funding past the initial 1 ETH deposit.

EtherFiAdmin._approveValidators no longer builds top-up deposit roots using getEigenPod() alone. It now uses the same pod-or-node rule as StakingManager.confirmAndFundBeaconValidators: EigenPod when present, otherwise the EtherFi node address. That keeps compounding withdrawal credentials aligned with what was fixed at validator creation, so confirmAndFundBeaconValidators no longer reverts IncorrectBeaconRoot. Pod-backed validators behave as before; the fallback only applies when the pod is address(0).

Adds oracle-podless-funding.t.sol, which runs the production path executeValidatorApprovalTask_approveValidatorsconfirmAndFundBeaconValidators for a pod-less validator (including an in-place EtherFiAdmin impl swap on the fork) and asserts full-size funding without requiring hand-built deposit data.

Reviewed by Cursor Bugbot for commit c355f43. Bugbot is set up for automated code reviews on this repo. Configure here.

0xpanicError and others added 2 commits August 13, 2026 08:44
EtherFiAdmin._approveValidators (the production 31 ETH top-up builder, reached
via executeValidatorApprovalTask) hardcoded getEigenPod(). For a pod-less node
that is address(0), so it baked 0x02+address(0) credentials whose deposit root
never matches the node credentials fixed at creation -> confirmAndFundBeacon-
Validators reverts IncorrectBeaconRoot and the validator is stranded at 1 ETH.

Resolve the target as pod-or-node (raw, no PodRetired gate) so the oracle-built
deposit data matches what StakingManager.confirmAndFundBeaconValidators re-
derives, for both pod-backed and pod-less nodes.

Finding 1 of the independent re-review at head 0101757. The production builder
was outside the original 15-file diff, so the existing suite (which hand-builds
DepositData and pranks the admin) never exercised it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…valTask

Regression for the oracle top-up blocker: drives the REAL production path
(EtherFiAdmin.executeValidatorApprovalTask -> _approveValidators ->
LiquidityPool.confirmAndFundBeaconValidators) for a pod-less validator, instead
of hand-building the top-up DepositData and pranking the admin as the existing
pod-less tests do. That fixture skipped _approveValidators, which is why the
blocker survived 133 green tests.

Creates a pod-less validator (phase 1, 1 ETH), lets _approveValidators build
the top-up data, and asserts it funds to full validator size. Fails
IncorrectBeaconRoot against the pre-fix builder; passes after it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Credits must be used to enable repository wide code reviews.

@0xpanicError
0xpanicError merged commit d7a7e23 into pankaj/feat/non-eigenpod-withdrawal-credentials Aug 13, 2026
2 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.

1 participant