[Ethereum] Calling a contract method on a specific block number using Go

contract-invocationgo-ethereum

Using the go-ethereum library, I'm able to call contract methods using the generated Go bindings:

balance, err := wallet.Balance(&bind.CallOpts{
    Pending: false,
    From:    sender,
    Context: ctx,
})

However, I'd like to make the above method call for a specific block number.

To do this I would need to do two things:

  1. Get the latest block number.

There doesn't seem to be a function to do this dirrectly with the Ethereum client https://godoc.org/github.com/ethereum/go-ethereum/ethclient.

In web3.js there's a getBlockNumber() method, but I couldn't find the equivalent in Go.

  1. Use the obtained block number to call the balance method on the smart contract.

The bind.CallOpts object doesn't allow you to specify the block number directly.

How would I go about achieving this using the go-ethereum library?

Best Answer

  1. Get the latest block number:

    blockHeader, err := ethClient.HeaderByNumber(context.Background(), nil)
    if err != nil {
        return err
    }
    
    log.Printf("Last block: %s", blockHeader.Number)
    
  2. Use the obtained block number to call the balance method on the smart contract:

    // import "github.com/ethereum/go-ethereum/common/hexutil"
    data, err := hexutil.Decode("0xb69ef8a8") // First 4 bytes of keccak256("balance()")
    if err != nil {
        return err
    }
    callMsg := ethereum.CallMsg{
        To:   contractAddress,
        Data: data,
    }
    response := ethClient.CallContract(context.Background(), callMsg, blockHeader.Number)
    

    You can specify any block number as *big.Int instead of blockHeader.Number.

Related Topic