github.com/klaytn/klaytn@v1.12.1/accounts/abi/bind/backends/simulated_test.go (about)

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