Skip to content

feat(evm): mine + claim test ETH via evm.faucet#277

Open
qu0b wants to merge 3 commits into
masterfrom
qu0b/faucet-agent-command
Open

feat(evm): mine + claim test ETH via evm.faucet#277
qu0b wants to merge 3 commits into
masterfrom
qu0b/faucet-agent-command

Conversation

@qu0b

@qu0b qu0b commented Jul 2, 2026

Copy link
Copy Markdown
Member

What

evm.faucet(network, address) mines the network's PoW faucet and claims test ETH, returning the claim tx hash (it used to return a browser URL — useless to an agent). Crucially, the faucet is reachable only through the panda proxy, which authenticates the caller — a client-side login check is meaningless if the endpoint is open.

from ethpandaops import evm
w = evm.wallet()
tx = evm.faucet("glamsterdam-devnet-6", w["address"])   # mines + claims, returns tx hash

How

  • pkg/proxy /faucet/{network}/ passthrough (handlers/faucet.go) — mirrors the ethnode handler: the proxy's auth middleware authenticates the caller, then it forwards to the network's credential-gated faucet host with basic auth that only the proxy holds. No public faucet surface for panda users.
  • pkg/faucet Transport — the Argon2id mining flow (x/crypto/argon2, zero external deps) runs either directly (tests/CLI) or through the proxy.
  • evm.faucet op — routes via proxyRequest("/faucet/<network>/…"); the local panda auth check is only a fast pre-check now, the proxy is the real boundary.

Auth model

The proxy is the single authenticated gateway (same as every datasource). The faucet endpoint is credential-gated and only the proxy holds the credential, so there is no way to reach it except an authenticated request through the proxy.

Tests

  • Unit: mining core vs a faithful mock (real argon2 + difficulty), non-standard-param rejection, difficulty mask; proxy FaucetHandler (host derivation, bearer→basic-auth rewrite, path validation); op auth gate (401) + resolution errors.
  • e2e through a local panda-proxy against glamsterdam-devnet-6: pkg/faucet → proxy /faucet/… → faucet → mine → claim → funded 1 ETH in ~30 s (tx confirmed).

Deploy order — the faucet lockdown is LAST

  1. Merge this PR → panda-proxy build has the faucet handler.
  2. Deploy panda-proxy (with the handler) + panda-server.
  3. Then make the faucet non-public (basic-auth ingress). Doing this earlier breaks both the direct and proxy paths.

Faucet-side notes (ACG #554 / glamsterdam)

  • ipinfo disabled on the agent faucet: behind the proxy the faucet sees the proxy's IP, so IP-reputation checks fail — they don't apply to a proxy-gated faucet.
  • Follow-up: per-IP concurrency/recurring limits also collapse behind the proxy (all traffic shares the proxy IP); for multi-agent use these should key on the authenticated user rather than IP.

Requires a PoWFaucet build with the agent REST API at Argon2id/v19 (live: ghcr.io/qu0b/powfaucet:v2.5.0-agent.4).

qu0b added 2 commits July 2, 2026 12:07
evm.faucet(network, address) previously returned a browser URL, which an
agent cannot use (no browser, captcha, or WebSocket). It now runs the full
PoWFaucet agent-REST flow server-side and returns the claim transaction hash.

- pkg/faucet: Go mining core using golang.org/x/crypto/argon2 (Argon2id).
  Zero external/runtime deps, so it works on any OS panda ships to.
- evm.faucet server operation: auth-gated (requires 'panda auth'), resolves
  the network's faucet URL from Cartographoor, delegates to pkg/faucet.
- sandbox evm.faucet() delegates to the operation and returns the tx hash.

Requires the network's faucet to run a PoWFaucet build with the agent REST
API (Argon2id/v19). Tests: mining core against a faithful mock + auth gate;
faucet_live_test.go is an env-guarded live e2e.
The client-side auth check is meaningless if the faucet endpoint is open, so
the faucet is now reachable only through the panda proxy:

- pkg/proxy: add a /faucet/{network}/ passthrough that mirrors the ethnode
  handler — the proxy's auth middleware authenticates the caller, then it
  forwards to the network's credential-gated faucet host with basic auth the
  proxy alone holds.
- pkg/faucet: introduce a Transport so the mining flow runs either directly
  (tests/CLI) or through the proxy.
- evm.faucet op: route via proxyRequest(/faucet/<network>/...); the local
  auth check is now only a fast pre-check, the proxy is the real boundary.
@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

🐼 Smoke eval — 4488217: ❌ 0/8 pass

📊 Interactive report — tokens p50 0 · tokens/solve 0.

Reference points: v0.37.0 100% · master@9dd4c95 0% · qu0b/faucet-agent-command@64f282c 0%.

question result tokens tools
forky_node_coverage 14,477 4
tracoor_node_coverage 14,566 4
mainnet_block_arrival_p50 15,763 7
list_datasources 13,465 3
block_count_24h 15,381 7
missed_slots_24h 14,767 5
chartkit_default_arrival_distribution 23,260 18
storage_upload_session_scoped 24,865 13
🔭 Langfuse traces (8 runs; ⚠️ = failed)

The report walks this branch's commits against the master baseline and the most recent release. A self-contained copy is in the run's eval-smoke-* artifact.

Behind the proxy every faucet request carries the proxy's IP, so the
faucet's own per-IP protections collapse to one global bucket. Restore
per-user fairness where the authenticated identity is known: cap
startSession to 30/user/hour, keyed on the auth subject. Only
startSession is counted; the many powChallenge/powSubmit calls a single
claim makes pass through untouched.
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