Skip to content

feat(ui): devnet deposit tooling - faucet, wallet-free submission, batching, builder top-ups, ENS - #845

Open
barnabasbusa wants to merge 3 commits into
masterfrom
bbusa/devnet-deposit-tooling
Open

barnabasbusa wants to merge 3 commits into
masterfrom
bbusa/devnet-deposit-tooling

Conversation

@barnabasbusa

@barnabasbusa barnabasbusa commented Aug 21, 2026 •

Copy link
Copy Markdown
Collaborator
Screenshot 2026-08-21 at 12 51 21 Screenshot 2026-08-21 at 12 52 45 Screenshot 2026-08-21 at 12 53 11 Screenshot 2026-08-21 at 12 51 47

Summary

Devnet-focused overhaul of the submit deposit pages (validator + builder), making the full deposit lifecycle possible without any external tooling: generate a mnemonic in the browser, fund its wallet from a built-in faucet, and submit deposits / batches / top-ups signed locally - no wallet extension, no staking-deposit-cli, no separate faucet.

Features

Devnet faucet

  • frontend.faucet config: prefunded EL private keys, amount per request, per-address cooldown
  • POST /validators/deposits/faucet sends funds through a ready execution client
  • Dynamic gas estimation: on glamsterdam devnets a plain transfer to a new account needs ~207k gas - a hardcoded 21000 mines but fails out-of-gas with the funds silently bouncing. The faucet estimates (+25%), and every hardcoded gas limit in the submit paths (150k deposit, 300k builder deposit) was likewise replaced with estimation.
  • Faucet buttons track the funding tx to confirmation and surface on-chain failures

Wallet-free submission

  • The deposit generator hands its mnemonic to the pages; with no wallet connected, deposits, batches and top-ups are signed locally with the derived EL account (m/44'/60'/0'/0/0) via the rpc proxy
  • Proxy allowlist gains eth_getBlockByNumber, eth_sendRawTransaction, eth_getTransactionReceipt
  • Mnemonic + full generator config cached in sessionStorage (per-tab, per mode) so a broken setup can be edited instead of recreated

ENS support

  • GET /ens/resolve (name→address) and GET /ens/lookup (address→name) over the existing resolver
  • Address inputs (basic config + per-row overrides) accept ENS names; credential cells display 0xb0…name.eth
  • Devnet run.sh resolves mainnet ENS (canonical registry pinned explicitly - remote networks otherwise inherit the local registry address)

Generator modal

  • Builder-mode wording throughout; per-mode defaults (0xB0/50 ETH vs 0x02/32 ETH)
  • Dynamic deposit amount from the funding wallet's live balance / count (floors: 1 ETH builder, 32 ETH validator)
  • 0x00/0x01 deposits capped at 32 ETH (reactive UI enforcement + generation-time safety net); validator mode no longer offers 0xB0
  • Override rows seed from the current defaults and preview the effective credentials instead of "(use default)"

Batch submission

  • Submit All (N deposits, 1 tx): deploys a throwaway batching contract whose constructor performs every deposit call and self-destructs in the same tx (EIP-6780), refunding leftover value. Builder batches escalate the per-position EIP-8282 queue fee. ~50k gas fixed overhead, cheaper than N txs from N≈3.

Top-ups

  • Builder page gains a Topup tab reusing the validator topup form (new ?ajax=load_builders|search_builders endpoints query the builder registry only); top-ups send a zeroed signature (not verified for top-ups) + the live queue fee
  • Topup amounts hard-capped by the funding wallet balance (0.1 ETH gas headroom); exceeding the effective-balance room is a warning (devnet testing), not a blocker
  • Builders have no max EB - those rows are hidden for builder top-ups

Misc

  • Deposit source chooser split into two panels (wallet & file vs generator); frontend.disableDepositGenerator hides the generator for non-devnet deployments
  • New SubmitShared/ module: tracked-tx lifecycle hook + status button (Submit → Signing → Pending w/ tx link → Submitted / Failed-on-chain + Retry), ENS input, local-wallet banner, batcher, fee math, credential colors matched to utils/format.go
  • Transaction page: pending txs no longer render with the red failed badge (own hourglass badge)
  • Devnet run.sh: faucet prefunded with the ethereum-package dev keys, mainnet ENS, raised proxy rate limits

Test plan

Verified live on a glamsterdam-devnet-8 kurtosis enclave: faucet funding (incl. the out-of-gas root-cause analysis via debug_traceTransaction), wallet-free single submits, a 2-deposit builder batch (mined, batcher self-destructed, leftover refunded), mainnet ENS resolution (bbusa.eth/potuz.eth), pending/confirmed tracking. Builder topup tab and validator-page batch are code-complete but not yet exercised on-chain.

…tching, builder top-ups, ENS

Devnet-focused overhaul of the submit deposit pages (validator + builder):

Faucet:
- frontend.faucet config (prefunded EL keys, amount, per-address cooldown)
- POST /validators/deposits/faucet sends funds via a ready execution client
  with dynamic gas estimation (glamsterdam repricing: transfers to new
  accounts need ~207k gas, hardcoded 21000 mines but fails out-of-gas)
- faucet buttons track the funding tx to confirmation and surface
  on-chain failures

Wallet-free submission:
- the deposit generator hands its mnemonic to the pages; without a
  connected wallet, deposits/batches/top-ups are signed locally with the
  derived account (m/44'/60'/0'/0/0) through the rpc proxy
- proxy allowlist gains eth_getBlockByNumber, eth_sendRawTransaction,
  eth_getTransactionReceipt
- mnemonic + full generator config cached in sessionStorage per mode

ENS:
- GET /ens/resolve (forward) and /ens/lookup (reverse) over the existing
  resolver; address inputs accept ENS names, credential cells display them
- devnet run.sh resolves mainnet ENS (canonical registry pinned - remote
  networks otherwise inherit the local registry address)

Generator modal:
- builder-mode wording, per-mode defaults (0xB0/50 ETH vs 0x02/32 ETH),
  dynamic amount from live balance / count, 0x00/0x01 deposits capped at
  32 ETH (reactive + generation safety net), override rows seeded from
  defaults with an effective-credentials preview

Batching:
- Submit All: one tx deploying a throwaway constructor-executing batcher
  (self-destructs, refunds leftover), per-position queue fee escalation
  for the EIP-8282 predeploy

Top-ups:
- builder page gains a Topup tab (builder registry search endpoints,
  zeroed-signature top-up calldata + queue fee); topup amounts hard-capped
  by the funding wallet balance, EB-room overage downgraded to a warning

Misc:
- all hardcoded gas limits in tx paths replaced with estimation
- deposit source chooser split into wallet/file vs generator panels,
  hideable via frontend.disableDepositGenerator
- shared SubmitShared/ module (tracked-tx lifecycle, status button, ENS
  input, banner, fee math, credential colors matching utils/format.go)
- tx page: pending txs no longer render with the failed (red) badge
@barnabasbusa

Copy link
Copy Markdown
Collaborator Author

Companion config PR enabling these features on kurtosis devnets: ethpandaops/ethereum-package#1478 (depends on this PR - the config is forward-compatible and stays dormant until a dora image containing this change is used).

@redpandabot

redpandabot Bot commented Aug 21, 2026

Copy link
Copy Markdown

Summary

Large devnet-focused feature: a backend faucet (services/faucet.go + POST /validators/deposits/faucet), wallet-free deposit/top-up submission signed with a locally derived EL account via the RPC proxy (new allowlisted methods), ENS resolve/lookup endpoints, a reworked generator modal with session persistence, batch submission via a self-destructing deployer, and builder top-ups. The Go wiring, template/model plumbing and the frontend flows are consistent with existing patterns; the faucet has two robustness gaps worth a look, neither a merge blocker.

Issues

  • 🟡 services/faucet.go:162 — Gas estimation always uses wallets[0] even when a different key sends the transfer — EstimateGas is called with From: fs.wallets[0], but the wallet that actually signs/sends is whichever is first found with balance >= amount+maxFee (line 181). If wallets[0] cannot cover amountWei, EstimateGas errors, the err == nil guard silently falls back to the hardcoded 21000, and then the other (selected) wallet sends with that limit — reproducing on cold-access/gas-repriced devnets exactly the out-of-gas 'funds bounce' this PR claims to eliminate. Estimate from the selected wallet (or all candidates) instead.
  • 🟡 services/faucet.go:190 — Locally tracked nonce only ever advances and can permanently wedge the faucet — The counter takes max(node pending nonce, wallet.nonce) and updates wallet.nonce = nonce+1 only after a successful send, so it is never reconciled with chain/pool state. If a sent tx is dropped (reorg out and not re-added, or the EL pool is lost), the faucet keeps signing ever-higher nonces that reference the unfilled gap and can never be mined; since the counter stays ahead of the node's still-low pending nonce, there is no self-recovery short of restarting the process (which resets it to 0). Consider tracking/conflating against the node's pending nonce as the source of truth.

Reviewed @ 059c5968
"There's no bad weather, only bad clothing." — Eastern European

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