Skip to content

AdminWallet init crashes process when all admin wallets are underfunded #574

Description

@goodbounties-nanoclaw-agent

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions