Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion harnesses/bridge-monitor/cmd/monitor/onchain_balance.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,25 @@ func (tx *TxExecutor) erc20BalanceOf(chain string, token, owner common.Address)
}

// evmClientFor maps a Route chain name (Base / Arbitrum) to the cached ethclient.
func (tx *TxExecutor) evmClientFor(chain string) interface{ CallContract(context.Context, ethereum.CallMsg, *big.Int) ([]byte, error) } {
func (tx *TxExecutor) evmClientFor(chain string) interface {
CallContract(context.Context, ethereum.CallMsg, *big.Int) ([]byte, error)
} {
// Return a genuinely-nil interface when the concrete client failed to
// initialize. Returning a typed nil *ethclient.Client here would satisfy
// `client == nil` as FALSE in erc20BalanceOf (non-nil interface wrapping a
// nil pointer), then panic on CallContract. This is what crash-looped the
// VPS container when the portfolio API went down and the on-chain fallback
// ran against un-dialled EVM clients.
switch strings.ToLower(chain) {
case "base":
if tx.baseClient == nil {
return nil
}
return tx.baseClient
case "arbitrum":
if tx.arbitrumClient == nil {
return nil
}
return tx.arbitrumClient
}
return nil
Expand Down
19 changes: 19 additions & 0 deletions harnesses/bridge-monitor/cmd/monitor/onchain_balance_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package main

import (
"testing"

"github.com/ethereum/go-ethereum/common"
)

// TestErc20BalanceNilClientNoPanic guards the nil-interface trap that crash-
// looped the VPS: with un-dialled EVM clients, erc20BalanceOf must return an
// error, never panic on CallContract.
func TestErc20BalanceNilClientNoPanic(t *testing.T) {
tx := &TxExecutor{} // baseClient / arbitrumClient are nil
for _, chain := range []string{"base", "arbitrum"} {
if _, err := tx.erc20BalanceOf(chain, common.Address{}, common.Address{}); err == nil {
t.Errorf("%s: expected error for nil client, got nil (would have panicked)", chain)
}
}
}
Loading