Skip to content

op-devstack: replace faucet/funder with a prefunded EOA#21706

Draft
joshklop wants to merge 5 commits into
developfrom
joshklop/faucet-funder-eoa
Draft

op-devstack: replace faucet/funder with a prefunded EOA#21706
joshklop wants to merge 5 commits into
developfrom
joshklop/faucet-funder-eoa

Conversation

@joshklop

@joshklop joshklop commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Summary

Replaces the op-faucet service and the dsl.Faucet / dsl.Funder DSL types with a single prefunded *dsl.EOA per chain in the acceptance-test devstack.

Every sysgo runtime already prefunds a funder account at genesis (devkeys.UserKey(funderMnemonicIndex)); the op-faucet service was just relaying from it. Since devstack is sysgo-only (each test gets its own devnet, so the cross-process funder races the hosted service guarded against no longer apply), tests can fund directly from that prefunded account. This removes a whole hosted-service layer (txmgr, RPC frontend, stack.Faucet, sources.FaucetClient) and a load-related flake source.

Net: +243 / −561.

Scope note: this PR only rewires the devstack to stop using op-faucet. Deleting the op-faucet/ package + its Docker image is a follow-up, kept separate on purpose.

What changed

dsl.EOA becomes the funder (op-devstack/dsl/eoa.go)

  • NewFundingEOA(key, el, wallet) creates a prefunded funder EOA that owns the genesis-prefunded key and mints/funds child EOAs from the test's wallet.
  • The funding helpers (NewFundedEOA, NewFundedEOAs, Fund, FundNoWait, FundAtLeast) move onto EOA with identical signatures, backed by a mutex + locally-managed nonce (WithStaticNonce) so concurrent funding stays correct — this replaces the txmgr-managed nonce the faucet service provided.
  • EOA.AsFunder(el) rebinds a funder to a specific EL node (sharing nonce state) for the few tests that fund via a non-default node.
  • dsl/funder.go and dsl/faucet.go deleted.

sysgo / presets / stack

  • sysgo.FunderKey(keys) exported; all faucet-service wiring removed (startFaucets, startFaucetsForRPCs, FaucetService fields). Genesis prefunding unchanged.
  • Preset FunderX fields are now *dsl.EOA (built via a shared newFunderEOA helper); FaucetX fields removed. The ~142 sys.FunderX.NewFundedEOA(...) call sites are unchanged.
  • stack.Faucet, the preset faucet frontend, and op-service/sources/faucet_client.go removed.

The op-faucet/ package itself (and its Docker image) is untouched here and will be removed in a follow-up PR.

Testing

go build ./... and go vet pass across the module. Ran acceptance tests covering every distinct funding path:

Test Pattern Result
base/TestTransfer basic NewFundedEOA
custom_gas_token/…ValueTransferPaysGasInToken native-token funding (CGT)
interop/message/TestRandomDirectedGraph concurrent NewFundedEOAs (nonce safety)
isthmus/operator_fee/TestOperatorFee Fund + FundAtLeast + NewFundedEOA(0)

Notes

  • Funding now happens from the funder private key in the test process. Safe under sysgo (per-test devnet); if a preset were ever pointed at a shared external devnet, concurrent tests would share the funder key and race on nonces (documented near NewFundingEOA).

🤖 Generated with Claude Code

Remove the op-faucet service wiring and the dsl.Faucet/dsl.Funder types from
the acceptance-test devstack. Every sysgo runtime already prefunds a funder
account at genesis (devkeys.UserKey(funderMnemonicIndex)); tests now hand out
funds directly from a single prefunded *dsl.EOA per chain instead of relaying
through a hosted faucet service.

- dsl.EOA absorbs the funding helpers (NewFundedEOA/NewFundedEOAs, Fund,
  FundNoWait, FundAtLeast) via NewFundingEOA, with a mutex + locally-managed
  nonce (WithStaticNonce) for safe concurrent funding, replacing the faucet's
  txmgr-managed nonce. Adds EOA.AsFunder to rebind a funder to a specific EL.
- sysgo exposes FunderKey and drops the faucet service (startFaucets,
  startFaucetsForRPCs, FaucetService fields). Genesis prefunding is unchanged.
- presets build funder EOAs via a shared helper; FunderX fields are now
  *dsl.EOA and the FaucetX fields are removed.
- stack.Faucet, the preset faucet frontend, and sources.FaucetClient are
  removed (no remaining consumers).

Test call sites that used sys.FunderX.NewFundedEOA(...) are unchanged. The
op-faucet package itself is removed in a follow-up commit.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@joshklop joshklop requested a review from a team as a code owner July 10, 2026 21:48
@joshklop joshklop force-pushed the joshklop/faucet-funder-eoa branch from 872b58c to 354d607 Compare July 10, 2026 21:52
@joshklop joshklop marked this pull request as draft July 10, 2026 21:54
joshklop and others added 4 commits July 10, 2026 16:38
Follow-up to the faucet/funder removal. The previous commit kept the funding
helpers on dsl.EOA (behind a wallet + managed-nonce "glue" field) to minimize
test churn; move that responsibility into a dedicated dsl.FunderEOA so dsl.EOA
stays a plain primitive.

- Add dsl.FunderEOA{eoa, inner *SyncEOA, wallet}: NewFundedEOA/NewFundedEOAs,
  Fund, FundAtLeast, AsFunder. Funding goes through a SyncEOA (txinclude.Includer)
  which manages nonces, so many funding txs can be issued concurrently — e.g.
  NewFundedEOAs, or several goroutines sharing one FunderEOA.
- Move SyncEOA from the loadtest package into dsl so FunderEOA can reuse it (and
  to de-duplicate); loadtest and the osaka/fusaka spammers now use dsl.SyncEOA.
- Strip the funding glue (NewFundingEOA, fundingState, Fund*/NewFundedEOA*,
  AsFunder) from dsl.EOA.
- presets and helpers now build/pass *dsl.FunderEOA; tx_producer shares one
  FunderEOA across producer goroutines (safe under the shared includer).

sys.FunderX.NewFundedEOA(...) call sites are unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
CI fixes for the FunderEOA change:

- txinclude Monitor: treat op-reth's "transaction indexing is in progress"
  (note the "is") as transient, alongside geth's "in progress" wording. Funding
  through FunderEOA/SyncEOA/Persistent was failing on op-reth when a receipt was
  requested during the indexing window, because the Monitor only matched geth's
  string and treated op-reth's as fatal. Adds a regression test.
- FunderEOA.fund: assert the funding tx receipt is successful, so a reverted
  funding tx surfaces a clear error instead of a later WaitForBalance timeout.
- gofmt: fix blank-line formatting in the sysgo files left over from removing the
  faucet service (deployer.go, multichain_supernode_runtime.go, singlechain_build.go).

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

FunderEOA funded through txinclude's Persistent includer wrapped in a full
reliable EL (Monitor + Resubmitter). After a funding tx was mined, the
Resubmitter's next resubmit returned "nonce too low", which Persistent treats as
"advance the nonce and re-send" — re-sending the value transfer and over-funding
the recipient (observed: a single 0.1 ETH Fund delivering 2.7 ETH across 27 txs).
The exact-equality WaitForBalance then never matched and timed out. It was
timing-dependent (worse on slower L1 blocks vs the 1s poll cadence), which is why
it surfaced in the interop fault-proof tests on L1 but not in faster L2 funds.

Build the funder's includer with a Monitor (reliable receipt polling, including
the op-reth "indexing is in progress" retry) but a plain sender and no
resubmitter, mirroring loadtest's invalid-msg spammer. Each funding tx is sent
exactly once, so funding amounts are exact while concurrent funding stays
nonce-safe via the includer's nonce manager.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Removing the FaucetService field from the MultiChainRuntime literal left the
remaining field group over-aligned; go-lint (goimports) flagged it. This file was
missed by the earlier gofmt pass, which only checked uncommitted files.
Verified all branch-changed Go files are goimports-clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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