Summary
GoodServer's AdminWallet.init() crashes the process (process.exit(-1)) when every configured admin wallet address is underfunded, instead of just alerting and continuing in a degraded state.
Repo / File
src/server/blockchain/Web3Wallet.js
Evidence
Production logs (Base network, chain 8453):
2026-08-17T06:19:23.036275+00:00 app[web.1]: {"logMessage":"2026-08-17T06:19:23.036Z - workerId:0 - info (FROM: slack userId: )","level":"info","timestamp":"2026-08-17T06:19:23.036Z","from":"slack","message":"slack alert sent:","context":[{"res":"ok","json":{"msg":"critical: no fuse admin wallet with funds BaseAdminWallet"}}]}
2026-08-17T06:19:23.049502+00:00 app[web.1]: {"logMessage":"2026-08-17T06:19:23.048Z - workerId:0 - error (FROM: BaseAdminWallet/8453 userId: )","level":"error","timestamp":"2026-08-17T06:19:23.048Z","from":"BaseAdminWallet/8453","message":"WalletInit: Error initializing wallet","context":["Provided address undefined is invalid, the capitalization checksum test failed, or it's an indirect IBAN address which can't be converted.",{"type":"Error","message":"Provided address undefined is invalid, the capitalization checksum test failed, or it's an indirect IBAN address which can't be converted.","stack":"Error: Provided address undefined is invalid, the capitalization checksum test failed, or it's an indirect IBAN address which can't be converted.\n at c.p (/app/dist/server.js:2:8892873)\n at /app/dist/server.js:2:8598565\n at Array.map (<anonymous>)\n at c.formatInput (/app/dist/server.js:2:8598535)\n at c.toPayload (/app/dist/server.js:2:8598906)\n at I.o [as getBalance] (/app/dist/server.js:2:8604303)\n at bo.init (/app/dist/server.js:2:2516591)\n at process.processTicksAndRejections (node:internal/process/task_queues:104:5)"}]}
Root cause
In Web3Wallet.js#init():
this.address is only ever assigned inside the address-selection loop (~line 393-402), and only when a wallet is found with isVerifiedAdmin && balance > minAdminBalance.
- When every configured admin wallet is underfunded, that condition never hits, so
this.address stays undefined. The code correctly detects filledAddresses.length === 0 and sends a Slack alert ("critical: no fuse admin wallet with funds") — that part works as intended.
- Execution continues past the alert, and ~140 lines later calls
this.web3.eth.getBalance(this.address) (line 486) with this.address still undefined. Web3's client-side address-checksum validator throws before any RPC call is dispatched.
- The thrown error is caught by the outer
catch in init(), logged, and since this.conf.env isn't test/development, process.exit(-1) is called (line 501-502) — crashing the whole dyno.
Note: this is unrelated to open PR #573 (RPC-fallback exception-shape fix in transport.js) — that PR addresses connection-error detection during RPC calls, while this crash happens client-side before any RPC call is made.
Proposed fix
When filledAddresses is empty, fall back to a default address (e.g. this.addresses[0]) for the native-balance/nonce reads and contract from bindings, and don't process.exit on this specific condition — an all-wallets-underfunded state is an expected operational condition (wallets pending top-up), not a fatal startup error. Keep the existing Slack alert unchanged.
Summary
GoodServer's
AdminWallet.init()crashes the process (process.exit(-1)) when every configured admin wallet address is underfunded, instead of just alerting and continuing in a degraded state.Repo / File
src/server/blockchain/Web3Wallet.jsEvidence
Production logs (Base network, chain 8453):
Root cause
In
Web3Wallet.js#init():this.addressis only ever assigned inside the address-selection loop (~line 393-402), and only when a wallet is found withisVerifiedAdmin && balance > minAdminBalance.this.addressstaysundefined. The code correctly detectsfilledAddresses.length === 0and sends a Slack alert ("critical: no fuse admin wallet with funds") — that part works as intended.this.web3.eth.getBalance(this.address)(line 486) withthis.addressstillundefined. Web3's client-side address-checksum validator throws before any RPC call is dispatched.catchininit(), logged, and sincethis.conf.envisn'ttest/development,process.exit(-1)is called (line 501-502) — crashing the whole dyno.Note: this is unrelated to open PR #573 (RPC-fallback exception-shape fix in
transport.js) — that PR addresses connection-error detection during RPC calls, while this crash happens client-side before any RPC call is made.Proposed fix
When
filledAddressesis empty, fall back to a default address (e.g.this.addresses[0]) for the native-balance/nonce reads and contractfrombindings, and don'tprocess.exiton this specific condition — an all-wallets-underfunded state is an expected operational condition (wallets pending top-up), not a fatal startup error. Keep the existing Slack alert unchanged.