项目中使用 go-ethereum 相关接口与以太坊网络进行交互,本文整理了中间遇到的一些坑,方便后来人对应来排错。

代币转账

1. 调用合约方法时,报 Error: VM Exception while executing transaction: out of gas 的错误

可能原因:

  1. 对一个只读方法进行当成改值的方法执行了,比如 constant,view修饰的方法。
  2. 调用的合约方法有异常,有死循环之类的,造成消耗的gas过多。
  3. 第三个也就是笔者遇到的情况,接口中获取的预估价格(gasLimit)不准确,低于实际运行合约需要的gasLimit.

笔者的获取gasLimit是通过接口获取的,代码如下:

	gasLimit, err := cli.EstimateGas(context.Background(), ethereum.CallMsg{
		To:   &toAddress,
		Data: data,
	})

我们是合约转账交易,所以这个toAddress是接收者的地址,data是构造调用的全部数据。然而这个估值并不准确,往往比实际需要的gas要小,所以不得不放弃使用接口获取估值的方式。

最后通过把 gasLimit 改为最大值解决。

2. 调用合约方法,报 Error: VM Exception while executing transaction: revert 错误。

简而言之,方法id必须只截取前四个字节,没有截取,故发生了此报错。

笔者原先是根据这个指南 来实现的代币转账,代码是这样的:

hash := sha3.NewKeccak256()
hash.Write(transferFnSignature)
methodID := hash.Sum(nil)[:4]

新版本中sha3,已经没有 NewKeccak256 方法了,新版本放在了github.com/ethereum/go-ethereum/crypto包中

methodID := crypto.Keccak256(transferFnSignature)[:4]

在使用新接口时忘记了取前四个字节[:4],故造成悲剧。