github.com/zhiqiangxu/go-ethereum@v1.9.16-0.20210824055606-be91cfdebc48/accounts/abi/bind/backends/simulated_test.go (about)

     1  // Copyright 2019 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package backends
    18  
    19  import (
    20  	"bytes"
    21  	"context"
    22  	"errors"
    23  	"math/big"
    24  	"reflect"
    25  	"strings"
    26  	"testing"
    27  	"time"
    28  
    29  	"github.com/zhiqiangxu/go-ethereum"
    30  	"github.com/zhiqiangxu/go-ethereum/accounts/abi"
    31  	"github.com/zhiqiangxu/go-ethereum/accounts/abi/bind"
    32  	"github.com/zhiqiangxu/go-ethereum/common"
    33  	"github.com/zhiqiangxu/go-ethereum/core"
    34  	"github.com/zhiqiangxu/go-ethereum/core/types"
    35  	"github.com/zhiqiangxu/go-ethereum/crypto"
    36  	"github.com/zhiqiangxu/go-ethereum/params"
    37  )
    38  
    39  func TestSimulatedBackend(t *testing.T) {
    40  	var gasLimit uint64 = 8000029
    41  	key, _ := crypto.GenerateKey() // nolint: gosec
    42  	auth := bind.NewKeyedTransactor(key)
    43  	genAlloc := make(core.GenesisAlloc)
    44  	genAlloc[auth.From] = core.GenesisAccount{Balance: big.NewInt(9223372036854775807)}
    45  
    46  	sim := NewSimulatedBackend(genAlloc, gasLimit)
    47  	defer sim.Close()
    48  
    49  	// should return an error if the tx is not found
    50  	txHash := common.HexToHash("2")
    51  	_, isPending, err := sim.TransactionByHash(context.Background(), txHash)
    52  
    53  	if isPending {
    54  		t.Fatal("transaction should not be pending")
    55  	}
    56  	if err != ethereum.NotFound {
    57  		t.Fatalf("err should be `ethereum.NotFound` but received %v", err)
    58  	}
    59  
    60  	// generate a transaction and confirm you can retrieve it
    61  	code := `6060604052600a8060106000396000f360606040526008565b00`
    62  	var gas uint64 = 3000000
    63  	tx := types.NewContractCreation(0, big.NewInt(0), gas, big.NewInt(1), common.FromHex(code))
    64  	tx, _ = types.SignTx(tx, types.HomesteadSigner{}, key)
    65  
    66  	err = sim.SendTransaction(context.Background(), tx)
    67  	if err != nil {
    68  		t.Fatal("error sending transaction")
    69  	}
    70  
    71  	txHash = tx.Hash()
    72  	_, isPending, err = sim.TransactionByHash(context.Background(), txHash)
    73  	if err != nil {
    74  		t.Fatalf("error getting transaction with hash: %v", txHash.String())
    75  	}
    76  	if !isPending {
    77  		t.Fatal("transaction should have pending status")
    78  	}
    79  
    80  	sim.Commit()
    81  	_, isPending, err = sim.TransactionByHash(context.Background(), txHash)
    82  	if err != nil {
    83  		t.Fatalf("error getting transaction with hash: %v", txHash.String())
    84  	}
    85  	if isPending {
    86  		t.Fatal("transaction should not have pending status")
    87  	}
    88  }
    89  
    90  var testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
    91  
    92  //  the following is based on this contract:
    93  //  contract T {
    94  //  	event received(address sender, uint amount, bytes memo);
    95  //  	event receivedAddr(address sender);
    96  //
    97  //  	function receive(bytes calldata memo) external payable returns (string memory res) {
    98  //  		emit received(msg.sender, msg.value, memo);
    99  //  		emit receivedAddr(msg.sender);
   100  //		    return "hello world";
   101  //  	}
   102  //  }
   103  const abiJSON = `[ { "constant": false, "inputs": [ { "name": "memo", "type": "bytes" } ], "name": "receive", "outputs": [ { "name": "res", "type": "string" } ], "payable": true, "stateMutability": "payable", "type": "function" }, { "anonymous": false, "inputs": [ { "indexed": false, "name": "sender", "type": "address" }, { "indexed": false, "name": "amount", "type": "uint256" }, { "indexed": false, "name": "memo", "type": "bytes" } ], "name": "received", "type": "event" }, { "anonymous": false, "inputs": [ { "indexed": false, "name": "sender", "type": "address" } ], "name": "receivedAddr", "type": "event" } ]`
   104  const abiBin = `0x608060405234801561001057600080fd5b506102a0806100206000396000f3fe60806040526004361061003b576000357c010000000000000000000000000000000000000000000000000000000090048063a69b6ed014610040575b600080fd5b6100b76004803603602081101561005657600080fd5b810190808035906020019064010000000081111561007357600080fd5b82018360208201111561008557600080fd5b803590602001918460018302840111640100000000831117156100a757600080fd5b9091929391929390505050610132565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f75780820151818401526020810190506100dc565b50505050905090810190601f1680156101245780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b60607f75fd880d39c1daf53b6547ab6cb59451fc6452d27caa90e5b6649dd8293b9eed33348585604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f8201169050808301925050509550505050505060405180910390a17f46923992397eac56cf13058aced2a1871933622717e27b24eabc13bf9dd329c833604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a16040805190810160405280600b81526020017f68656c6c6f20776f726c6400000000000000000000000000000000000000000081525090509291505056fea165627a7a72305820ff0c57dad254cfeda48c9cfb47f1353a558bccb4d1bc31da1dae69315772d29e0029`
   105  const deployedCode = `60806040526004361061003b576000357c010000000000000000000000000000000000000000000000000000000090048063a69b6ed014610040575b600080fd5b6100b76004803603602081101561005657600080fd5b810190808035906020019064010000000081111561007357600080fd5b82018360208201111561008557600080fd5b803590602001918460018302840111640100000000831117156100a757600080fd5b9091929391929390505050610132565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f75780820151818401526020810190506100dc565b50505050905090810190601f1680156101245780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b60607f75fd880d39c1daf53b6547ab6cb59451fc6452d27caa90e5b6649dd8293b9eed33348585604051808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001848152602001806020018281038252848482818152602001925080828437600081840152601f19601f8201169050808301925050509550505050505060405180910390a17f46923992397eac56cf13058aced2a1871933622717e27b24eabc13bf9dd329c833604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a16040805190810160405280600b81526020017f68656c6c6f20776f726c6400000000000000000000000000000000000000000081525090509291505056fea165627a7a72305820ff0c57dad254cfeda48c9cfb47f1353a558bccb4d1bc31da1dae69315772d29e0029`
   106  
   107  // expected return value contains "hello world"
   108  var expectedReturn = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
   109  
   110  func simTestBackend(testAddr common.Address) *SimulatedBackend {
   111  	return NewSimulatedBackend(
   112  		core.GenesisAlloc{
   113  			testAddr: {Balance: big.NewInt(10000000000)},
   114  		}, 10000000,
   115  	)
   116  }
   117  
   118  func TestNewSimulatedBackend(t *testing.T) {
   119  	testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
   120  	expectedBal := big.NewInt(10000000000)
   121  	sim := simTestBackend(testAddr)
   122  	defer sim.Close()
   123  
   124  	if sim.config != params.AllEthashProtocolChanges {
   125  		t.Errorf("expected sim config to equal params.AllEthashProtocolChanges, got %v", sim.config)
   126  	}
   127  
   128  	if sim.blockchain.Config() != params.AllEthashProtocolChanges {
   129  		t.Errorf("expected sim blockchain config to equal params.AllEthashProtocolChanges, got %v", sim.config)
   130  	}
   131  
   132  	statedb, _ := sim.blockchain.State()
   133  	bal := statedb.GetBalance(testAddr)
   134  	if bal.Cmp(expectedBal) != 0 {
   135  		t.Errorf("expected balance for test address not received. expected: %v actual: %v", expectedBal, bal)
   136  	}
   137  }
   138  
   139  func TestSimulatedBackend_AdjustTime(t *testing.T) {
   140  	sim := NewSimulatedBackend(
   141  		core.GenesisAlloc{}, 10000000,
   142  	)
   143  	defer sim.Close()
   144  
   145  	prevTime := sim.pendingBlock.Time()
   146  	err := sim.AdjustTime(time.Second)
   147  	if err != nil {
   148  		t.Error(err)
   149  	}
   150  	newTime := sim.pendingBlock.Time()
   151  
   152  	if newTime-prevTime != uint64(time.Second.Seconds()) {
   153  		t.Errorf("adjusted time not equal to a second. prev: %v, new: %v", prevTime, newTime)
   154  	}
   155  }
   156  
   157  func TestSimulatedBackend_BalanceAt(t *testing.T) {
   158  	testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
   159  	expectedBal := big.NewInt(10000000000)
   160  	sim := simTestBackend(testAddr)
   161  	defer sim.Close()
   162  	bgCtx := context.Background()
   163  
   164  	bal, err := sim.BalanceAt(bgCtx, testAddr, nil)
   165  	if err != nil {
   166  		t.Error(err)
   167  	}
   168  
   169  	if bal.Cmp(expectedBal) != 0 {
   170  		t.Errorf("expected balance for test address not received. expected: %v actual: %v", expectedBal, bal)
   171  	}
   172  }
   173  
   174  func TestSimulatedBackend_BlockByHash(t *testing.T) {
   175  	sim := NewSimulatedBackend(
   176  		core.GenesisAlloc{}, 10000000,
   177  	)
   178  	defer sim.Close()
   179  	bgCtx := context.Background()
   180  
   181  	block, err := sim.BlockByNumber(bgCtx, nil)
   182  	if err != nil {
   183  		t.Errorf("could not get recent block: %v", err)
   184  	}
   185  	blockByHash, err := sim.BlockByHash(bgCtx, block.Hash())
   186  	if err != nil {
   187  		t.Errorf("could not get recent block: %v", err)
   188  	}
   189  
   190  	if block.Hash() != blockByHash.Hash() {
   191  		t.Errorf("did not get expected block")
   192  	}
   193  }
   194  
   195  func TestSimulatedBackend_BlockByNumber(t *testing.T) {
   196  	sim := NewSimulatedBackend(
   197  		core.GenesisAlloc{}, 10000000,
   198  	)
   199  	defer sim.Close()
   200  	bgCtx := context.Background()
   201  
   202  	block, err := sim.BlockByNumber(bgCtx, nil)
   203  	if err != nil {
   204  		t.Errorf("could not get recent block: %v", err)
   205  	}
   206  	if block.NumberU64() != 0 {
   207  		t.Errorf("did not get most recent block, instead got block number %v", block.NumberU64())
   208  	}
   209  
   210  	// create one block
   211  	sim.Commit()
   212  
   213  	block, err = sim.BlockByNumber(bgCtx, nil)
   214  	if err != nil {
   215  		t.Errorf("could not get recent block: %v", err)
   216  	}
   217  	if block.NumberU64() != 1 {
   218  		t.Errorf("did not get most recent block, instead got block number %v", block.NumberU64())
   219  	}
   220  
   221  	blockByNumber, err := sim.BlockByNumber(bgCtx, big.NewInt(1))
   222  	if err != nil {
   223  		t.Errorf("could not get block by number: %v", err)
   224  	}
   225  	if blockByNumber.Hash() != block.Hash() {
   226  		t.Errorf("did not get the same block with height of 1 as before")
   227  	}
   228  }
   229  
   230  func TestSimulatedBackend_NonceAt(t *testing.T) {
   231  	testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
   232  
   233  	sim := simTestBackend(testAddr)
   234  	defer sim.Close()
   235  	bgCtx := context.Background()
   236  
   237  	nonce, err := sim.NonceAt(bgCtx, testAddr, big.NewInt(0))
   238  	if err != nil {
   239  		t.Errorf("could not get nonce for test addr: %v", err)
   240  	}
   241  
   242  	if nonce != uint64(0) {
   243  		t.Errorf("received incorrect nonce. expected 0, got %v", nonce)
   244  	}
   245  
   246  	// create a signed transaction to send
   247  	tx := types.NewTransaction(nonce, testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil)
   248  	signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey)
   249  	if err != nil {
   250  		t.Errorf("could not sign tx: %v", err)
   251  	}
   252  
   253  	// send tx to simulated backend
   254  	err = sim.SendTransaction(bgCtx, signedTx)
   255  	if err != nil {
   256  		t.Errorf("could not add tx to pending block: %v", err)
   257  	}
   258  	sim.Commit()
   259  
   260  	newNonce, err := sim.NonceAt(bgCtx, testAddr, big.NewInt(1))
   261  	if err != nil {
   262  		t.Errorf("could not get nonce for test addr: %v", err)
   263  	}
   264  
   265  	if newNonce != nonce+uint64(1) {
   266  		t.Errorf("received incorrect nonce. expected 1, got %v", nonce)
   267  	}
   268  	// create some more blocks
   269  	sim.Commit()
   270  	// Check that we can get data for an older block/state
   271  	newNonce, err = sim.NonceAt(bgCtx, testAddr, big.NewInt(1))
   272  	if err != nil {
   273  		t.Fatalf("could not get nonce for test addr: %v", err)
   274  	}
   275  	if newNonce != nonce+uint64(1) {
   276  		t.Fatalf("received incorrect nonce. expected 1, got %v", nonce)
   277  	}
   278  }
   279  
   280  func TestSimulatedBackend_SendTransaction(t *testing.T) {
   281  	testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
   282  
   283  	sim := simTestBackend(testAddr)
   284  	defer sim.Close()
   285  	bgCtx := context.Background()
   286  
   287  	// create a signed transaction to send
   288  	tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil)
   289  	signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey)
   290  	if err != nil {
   291  		t.Errorf("could not sign tx: %v", err)
   292  	}
   293  
   294  	// send tx to simulated backend
   295  	err = sim.SendTransaction(bgCtx, signedTx)
   296  	if err != nil {
   297  		t.Errorf("could not add tx to pending block: %v", err)
   298  	}
   299  	sim.Commit()
   300  
   301  	block, err := sim.BlockByNumber(bgCtx, big.NewInt(1))
   302  	if err != nil {
   303  		t.Errorf("could not get block at height 1: %v", err)
   304  	}
   305  
   306  	if signedTx.Hash() != block.Transactions()[0].Hash() {
   307  		t.Errorf("did not commit sent transaction. expected hash %v got hash %v", block.Transactions()[0].Hash(), signedTx.Hash())
   308  	}
   309  }
   310  
   311  func TestSimulatedBackend_TransactionByHash(t *testing.T) {
   312  	testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
   313  
   314  	sim := NewSimulatedBackend(
   315  		core.GenesisAlloc{
   316  			testAddr: {Balance: big.NewInt(10000000000)},
   317  		}, 10000000,
   318  	)
   319  	defer sim.Close()
   320  	bgCtx := context.Background()
   321  
   322  	// create a signed transaction to send
   323  	tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil)
   324  	signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey)
   325  	if err != nil {
   326  		t.Errorf("could not sign tx: %v", err)
   327  	}
   328  
   329  	// send tx to simulated backend
   330  	err = sim.SendTransaction(bgCtx, signedTx)
   331  	if err != nil {
   332  		t.Errorf("could not add tx to pending block: %v", err)
   333  	}
   334  
   335  	// ensure tx is committed pending
   336  	receivedTx, pending, err := sim.TransactionByHash(bgCtx, signedTx.Hash())
   337  	if err != nil {
   338  		t.Errorf("could not get transaction by hash %v: %v", signedTx.Hash(), err)
   339  	}
   340  	if !pending {
   341  		t.Errorf("expected transaction to be in pending state")
   342  	}
   343  	if receivedTx.Hash() != signedTx.Hash() {
   344  		t.Errorf("did not received committed transaction. expected hash %v got hash %v", signedTx.Hash(), receivedTx.Hash())
   345  	}
   346  
   347  	sim.Commit()
   348  
   349  	// ensure tx is not and committed pending
   350  	receivedTx, pending, err = sim.TransactionByHash(bgCtx, signedTx.Hash())
   351  	if err != nil {
   352  		t.Errorf("could not get transaction by hash %v: %v", signedTx.Hash(), err)
   353  	}
   354  	if pending {
   355  		t.Errorf("expected transaction to not be in pending state")
   356  	}
   357  	if receivedTx.Hash() != signedTx.Hash() {
   358  		t.Errorf("did not received committed transaction. expected hash %v got hash %v", signedTx.Hash(), receivedTx.Hash())
   359  	}
   360  }
   361  
   362  func TestSimulatedBackend_EstimateGas(t *testing.T) {
   363  	/*
   364  		pragma solidity ^0.6.4;
   365  		contract GasEstimation {
   366  		    function PureRevert() public { revert(); }
   367  		    function Revert() public { revert("revert reason");}
   368  		    function OOG() public { for (uint i = 0; ; i++) {}}
   369  		    function Assert() public { assert(false);}
   370  		    function Valid() public {}
   371  		}*/
   372  	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\"}]"
   373  	const contractBin = "0x60806040523480156100115760006000fd5b50610017565b61016e806100266000396000f3fe60806040523480156100115760006000fd5b506004361061005c5760003560e01c806350f6fe3414610062578063aa8b1d301461006c578063b9b046f914610076578063d8b9839114610080578063e09fface1461008a5761005c565b60006000fd5b61006a610094565b005b6100746100ad565b005b61007e6100b5565b005b6100886100c2565b005b610092610135565b005b6000600090505b5b808060010191505061009b565b505b565b60006000fd5b565b600015156100bf57fe5b5b565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600d8152602001807f72657665727420726561736f6e0000000000000000000000000000000000000081526020015060200191505060405180910390fd5b565b5b56fea2646970667358221220345bbcbb1a5ecf22b53a78eaebf95f8ee0eceff6d10d4b9643495084d2ec934a64736f6c63430006040033"
   374  
   375  	key, _ := crypto.GenerateKey()
   376  	addr := crypto.PubkeyToAddress(key.PublicKey)
   377  	opts := bind.NewKeyedTransactor(key)
   378  
   379  	sim := NewSimulatedBackend(core.GenesisAlloc{addr: {Balance: big.NewInt(params.Ether)}}, 10000000)
   380  	defer sim.Close()
   381  
   382  	parsed, _ := abi.JSON(strings.NewReader(contractAbi))
   383  	contractAddr, _, _, _ := bind.DeployContract(opts, parsed, common.FromHex(contractBin), sim)
   384  	sim.Commit()
   385  
   386  	var cases = []struct {
   387  		name        string
   388  		message     ethereum.CallMsg
   389  		expect      uint64
   390  		expectError error
   391  		expectData  interface{}
   392  	}{
   393  		{"plain transfer(valid)", ethereum.CallMsg{
   394  			From:     addr,
   395  			To:       &addr,
   396  			Gas:      0,
   397  			GasPrice: big.NewInt(0),
   398  			Value:    big.NewInt(1),
   399  			Data:     nil,
   400  		}, params.TxGas, nil, nil},
   401  
   402  		{"plain transfer(invalid)", ethereum.CallMsg{
   403  			From:     addr,
   404  			To:       &contractAddr,
   405  			Gas:      0,
   406  			GasPrice: big.NewInt(0),
   407  			Value:    big.NewInt(1),
   408  			Data:     nil,
   409  		}, 0, errors.New("execution reverted"), nil},
   410  
   411  		{"Revert", ethereum.CallMsg{
   412  			From:     addr,
   413  			To:       &contractAddr,
   414  			Gas:      0,
   415  			GasPrice: big.NewInt(0),
   416  			Value:    nil,
   417  			Data:     common.Hex2Bytes("d8b98391"),
   418  		}, 0, errors.New("execution reverted: revert reason"), "0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000d72657665727420726561736f6e00000000000000000000000000000000000000"},
   419  
   420  		{"PureRevert", ethereum.CallMsg{
   421  			From:     addr,
   422  			To:       &contractAddr,
   423  			Gas:      0,
   424  			GasPrice: big.NewInt(0),
   425  			Value:    nil,
   426  			Data:     common.Hex2Bytes("aa8b1d30"),
   427  		}, 0, errors.New("execution reverted"), nil},
   428  
   429  		{"OOG", ethereum.CallMsg{
   430  			From:     addr,
   431  			To:       &contractAddr,
   432  			Gas:      100000,
   433  			GasPrice: big.NewInt(0),
   434  			Value:    nil,
   435  			Data:     common.Hex2Bytes("50f6fe34"),
   436  		}, 0, errors.New("gas required exceeds allowance (100000)"), nil},
   437  
   438  		{"Assert", ethereum.CallMsg{
   439  			From:     addr,
   440  			To:       &contractAddr,
   441  			Gas:      100000,
   442  			GasPrice: big.NewInt(0),
   443  			Value:    nil,
   444  			Data:     common.Hex2Bytes("b9b046f9"),
   445  		}, 0, errors.New("invalid opcode: opcode 0xfe not defined"), nil},
   446  
   447  		{"Valid", ethereum.CallMsg{
   448  			From:     addr,
   449  			To:       &contractAddr,
   450  			Gas:      100000,
   451  			GasPrice: big.NewInt(0),
   452  			Value:    nil,
   453  			Data:     common.Hex2Bytes("e09fface"),
   454  		}, 21275, nil, nil},
   455  	}
   456  	for _, c := range cases {
   457  		got, err := sim.EstimateGas(context.Background(), c.message)
   458  		if c.expectError != nil {
   459  			if err == nil {
   460  				t.Fatalf("Expect error, got nil")
   461  			}
   462  			if c.expectError.Error() != err.Error() {
   463  				t.Fatalf("Expect error, want %v, got %v", c.expectError, err)
   464  			}
   465  			if c.expectData != nil {
   466  				if err, ok := err.(*revertError); !ok {
   467  					t.Fatalf("Expect revert error, got %T", err)
   468  				} else if !reflect.DeepEqual(err.ErrorData(), c.expectData) {
   469  					t.Fatalf("Error data mismatch, want %v, got %v", c.expectData, err.ErrorData())
   470  				}
   471  			}
   472  			continue
   473  		}
   474  		if got != c.expect {
   475  			t.Fatalf("Gas estimation mismatch, want %d, got %d", c.expect, got)
   476  		}
   477  	}
   478  }
   479  
   480  func TestSimulatedBackend_EstimateGasWithPrice(t *testing.T) {
   481  	key, _ := crypto.GenerateKey()
   482  	addr := crypto.PubkeyToAddress(key.PublicKey)
   483  
   484  	sim := NewSimulatedBackend(core.GenesisAlloc{addr: {Balance: big.NewInt(params.Ether*2 + 2e17)}}, 10000000)
   485  	defer sim.Close()
   486  
   487  	receipant := common.HexToAddress("deadbeef")
   488  	var cases = []struct {
   489  		name        string
   490  		message     ethereum.CallMsg
   491  		expect      uint64
   492  		expectError error
   493  	}{
   494  		{"EstimateWithoutPrice", ethereum.CallMsg{
   495  			From:     addr,
   496  			To:       &receipant,
   497  			Gas:      0,
   498  			GasPrice: big.NewInt(0),
   499  			Value:    big.NewInt(1000),
   500  			Data:     nil,
   501  		}, 21000, nil},
   502  
   503  		{"EstimateWithPrice", ethereum.CallMsg{
   504  			From:     addr,
   505  			To:       &receipant,
   506  			Gas:      0,
   507  			GasPrice: big.NewInt(1000),
   508  			Value:    big.NewInt(1000),
   509  			Data:     nil,
   510  		}, 21000, nil},
   511  
   512  		{"EstimateWithVeryHighPrice", ethereum.CallMsg{
   513  			From:     addr,
   514  			To:       &receipant,
   515  			Gas:      0,
   516  			GasPrice: big.NewInt(1e14), // gascost = 2.1ether
   517  			Value:    big.NewInt(1e17), // the remaining balance for fee is 2.1ether
   518  			Data:     nil,
   519  		}, 21000, nil},
   520  
   521  		{"EstimateWithSuperhighPrice", ethereum.CallMsg{
   522  			From:     addr,
   523  			To:       &receipant,
   524  			Gas:      0,
   525  			GasPrice: big.NewInt(2e14), // gascost = 4.2ether
   526  			Value:    big.NewInt(1000),
   527  			Data:     nil,
   528  		}, 21000, errors.New("gas required exceeds allowance (10999)")}, // 10999=(2.2ether-1000wei)/(2e14)
   529  	}
   530  	for _, c := range cases {
   531  		got, err := sim.EstimateGas(context.Background(), c.message)
   532  		if c.expectError != nil {
   533  			if err == nil {
   534  				t.Fatalf("Expect error, got nil")
   535  			}
   536  			if c.expectError.Error() != err.Error() {
   537  				t.Fatalf("Expect error, want %v, got %v", c.expectError, err)
   538  			}
   539  			continue
   540  		}
   541  		if got != c.expect {
   542  			t.Fatalf("Gas estimation mismatch, want %d, got %d", c.expect, got)
   543  		}
   544  	}
   545  }
   546  
   547  func TestSimulatedBackend_HeaderByHash(t *testing.T) {
   548  	testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
   549  
   550  	sim := simTestBackend(testAddr)
   551  	defer sim.Close()
   552  	bgCtx := context.Background()
   553  
   554  	header, err := sim.HeaderByNumber(bgCtx, nil)
   555  	if err != nil {
   556  		t.Errorf("could not get recent block: %v", err)
   557  	}
   558  	headerByHash, err := sim.HeaderByHash(bgCtx, header.Hash())
   559  	if err != nil {
   560  		t.Errorf("could not get recent block: %v", err)
   561  	}
   562  
   563  	if header.Hash() != headerByHash.Hash() {
   564  		t.Errorf("did not get expected block")
   565  	}
   566  }
   567  
   568  func TestSimulatedBackend_HeaderByNumber(t *testing.T) {
   569  	testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
   570  
   571  	sim := simTestBackend(testAddr)
   572  	defer sim.Close()
   573  	bgCtx := context.Background()
   574  
   575  	latestBlockHeader, err := sim.HeaderByNumber(bgCtx, nil)
   576  	if err != nil {
   577  		t.Errorf("could not get header for tip of chain: %v", err)
   578  	}
   579  	if latestBlockHeader == nil {
   580  		t.Errorf("received a nil block header")
   581  	}
   582  	if latestBlockHeader.Number.Uint64() != uint64(0) {
   583  		t.Errorf("expected block header number 0, instead got %v", latestBlockHeader.Number.Uint64())
   584  	}
   585  
   586  	sim.Commit()
   587  
   588  	latestBlockHeader, err = sim.HeaderByNumber(bgCtx, nil)
   589  	if err != nil {
   590  		t.Errorf("could not get header for blockheight of 1: %v", err)
   591  	}
   592  
   593  	blockHeader, err := sim.HeaderByNumber(bgCtx, big.NewInt(1))
   594  	if err != nil {
   595  		t.Errorf("could not get header for blockheight of 1: %v", err)
   596  	}
   597  
   598  	if blockHeader.Hash() != latestBlockHeader.Hash() {
   599  		t.Errorf("block header and latest block header are not the same")
   600  	}
   601  	if blockHeader.Number.Int64() != int64(1) {
   602  		t.Errorf("did not get blockheader for block 1. instead got block %v", blockHeader.Number.Int64())
   603  	}
   604  
   605  	block, err := sim.BlockByNumber(bgCtx, big.NewInt(1))
   606  	if err != nil {
   607  		t.Errorf("could not get block for blockheight of 1: %v", err)
   608  	}
   609  
   610  	if block.Hash() != blockHeader.Hash() {
   611  		t.Errorf("block hash and block header hash do not match. expected %v, got %v", block.Hash(), blockHeader.Hash())
   612  	}
   613  }
   614  
   615  func TestSimulatedBackend_TransactionCount(t *testing.T) {
   616  	testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
   617  
   618  	sim := simTestBackend(testAddr)
   619  	defer sim.Close()
   620  	bgCtx := context.Background()
   621  	currentBlock, err := sim.BlockByNumber(bgCtx, nil)
   622  	if err != nil || currentBlock == nil {
   623  		t.Error("could not get current block")
   624  	}
   625  
   626  	count, err := sim.TransactionCount(bgCtx, currentBlock.Hash())
   627  	if err != nil {
   628  		t.Error("could not get current block's transaction count")
   629  	}
   630  
   631  	if count != 0 {
   632  		t.Errorf("expected transaction count of %v does not match actual count of %v", 0, count)
   633  	}
   634  
   635  	// create a signed transaction to send
   636  	tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil)
   637  	signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey)
   638  	if err != nil {
   639  		t.Errorf("could not sign tx: %v", err)
   640  	}
   641  
   642  	// send tx to simulated backend
   643  	err = sim.SendTransaction(bgCtx, signedTx)
   644  	if err != nil {
   645  		t.Errorf("could not add tx to pending block: %v", err)
   646  	}
   647  
   648  	sim.Commit()
   649  
   650  	lastBlock, err := sim.BlockByNumber(bgCtx, nil)
   651  	if err != nil {
   652  		t.Errorf("could not get header for tip of chain: %v", err)
   653  	}
   654  
   655  	count, err = sim.TransactionCount(bgCtx, lastBlock.Hash())
   656  	if err != nil {
   657  		t.Error("could not get current block's transaction count")
   658  	}
   659  
   660  	if count != 1 {
   661  		t.Errorf("expected transaction count of %v does not match actual count of %v", 1, count)
   662  	}
   663  }
   664  
   665  func TestSimulatedBackend_TransactionInBlock(t *testing.T) {
   666  	testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
   667  
   668  	sim := simTestBackend(testAddr)
   669  	defer sim.Close()
   670  	bgCtx := context.Background()
   671  
   672  	transaction, err := sim.TransactionInBlock(bgCtx, sim.pendingBlock.Hash(), uint(0))
   673  	if err == nil && err != errTransactionDoesNotExist {
   674  		t.Errorf("expected a transaction does not exist error to be received but received %v", err)
   675  	}
   676  	if transaction != nil {
   677  		t.Errorf("expected transaction to be nil but received %v", transaction)
   678  	}
   679  
   680  	// expect pending nonce to be 0 since account has not been used
   681  	pendingNonce, err := sim.PendingNonceAt(bgCtx, testAddr)
   682  	if err != nil {
   683  		t.Errorf("did not get the pending nonce: %v", err)
   684  	}
   685  
   686  	if pendingNonce != uint64(0) {
   687  		t.Errorf("expected pending nonce of 0 got %v", pendingNonce)
   688  	}
   689  
   690  	// create a signed transaction to send
   691  	tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil)
   692  	signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey)
   693  	if err != nil {
   694  		t.Errorf("could not sign tx: %v", err)
   695  	}
   696  
   697  	// send tx to simulated backend
   698  	err = sim.SendTransaction(bgCtx, signedTx)
   699  	if err != nil {
   700  		t.Errorf("could not add tx to pending block: %v", err)
   701  	}
   702  
   703  	sim.Commit()
   704  
   705  	lastBlock, err := sim.BlockByNumber(bgCtx, nil)
   706  	if err != nil {
   707  		t.Errorf("could not get header for tip of chain: %v", err)
   708  	}
   709  
   710  	transaction, err = sim.TransactionInBlock(bgCtx, lastBlock.Hash(), uint(1))
   711  	if err == nil && err != errTransactionDoesNotExist {
   712  		t.Errorf("expected a transaction does not exist error to be received but received %v", err)
   713  	}
   714  	if transaction != nil {
   715  		t.Errorf("expected transaction to be nil but received %v", transaction)
   716  	}
   717  
   718  	transaction, err = sim.TransactionInBlock(bgCtx, lastBlock.Hash(), uint(0))
   719  	if err != nil {
   720  		t.Errorf("could not get transaction in the lastest block with hash %v: %v", lastBlock.Hash().String(), err)
   721  	}
   722  
   723  	if signedTx.Hash().String() != transaction.Hash().String() {
   724  		t.Errorf("received transaction that did not match the sent transaction. expected hash %v, got hash %v", signedTx.Hash().String(), transaction.Hash().String())
   725  	}
   726  }
   727  
   728  func TestSimulatedBackend_PendingNonceAt(t *testing.T) {
   729  	testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
   730  
   731  	sim := simTestBackend(testAddr)
   732  	defer sim.Close()
   733  	bgCtx := context.Background()
   734  
   735  	// expect pending nonce to be 0 since account has not been used
   736  	pendingNonce, err := sim.PendingNonceAt(bgCtx, testAddr)
   737  	if err != nil {
   738  		t.Errorf("did not get the pending nonce: %v", err)
   739  	}
   740  
   741  	if pendingNonce != uint64(0) {
   742  		t.Errorf("expected pending nonce of 0 got %v", pendingNonce)
   743  	}
   744  
   745  	// create a signed transaction to send
   746  	tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil)
   747  	signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey)
   748  	if err != nil {
   749  		t.Errorf("could not sign tx: %v", err)
   750  	}
   751  
   752  	// send tx to simulated backend
   753  	err = sim.SendTransaction(bgCtx, signedTx)
   754  	if err != nil {
   755  		t.Errorf("could not add tx to pending block: %v", err)
   756  	}
   757  
   758  	// expect pending nonce to be 1 since account has submitted one transaction
   759  	pendingNonce, err = sim.PendingNonceAt(bgCtx, testAddr)
   760  	if err != nil {
   761  		t.Errorf("did not get the pending nonce: %v", err)
   762  	}
   763  
   764  	if pendingNonce != uint64(1) {
   765  		t.Errorf("expected pending nonce of 1 got %v", pendingNonce)
   766  	}
   767  
   768  	// make a new transaction with a nonce of 1
   769  	tx = types.NewTransaction(uint64(1), testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil)
   770  	signedTx, err = types.SignTx(tx, types.HomesteadSigner{}, testKey)
   771  	if err != nil {
   772  		t.Errorf("could not sign tx: %v", err)
   773  	}
   774  	err = sim.SendTransaction(bgCtx, signedTx)
   775  	if err != nil {
   776  		t.Errorf("could not send tx: %v", err)
   777  	}
   778  
   779  	// expect pending nonce to be 2 since account now has two transactions
   780  	pendingNonce, err = sim.PendingNonceAt(bgCtx, testAddr)
   781  	if err != nil {
   782  		t.Errorf("did not get the pending nonce: %v", err)
   783  	}
   784  
   785  	if pendingNonce != uint64(2) {
   786  		t.Errorf("expected pending nonce of 2 got %v", pendingNonce)
   787  	}
   788  }
   789  
   790  func TestSimulatedBackend_TransactionReceipt(t *testing.T) {
   791  	testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
   792  
   793  	sim := simTestBackend(testAddr)
   794  	defer sim.Close()
   795  	bgCtx := context.Background()
   796  
   797  	// create a signed transaction to send
   798  	tx := types.NewTransaction(uint64(0), testAddr, big.NewInt(1000), params.TxGas, big.NewInt(1), nil)
   799  	signedTx, err := types.SignTx(tx, types.HomesteadSigner{}, testKey)
   800  	if err != nil {
   801  		t.Errorf("could not sign tx: %v", err)
   802  	}
   803  
   804  	// send tx to simulated backend
   805  	err = sim.SendTransaction(bgCtx, signedTx)
   806  	if err != nil {
   807  		t.Errorf("could not add tx to pending block: %v", err)
   808  	}
   809  	sim.Commit()
   810  
   811  	receipt, err := sim.TransactionReceipt(bgCtx, signedTx.Hash())
   812  	if err != nil {
   813  		t.Errorf("could not get transaction receipt: %v", err)
   814  	}
   815  
   816  	if receipt.ContractAddress != testAddr && receipt.TxHash != signedTx.Hash() {
   817  		t.Errorf("received receipt is not correct: %v", receipt)
   818  	}
   819  }
   820  
   821  func TestSimulatedBackend_SuggestGasPrice(t *testing.T) {
   822  	sim := NewSimulatedBackend(
   823  		core.GenesisAlloc{},
   824  		10000000,
   825  	)
   826  	defer sim.Close()
   827  	bgCtx := context.Background()
   828  	gasPrice, err := sim.SuggestGasPrice(bgCtx)
   829  	if err != nil {
   830  		t.Errorf("could not get gas price: %v", err)
   831  	}
   832  	if gasPrice.Uint64() != uint64(1) {
   833  		t.Errorf("gas price was not expected value of 1. actual: %v", gasPrice.Uint64())
   834  	}
   835  }
   836  
   837  func TestSimulatedBackend_PendingCodeAt(t *testing.T) {
   838  	testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
   839  	sim := simTestBackend(testAddr)
   840  	defer sim.Close()
   841  	bgCtx := context.Background()
   842  	code, err := sim.CodeAt(bgCtx, testAddr, nil)
   843  	if err != nil {
   844  		t.Errorf("could not get code at test addr: %v", err)
   845  	}
   846  	if len(code) != 0 {
   847  		t.Errorf("got code for account that does not have contract code")
   848  	}
   849  
   850  	parsed, err := abi.JSON(strings.NewReader(abiJSON))
   851  	if err != nil {
   852  		t.Errorf("could not get code at test addr: %v", err)
   853  	}
   854  	auth := bind.NewKeyedTransactor(testKey)
   855  	contractAddr, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(abiBin), sim)
   856  	if err != nil {
   857  		t.Errorf("could not deploy contract: %v tx: %v contract: %v", err, tx, contract)
   858  	}
   859  
   860  	code, err = sim.PendingCodeAt(bgCtx, contractAddr)
   861  	if err != nil {
   862  		t.Errorf("could not get code at test addr: %v", err)
   863  	}
   864  	if len(code) == 0 {
   865  		t.Errorf("did not get code for account that has contract code")
   866  	}
   867  	// ensure code received equals code deployed
   868  	if !bytes.Equal(code, common.FromHex(deployedCode)) {
   869  		t.Errorf("code received did not match expected deployed code:\n expected %v\n actual %v", common.FromHex(deployedCode), code)
   870  	}
   871  }
   872  
   873  func TestSimulatedBackend_CodeAt(t *testing.T) {
   874  	testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
   875  	sim := simTestBackend(testAddr)
   876  	defer sim.Close()
   877  	bgCtx := context.Background()
   878  	code, err := sim.CodeAt(bgCtx, testAddr, nil)
   879  	if err != nil {
   880  		t.Errorf("could not get code at test addr: %v", err)
   881  	}
   882  	if len(code) != 0 {
   883  		t.Errorf("got code for account that does not have contract code")
   884  	}
   885  
   886  	parsed, err := abi.JSON(strings.NewReader(abiJSON))
   887  	if err != nil {
   888  		t.Errorf("could not get code at test addr: %v", err)
   889  	}
   890  	auth := bind.NewKeyedTransactor(testKey)
   891  	contractAddr, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(abiBin), sim)
   892  	if err != nil {
   893  		t.Errorf("could not deploy contract: %v tx: %v contract: %v", err, tx, contract)
   894  	}
   895  
   896  	sim.Commit()
   897  	code, err = sim.CodeAt(bgCtx, contractAddr, nil)
   898  	if err != nil {
   899  		t.Errorf("could not get code at test addr: %v", err)
   900  	}
   901  	if len(code) == 0 {
   902  		t.Errorf("did not get code for account that has contract code")
   903  	}
   904  	// ensure code received equals code deployed
   905  	if !bytes.Equal(code, common.FromHex(deployedCode)) {
   906  		t.Errorf("code received did not match expected deployed code:\n expected %v\n actual %v", common.FromHex(deployedCode), code)
   907  	}
   908  }
   909  
   910  // When receive("X") is called with sender 0x00... and value 1, it produces this tx receipt:
   911  //   receipt{status=1 cgas=23949 bloom=00000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000040200000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 logs=[log: b6818c8064f645cd82d99b59a1a267d6d61117ef [75fd880d39c1daf53b6547ab6cb59451fc6452d27caa90e5b6649dd8293b9eed] 000000000000000000000000376c47978271565f56deb45495afa69e59c16ab200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000158 9ae378b6d4409eada347a5dc0c180f186cb62dc68fcc0f043425eb917335aa28 0 95d429d309bb9d753954195fe2d69bd140b4ae731b9b5b605c34323de162cf00 0]}
   912  func TestSimulatedBackend_PendingAndCallContract(t *testing.T) {
   913  	testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
   914  	sim := simTestBackend(testAddr)
   915  	defer sim.Close()
   916  	bgCtx := context.Background()
   917  
   918  	parsed, err := abi.JSON(strings.NewReader(abiJSON))
   919  	if err != nil {
   920  		t.Errorf("could not get code at test addr: %v", err)
   921  	}
   922  	contractAuth := bind.NewKeyedTransactor(testKey)
   923  	addr, _, _, err := bind.DeployContract(contractAuth, parsed, common.FromHex(abiBin), sim)
   924  	if err != nil {
   925  		t.Errorf("could not deploy contract: %v", err)
   926  	}
   927  
   928  	input, err := parsed.Pack("receive", []byte("X"))
   929  	if err != nil {
   930  		t.Errorf("could not pack receive function on contract: %v", err)
   931  	}
   932  
   933  	// make sure you can call the contract in pending state
   934  	res, err := sim.PendingCallContract(bgCtx, ethereum.CallMsg{
   935  		From: testAddr,
   936  		To:   &addr,
   937  		Data: input,
   938  	})
   939  	if err != nil {
   940  		t.Errorf("could not call receive method on contract: %v", err)
   941  	}
   942  	if len(res) == 0 {
   943  		t.Errorf("result of contract call was empty: %v", res)
   944  	}
   945  
   946  	// while comparing against the byte array is more exact, also compare against the human readable string for readability
   947  	if !bytes.Equal(res, expectedReturn) || !strings.Contains(string(res), "hello world") {
   948  		t.Errorf("response from calling contract was expected to be 'hello world' instead received %v", string(res))
   949  	}
   950  
   951  	sim.Commit()
   952  
   953  	// make sure you can call the contract
   954  	res, err = sim.CallContract(bgCtx, ethereum.CallMsg{
   955  		From: testAddr,
   956  		To:   &addr,
   957  		Data: input,
   958  	}, nil)
   959  	if err != nil {
   960  		t.Errorf("could not call receive method on contract: %v", err)
   961  	}
   962  	if len(res) == 0 {
   963  		t.Errorf("result of contract call was empty: %v", res)
   964  	}
   965  
   966  	if !bytes.Equal(res, expectedReturn) || !strings.Contains(string(res), "hello world") {
   967  		t.Errorf("response from calling contract was expected to be 'hello world' instead received %v", string(res))
   968  	}
   969  }
   970  
   971  // This test is based on the following contract:
   972  /*
   973  contract Reverter {
   974      function revertString() public pure{
   975          require(false, "some error");
   976      }
   977      function revertNoString() public pure {
   978          require(false, "");
   979      }
   980      function revertASM() public pure {
   981          assembly {
   982              revert(0x0, 0x0)
   983          }
   984      }
   985      function noRevert() public pure {
   986          assembly {
   987              // Assembles something that looks like require(false, "some error") but is not reverted
   988              mstore(0x0, 0x08c379a000000000000000000000000000000000000000000000000000000000)
   989              mstore(0x4, 0x0000000000000000000000000000000000000000000000000000000000000020)
   990              mstore(0x24, 0x000000000000000000000000000000000000000000000000000000000000000a)
   991              mstore(0x44, 0x736f6d65206572726f7200000000000000000000000000000000000000000000)
   992              return(0x0, 0x64)
   993          }
   994      }
   995  }*/
   996  func TestSimulatedBackend_CallContractRevert(t *testing.T) {
   997  	testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
   998  	sim := simTestBackend(testAddr)
   999  	defer sim.Close()
  1000  	bgCtx := context.Background()
  1001  
  1002  	reverterABI := `[{"inputs": [],"name": "noRevert","outputs": [],"stateMutability": "pure","type": "function"},{"inputs": [],"name": "revertASM","outputs": [],"stateMutability": "pure","type": "function"},{"inputs": [],"name": "revertNoString","outputs": [],"stateMutability": "pure","type": "function"},{"inputs": [],"name": "revertString","outputs": [],"stateMutability": "pure","type": "function"}]`
  1003  	reverterBin := "608060405234801561001057600080fd5b506101d3806100206000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80634b409e01146100515780639b340e361461005b5780639bd6103714610065578063b7246fc11461006f575b600080fd5b610059610079565b005b6100636100ca565b005b61006d6100cf565b005b610077610145565b005b60006100c8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526000815260200160200191505060405180910390fd5b565b600080fd5b6000610143576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600a8152602001807f736f6d65206572726f720000000000000000000000000000000000000000000081525060200191505060405180910390fd5b565b7f08c379a0000000000000000000000000000000000000000000000000000000006000526020600452600a6024527f736f6d65206572726f720000000000000000000000000000000000000000000060445260646000f3fea2646970667358221220cdd8af0609ec4996b7360c7c780bad5c735740c64b1fffc3445aa12d37f07cb164736f6c63430006070033"
  1004  
  1005  	parsed, err := abi.JSON(strings.NewReader(reverterABI))
  1006  	if err != nil {
  1007  		t.Errorf("could not get code at test addr: %v", err)
  1008  	}
  1009  	contractAuth := bind.NewKeyedTransactor(testKey)
  1010  	addr, _, _, err := bind.DeployContract(contractAuth, parsed, common.FromHex(reverterBin), sim)
  1011  	if err != nil {
  1012  		t.Errorf("could not deploy contract: %v", err)
  1013  	}
  1014  
  1015  	inputs := make(map[string]interface{}, 3)
  1016  	inputs["revertASM"] = nil
  1017  	inputs["revertNoString"] = ""
  1018  	inputs["revertString"] = "some error"
  1019  
  1020  	call := make([]func([]byte) ([]byte, error), 2)
  1021  	call[0] = func(input []byte) ([]byte, error) {
  1022  		return sim.PendingCallContract(bgCtx, ethereum.CallMsg{
  1023  			From: testAddr,
  1024  			To:   &addr,
  1025  			Data: input,
  1026  		})
  1027  	}
  1028  	call[1] = func(input []byte) ([]byte, error) {
  1029  		return sim.CallContract(bgCtx, ethereum.CallMsg{
  1030  			From: testAddr,
  1031  			To:   &addr,
  1032  			Data: input,
  1033  		}, nil)
  1034  	}
  1035  
  1036  	// Run pending calls then commit
  1037  	for _, cl := range call {
  1038  		for key, val := range inputs {
  1039  			input, err := parsed.Pack(key)
  1040  			if err != nil {
  1041  				t.Errorf("could not pack %v function on contract: %v", key, err)
  1042  			}
  1043  
  1044  			res, err := cl(input)
  1045  			if err == nil {
  1046  				t.Errorf("call to %v was not reverted", key)
  1047  			}
  1048  			if res != nil {
  1049  				t.Errorf("result from %v was not nil: %v", key, res)
  1050  			}
  1051  			if val != nil {
  1052  				rerr, ok := err.(*revertError)
  1053  				if !ok {
  1054  					t.Errorf("expect revert error")
  1055  				}
  1056  				if rerr.Error() != "execution reverted: "+val.(string) {
  1057  					t.Errorf("error was malformed: got %v want %v", rerr.Error(), val)
  1058  				}
  1059  			} else {
  1060  				// revert(0x0,0x0)
  1061  				if err.Error() != "execution reverted" {
  1062  					t.Errorf("error was malformed: got %v want %v", err, "execution reverted")
  1063  				}
  1064  			}
  1065  		}
  1066  		input, err := parsed.Pack("noRevert")
  1067  		if err != nil {
  1068  			t.Errorf("could not pack noRevert function on contract: %v", err)
  1069  		}
  1070  		res, err := cl(input)
  1071  		if err != nil {
  1072  			t.Error("call to noRevert was reverted")
  1073  		}
  1074  		if res == nil {
  1075  			t.Errorf("result from noRevert was nil")
  1076  		}
  1077  		sim.Commit()
  1078  	}
  1079  }