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