Geth 私有网络在执行简单合约时返回错误“invalid opcode: SELFBALANCE”

问题描述

我设置了一个简单的 Geth (v1.10.2-stable-97d11b01) 专用网络(genesis.json 下面的配置)。我编译并部署了这个简单的测试合约(solidity 版本:0.8.4+commit.c7e474f2.Emscripten.clang):

// SPDX-License-Identifier: UNLICENSED;
pragma solidity >=0.8;

contract CoinA {
    
    bytes32 public coinName = "FAKE";

    mapping (address => uint) public balances;

    function transfer(address receiver,uint amount) public {
        require(balances[msg.sender] >= amount,"Not enough amount");
        
        balances[msg.sender] -= amount;
        balances[receiver] += amount;
    }

    function set(uint amount) public {
        require(amount >= 0);
        balances[msg.sender] = amount;
    }

    function get() view public returns (uint) {
        return balances[msg.sender];
    }

}

但是,在调用 set 方法时,我收到此错误

UnhandledPromiseRejectionWarning:错误:返回错误:操作码无效:SELFBALANCE

请就如何解决此问题提出建议。是因为服务器没有支持该操作码的最新功能吗?无论如何,我可以在不使用该操作码的情况下编译代码吗?

如果相关,我在 Node 上使用 Web3JS 调用它:

    async function setCoin() {
        const contract = new w3.eth.Contract(abi,coinAddr);
        const query = contract.methods.set(1000);

        const tx: TransactionConfig = {
            data: query.encodeABI(),from: accpublicKey,};
        const gas = await w3.eth.estimateGas(tx);
        console.log("Estimate Gas: " + gas);
        tx.gas = gas;

        const signedTx = await w3.eth.accounts.signTransaction(tx,accPrivateKey);
        const result = await w3.eth.sendSignedTransaction(signedTx.rawTransaction);

        console.log("Done. Gas used: " + result.gasUsed);
    }

genesis.json 配置:

{
  "config": {
    "chainId": 5777,"homesteadBlock": 0,"eip150Block": 0,"eip155Block": 0,"eip158Block": 0,"byzantiumBlock": 0,"constantinopleBlock": 0,"petersburgBlock": 0,"clique": {
      "period": 15,"epoch": 30000
    }
  },"difficulty": "1","gasLimit": "10000000","exTradata": "0x00000000000000000000000000000000000000000000000000000000000000001ac7d6c5ecdd24067221a44ee839ba0b847058a30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000","alloc": {
    "1ac7d6c5ecdd24067221a44ee839ba0b847058a3": { "balance": "300000000000000000000000" },"485012dCc48219dbE955C39e1cee4b71F041d178": { "balance": "300000000000000000000000" },"ea673022022Ea39a635C7336c6deA8BFa97778D9": { "balance": "300000000000000000000000" }
  }
}

解决方法

selfbalance 操作码是在伊斯坦布尔链分叉 (source) 中实现的。

您需要在 genesis.json

中允许分叉
{
  "config": {
    "istanbulBlock": 0,