crypto test fix
All checks were successful
Deploy / build-deploy (push) Successful in 3m40s

This commit is contained in:
Jorijn van der Graaf 2026-08-20 01:49:15 +02:00
commit 5d3a3adb86
2 changed files with 24 additions and 13 deletions

View file

@ -55,12 +55,16 @@ namespace {
// https://developers.circle.com/stablecoins/eurc-contract-addresses // https://developers.circle.com/stablecoins/eurc-contract-addresses
constexpr std::string_view kContract = "0x08210F9170F89Ab7658F0B5E3fF39b0E03C594D4"; constexpr std::string_view kContract = "0x08210F9170F89Ab7658F0B5E3fF39b0E03C594D4";
constexpr std::string_view kChainId = "11155111"; constexpr std::string_view kChainId = "11155111";
// Two endpoints from different operators (Allnodes, 1RPC) — the same two // Three endpoints from different operators (Allnodes, Tenderly, 1RPC) with
// operators the production ethereum entry uses — because the rule under test // min_confirmations=2, because the rule under test is "no single node's word
// is "no single node's word settles an order": min_confirmations=2 below // settles an order" — and because public RPCs differ by VANTAGE POINT, not
// makes both agree, same as the mainnet chains file. // just uptime: 1RPC answers residential IPs and 403s the Hetzner runner,
// which stalled the first CI run at 1-of-2 forever. Any two of three settle;
// the corroboration loop stops at quorum, so the third is only ever dialed
// when one of the first two fails.
constexpr std::string_view kRpcPrimary = "https://ethereum-sepolia-rpc.publicnode.com"; constexpr std::string_view kRpcPrimary = "https://ethereum-sepolia-rpc.publicnode.com";
constexpr std::string_view kRpcSecondary = "https://1rpc.io/sepolia"; constexpr std::string_view kRpcSecondary = "https://sepolia.gateway.tenderly.co";
constexpr std::string_view kRpcTertiary = "https://1rpc.io/sepolia";
// €1 donation = 100 cents = 100 × 10^(6-2) EURC base units. // €1 donation = 100 cents = 100 × 10^(6-2) EURC base units.
constexpr std::string_view kTransferUnits = "1000000"; constexpr std::string_view kTransferUnits = "1000000";
@ -144,11 +148,11 @@ int main(int argc, char** argv) {
const fs::path chains = dir / "chains.json"; const fs::path chains = dir / "chains.json";
WriteFile(chains, std::format( WriteFile(chains, std::format(
R"({{"chains":[{{"name":"ethereum-sepolia",)" R"({{"chains":[{{"name":"ethereum-sepolia",)"
R"("rpcs":["{}","{}"],)" R"("rpcs":["{}","{}","{}"],)"
R"("min_confirmations":2,)" R"("min_confirmations":2,)"
R"("contract":"{}","chain_id":{},)" R"("contract":"{}","chain_id":{},)"
R"("block_tag":"latest","note":"testnet"}}]}})", R"("block_tag":"latest","note":"testnet"}}]}})",
kRpcPrimary, kRpcSecondary, kContract, kChainId)); kRpcPrimary, kRpcSecondary, kRpcTertiary, kContract, kChainId));
// Fresh random addresses — see the header for why reuse would false-pass. // Fresh random addresses — see the header for why reuse would false-pass.
const fs::path pool = dir / "pool.txt"; const fs::path pool = dir / "pool.txt";

View file

@ -90,12 +90,18 @@ if [ -n "$CHAINS_SRC" ]; then
else else
# Several endpoints per chain, from DIFFERENT operators, because a payment # Several endpoints per chain, from DIFFERENT operators, because a payment
# is confirmed only when min_confirmations of them independently agree that # is confirmed only when min_confirmations of them independently agree that
# the money is there — no single node's word settles an order. Base gets # the money is there — no single node's word settles an order. THREE per
# three (Coinbase's own, Allnodes, Automata) so one being down still leaves # chain, always: public RPCs differ by VANTAGE POINT as well as uptime —
# a quorum; Ethereum gets two. All five were checked to answer # 1RPC answers residential IPs but 403s requests from Hetzner, which a
# eth_chainId AND a balanceOf eth_call at block_tag=finalized, which is # two-endpoint quorum polled from the Hetzner box can never survive (the
# what this rail actually asks of them (Cloudflare's endpoint refuses # CI testnet gate hit exactly this: 1-of-2 forever, order never settles).
# finalized eth_call, which is why it is not here). # Any two of three agreeing settle; the corroboration loop stops at
# quorum, so the third is only dialed when one of the first two fails.
# All were checked to answer eth_chainId AND a balanceOf eth_call at
# block_tag=finalized, which is what this rail actually asks of them
# (Cloudflare's endpoint refuses finalized eth_call, which is why it is
# not here) — but check them FROM THE BOX, not from home: that is the
# vantage point that matters.
cat > "$WORK/chains.json" <<'JSON' cat > "$WORK/chains.json" <<'JSON'
{"chains": [ {"chains": [
{"name": "base", {"name": "base",
@ -107,6 +113,7 @@ else
"chain_id": 8453, "note": "lowest network fees"}, "chain_id": 8453, "note": "lowest network fees"},
{"name": "ethereum", {"name": "ethereum",
"rpcs": ["https://ethereum-rpc.publicnode.com", "rpcs": ["https://ethereum-rpc.publicnode.com",
"https://mainnet.gateway.tenderly.co",
"https://1rpc.io/eth"], "https://1rpc.io/eth"],
"min_confirmations": 2, "min_confirmations": 2,
"contract": "0x1aBaEA1f7C830bD89Acc67eC4af516284b1bC33c", "contract": "0x1aBaEA1f7C830bD89Acc67eC4af516284b1bC33c",