2

I setup a simple Geth (v1.10.2-stable-97d11b01) private network (genesis.json config below). I compiled and deployed this simple test contract (solidity version: 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];
    }

}

However, upon invoking the set method, I received this error:

UnhandledPromiseRejectionWarning: Error: Returned error: invalid opcode: SELFBALANCE

Please advice on how to fix this. Is it because the server doesn't have latest feature that support that opcode? Is there anyway I can compile the code without using that opcode?

I invoked it using Web3JS on Node if it's relevant:

    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:

{
  "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" }
  }
}
Luke Vo
  • 17,859
  • 21
  • 105
  • 181

1 Answers1

5

The selfbalance opcode was implemented in the Istanbul chain fork (source).

You need to allow the fork in your genesis.json

{
  "config": {
    "istanbulBlock": 0,
Petr Hejda
  • 40,554
  • 8
  • 72
  • 100
  • Thank you, it works! There is another problem, I now have another invalid opcode `DUP`. Is it good to simply use the latest chain fork? How do you get these info? My Google didn't come up with any useful info (i.e. what's the release/version roadmap, what is the mainnet fork currently is). Sorry if I ask stupid questions, I am new – Luke Vo May 03 '21 at 15:19
  • 1
    Not sure if you mean the original `DUP` or `DUP`. If you mean the newer `DUP`, it was added in the Berlin hardfork. The original I'm not sure ... How I got to the Istanbul fork: I googled "selfbalance ethereum opcode" and found the EIP-1884. Then I searched for "EIP-1884 hardfork" because I learned somewhere earlier that new opcodes get implemented mostly in hardforks... But it's a good idea to include all the forks first (not just the latest one), and experiment later. The forks define a diff of added/removed features - not the whole sum of them, so you need to include all forks. – Petr Hejda May 03 '21 at 15:40
  • Thanks you are correct, I have just tested it. I added Berlin hardfork to genesis but still have the problem, so I can confirm the forks are not the whole sum of them. I am using this [code](https://github.com/ethereum/go-ethereum/blob/master/params/config.go) to determine what forks there are for now. – Luke Vo May 03 '21 at 15:43
  • It looks like something's wrong with my Solc compiler because I have the same problem even on Ropsten testnet. I think there is no `DUP` opcode, just `DUP1` to `DUP16`. – Luke Vo May 03 '21 at 21:20