// Copyright 2019 The go-ethereum Authors // This file is part of the go-ethereum library. // // The go-ethereum library is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // The go-ethereum library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . package backends import ( "context" "errors" "math/big" "strings" "testing" ethereum "github.com/XinFinOrg/XDPoSChain" "github.com/XinFinOrg/XDPoSChain/accounts/abi" "github.com/XinFinOrg/XDPoSChain/accounts/abi/bind" "github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/core" "github.com/XinFinOrg/XDPoSChain/core/types" "github.com/XinFinOrg/XDPoSChain/crypto" "github.com/XinFinOrg/XDPoSChain/params" ) func TestSimulatedBackend(t *testing.T) { var gasLimit uint64 = 8000029 key, _ := crypto.GenerateKey() // nolint: gosec auth := bind.NewKeyedTransactor(key) genAlloc := make(core.GenesisAlloc) genAlloc[auth.From] = core.GenesisAccount{Balance: big.NewInt(9223372036854775807)} sim := NewSimulatedBackend(genAlloc, gasLimit) defer sim.Close() // should return an error if the tx is not found txHash := common.HexToHash("2") _, isPending, err := sim.TransactionByHash(context.Background(), txHash) if isPending { t.Fatal("transaction should not be pending") } if err != ethereum.ErrNotFound { t.Fatalf("err should be `ethereum.ErrNotFound` but received %v", err) } // generate a transaction and confirm you can retrieve it code := `6060604052600a8060106000396000f360606040526008565b00` var gas uint64 = 3000000 tx := types.NewContractCreation(0, big.NewInt(0), gas, big.NewInt(1), common.FromHex(code)) tx, _ = types.SignTx(tx, types.HomesteadSigner{}, key) err = sim.SendTransaction(context.Background(), tx) if err != nil { t.Fatal("error sending transaction") } txHash = tx.Hash() _, isPending, err = sim.TransactionByHash(context.Background(), txHash) if err != nil { t.Fatalf("error getting transaction with hash: %v", txHash.String()) } if !isPending { t.Fatal("transaction should have pending status") } sim.Commit() tx, isPending, err = sim.TransactionByHash(context.Background(), txHash) if err != nil { t.Fatalf("error getting transaction with hash: %v", txHash.String()) } if isPending { t.Fatal("transaction should not have pending status") } } func TestSimulatedBackend_EstimateGas(t *testing.T) { /* pragma solidity ^0.6.4; contract GasEstimation { function PureRevert() public { revert(); } function Revert() public { revert("revert reason");} function OOG() public { for (uint i = 0; ; i++) {}} function Assert() public { assert(false);} function Valid() public {} }*/ const contractAbi = "[{\"inputs\":[],\"name\":\"Assert\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"OOG\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"PureRevert\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"Revert\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"Valid\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]" const contractBin = "0x60806040523480156100115760006000fd5b50610017565b61016e806100266000396000f3fe60806040523480156100115760006000fd5b506004361061005c5760003560e01c806350f6fe3414610062578063aa8b1d301461006c578063b9b046f914610076578063d8b9839114610080578063e09fface1461008a5761005c565b60006000fd5b61006a610094565b005b6100746100ad565b005b61007e6100b5565b005b6100886100c2565b005b610092610135565b005b6000600090505b5b808060010191505061009b565b505b565b60006000fd5b565b600015156100bf57fe5b5b565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600d8152602001807f72657665727420726561736f6e0000000000000000000000000000000000000081526020015060200191505060405180910390fd5b565b5b56fea2646970667358221220345bbcbb1a5ecf22b53a78eaebf95f8ee0eceff6d10d4b9643495084d2ec934a64736f6c63430006040033" key, _ := crypto.GenerateKey() addr := crypto.PubkeyToAddress(key.PublicKey) opts := bind.NewKeyedTransactor(key) sim := NewXDCSimulatedBackend(core.GenesisAlloc{addr: {Balance: big.NewInt(params.Ether)}}, 10000000, ¶ms.ChainConfig{ ConstantinopleBlock: big.NewInt(0), XDPoS: ¶ms.XDPoSConfig{ Epoch: 900, SkipV1Validation: true, V2: ¶ms.V2{ SwitchBlock: big.NewInt(900), CurrentConfig: params.UnitTestV2Configs[0], }, }, }) defer sim.Close() parsed, _ := abi.JSON(strings.NewReader(contractAbi)) contractAddr, _, _, _ := bind.DeployContract(opts, parsed, common.FromHex(contractBin), sim) sim.Commit() var cases = []struct { name string message ethereum.CallMsg expect uint64 expectError error }{ {"plain transfer(valid)", ethereum.CallMsg{ From: addr, To: &addr, Gas: 0, GasPrice: big.NewInt(0), Value: big.NewInt(1), Data: nil, }, params.TxGas, nil}, {"plain transfer(invalid)", ethereum.CallMsg{ From: addr, To: &contractAddr, Gas: 0, GasPrice: big.NewInt(0), Value: big.NewInt(1), Data: nil, }, 0, errors.New("always failing transaction (execution reverted)")}, {"Revert", ethereum.CallMsg{ From: addr, To: &contractAddr, Gas: 0, GasPrice: big.NewInt(0), Value: nil, Data: common.Hex2Bytes("d8b98391"), }, 0, errors.New("always failing transaction (execution reverted) (revert reason)")}, {"PureRevert", ethereum.CallMsg{ From: addr, To: &contractAddr, Gas: 0, GasPrice: big.NewInt(0), Value: nil, Data: common.Hex2Bytes("aa8b1d30"), }, 0, errors.New("always failing transaction (execution reverted)")}, {"OOG", ethereum.CallMsg{ From: addr, To: &contractAddr, Gas: 100000, GasPrice: big.NewInt(0), Value: nil, Data: common.Hex2Bytes("50f6fe34"), }, 0, errors.New("gas required exceeds allowance (100000)")}, {"Assert", ethereum.CallMsg{ From: addr, To: &contractAddr, Gas: 100000, GasPrice: big.NewInt(0), Value: nil, Data: common.Hex2Bytes("b9b046f9"), }, 0, errors.New("always failing transaction (invalid opcode: INVALID)")}, {"Valid", ethereum.CallMsg{ From: addr, To: &contractAddr, Gas: 100000, GasPrice: big.NewInt(0), Value: nil, Data: common.Hex2Bytes("e09fface"), }, 21483, nil}, } for _, c := range cases { got, err := sim.EstimateGas(context.Background(), c.message) if c.expectError != nil { if err == nil { t.Fatalf("Expect error, got nil") } if c.expectError.Error() != err.Error() { t.Fatalf("Expect error, want %v, got %v", c.expectError, err) } continue } if got != c.expect { t.Fatalf("Gas estimation mismatch, want %d, got %d", c.expect, got) } } }