github.com/iotexproject/iotex-core@v1.14.1-rc1/api/web3server_integrity_test.go (about)

     1  // Copyright (c) 2022 IoTeX Foundation
     2  // This source code is provided 'as is' and no warranties are given as to title or non-infringement, merchantability
     3  // or fitness for purpose and, to the extent permitted by law, all liability for your use of the code is disclaimed.
     4  // This source code is governed by Apache License 2.0 that can be found in the LICENSE file.
     5  
     6  package api
     7  
     8  import (
     9  	"context"
    10  	"crypto/ecdsa"
    11  	"encoding/hex"
    12  	"encoding/json"
    13  	"fmt"
    14  	"math/big"
    15  	"net/http"
    16  	"net/http/httptest"
    17  	"strings"
    18  	"testing"
    19  
    20  	"github.com/ethereum/go-ethereum/common"
    21  	"github.com/ethereum/go-ethereum/core/types"
    22  	"github.com/iotexproject/go-pkgs/util"
    23  	"github.com/iotexproject/iotex-address/address"
    24  	"github.com/iotexproject/iotex-proto/golang/iotextypes"
    25  	"github.com/stretchr/testify/require"
    26  
    27  	"github.com/iotexproject/iotex-core/action"
    28  	"github.com/iotexproject/iotex-core/actpool"
    29  	"github.com/iotexproject/iotex-core/blockchain"
    30  	"github.com/iotexproject/iotex-core/blockchain/blockdao"
    31  	"github.com/iotexproject/iotex-core/test/identityset"
    32  	"github.com/iotexproject/iotex-core/testutil"
    33  )
    34  
    35  const (
    36  	_evmNetworkID uint32 = 1
    37  )
    38  
    39  func TestWeb3ServerIntegrity(t *testing.T) {
    40  	svr, bc, dao, actPool, cleanIndexFile := setupTestServer()
    41  	web3svr := svr.httpSvr
    42  	defer cleanIndexFile()
    43  	ctx := context.Background()
    44  	web3svr.Start(ctx)
    45  	defer web3svr.Stop(ctx)
    46  	handler := newHTTPHandler(NewWeb3Handler(svr.core, "", _defaultBatchRequestLimit))
    47  
    48  	// send request
    49  	t.Run("eth_gasPrice", func(t *testing.T) {
    50  		gasPrice(t, handler)
    51  	})
    52  
    53  	t.Run("eth_chainId", func(t *testing.T) {
    54  		chainID(t, handler)
    55  	})
    56  
    57  	t.Run("eth_blockNumber", func(t *testing.T) {
    58  		blockNumber(t, handler)
    59  	})
    60  
    61  	t.Run("eth_getBlockByNumber", func(t *testing.T) {
    62  		getBlockByNumber(t, handler)
    63  	})
    64  
    65  	t.Run("eth_getBalance", func(t *testing.T) {
    66  		getBalance(t, handler)
    67  	})
    68  
    69  	t.Run("eth_getTransactionCount", func(t *testing.T) {
    70  		getTransactionCount(t, handler)
    71  	})
    72  
    73  	t.Run("eth_call", func(t *testing.T) {
    74  		ethCall(t, handler)
    75  	})
    76  
    77  	t.Run("web3_clientVersion", func(t *testing.T) {
    78  		getNodeInfo(t, handler)
    79  	})
    80  
    81  	t.Run("eth_getBlockTransactionCountByHash", func(t *testing.T) {
    82  		getBlockTransactionCountByHash(t, handler, bc)
    83  	})
    84  
    85  	t.Run("eth_getBlockByHash", func(t *testing.T) {
    86  		getBlockByHash(t, handler, bc)
    87  	})
    88  
    89  	t.Run("eth_getTransactionByHash", func(t *testing.T) {
    90  		getTransactionByHash(t, handler)
    91  	})
    92  
    93  	t.Run("eth_getLogs", func(t *testing.T) {
    94  		getLogs(t, handler)
    95  	})
    96  
    97  	t.Run("eth_getTransactionReceipt", func(t *testing.T) {
    98  		getTransactionReceipt(t, handler)
    99  	})
   100  
   101  	t.Run("eth_getBlockTransactionCountByNumber", func(t *testing.T) {
   102  		getBlockTransactionCountByNumber(t, handler)
   103  	})
   104  
   105  	t.Run("eth_getTransactionByBlockHashAndIndex", func(t *testing.T) {
   106  		getTransactionByBlockHashAndIndex(t, handler, bc)
   107  	})
   108  
   109  	t.Run("eth_getTransactionByBlockNumberAndIndex", func(t *testing.T) {
   110  		getTransactionByBlockNumberAndIndex(t, handler)
   111  	})
   112  
   113  	t.Run("eth_newFilter", func(t *testing.T) {
   114  		newfilter(t, handler)
   115  	})
   116  
   117  	t.Run("eth_newBlockFilter", func(t *testing.T) {
   118  		newBlockFilter(t, handler)
   119  	})
   120  
   121  	t.Run("eth_getFilterChanges", func(t *testing.T) {
   122  		getFilterChanges(t, handler)
   123  	})
   124  
   125  	t.Run("eth_getFilterLogs", func(t *testing.T) {
   126  		getFilterLogs(t, handler)
   127  	})
   128  
   129  	t.Run("net_version", func(t *testing.T) {
   130  		getNetworkID(t, handler)
   131  	})
   132  
   133  	t.Run("eth_accounts", func(t *testing.T) {
   134  		ethAccounts(t, handler)
   135  	})
   136  
   137  	t.Run("web3Staking", func(t *testing.T) {
   138  		web3Staking(t, handler)
   139  	})
   140  
   141  	t.Run("eth_sendRawTransaction", func(t *testing.T) {
   142  		sendRawTransaction(t, handler)
   143  	})
   144  
   145  	t.Run("eth_estimateGas", func(t *testing.T) {
   146  		estimateGas(t, handler, bc, dao, actPool)
   147  	})
   148  
   149  	t.Run("eth_getCode", func(t *testing.T) {
   150  		getCode(t, handler, bc, dao, actPool)
   151  	})
   152  
   153  	t.Run("eth_getStorageAt", func(t *testing.T) {
   154  		getStorageAt(t, handler, bc, dao, actPool)
   155  	})
   156  }
   157  
   158  func setupTestServer() (*ServerV2, blockchain.Blockchain, blockdao.BlockDAO, actpool.ActPool, func()) {
   159  	cfg := newConfig()
   160  	cfg.chain.EVMNetworkID = _evmNetworkID
   161  	cfg.api.HTTPPort = testutil.RandomPort()
   162  	svr, bc, dao, _, _, actPool, bfIndexFile, _ := createServerV2(cfg, false)
   163  	return svr, bc, dao, actPool, func() {
   164  		testutil.CleanupPath(bfIndexFile)
   165  	}
   166  }
   167  
   168  func serveTestHTTP(require *require.Assertions, handler *hTTPHandler, method string, param string) interface{} {
   169  	req, _ := http.NewRequest(http.MethodPost, "http://url.com",
   170  		strings.NewReader(fmt.Sprintf(`[{"jsonrpc":"2.0","method":"%s","params":%s,"id":1}]`, method, param)))
   171  	resp := httptest.NewRecorder()
   172  
   173  	handler.ServeHTTP(resp, req)
   174  
   175  	var vals []struct {
   176  		Jsonrpc string      `json:"jsonrpc"`
   177  		ID      int         `json:"id"`
   178  		Result  interface{} `json:"result"`
   179  	}
   180  	err := json.NewDecoder(resp.Body).Decode(&vals)
   181  	require.NoError(err)
   182  	require.NotEmpty(vals)
   183  	return vals[0].Result
   184  }
   185  
   186  func gasPrice(t *testing.T, handler *hTTPHandler) {
   187  	require := require.New(t)
   188  	result := serveTestHTTP(require, handler, "eth_gasPrice", "[]")
   189  	actual, ok := result.(string)
   190  	require.True(ok)
   191  	require.Equal(uint64ToHex(1000000000000), actual)
   192  }
   193  
   194  func chainID(t *testing.T, handler *hTTPHandler) {
   195  	require := require.New(t)
   196  	result := serveTestHTTP(require, handler, "eth_chainId", "[]")
   197  	actual, ok := result.(string)
   198  	require.True(ok)
   199  	require.Equal(uint64ToHex(1), actual)
   200  	require.Equal(uint64ToHex(uint64(_evmNetworkID)), actual)
   201  }
   202  
   203  func blockNumber(t *testing.T, handler *hTTPHandler) {
   204  	require := require.New(t)
   205  	result := serveTestHTTP(require, handler, "eth_blockNumber", "[]")
   206  	actual, ok := result.(string)
   207  	require.True(ok)
   208  	require.Equal(uint64ToHex(4), actual)
   209  }
   210  
   211  func getBlockByNumber(t *testing.T, handler *hTTPHandler) {
   212  	require := require.New(t)
   213  	for _, test := range []struct {
   214  		params   string
   215  		expected int
   216  	}{
   217  		{`["1", true]`, 2},
   218  		{`["1", false]`, 2},
   219  		{`["10", false]`, 0},
   220  	} {
   221  		result := serveTestHTTP(require, handler, "eth_getBlockByNumber", test.params)
   222  		if test.expected == 0 {
   223  			require.Nil(result)
   224  		} else {
   225  			actual, ok := result.(map[string]interface{})["transactions"]
   226  			require.True(ok)
   227  			require.Equal(test.expected, len(actual.([]interface{})))
   228  		}
   229  	}
   230  }
   231  
   232  func getBalance(t *testing.T, handler *hTTPHandler) {
   233  	require := require.New(t)
   234  	result := serveTestHTTP(require, handler, "eth_getBalance", `["0xDa7e12Ef57c236a06117c5e0d04a228e7181CF36", 1]`)
   235  	ans, ok := new(big.Int).SetString("9999999999999999999999999991", 10)
   236  	require.True(ok)
   237  	actual, ok := result.(string)
   238  	require.True(ok)
   239  	ans, ok = new(big.Int).SetString("9999999999999999999999999991", 10)
   240  	require.True(ok)
   241  	require.Equal("0x"+fmt.Sprintf("%x", ans), actual)
   242  }
   243  
   244  func getTransactionCount(t *testing.T, handler *hTTPHandler) {
   245  	require := require.New(t)
   246  	for _, test := range []struct {
   247  		params   string
   248  		expected int
   249  	}{
   250  		{`["0xDa7e12Ef57c236a06117c5e0d04a228e7181CF36", "0x1"]`, 2},
   251  		{`["0xDa7e12Ef57c236a06117c5e0d04a228e7181CF36", "pending"]`, 2},
   252  	} {
   253  		result := serveTestHTTP(require, handler, "eth_getTransactionCount", test.params)
   254  		actual, ok := result.(string)
   255  		require.True(ok)
   256  		require.Equal(uint64ToHex(uint64(test.expected)), actual)
   257  	}
   258  }
   259  
   260  func ethCall(t *testing.T, handler *hTTPHandler) {
   261  	require := require.New(t)
   262  	for _, test := range []struct {
   263  		params   string
   264  		expected int
   265  	}{
   266  		{
   267  			`[{
   268  				"from":     "",
   269  				"to":       "0x7c13866F9253DEf79e20034eDD011e1d69E67fe5",
   270  				"gas":      "0x4e20",
   271  				"gasPrice": "0xe8d4a51000",
   272  				"value":    "0x1",
   273  				"data":     "0x1"
   274  			  },
   275  			1]`,
   276  			1,
   277  		},
   278  		{
   279  			`[{
   280  				"from":     "",
   281  				"to":       "0xb1f8e55c7f64d203c1400b9d8555d050f94adf39",
   282  				"gas":      "0x4e20",
   283  				"gasPrice": "0xe8d4a51000",
   284  				"value":    "0x1",
   285  				"data":     "0x1"
   286  			   },
   287  			1]`,
   288  			0,
   289  		},
   290  	} {
   291  		result := serveTestHTTP(require, handler, "eth_call", test.params)
   292  		if test.expected == 0 {
   293  			require.Nil(result)
   294  			continue
   295  		}
   296  		actual, ok := result.(string)
   297  		require.True(ok)
   298  		require.Equal("0x", actual)
   299  	}
   300  }
   301  
   302  func getNodeInfo(t *testing.T, handler *hTTPHandler) {
   303  	require := require.New(t)
   304  	result := serveTestHTTP(require, handler, "web3_clientVersion", "[]")
   305  	actual, ok := result.(string)
   306  	require.True(ok)
   307  	require.Equal("NoBuildInfo/NoBuildInfo", actual)
   308  }
   309  
   310  func getBlockTransactionCountByHash(t *testing.T, handler *hTTPHandler, bc blockchain.Blockchain) {
   311  	require := require.New(t)
   312  	header, err := bc.BlockHeaderByHeight(1)
   313  	require.NoError(err)
   314  	blkHash := header.HashBlock()
   315  	result := serveTestHTTP(require, handler, "eth_getBlockTransactionCountByHash",
   316  		fmt.Sprintf(`["0x%s", 1]`, hex.EncodeToString(blkHash[:])))
   317  	actual, ok := result.(string)
   318  	require.True(ok)
   319  	require.Equal(uint64ToHex(2), actual)
   320  }
   321  
   322  func getBlockByHash(t *testing.T, handler *hTTPHandler, bc blockchain.Blockchain) {
   323  	require := require.New(t)
   324  	header, err := bc.BlockHeaderByHeight(1)
   325  	require.NoError(err)
   326  	blkHash := header.HashBlock()
   327  
   328  	for _, test := range []struct {
   329  		params   string
   330  		expected int
   331  	}{
   332  		{fmt.Sprintf(`["0x%s", false]`, hex.EncodeToString(blkHash[:])), 1},
   333  		{`["0xa2e8e0c9cafbe93f2b7f7c9d32534bc6fde95f2185e5f2aaa6bf7ebdf1a6610a", false]`, 0},
   334  	} {
   335  		result := serveTestHTTP(require, handler, "eth_getBlockByHash", test.params)
   336  		if test.expected == 0 {
   337  			require.Nil(result)
   338  			continue
   339  		}
   340  		hash, ok := result.(map[string]interface{})["hash"]
   341  		require.True(ok)
   342  		require.Equal("0x"+hex.EncodeToString(blkHash[:]), hash)
   343  		transactions, ok := result.(map[string]interface{})["transactions"]
   344  		require.True(ok)
   345  		require.Equal(2, len(transactions.([]interface{})))
   346  	}
   347  }
   348  
   349  func getTransactionByHash(t *testing.T, handler *hTTPHandler) {
   350  	require := require.New(t)
   351  	for _, test := range []struct {
   352  		params   string
   353  		expected int
   354  	}{
   355  		{fmt.Sprintf(`["0x%s", false]`, hex.EncodeToString(_transferHash1[:])), 1},
   356  		{`["0x58df1e9cb0572fea48e8ce9d9b787ae557c304657d01890f4fc5ea88a1f44c3e", false]`, 0},
   357  	} {
   358  		result := serveTestHTTP(require, handler, "eth_getTransactionByHash", test.params)
   359  		if test.expected == 0 {
   360  			require.Nil(result)
   361  			continue
   362  		}
   363  		hash, ok := result.(map[string]interface{})["hash"]
   364  		require.True(ok)
   365  		require.Equal("0x"+hex.EncodeToString(_transferHash1[:]), hash)
   366  	}
   367  }
   368  
   369  func getLogs(t *testing.T, handler *hTTPHandler) {
   370  	require := require.New(t)
   371  	for _, test := range []struct {
   372  		params   string
   373  		expected int
   374  	}{
   375  		{
   376  			`[{"fromBlock":"0x1"}]`,
   377  			4, // if deployed contract, +1
   378  		},
   379  		{
   380  			// empty log
   381  			`[{"address":"0x8ce313ab12bf7aed8136ab36c623ff98c8eaad34"}]`,
   382  			0,
   383  		},
   384  	} {
   385  		result := serveTestHTTP(require, handler, "eth_getLogs", test.params)
   386  		ret, ok := result.([]interface{})
   387  		require.True(ok)
   388  		require.Equal(test.expected, len(ret))
   389  	}
   390  }
   391  
   392  func getTransactionReceipt(t *testing.T, handler *hTTPHandler) {
   393  	require := require.New(t)
   394  	for _, test := range []struct {
   395  		params   string
   396  		expected int
   397  	}{
   398  		{fmt.Sprintf(`["0x%s", false]`, hex.EncodeToString(_transferHash1[:])), 1},
   399  		{`["0x58df1e9cb0572fea48e8ce9d9b787ae557c304657d01890f4fc5ea88a1f44c3e", false]`, 0},
   400  	} {
   401  		result := serveTestHTTP(require, handler, "eth_getTransactionReceipt", test.params)
   402  		if test.expected == 0 {
   403  			require.Nil(result)
   404  			continue
   405  		}
   406  		transactionHash, ok := result.(map[string]interface{})["transactionHash"]
   407  		require.True(ok)
   408  		require.Equal("0x"+hex.EncodeToString(_transferHash1[:]), transactionHash)
   409  		fromAddr, _ := ioAddrToEthAddr(identityset.Address(27).String())
   410  		toAddr, _ := ioAddrToEthAddr(identityset.Address(30).String())
   411  		from, ok := result.(map[string]interface{})["from"]
   412  		require.True(ok)
   413  		to, ok := result.(map[string]interface{})["to"]
   414  		require.True(ok)
   415  		require.Equal(strings.ToLower(fromAddr), from)
   416  		require.Equal(toAddr, to)
   417  		contractAddress, ok := result.(map[string]interface{})["contractAddress"]
   418  		require.True(ok)
   419  		require.Nil(nil, contractAddress)
   420  		gasUsed, ok := result.(map[string]interface{})["gasUsed"]
   421  		require.True(ok)
   422  		require.Equal(uint64ToHex(10000), gasUsed)
   423  		blockNumber, ok := result.(map[string]interface{})["blockNumber"]
   424  		require.True(ok)
   425  		require.Equal(uint64ToHex(1), blockNumber)
   426  	}
   427  }
   428  
   429  func getBlockTransactionCountByNumber(t *testing.T, handler *hTTPHandler) {
   430  	require := require.New(t)
   431  	result := serveTestHTTP(require, handler, "eth_getBlockTransactionCountByNumber", `["0x1"]`)
   432  	actual, ok := result.(string)
   433  	require.True(ok)
   434  	require.Equal(uint64ToHex(2), actual)
   435  }
   436  
   437  func getTransactionByBlockHashAndIndex(t *testing.T, handler *hTTPHandler, bc blockchain.Blockchain) {
   438  	require := require.New(t)
   439  	header, err := bc.BlockHeaderByHeight(1)
   440  	require.NoError(err)
   441  	blkHash := header.HashBlock()
   442  
   443  	for _, test := range []struct {
   444  		params   string
   445  		expected int
   446  	}{
   447  		{fmt.Sprintf(`["0x%s", "0x0"]`, hex.EncodeToString(blkHash[:])), 1},
   448  		{fmt.Sprintf(`["0x%s", "0x10"]`, hex.EncodeToString(blkHash[:])), 0},
   449  		{`["0xa2e8e0c9cafbe93f2b7f7c9d32534bc6fde95f2185e5f2aaa6bf7ebdf1a6610a", "0x0"]`, 0},
   450  	} {
   451  		result := serveTestHTTP(require, handler, "eth_getTransactionByBlockHashAndIndex", test.params)
   452  		if test.expected == 0 {
   453  			require.Nil(result)
   454  			continue
   455  		}
   456  		hash, ok := result.(map[string]interface{})["hash"]
   457  		require.True(ok)
   458  		require.Equal("0x"+hex.EncodeToString(_transferHash1[:]), hash)
   459  		fromAddr, _ := ioAddrToEthAddr(identityset.Address(27).String())
   460  		toAddr, _ := ioAddrToEthAddr(identityset.Address(30).String())
   461  		from, ok := result.(map[string]interface{})["from"]
   462  		require.True(ok)
   463  		to, ok := result.(map[string]interface{})["to"]
   464  		require.True(ok)
   465  		require.Equal(strings.ToLower(fromAddr), from)
   466  		require.Equal(toAddr, to)
   467  
   468  		gas, ok := result.(map[string]interface{})["gas"]
   469  		require.True(ok)
   470  		require.Equal(uint64ToHex(20000), gas)
   471  		gasPrice, ok := result.(map[string]interface{})["gasPrice"]
   472  		require.True(ok)
   473  		require.Equal(uint64ToHex(0), gasPrice)
   474  	}
   475  }
   476  
   477  func getTransactionByBlockNumberAndIndex(t *testing.T, handler *hTTPHandler) {
   478  	require := require.New(t)
   479  	for _, test := range []struct {
   480  		params   string
   481  		expected int
   482  	}{
   483  		{`["0x1", "0x0"]`, 1},
   484  		{`["0x1", "0x10"]`, 0},
   485  		{`["0x10", "0x0"]`, 0},
   486  	} {
   487  		result := serveTestHTTP(require, handler, "eth_getTransactionByBlockNumberAndIndex", test.params)
   488  		if test.expected == 0 {
   489  			require.Nil(result)
   490  			continue
   491  		}
   492  		hash, ok := result.(map[string]interface{})["hash"]
   493  		require.True(ok)
   494  		require.Equal("0x"+hex.EncodeToString(_transferHash1[:]), hash)
   495  		fromAddr, _ := ioAddrToEthAddr(identityset.Address(27).String())
   496  		toAddr, _ := ioAddrToEthAddr(identityset.Address(30).String())
   497  		from, ok := result.(map[string]interface{})["from"]
   498  		require.True(ok)
   499  		to, ok := result.(map[string]interface{})["to"]
   500  		require.True(ok)
   501  		require.Equal(strings.ToLower(fromAddr), from)
   502  		require.Equal(toAddr, to)
   503  
   504  		gas, ok := result.(map[string]interface{})["gas"]
   505  		require.True(ok)
   506  		require.Equal(uint64ToHex(20000), gas)
   507  		gasPrice, ok := result.(map[string]interface{})["gasPrice"]
   508  		require.True(ok)
   509  		require.Equal(uint64ToHex(0), gasPrice)
   510  	}
   511  }
   512  
   513  func newfilter(t *testing.T, handler *hTTPHandler) {
   514  	require := require.New(t)
   515  	result := serveTestHTTP(require, handler, "eth_newFilter", `[{"fromBlock":"0x1"}]`)
   516  	actual, ok := result.(string)
   517  	require.True(ok)
   518  	require.Equal("0xe10f7dd489b75a36de8e246eb974827fe86a02ed19d9b475a1600cf4f935feff", actual)
   519  }
   520  
   521  func newBlockFilter(t *testing.T, handler *hTTPHandler) {
   522  	require := require.New(t)
   523  	result := serveTestHTTP(require, handler, "eth_newBlockFilter", "[]")
   524  	actual, ok := result.(string)
   525  	require.True(ok)
   526  	require.Equal("0x71371f8dbaefc4c96d2534163a1b461951c88520cd32bc03b5bfdfe7340bc187", actual)
   527  }
   528  
   529  func getFilterChanges(t *testing.T, handler *hTTPHandler) {
   530  	require := require.New(t)
   531  
   532  	result := serveTestHTTP(require, handler, "eth_newFilter", `[{"fromBlock":"0x1"}]`)
   533  	actual, ok := result.(string)
   534  	require.True(ok)
   535  	result1 := serveTestHTTP(require, handler, "eth_getFilterChanges", fmt.Sprintf(`["%s"]`, actual))
   536  	actual1, ok := result1.([]interface{})
   537  	require.True(ok)
   538  	require.Len(actual1, 4)
   539  	// request again after last rolling
   540  	result1 = serveTestHTTP(require, handler, "eth_getFilterChanges", fmt.Sprintf(`["%s"]`, actual))
   541  	actual1, ok = result1.([]interface{})
   542  	require.True(ok)
   543  	require.Len(actual1, 0)
   544  
   545  	result = serveTestHTTP(require, handler, "eth_newBlockFilter", `[]`)
   546  	actual, ok = result.(string)
   547  	require.True(ok)
   548  	result1 = serveTestHTTP(require, handler, "eth_getFilterChanges", fmt.Sprintf(`["%s"]`, actual))
   549  	actual1, ok = result1.([]interface{})
   550  	require.True(ok)
   551  	require.Len(actual1, 1)
   552  	// request again after last rolling
   553  	result1 = serveTestHTTP(require, handler, "eth_getFilterChanges", fmt.Sprintf(`["%s"]`, actual))
   554  	actual1, ok = result1.([]interface{})
   555  	require.True(ok)
   556  	require.Len(actual1, 0)
   557  }
   558  
   559  func getFilterLogs(t *testing.T, handler *hTTPHandler) {
   560  	require := require.New(t)
   561  	result := serveTestHTTP(require, handler, "eth_newFilter", `[{"fromBlock":"0x1"}]`)
   562  	actual, ok := result.(string)
   563  	require.True(ok)
   564  
   565  	result1 := serveTestHTTP(require, handler, "eth_getFilterLogs", fmt.Sprintf(`["%s"]`, actual))
   566  	actual1, ok := result1.([]interface{})
   567  	require.True(ok)
   568  	require.Equal(4, len(actual1))
   569  }
   570  
   571  func getNetworkID(t *testing.T, handler *hTTPHandler) {
   572  	require := require.New(t)
   573  	result := serveTestHTTP(require, handler, "net_version", "[]")
   574  	actual, ok := result.(string)
   575  	require.True(ok)
   576  	require.Equal(fmt.Sprintf("%d", _evmNetworkID), actual)
   577  }
   578  
   579  func ethAccounts(t *testing.T, handler *hTTPHandler) {
   580  	require := require.New(t)
   581  	result := serveTestHTTP(require, handler, "eth_accounts", "[]")
   582  	actual, ok := result.([]interface{})
   583  	require.True(ok)
   584  	require.Equal(0, len(actual))
   585  }
   586  
   587  func web3Staking(t *testing.T, handler *hTTPHandler) {
   588  	require := require.New(t)
   589  	ecdsaPvk, ok := identityset.PrivateKey(28).EcdsaPrivateKey().(*ecdsa.PrivateKey)
   590  	require.True(ok)
   591  	toAddr, err := ioAddrToEthAddr(address.StakingProtocolAddr)
   592  	require.NoError(err)
   593  
   594  	type stakeData struct {
   595  		actType string
   596  		data    []byte
   597  	}
   598  	var testDatas []stakeData
   599  
   600  	// encode stake data
   601  	act1, err := action.NewCreateStake(1, "test", "100", 7, false, []byte{}, 1000000, big.NewInt(0))
   602  	require.NoError(err)
   603  	data, err := act1.EncodeABIBinary()
   604  	require.NoError(err)
   605  	testDatas = append(testDatas, stakeData{"createStake", data})
   606  
   607  	act2, err := action.NewDepositToStake(2, 7, "100", []byte{}, 1000000, big.NewInt(0))
   608  	require.NoError(err)
   609  	data2, err := act2.EncodeABIBinary()
   610  	require.NoError(err)
   611  	testDatas = append(testDatas, stakeData{"depositToStake", data2})
   612  
   613  	act3, err := action.NewChangeCandidate(3, "test", 7, []byte{}, 1000000, big.NewInt(0))
   614  	require.NoError(err)
   615  	data3, err := act3.EncodeABIBinary()
   616  	require.NoError(err)
   617  	testDatas = append(testDatas, stakeData{"changeCandidate", data3})
   618  
   619  	act4, err := action.NewUnstake(4, 7, []byte{}, 1000000, big.NewInt(0))
   620  	require.NoError(err)
   621  	data4, err := act4.EncodeABIBinary()
   622  	require.NoError(err)
   623  	testDatas = append(testDatas, stakeData{"unstake", data4})
   624  
   625  	act5, err := action.NewWithdrawStake(5, 7, []byte{}, 1000000, big.NewInt(0))
   626  	require.NoError(err)
   627  	data5, err := act5.EncodeABIBinary()
   628  	require.NoError(err)
   629  	testDatas = append(testDatas, stakeData{"withdrawStake", data5})
   630  
   631  	act6, err := action.NewRestake(6, 7, 7, false, []byte{}, 1000000, big.NewInt(0))
   632  	require.NoError(err)
   633  	data6, err := act6.EncodeABIBinary()
   634  	require.NoError(err)
   635  	testDatas = append(testDatas, stakeData{"restake", data6})
   636  
   637  	act7, err := action.NewTransferStake(7, "io1xpq62aw85uqzrccg9y5hnryv8ld2nkpycc3gza", 7, []byte{}, 1000000, big.NewInt(0))
   638  	require.NoError(err)
   639  	data7, err := act7.EncodeABIBinary()
   640  	require.NoError(err)
   641  	testDatas = append(testDatas, stakeData{"transferStake", data7})
   642  
   643  	act8, err := action.NewCandidateRegister(
   644  		8,
   645  		"test",
   646  		"io1xpq62aw85uqzrccg9y5hnryv8ld2nkpycc3gza",
   647  		"io1xpq62aw85uqzrccg9y5hnryv8ld2nkpycc3gza",
   648  		"io1xpq62aw85uqzrccg9y5hnryv8ld2nkpycc3gza",
   649  		"100",
   650  		7,
   651  		false,
   652  		[]byte{},
   653  		1000000,
   654  		big.NewInt(0))
   655  	require.NoError(err)
   656  	data8, err := act8.EncodeABIBinary()
   657  	require.NoError(err)
   658  	testDatas = append(testDatas, stakeData{"candidateRegister", data8})
   659  
   660  	act9, err := action.NewCandidateUpdate(
   661  		9,
   662  		"test",
   663  		"io1xpq62aw85uqzrccg9y5hnryv8ld2nkpycc3gza",
   664  		"io1xpq62aw85uqzrccg9y5hnryv8ld2nkpycc3gza",
   665  		1000000,
   666  		big.NewInt(0))
   667  	require.NoError(err)
   668  	data9, err := act9.EncodeABIBinary()
   669  	require.NoError(err)
   670  	testDatas = append(testDatas, stakeData{"candidateUpdate", data9})
   671  
   672  	for i, test := range testDatas {
   673  		// estimate gas
   674  		result := serveTestHTTP(require, handler, "eth_estimateGas",
   675  			fmt.Sprintf(`[{
   676  				"from":     "%s",
   677  				"to":       "%s",
   678  				"gas":      "0x0",
   679  				"gasPrice": "0x0",
   680  				"value":    "0x0",
   681  				"data":     "%s"},
   682  			    1]`, identityset.Address(28).Hex(), toAddr, hex.EncodeToString(test.data)))
   683  		actual, ok := result.(string)
   684  		require.True(ok)
   685  		gasLimit, err := hexStringToNumber(actual)
   686  		require.NoError(err)
   687  
   688  		// create tx
   689  		to := common.HexToAddress(toAddr)
   690  		rawTx := types.NewTx(&types.LegacyTx{
   691  			Nonce:    uint64(9 + i),
   692  			GasPrice: big.NewInt(0),
   693  			Gas:      gasLimit,
   694  			To:       &to,
   695  			Value:    big.NewInt(0),
   696  			Data:     test.data,
   697  		})
   698  		signer, err := action.NewEthSigner(iotextypes.Encoding_ETHEREUM_EIP155, _evmNetworkID)
   699  		require.NoError(err)
   700  		tx, err := types.SignTx(rawTx, signer, ecdsaPvk)
   701  		require.NoError(err)
   702  		BinaryData, err := tx.MarshalBinary()
   703  		require.NoError(err)
   704  
   705  		// send tx
   706  		result = serveTestHTTP(require, handler, "eth_sendRawTransaction", fmt.Sprintf(`["%s"]`, hex.EncodeToString(BinaryData)))
   707  		ret, ok := result.(string)
   708  		require.True(ok)
   709  		require.Equal(tx.Hash().Hex(), ret)
   710  	}
   711  }
   712  
   713  func sendRawTransaction(t *testing.T, handler *hTTPHandler) {
   714  	require := require.New(t)
   715  	rawData := "0xf8600180830186a09412745fec82b585f239c01090882eb40702c32b04808025a0b0e1aab5b64d744ae01fc9f1c3e9919844a799e90c23129d611f7efe6aec8a29a0195e28d22d9b280e00d501ff63525bb76f5c87b8646c89d5d9c5485edcb1b498"
   716  	tx, err := action.DecodeEtherTx(rawData)
   717  	require.NoError(err)
   718  	result := serveTestHTTP(require, handler, "eth_sendRawTransaction", fmt.Sprintf(`["%s"]`, rawData))
   719  	actual, ok := result.(string)
   720  	require.True(ok)
   721  	require.Equal(tx.Hash().Hex(), actual)
   722  }
   723  
   724  func estimateGas(t *testing.T, handler *hTTPHandler, bc blockchain.Blockchain, dao blockdao.BlockDAO, actPool actpool.ActPool) {
   725  	require := require.New(t)
   726  
   727  	// deploy a contract
   728  	contractCode := "608060405234801561001057600080fd5b50610150806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806360fe47b11461003b5780636d4ce63c14610057575b600080fd5b6100556004803603810190610050919061009d565b610075565b005b61005f61007f565b60405161006c91906100d9565b60405180910390f35b8060008190555050565b60008054905090565b60008135905061009781610103565b92915050565b6000602082840312156100b3576100b26100fe565b5b60006100c184828501610088565b91505092915050565b6100d3816100f4565b82525050565b60006020820190506100ee60008301846100ca565b92915050565b6000819050919050565b600080fd5b61010c816100f4565b811461011757600080fd5b5056fea2646970667358221220c86a8c4dd175f55f5732b75b721d714ceb38a835b87c6cf37cf28c790813e19064736f6c63430008070033"
   729  	contract, _ := deployContractV2(bc, dao, actPool, identityset.PrivateKey(13), 1, bc.TipHeight(), contractCode)
   730  
   731  	fromAddr, _ := ioAddrToEthAddr(identityset.Address(0).String())
   732  	toAddr, _ := ioAddrToEthAddr(identityset.Address(28).String())
   733  	contractAddr, _ := ioAddrToEthAddr(contract)
   734  
   735  	for _, test := range []struct {
   736  		params   string
   737  		expected uint64
   738  	}{
   739  		{
   740  			fmt.Sprintf(`[{
   741  				"from":     "%s",
   742  				"to":       "%s",
   743  				"gas":      "0x0",
   744  				"gasPrice": "0x0",
   745  				"value":    "0x0",
   746  				"data":     "0x1123123c"},
   747  			    1]`, fromAddr, toAddr),
   748  			21000,
   749  		},
   750  		{
   751  			fmt.Sprintf(`[{
   752  			    "from":     "%s",
   753  			    "to":       "%s",
   754  			    "gas":      "0x0",
   755  				"gasPrice": "0x0",
   756  				"value":    "0x0",
   757  				"data":      "344933be000000000000000000000000000000000000000000000000000be497a92e9f3300000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000f8be4046fd89199906ca348bcd3822c4b250e246000000000000000000000000000000000000000000000000000000006173a15400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000a00744882684c3e4747faefd68d283ea44099d030000000000000000000000000258866edaf84d6081df17660357ab20a07d0c80"},
   758  				1]`, fromAddr, toAddr),
   759  			36000,
   760  		},
   761  		{
   762  			fmt.Sprintf(`[{
   763  				"from":     "%s",
   764  				"to":       "%s",
   765  				"gas":      "0x0",
   766  				"gasPrice": "0x0",
   767  				"value":    "0x0",
   768  				"data":     "0x6d4ce63c"},
   769  				1]`, fromAddr, contractAddr),
   770  			21000,
   771  		},
   772  	} {
   773  		result := serveTestHTTP(require, handler, "eth_estimateGas", test.params)
   774  		actual, ok := result.(string)
   775  		require.True(ok)
   776  		require.Equal(uint64ToHex(test.expected), actual)
   777  	}
   778  }
   779  
   780  func getCode(t *testing.T, handler *hTTPHandler, bc blockchain.Blockchain, dao blockdao.BlockDAO, actPool actpool.ActPool) {
   781  	require := require.New(t)
   782  	// deploy a contract
   783  	contractCode := "608060405234801561001057600080fd5b50610150806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806360fe47b11461003b5780636d4ce63c14610057575b600080fd5b6100556004803603810190610050919061009d565b610075565b005b61005f61007f565b60405161006c91906100d9565b60405180910390f35b8060008190555050565b60008054905090565b60008135905061009781610103565b92915050565b6000602082840312156100b3576100b26100fe565b5b60006100c184828501610088565b91505092915050565b6100d3816100f4565b82525050565b60006020820190506100ee60008301846100ca565b92915050565b6000819050919050565b600080fd5b61010c816100f4565b811461011757600080fd5b5056fea2646970667358221220c86a8c4dd175f55f5732b75b721d714ceb38a835b87c6cf37cf28c790813e19064736f6c63430008070033"
   784  	contract, _ := deployContractV2(bc, dao, actPool, identityset.PrivateKey(13), 2, bc.TipHeight(), contractCode)
   785  	contractAddr, _ := ioAddrToEthAddr(contract)
   786  
   787  	result := serveTestHTTP(require, handler, "eth_getCode", fmt.Sprintf(`["%s", "0x1"]`, contractAddr))
   788  	actual, ok := result.(string)
   789  	require.True(ok)
   790  	require.Contains(contractCode, util.Remove0xPrefix(actual))
   791  }
   792  
   793  func getStorageAt(t *testing.T, handler *hTTPHandler, bc blockchain.Blockchain, dao blockdao.BlockDAO, actPool actpool.ActPool) {
   794  	require := require.New(t)
   795  	// deploy a contract
   796  	contractCode := "608060405234801561001057600080fd5b50610150806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806360fe47b11461003b5780636d4ce63c14610057575b600080fd5b6100556004803603810190610050919061009d565b610075565b005b61005f61007f565b60405161006c91906100d9565b60405180910390f35b8060008190555050565b60008054905090565b60008135905061009781610103565b92915050565b6000602082840312156100b3576100b26100fe565b5b60006100c184828501610088565b91505092915050565b6100d3816100f4565b82525050565b60006020820190506100ee60008301846100ca565b92915050565b6000819050919050565b600080fd5b61010c816100f4565b811461011757600080fd5b5056fea2646970667358221220c86a8c4dd175f55f5732b75b721d714ceb38a835b87c6cf37cf28c790813e19064736f6c63430008070033"
   797  	contract, _ := deployContractV2(bc, dao, actPool, identityset.PrivateKey(13), 3, bc.TipHeight(), contractCode)
   798  	contractAddr, _ := ioAddrToEthAddr(contract)
   799  
   800  	for _, test := range []struct {
   801  		params   string
   802  		expected int
   803  	}{
   804  		{fmt.Sprintf(`["%s", "0x0"]`, contractAddr), 1},
   805  		{`[1]`, 0},
   806  		{`["TEST", "TEST"]`, 0},
   807  	} {
   808  		result := serveTestHTTP(require, handler, "eth_getStorageAt", test.params)
   809  		if test.expected == 0 {
   810  			require.Nil(result)
   811  			continue
   812  		}
   813  		actual, ok := result.(string)
   814  		require.True(ok)
   815  		// the value of any contract at pos0 is be "0x0000000000000000000000000000000000000000000000000000000000000000"
   816  		require.Equal("0x0000000000000000000000000000000000000000000000000000000000000000", actual)
   817  	}
   818  }