github.com/iotexproject/iotex-core@v1.14.1-rc1/action/protocol/execution/protocol_test.go (about)

     1  // Copyright (c) 2019 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 execution
     7  
     8  import (
     9  	"bytes"
    10  	"context"
    11  	"encoding/hex"
    12  	"encoding/json"
    13  	"fmt"
    14  	"io"
    15  	"math/big"
    16  	"os"
    17  	"testing"
    18  	"time"
    19  
    20  	"github.com/ethereum/go-ethereum/common"
    21  	"github.com/ethereum/go-ethereum/core/types"
    22  	"github.com/mohae/deepcopy"
    23  	"github.com/pkg/errors"
    24  	"github.com/stretchr/testify/require"
    25  	"go.uber.org/zap"
    26  
    27  	"github.com/iotexproject/go-pkgs/crypto"
    28  	"github.com/iotexproject/go-pkgs/hash"
    29  	"github.com/iotexproject/iotex-address/address"
    30  	"github.com/iotexproject/iotex-proto/golang/iotextypes"
    31  
    32  	"github.com/iotexproject/iotex-core/action"
    33  	"github.com/iotexproject/iotex-core/action/protocol"
    34  	"github.com/iotexproject/iotex-core/action/protocol/account"
    35  	accountutil "github.com/iotexproject/iotex-core/action/protocol/account/util"
    36  	"github.com/iotexproject/iotex-core/action/protocol/execution/evm"
    37  	"github.com/iotexproject/iotex-core/action/protocol/rewarding"
    38  	"github.com/iotexproject/iotex-core/action/protocol/rolldpos"
    39  	"github.com/iotexproject/iotex-core/actpool"
    40  	"github.com/iotexproject/iotex-core/blockchain"
    41  	"github.com/iotexproject/iotex-core/blockchain/block"
    42  	"github.com/iotexproject/iotex-core/blockchain/blockdao"
    43  	"github.com/iotexproject/iotex-core/blockchain/filedao"
    44  	"github.com/iotexproject/iotex-core/blockchain/genesis"
    45  	"github.com/iotexproject/iotex-core/blockindex"
    46  	"github.com/iotexproject/iotex-core/config"
    47  	"github.com/iotexproject/iotex-core/db"
    48  	"github.com/iotexproject/iotex-core/pkg/log"
    49  	"github.com/iotexproject/iotex-core/pkg/unit"
    50  	"github.com/iotexproject/iotex-core/state/factory"
    51  	"github.com/iotexproject/iotex-core/test/identityset"
    52  	"github.com/iotexproject/iotex-core/testutil"
    53  )
    54  
    55  type (
    56  	// ExpectedBalance defines an account-balance pair
    57  	ExpectedBalance struct {
    58  		Account    string `json:"account"`
    59  		RawBalance string `json:"rawBalance"`
    60  	}
    61  
    62  	ExpectedBlockInfo struct {
    63  		TxRootHash      string `json:"txRootHash"`
    64  		StateRootHash   string `json:"stateRootHash"`
    65  		ReceiptRootHash string `json:"receiptRootHash"`
    66  	}
    67  
    68  	// GenesisBlockHeight defines an genesis blockHeight
    69  	GenesisBlockHeight struct {
    70  		IsBering   bool `json:"isBering"`
    71  		IsIceland  bool `json:"isIceland"`
    72  		IsLondon   bool `json:"isLondon"`
    73  		IsShanghai bool `json:"isShanghai"`
    74  	}
    75  
    76  	Log struct {
    77  		Topics []string `json:"topics"`
    78  		Data   string   `json:"data"`
    79  	}
    80  
    81  	AccessTuple struct {
    82  		Address     string   `json:"address"`
    83  		StorageKeys []string `json:"storageKeys"`
    84  	}
    85  
    86  	ExecutionConfig struct {
    87  		Comment                 string            `json:"comment"`
    88  		ContractIndex           int               `json:"contractIndex"`
    89  		AppendContractAddress   bool              `json:"appendContractAddress"`
    90  		ContractIndexToAppend   int               `json:"contractIndexToAppend"`
    91  		ContractAddressToAppend string            `json:"contractAddressToAppend"`
    92  		ReadOnly                bool              `json:"readOnly"`
    93  		RawPrivateKey           string            `json:"rawPrivateKey"`
    94  		RawByteCode             string            `json:"rawByteCode"`
    95  		RawAmount               string            `json:"rawAmount"`
    96  		RawGasLimit             uint              `json:"rawGasLimit"`
    97  		RawGasPrice             string            `json:"rawGasPrice"`
    98  		RawAccessList           []AccessTuple     `json:"rawAccessList"`
    99  		Failed                  bool              `json:"failed"`
   100  		RawReturnValue          string            `json:"rawReturnValue"`
   101  		RawExpectedGasConsumed  uint              `json:"rawExpectedGasConsumed"`
   102  		ExpectedStatus          uint64            `json:"expectedStatus"`
   103  		ExpectedBalances        []ExpectedBalance `json:"expectedBalances"`
   104  		ExpectedLogs            []Log             `json:"expectedLogs"`
   105  		ExpectedErrorMsg        string            `json:"expectedErrorMsg"`
   106  		ExpectedBlockInfos      ExpectedBlockInfo `json:"expectedBlockInfos"`
   107  	}
   108  )
   109  
   110  var (
   111  	fixedTime = time.Unix(genesis.Default.Timestamp, 0)
   112  )
   113  
   114  func (eb *ExpectedBalance) Balance() *big.Int {
   115  	balance, ok := new(big.Int).SetString(eb.RawBalance, 10)
   116  	if !ok {
   117  		log.L().Panic("invalid balance", zap.String("balance", eb.RawBalance))
   118  	}
   119  	return balance
   120  }
   121  
   122  func readCode(sr protocol.StateReader, addr []byte) ([]byte, error) {
   123  	var c protocol.SerializableBytes
   124  	account, err := accountutil.LoadAccountByHash160(sr, hash.BytesToHash160(addr))
   125  	if err != nil {
   126  		return nil, err
   127  	}
   128  	_, err = sr.State(&c, protocol.NamespaceOption(evm.CodeKVNameSpace), protocol.KeyOption(account.CodeHash[:]))
   129  
   130  	return c[:], err
   131  }
   132  
   133  func (cfg *ExecutionConfig) PrivateKey() crypto.PrivateKey {
   134  	priKey, err := crypto.HexStringToPrivateKey(cfg.RawPrivateKey)
   135  	if err != nil {
   136  		log.L().Panic(
   137  			"invalid private key",
   138  			zap.String("privateKey", cfg.RawPrivateKey),
   139  			zap.Error(err),
   140  		)
   141  	}
   142  
   143  	return priKey
   144  }
   145  
   146  func (cfg *ExecutionConfig) Executor() address.Address {
   147  	priKey := cfg.PrivateKey()
   148  	addr := priKey.PublicKey().Address()
   149  	if addr == nil {
   150  		log.L().Panic(
   151  			"invalid private key",
   152  			zap.String("privateKey", cfg.RawPrivateKey),
   153  			zap.Error(errors.New("failed to get address")),
   154  		)
   155  	}
   156  
   157  	return addr
   158  }
   159  
   160  func (cfg *ExecutionConfig) ByteCode() []byte {
   161  	byteCode, err := hex.DecodeString(cfg.RawByteCode)
   162  	if err != nil {
   163  		log.L().Panic(
   164  			"invalid byte code",
   165  			zap.String("byteCode", cfg.RawByteCode),
   166  			zap.Error(err),
   167  		)
   168  	}
   169  	if cfg.AppendContractAddress {
   170  		addr, err := address.FromString(cfg.ContractAddressToAppend)
   171  		if err != nil {
   172  			log.L().Panic(
   173  				"invalid contract address to append",
   174  				zap.String("contractAddressToAppend", cfg.ContractAddressToAppend),
   175  				zap.Error(err),
   176  			)
   177  		}
   178  		ba := addr.Bytes()
   179  		ba = append(make([]byte, 12), ba...)
   180  		byteCode = append(byteCode, ba...)
   181  	}
   182  
   183  	return byteCode
   184  }
   185  
   186  func (cfg *ExecutionConfig) Amount() *big.Int {
   187  	amount, ok := new(big.Int).SetString(cfg.RawAmount, 10)
   188  	if !ok {
   189  		log.L().Panic("invalid amount", zap.String("amount", cfg.RawAmount))
   190  	}
   191  
   192  	return amount
   193  }
   194  
   195  func (cfg *ExecutionConfig) GasPrice() *big.Int {
   196  	price, ok := new(big.Int).SetString(cfg.RawGasPrice, 10)
   197  	if !ok {
   198  		log.L().Panic("invalid gas price", zap.String("gasPrice", cfg.RawGasPrice))
   199  	}
   200  
   201  	return price
   202  }
   203  
   204  func (cfg *ExecutionConfig) GasLimit() uint64 {
   205  	return uint64(cfg.RawGasLimit)
   206  }
   207  
   208  func (cfg *ExecutionConfig) AccessList() types.AccessList {
   209  	if len(cfg.RawAccessList) == 0 {
   210  		return nil
   211  	}
   212  	accessList := make(types.AccessList, len(cfg.RawAccessList))
   213  	for i, rawAccessList := range cfg.RawAccessList {
   214  		accessList[i].Address = common.HexToAddress(rawAccessList.Address)
   215  		if numKey := len(rawAccessList.StorageKeys); numKey > 0 {
   216  			accessList[i].StorageKeys = make([]common.Hash, numKey)
   217  			for j, rawStorageKey := range rawAccessList.StorageKeys {
   218  				accessList[i].StorageKeys[j] = common.HexToHash(rawStorageKey)
   219  			}
   220  		}
   221  	}
   222  	return accessList
   223  }
   224  
   225  func (cfg *ExecutionConfig) ExpectedGasConsumed() uint64 {
   226  	return uint64(cfg.RawExpectedGasConsumed)
   227  }
   228  
   229  func (cfg *ExecutionConfig) ExpectedReturnValue() []byte {
   230  	retval, err := hex.DecodeString(cfg.RawReturnValue)
   231  	if err != nil {
   232  		log.L().Panic(
   233  			"invalid return value",
   234  			zap.String("returnValue", cfg.RawReturnValue),
   235  			zap.Error(err),
   236  		)
   237  	}
   238  
   239  	return retval
   240  }
   241  
   242  type SmartContractTest struct {
   243  	// the order matters
   244  	InitGenesis  GenesisBlockHeight `json:"initGenesis"`
   245  	InitBalances []ExpectedBalance  `json:"initBalances"`
   246  	Deployments  []ExecutionConfig  `json:"deployments"`
   247  	Executions   []ExecutionConfig  `json:"executions"`
   248  }
   249  
   250  func NewSmartContractTest(t *testing.T, file string) {
   251  	require := require.New(t)
   252  	jsonFile, err := os.Open(file)
   253  	require.NoError(err)
   254  	sctBytes, err := io.ReadAll(jsonFile)
   255  	require.NoError(err)
   256  	sct := &SmartContractTest{}
   257  	require.NoError(json.Unmarshal(sctBytes, sct))
   258  	sct.run(require)
   259  }
   260  
   261  func readExecution(
   262  	bc blockchain.Blockchain,
   263  	sf factory.Factory,
   264  	dao blockdao.BlockDAO,
   265  	ap actpool.ActPool,
   266  	ecfg *ExecutionConfig,
   267  	contractAddr string,
   268  ) ([]byte, *action.Receipt, error) {
   269  	log.S().Info(ecfg.Comment)
   270  	state, err := accountutil.AccountState(genesis.WithGenesisContext(context.Background(), bc.Genesis()), sf, ecfg.Executor())
   271  	if err != nil {
   272  		return nil, nil, err
   273  	}
   274  	exec, err := action.NewExecutionWithAccessList(
   275  		contractAddr,
   276  		state.PendingNonce(),
   277  		ecfg.Amount(),
   278  		ecfg.GasLimit(),
   279  		ecfg.GasPrice(),
   280  		ecfg.ByteCode(),
   281  		ecfg.AccessList(),
   282  	)
   283  	if err != nil {
   284  		return nil, nil, err
   285  	}
   286  	addr := ecfg.PrivateKey().PublicKey().Address()
   287  	if addr == nil {
   288  		return nil, nil, errors.New("failed to get address")
   289  	}
   290  	ctx, err := bc.Context(context.Background())
   291  	if err != nil {
   292  		return nil, nil, err
   293  	}
   294  	ctx = evm.WithHelperCtx(ctx, evm.HelperContext{
   295  		GetBlockHash: dao.GetBlockHash,
   296  		GetBlockTime: getBlockTimeForTest,
   297  	})
   298  	return sf.SimulateExecution(ctx, addr, exec)
   299  }
   300  
   301  func (sct *SmartContractTest) runExecutions(
   302  	bc blockchain.Blockchain,
   303  	sf factory.Factory,
   304  	dao blockdao.BlockDAO,
   305  	ap actpool.ActPool,
   306  	ecfgs []*ExecutionConfig,
   307  	contractAddrs []string,
   308  ) ([]*action.Receipt, *ExpectedBlockInfo, error) {
   309  	nonces := map[string]uint64{}
   310  	hashes := []hash.Hash256{}
   311  	for i, ecfg := range ecfgs {
   312  		log.S().Info(ecfg.Comment)
   313  		nonce := uint64(1)
   314  		var ok bool
   315  		executor := ecfg.Executor()
   316  		if nonce, ok = nonces[executor.String()]; !ok {
   317  			state, err := accountutil.AccountState(genesis.WithGenesisContext(context.Background(), bc.Genesis()), sf, executor)
   318  			if err != nil {
   319  				return nil, nil, err
   320  			}
   321  			nonce = state.PendingNonce()
   322  		}
   323  		nonces[executor.String()] = nonce
   324  		exec, err := action.NewExecutionWithAccessList(
   325  			contractAddrs[i],
   326  			nonce,
   327  			ecfg.Amount(),
   328  			ecfg.GasLimit(),
   329  			ecfg.GasPrice(),
   330  			ecfg.ByteCode(),
   331  			ecfg.AccessList(),
   332  		)
   333  		if err != nil {
   334  			return nil, nil, err
   335  		}
   336  		builder := &action.EnvelopeBuilder{}
   337  		builder.SetAction(exec).
   338  			SetNonce(exec.Nonce()).
   339  			SetGasLimit(ecfg.GasLimit()).
   340  			SetGasPrice(ecfg.GasPrice())
   341  		if sct.InitGenesis.IsShanghai {
   342  			builder.SetChainID(bc.ChainID())
   343  		}
   344  		elp := builder.Build()
   345  		selp, err := action.Sign(elp, ecfg.PrivateKey())
   346  		if err != nil {
   347  			return nil, nil, err
   348  		}
   349  		if err := ap.Add(context.Background(), selp); err != nil {
   350  			return nil, nil, err
   351  		}
   352  		selpHash, err := selp.Hash()
   353  		if err != nil {
   354  			return nil, nil, err
   355  		}
   356  		hashes = append(hashes, selpHash)
   357  	}
   358  	blk, err := bc.MintNewBlock(fixedTime)
   359  	if err != nil {
   360  		return nil, nil, err
   361  	}
   362  
   363  	if err := bc.CommitBlock(blk); err != nil {
   364  		return nil, nil, err
   365  	}
   366  	receipts, err := dao.GetReceipts(blk.Height())
   367  	if err != nil {
   368  		return nil, nil, err
   369  	}
   370  	receiptMap := make(map[hash.Hash256]*action.Receipt, len(receipts))
   371  	for _, receipt := range receipts {
   372  		receiptMap[receipt.ActionHash] = receipt
   373  	}
   374  	receipts = receipts[:0]
   375  	for _, h := range hashes {
   376  		receipt, ok := receiptMap[h]
   377  		if !ok {
   378  			return nil, nil, errors.Errorf("failed to find receipt for action %x", h)
   379  		}
   380  		receipts = append(receipts, receipt)
   381  	}
   382  	stateRootHash, txRootHash, receiptRootHash := blk.DeltaStateDigest(), blk.TxRoot(), blk.ReceiptRoot()
   383  	blkInfo := &ExpectedBlockInfo{
   384  		hex.EncodeToString(txRootHash[:]),
   385  		hex.EncodeToString(stateRootHash[:]),
   386  		hex.EncodeToString(receiptRootHash[:]),
   387  	}
   388  	return receipts, blkInfo, nil
   389  }
   390  
   391  func (sct *SmartContractTest) prepareBlockchain(
   392  	ctx context.Context,
   393  	cfg config.Config,
   394  	r *require.Assertions,
   395  ) (blockchain.Blockchain, factory.Factory, blockdao.BlockDAO, actpool.ActPool) {
   396  	defer func() {
   397  		delete(cfg.Plugins, config.GatewayPlugin)
   398  	}()
   399  	cfg.Plugins[config.GatewayPlugin] = true
   400  	cfg.Chain.EnableAsyncIndexWrite = false
   401  	cfg.Genesis.EnableGravityChainVoting = false
   402  	testTriePath, err := testutil.PathOfTempFile("trie")
   403  	r.NoError(err)
   404  	defer testutil.CleanupPath(testTriePath)
   405  
   406  	cfg.Chain.TrieDBPath = testTriePath
   407  	cfg.ActPool.MinGasPriceStr = "0"
   408  	if sct.InitGenesis.IsBering {
   409  		cfg.Genesis.Blockchain.AleutianBlockHeight = 0
   410  		cfg.Genesis.Blockchain.BeringBlockHeight = 0
   411  	}
   412  	cfg.Genesis.HawaiiBlockHeight = 0
   413  	if sct.InitGenesis.IsIceland {
   414  		cfg.Genesis.CookBlockHeight = 0
   415  		cfg.Genesis.DardanellesBlockHeight = 0
   416  		cfg.Genesis.DaytonaBlockHeight = 0
   417  		cfg.Genesis.EasterBlockHeight = 0
   418  		cfg.Genesis.FbkMigrationBlockHeight = 0
   419  		cfg.Genesis.FairbankBlockHeight = 0
   420  		cfg.Genesis.GreenlandBlockHeight = 0
   421  		cfg.Genesis.IcelandBlockHeight = 0
   422  	}
   423  	if sct.InitGenesis.IsLondon {
   424  		// London is enabled at okhotsk height
   425  		cfg.Genesis.Blockchain.JutlandBlockHeight = 0
   426  		cfg.Genesis.Blockchain.KamchatkaBlockHeight = 0
   427  		cfg.Genesis.Blockchain.LordHoweBlockHeight = 0
   428  		cfg.Genesis.Blockchain.MidwayBlockHeight = 0
   429  		cfg.Genesis.Blockchain.NewfoundlandBlockHeight = 0
   430  		cfg.Genesis.Blockchain.OkhotskBlockHeight = 0
   431  	}
   432  	if sct.InitGenesis.IsShanghai {
   433  		// Shanghai is enabled at Sumatra height
   434  		cfg.Genesis.Blockchain.PalauBlockHeight = 0
   435  		cfg.Genesis.Blockchain.QuebecBlockHeight = 0
   436  		cfg.Genesis.Blockchain.RedseaBlockHeight = 0
   437  		cfg.Genesis.Blockchain.SumatraBlockHeight = 0
   438  		cfg.Genesis.ActionGasLimit = 10000000
   439  	}
   440  	for _, expectedBalance := range sct.InitBalances {
   441  		cfg.Genesis.InitBalanceMap[expectedBalance.Account] = expectedBalance.Balance().String()
   442  	}
   443  	registry := protocol.NewRegistry()
   444  	acc := account.NewProtocol(rewarding.DepositGas)
   445  	r.NoError(acc.Register(registry))
   446  	rp := rolldpos.NewProtocol(cfg.Genesis.NumCandidateDelegates, cfg.Genesis.NumDelegates, cfg.Genesis.NumSubEpochs)
   447  	r.NoError(rp.Register(registry))
   448  	// create state factory
   449  	var sf factory.Factory
   450  	var daoKV db.KVStore
   451  
   452  	factoryCfg := factory.GenerateConfig(cfg.Chain, cfg.Genesis)
   453  	if cfg.Chain.EnableTrielessStateDB {
   454  		if cfg.Chain.EnableStateDBCaching {
   455  			daoKV, err = db.CreateKVStoreWithCache(cfg.DB, cfg.Chain.TrieDBPath, cfg.Chain.StateDBCacheSize)
   456  		} else {
   457  			daoKV, err = db.CreateKVStore(cfg.DB, cfg.Chain.TrieDBPath)
   458  		}
   459  		r.NoError(err)
   460  		sf, err = factory.NewStateDB(factoryCfg, daoKV, factory.RegistryStateDBOption(registry))
   461  	} else {
   462  		sf, err = factory.NewFactory(factoryCfg, db.NewMemKVStore(), factory.RegistryOption(registry))
   463  	}
   464  	r.NoError(err)
   465  	ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool)
   466  	r.NoError(err)
   467  	// create indexer
   468  	indexer, err := blockindex.NewIndexer(db.NewMemKVStore(), cfg.Genesis.Hash())
   469  	r.NoError(err)
   470  	// create BlockDAO
   471  	store, err := filedao.NewFileDAOInMemForTest()
   472  	r.NoError(err)
   473  	dao := blockdao.NewBlockDAOWithIndexersAndCache(store, []blockdao.BlockIndexer{sf, indexer}, cfg.DB.MaxCacheSize)
   474  	r.NotNil(dao)
   475  	bc := blockchain.NewBlockchain(
   476  		cfg.Chain,
   477  		cfg.Genesis,
   478  		dao,
   479  		factory.NewMinter(sf, ap),
   480  		blockchain.BlockValidatorOption(block.NewValidator(
   481  			sf,
   482  			protocol.NewGenericValidator(sf, accountutil.AccountState),
   483  		)),
   484  	)
   485  	reward := rewarding.NewProtocol(cfg.Genesis.Rewarding)
   486  	r.NoError(reward.Register(registry))
   487  
   488  	r.NotNil(bc)
   489  	execution := NewProtocol(dao.GetBlockHash, rewarding.DepositGasWithSGD, nil, getBlockTimeForTest)
   490  	r.NoError(execution.Register(registry))
   491  	r.NoError(bc.Start(ctx))
   492  
   493  	return bc, sf, dao, ap
   494  }
   495  
   496  func (sct *SmartContractTest) deployContracts(
   497  	bc blockchain.Blockchain,
   498  	sf factory.Factory,
   499  	dao blockdao.BlockDAO,
   500  	ap actpool.ActPool,
   501  	r *require.Assertions,
   502  ) (contractAddresses []string) {
   503  	for i, contract := range sct.Deployments {
   504  		if contract.AppendContractAddress {
   505  			contract.ContractAddressToAppend = contractAddresses[contract.ContractIndexToAppend]
   506  		}
   507  		receipts, _, err := sct.runExecutions(bc, sf, dao, ap, []*ExecutionConfig{&contract}, []string{action.EmptyAddress})
   508  		r.NoError(err)
   509  		r.Equal(1, len(receipts))
   510  		receipt := receipts[0]
   511  		r.NotNil(receipt)
   512  		if sct.InitGenesis.IsBering {
   513  			// if it is post bering, it compares the status with expected status
   514  			r.Equal(sct.Deployments[i].ExpectedStatus, receipt.Status)
   515  			if receipt.Status != uint64(iotextypes.ReceiptStatus_Success) {
   516  				return []string{}
   517  			}
   518  		} else {
   519  			if !sct.Deployments[i].Failed {
   520  				r.Equal(uint64(iotextypes.ReceiptStatus_Success), receipt.Status, i)
   521  			} else {
   522  				r.Equal(uint64(iotextypes.ReceiptStatus_Failure), receipt.Status, i)
   523  				return []string{}
   524  			}
   525  		}
   526  		if sct.Deployments[i].ExpectedGasConsumed() != 0 {
   527  			r.Equal(sct.Deployments[i].ExpectedGasConsumed(), receipt.GasConsumed)
   528  		}
   529  
   530  		addr, _ := address.FromString(receipt.ContractAddress)
   531  		c, err := readCode(sf, addr.Bytes())
   532  		r.NoError(err)
   533  		if contract.AppendContractAddress {
   534  			lenOfByteCode := len(contract.ByteCode())
   535  			r.True(bytes.Contains(contract.ByteCode()[:lenOfByteCode-32], c))
   536  		} else {
   537  			r.True(bytes.Contains(sct.Deployments[i].ByteCode(), c))
   538  		}
   539  		contractAddresses = append(contractAddresses, receipt.ContractAddress)
   540  	}
   541  	return
   542  }
   543  
   544  func (sct *SmartContractTest) run(r *require.Assertions) {
   545  	// prepare blockchain
   546  	ctx := context.Background()
   547  	cfg := deepcopy.Copy(config.Default).(config.Config)
   548  	cfg.Chain.ProducerPrivKey = identityset.PrivateKey(28).HexString()
   549  	cfg.Chain.EnableTrielessStateDB = false
   550  	bc, sf, dao, ap := sct.prepareBlockchain(ctx, cfg, r)
   551  	defer func() {
   552  		r.NoError(bc.Stop(ctx))
   553  	}()
   554  	ctx = genesis.WithGenesisContext(context.Background(), bc.Genesis())
   555  	// deploy smart contract
   556  	contractAddresses := sct.deployContracts(bc, sf, dao, ap, r)
   557  	if len(contractAddresses) == 0 {
   558  		return
   559  	}
   560  
   561  	// run executions
   562  	for i, exec := range sct.Executions {
   563  		contractAddr := contractAddresses[exec.ContractIndex]
   564  		if exec.AppendContractAddress {
   565  			exec.ContractAddressToAppend = contractAddresses[exec.ContractIndexToAppend]
   566  		}
   567  		var retval []byte
   568  		var receipt *action.Receipt
   569  		var blkInfo *ExpectedBlockInfo
   570  		var err error
   571  		if exec.ReadOnly {
   572  			retval, receipt, err = readExecution(bc, sf, dao, ap, &exec, contractAddr)
   573  			r.NoError(err)
   574  			expected := exec.ExpectedReturnValue()
   575  			if len(expected) == 0 {
   576  				r.Equal(0, len(retval))
   577  			} else {
   578  				r.Equal(expected, retval)
   579  			}
   580  		} else {
   581  			var receipts []*action.Receipt
   582  			receipts, blkInfo, err = sct.runExecutions(bc, sf, dao, ap, []*ExecutionConfig{&exec}, []string{contractAddr})
   583  			r.NoError(err)
   584  			r.Equal(1, len(receipts))
   585  			receipt = receipts[0]
   586  			r.NotNil(receipt)
   587  		}
   588  
   589  		if sct.InitGenesis.IsBering {
   590  			// if it is post bering, it compares the status with expected status
   591  			r.Equal(exec.ExpectedStatus, receipt.Status)
   592  		} else {
   593  			if exec.Failed {
   594  				r.Equal(uint64(iotextypes.ReceiptStatus_Failure), receipt.Status)
   595  			} else {
   596  				r.Equal(uint64(iotextypes.ReceiptStatus_Success), receipt.Status)
   597  			}
   598  		}
   599  		if exec.ExpectedGasConsumed() != 0 {
   600  			r.Equal(exec.ExpectedGasConsumed(), receipt.GasConsumed, i)
   601  		}
   602  		if exec.ExpectedBlockInfos != (ExpectedBlockInfo{}) {
   603  			r.Equal(exec.ExpectedBlockInfos.ReceiptRootHash, blkInfo.ReceiptRootHash)
   604  			r.Equal(exec.ExpectedBlockInfos.TxRootHash, blkInfo.TxRootHash)
   605  			r.Equal(exec.ExpectedBlockInfos.StateRootHash, blkInfo.StateRootHash)
   606  		}
   607  		for _, expectedBalance := range exec.ExpectedBalances {
   608  			account := expectedBalance.Account
   609  			if account == "" {
   610  				account = contractAddr
   611  			}
   612  			addr, err := address.FromString(account)
   613  			r.NoError(err)
   614  			state, err := accountutil.AccountState(ctx, sf, addr)
   615  			r.NoError(err)
   616  			r.Equal(
   617  				0,
   618  				state.Balance.Cmp(expectedBalance.Balance()),
   619  				"balance of account %s is different from expectation, %d vs %d",
   620  				account,
   621  				state.Balance,
   622  				expectedBalance.Balance(),
   623  			)
   624  		}
   625  		if receipt.Status == uint64(iotextypes.ReceiptStatus_Success) {
   626  			r.Equal(len(exec.ExpectedLogs), len(receipt.Logs()), i)
   627  			// TODO: check value of logs
   628  		}
   629  		if receipt.Status == uint64(iotextypes.ReceiptStatus_ErrExecutionReverted) {
   630  			r.Equal(exec.ExpectedErrorMsg, receipt.ExecutionRevertMsg())
   631  		}
   632  	}
   633  }
   634  
   635  func TestProtocol_Validate(t *testing.T) {
   636  	require := require.New(t)
   637  	p := NewProtocol(func(uint64) (hash.Hash256, error) {
   638  		return hash.ZeroHash256, nil
   639  	}, rewarding.DepositGasWithSGD, nil, getBlockTimeForTest)
   640  
   641  	cases := []struct {
   642  		name      string
   643  		height    uint64
   644  		size      uint64
   645  		expectErr error
   646  	}{
   647  		{"limit 32KB", 0, 32683, nil},
   648  		{"exceed 32KB", 0, 32684, action.ErrOversizedData},
   649  		{"limit 48KB", genesis.Default.SumatraBlockHeight, uint64(_executionSizeLimit48KB), nil},
   650  		{"exceed 48KB", genesis.Default.SumatraBlockHeight, uint64(_executionSizeLimit48KB) + 1, action.ErrOversizedData},
   651  	}
   652  
   653  	for i := range cases {
   654  		t.Run(cases[i].name, func(t *testing.T) {
   655  			ex, err := action.NewExecution("2", uint64(1), big.NewInt(0), uint64(0), big.NewInt(0), make([]byte, cases[i].size))
   656  			require.NoError(err)
   657  			ctx := genesis.WithGenesisContext(context.Background(), config.Default.Genesis)
   658  			ctx = protocol.WithBlockCtx(ctx, protocol.BlockCtx{
   659  				BlockHeight: cases[i].height,
   660  			})
   661  			ctx = protocol.WithFeatureCtx(ctx)
   662  			require.Equal(cases[i].expectErr, errors.Cause(p.Validate(ctx, ex, nil)))
   663  		})
   664  	}
   665  }
   666  
   667  func TestProtocol_Handle(t *testing.T) {
   668  	testEVM := func(t *testing.T) {
   669  		log.S().Info("Test EVM")
   670  		require := require.New(t)
   671  
   672  		cfg := config.Default
   673  		defer func() {
   674  			delete(cfg.Plugins, config.GatewayPlugin)
   675  		}()
   676  
   677  		testTriePath, err := testutil.PathOfTempFile("trie")
   678  		require.NoError(err)
   679  		testDBPath, err := testutil.PathOfTempFile("db")
   680  		require.NoError(err)
   681  		testIndexPath, err := testutil.PathOfTempFile("index")
   682  		require.NoError(err)
   683  		defer func() {
   684  			testutil.CleanupPath(testTriePath)
   685  			testutil.CleanupPath(testDBPath)
   686  			testutil.CleanupPath(testIndexPath)
   687  		}()
   688  
   689  		cfg.Plugins[config.GatewayPlugin] = true
   690  		cfg.Chain.TrieDBPath = testTriePath
   691  		cfg.Chain.ChainDBPath = testDBPath
   692  		cfg.Chain.IndexDBPath = testIndexPath
   693  		cfg.Chain.EnableAsyncIndexWrite = false
   694  		cfg.Genesis.EnableGravityChainVoting = false
   695  		cfg.ActPool.MinGasPriceStr = "0"
   696  		cfg.Genesis.InitBalanceMap[identityset.Address(27).String()] = unit.ConvertIotxToRau(1000000000).String()
   697  		ctx := genesis.WithGenesisContext(context.Background(), cfg.Genesis)
   698  
   699  		registry := protocol.NewRegistry()
   700  		acc := account.NewProtocol(rewarding.DepositGas)
   701  		require.NoError(acc.Register(registry))
   702  		rp := rolldpos.NewProtocol(cfg.Genesis.NumCandidateDelegates, cfg.Genesis.NumDelegates, cfg.Genesis.NumSubEpochs)
   703  		require.NoError(rp.Register(registry))
   704  		factoryCfg := factory.GenerateConfig(cfg.Chain, cfg.Genesis)
   705  		db2, err := db.CreateKVStoreWithCache(cfg.DB, cfg.Chain.TrieDBPath, cfg.Chain.StateDBCacheSize)
   706  		require.NoError(err)
   707  		// create state factory
   708  		sf, err := factory.NewStateDB(factoryCfg, db2, factory.RegistryStateDBOption(registry))
   709  		require.NoError(err)
   710  		ap, err := actpool.NewActPool(cfg.Genesis, sf, cfg.ActPool)
   711  		require.NoError(err)
   712  		// create indexer
   713  		cfg.DB.DbPath = cfg.Chain.IndexDBPath
   714  		indexer, err := blockindex.NewIndexer(db.NewBoltDB(cfg.DB), hash.ZeroHash256)
   715  		require.NoError(err)
   716  		// create BlockDAO
   717  		cfg.DB.DbPath = cfg.Chain.ChainDBPath
   718  		store, err := filedao.NewFileDAOInMemForTest()
   719  		require.NoError(err)
   720  		dao := blockdao.NewBlockDAOWithIndexersAndCache(store, []blockdao.BlockIndexer{sf, indexer}, cfg.DB.MaxCacheSize)
   721  		require.NotNil(dao)
   722  		bc := blockchain.NewBlockchain(
   723  			cfg.Chain,
   724  			cfg.Genesis,
   725  			dao,
   726  			factory.NewMinter(sf, ap),
   727  			blockchain.BlockValidatorOption(block.NewValidator(
   728  				sf,
   729  				protocol.NewGenericValidator(sf, accountutil.AccountState),
   730  			)),
   731  		)
   732  		exeProtocol := NewProtocol(dao.GetBlockHash, rewarding.DepositGasWithSGD, nil, getBlockTimeForTest)
   733  		require.NoError(exeProtocol.Register(registry))
   734  		require.NoError(bc.Start(ctx))
   735  		require.NotNil(bc)
   736  		defer func() {
   737  			require.NoError(bc.Stop(ctx))
   738  		}()
   739  
   740  		data, _ := hex.DecodeString("608060405234801561001057600080fd5b5060df8061001f6000396000f3006080604052600436106049576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806360fe47b114604e5780636d4ce63c146078575b600080fd5b348015605957600080fd5b5060766004803603810190808035906020019092919050505060a0565b005b348015608357600080fd5b50608a60aa565b6040518082815260200191505060405180910390f35b8060008190555050565b600080549050905600a165627a7a7230582002faabbefbbda99b20217cf33cb8ab8100caf1542bf1f48117d72e2c59139aea0029")
   741  		execution, err := action.NewExecution(action.EmptyAddress, 1, big.NewInt(0), uint64(100000), big.NewInt(0), data)
   742  		require.NoError(err)
   743  
   744  		bd := &action.EnvelopeBuilder{}
   745  		elp := bd.SetAction(execution).
   746  			SetNonce(1).
   747  			SetGasLimit(100000).Build()
   748  		selp, err := action.Sign(elp, identityset.PrivateKey(27))
   749  		require.NoError(err)
   750  
   751  		require.NoError(ap.Add(context.Background(), selp))
   752  		blk, err := bc.MintNewBlock(fixedTime)
   753  		require.NoError(err)
   754  		require.NoError(bc.CommitBlock(blk))
   755  		require.Equal(1, len(blk.Receipts))
   756  
   757  		eHash, err := selp.Hash()
   758  		require.NoError(err)
   759  		r := blk.Receipts[0]
   760  		require.Equal(eHash, r.ActionHash)
   761  		contract, err := address.FromString(r.ContractAddress)
   762  		require.NoError(err)
   763  
   764  		// test IsContract
   765  		state, err := accountutil.AccountState(ctx, sf, contract)
   766  		require.NoError(err)
   767  		require.True(state.IsContract())
   768  
   769  		c, err := readCode(sf, contract.Bytes())
   770  		require.NoError(err)
   771  		require.Equal(data[31:], c)
   772  
   773  		exe, _, err := blk.ActionByHash(eHash)
   774  		require.NoError(err)
   775  		exeHash, err := exe.Hash()
   776  		require.NoError(err)
   777  		require.Equal(eHash, exeHash)
   778  
   779  		addr27 := hash.BytesToHash160(identityset.Address(27).Bytes())
   780  		total, err := indexer.GetActionCountByAddress(addr27)
   781  		require.NoError(err)
   782  		exes, err := indexer.GetActionsByAddress(addr27, 0, total)
   783  		require.NoError(err)
   784  		require.Equal(1, len(exes))
   785  		require.Equal(eHash[:], exes[0])
   786  
   787  		actIndex, err := indexer.GetActionIndex(eHash[:])
   788  		require.NoError(err)
   789  		blkHash, err := dao.GetBlockHash(actIndex.BlockHeight())
   790  		require.NoError(err)
   791  		require.Equal(blk.HashBlock(), blkHash)
   792  
   793  		// store to key 0
   794  		data, _ = hex.DecodeString("60fe47b1000000000000000000000000000000000000000000000000000000000000000f")
   795  		execution, err = action.NewExecution(r.ContractAddress, 2, big.NewInt(0), uint64(120000), big.NewInt(0), data)
   796  		require.NoError(err)
   797  
   798  		bd = &action.EnvelopeBuilder{}
   799  		elp = bd.SetAction(execution).
   800  			SetNonce(2).
   801  			SetGasLimit(120000).Build()
   802  		selp, err = action.Sign(elp, identityset.PrivateKey(27))
   803  		require.NoError(err)
   804  
   805  		log.S().Infof("execution %+v", execution)
   806  
   807  		require.NoError(ap.Add(context.Background(), selp))
   808  		blk, err = bc.MintNewBlock(fixedTime)
   809  		require.NoError(err)
   810  		require.NoError(bc.CommitBlock(blk))
   811  		require.Equal(1, len(blk.Receipts))
   812  
   813  		// TODO (zhi): reenable the unit test
   814  		/*
   815  			ws, err = sf.NewWorkingSet()
   816  			require.NoError(err)
   817  			stateDB = evm.NewStateDBAdapter(ws, uint64(0), true, hash.ZeroHash256)
   818  			var emptyEVMHash common.Hash
   819  			v := stateDB.GetState(evmContractAddrHash, emptyEVMHash)
   820  			require.Equal(byte(15), v[31])
   821  		*/
   822  		eHash, err = selp.Hash()
   823  		require.NoError(err)
   824  		require.Equal(eHash, blk.Receipts[0].ActionHash)
   825  
   826  		// read from key 0
   827  		data, err = hex.DecodeString("6d4ce63c")
   828  		require.NoError(err)
   829  		execution, err = action.NewExecution(r.ContractAddress, 3, big.NewInt(0), uint64(120000), big.NewInt(0), data)
   830  		require.NoError(err)
   831  
   832  		bd = &action.EnvelopeBuilder{}
   833  		elp = bd.SetAction(execution).
   834  			SetNonce(3).
   835  			SetGasLimit(120000).Build()
   836  		selp, err = action.Sign(elp, identityset.PrivateKey(27))
   837  		require.NoError(err)
   838  
   839  		log.S().Infof("execution %+v", execution)
   840  		require.NoError(ap.Add(context.Background(), selp))
   841  		blk, err = bc.MintNewBlock(fixedTime)
   842  		require.NoError(err)
   843  		require.NoError(bc.CommitBlock(blk))
   844  		require.Equal(1, len(blk.Receipts))
   845  
   846  		eHash, err = selp.Hash()
   847  		require.NoError(err)
   848  		require.Equal(eHash, blk.Receipts[0].ActionHash)
   849  
   850  		data, _ = hex.DecodeString("608060405234801561001057600080fd5b5060df8061001f6000396000f3006080604052600436106049576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806360fe47b114604e5780636d4ce63c146078575b600080fd5b348015605957600080fd5b5060766004803603810190808035906020019092919050505060a0565b005b348015608357600080fd5b50608a60aa565b6040518082815260200191505060405180910390f35b8060008190555050565b600080549050905600a165627a7a7230582002faabbefbbda99b20217cf33cb8ab8100caf1542bf1f48117d72e2c59139aea0029")
   851  		execution1, err := action.NewExecution(action.EmptyAddress, 4, big.NewInt(0), uint64(100000), big.NewInt(10), data)
   852  		require.NoError(err)
   853  		bd = &action.EnvelopeBuilder{}
   854  
   855  		elp = bd.SetAction(execution1).
   856  			SetNonce(4).
   857  			SetGasLimit(100000).SetGasPrice(big.NewInt(10)).Build()
   858  		selp, err = action.Sign(elp, identityset.PrivateKey(27))
   859  		require.NoError(err)
   860  
   861  		require.NoError(ap.Add(context.Background(), selp))
   862  		blk, err = bc.MintNewBlock(fixedTime)
   863  		require.NoError(err)
   864  		require.NoError(bc.CommitBlock(blk))
   865  		require.Equal(1, len(blk.Receipts))
   866  	}
   867  
   868  	t.Run("EVM", func(t *testing.T) {
   869  		testEVM(t)
   870  	})
   871  	/**
   872  	 * source of smart contract: https://etherscan.io/address/0x6fb3e0a217407efff7ca062d46c26e5d60a14d69#code
   873  	 */
   874  	t.Run("ERC20", func(t *testing.T) {
   875  		NewSmartContractTest(t, "testdata/erc20.json")
   876  	})
   877  	/**
   878  	 * Source of smart contract: https://etherscan.io/address/0x8dd5fbce2f6a956c3022ba3663759011dd51e73e#code
   879  	 */
   880  	t.Run("DelegateERC20", func(t *testing.T) {
   881  		NewSmartContractTest(t, "testdata/delegate_erc20.json")
   882  	})
   883  	/*
   884  	 * Source code: https://kovan.etherscan.io/address/0x81f85886749cbbf3c2ec742db7255c6b07c63c69
   885  	 */
   886  	t.Run("InfiniteLoop", func(t *testing.T) {
   887  		NewSmartContractTest(t, "testdata/infiniteloop.json")
   888  	})
   889  	// RollDice
   890  	t.Run("RollDice", func(t *testing.T) {
   891  		NewSmartContractTest(t, "testdata/rolldice.json")
   892  	})
   893  	// ChangeState
   894  	t.Run("ChangeState", func(t *testing.T) {
   895  		NewSmartContractTest(t, "testdata/changestate.json")
   896  	})
   897  	// array-return
   898  	t.Run("ArrayReturn", func(t *testing.T) {
   899  		NewSmartContractTest(t, "testdata/array-return.json")
   900  	})
   901  	// basic-token
   902  	t.Run("BasicToken", func(t *testing.T) {
   903  		NewSmartContractTest(t, "testdata/basic-token.json")
   904  	})
   905  	// call-dynamic
   906  	t.Run("CallDynamic", func(t *testing.T) {
   907  		NewSmartContractTest(t, "testdata/call-dynamic.json")
   908  	})
   909  	// factory
   910  	t.Run("Factory", func(t *testing.T) {
   911  		NewSmartContractTest(t, "testdata/factory.json")
   912  	})
   913  	// mapping-delete
   914  	t.Run("MappingDelete", func(t *testing.T) {
   915  		NewSmartContractTest(t, "testdata/mapping-delete.json")
   916  	})
   917  	// f.value
   918  	t.Run("F.value", func(t *testing.T) {
   919  		NewSmartContractTest(t, "testdata/f.value.json")
   920  	})
   921  	// proposal
   922  	t.Run("Proposal", func(t *testing.T) {
   923  		NewSmartContractTest(t, "testdata/proposal.json")
   924  	})
   925  	// public-length
   926  	t.Run("PublicLength", func(t *testing.T) {
   927  		NewSmartContractTest(t, "testdata/public-length.json")
   928  	})
   929  	// public-mapping
   930  	t.Run("PublicMapping", func(t *testing.T) {
   931  		NewSmartContractTest(t, "testdata/public-mapping.json")
   932  	})
   933  	// no-variable-length-returns
   934  	t.Run("NoVariableLengthReturns", func(t *testing.T) {
   935  		NewSmartContractTest(t, "testdata/no-variable-length-returns.json")
   936  	})
   937  	// tuple
   938  	t.Run("Tuple", func(t *testing.T) {
   939  		NewSmartContractTest(t, "testdata/tuple.json")
   940  	})
   941  	// tail-recursion
   942  	t.Run("TailRecursion", func(t *testing.T) {
   943  		NewSmartContractTest(t, "testdata/tail-recursion.json")
   944  	})
   945  	// sha3
   946  	t.Run("Sha3", func(t *testing.T) {
   947  		NewSmartContractTest(t, "testdata/sha3.json")
   948  	})
   949  	// remove-from-array
   950  	t.Run("RemoveFromArray", func(t *testing.T) {
   951  		NewSmartContractTest(t, "testdata/remove-from-array.json")
   952  	})
   953  	// send-eth
   954  	t.Run("SendEth", func(t *testing.T) {
   955  		NewSmartContractTest(t, "testdata/send-eth.json")
   956  	})
   957  	// modifier
   958  	t.Run("Modifier", func(t *testing.T) {
   959  		NewSmartContractTest(t, "testdata/modifiers.json")
   960  	})
   961  	// multisend
   962  	t.Run("Multisend", func(t *testing.T) {
   963  		NewSmartContractTest(t, "testdata/multisend.json")
   964  	})
   965  	t.Run("Multisend2", func(t *testing.T) {
   966  		NewSmartContractTest(t, "testdata/multisend2.json")
   967  	})
   968  	// reentry
   969  	t.Run("reentry-attack", func(t *testing.T) {
   970  		NewSmartContractTest(t, "testdata/reentry-attack.json")
   971  	})
   972  	// cashier
   973  	t.Run("cashier", func(t *testing.T) {
   974  		NewSmartContractTest(t, "testdata/cashier.json")
   975  	})
   976  	// wireconnection
   977  	// [Issue #1422] This unit test proves that there is no problem when we want to deploy and execute the contract
   978  	// which inherits abstract contract and implements abstract functions and call each other (Utterance() calls utterance())
   979  	t.Run("wireconnection", func(t *testing.T) {
   980  		NewSmartContractTest(t, "testdata/wireconnection.json")
   981  	})
   982  	// gas-test
   983  	t.Run("gas-test", func(t *testing.T) {
   984  		NewSmartContractTest(t, "testdata/gas-test.json")
   985  	})
   986  	// storage-test
   987  	t.Run("storage-test", func(t *testing.T) {
   988  		NewSmartContractTest(t, "testdata/storage-test.json")
   989  	})
   990  	// cashier-bering
   991  	t.Run("cashier-bering", func(t *testing.T) {
   992  		NewSmartContractTest(t, "testdata/cashier-bering.json")
   993  	})
   994  	// infiniteloop-bering
   995  	t.Run("infiniteloop-bering", func(t *testing.T) {
   996  		NewSmartContractTest(t, "testdata/infiniteloop-bering.json")
   997  	})
   998  	// self-destruct
   999  	t.Run("self-destruct", func(t *testing.T) {
  1000  		NewSmartContractTest(t, "testdata/self-destruct.json")
  1001  	})
  1002  	// datacopy
  1003  	t.Run("datacopy", func(t *testing.T) {
  1004  		NewSmartContractTest(t, "testdata/datacopy.json")
  1005  	})
  1006  	// this test replay CVE-2021-39137 attack, see attack details
  1007  	// at https://github.com/ethereum/go-ethereum/blob/master/docs/postmortems/2021-08-22-split-postmortem.md
  1008  	t.Run("CVE-2021-39137-attack-replay", func(t *testing.T) {
  1009  		NewSmartContractTest(t, "testdata/CVE-2021-39137-attack-replay.json")
  1010  	})
  1011  }
  1012  
  1013  func TestMaxTime(t *testing.T) {
  1014  	t.Run("max-time", func(t *testing.T) {
  1015  		NewSmartContractTest(t, "testdata/maxtime.json")
  1016  	})
  1017  
  1018  	t.Run("max-time-2", func(t *testing.T) {
  1019  		NewSmartContractTest(t, "testdata/maxtime2.json")
  1020  	})
  1021  }
  1022  
  1023  func TestIstanbulEVM(t *testing.T) {
  1024  	t.Run("ArrayReturn", func(t *testing.T) {
  1025  		NewSmartContractTest(t, "testdata-istanbul/array-return.json")
  1026  	})
  1027  	t.Run("BasicToken", func(t *testing.T) {
  1028  		NewSmartContractTest(t, "testdata-istanbul/basic-token.json")
  1029  	})
  1030  	t.Run("CallDynamic", func(t *testing.T) {
  1031  		NewSmartContractTest(t, "testdata-istanbul/call-dynamic.json")
  1032  	})
  1033  	t.Run("chainid-selfbalance", func(t *testing.T) {
  1034  		NewSmartContractTest(t, "testdata-istanbul/chainid-selfbalance.json")
  1035  	})
  1036  	t.Run("ChangeState", func(t *testing.T) {
  1037  		NewSmartContractTest(t, "testdata-istanbul/changestate.json")
  1038  	})
  1039  	t.Run("F.value", func(t *testing.T) {
  1040  		NewSmartContractTest(t, "testdata-istanbul/f.value.json")
  1041  	})
  1042  	t.Run("Gas-test", func(t *testing.T) {
  1043  		NewSmartContractTest(t, "testdata-istanbul/gas-test.json")
  1044  	})
  1045  	t.Run("InfiniteLoop", func(t *testing.T) {
  1046  		NewSmartContractTest(t, "testdata-istanbul/infiniteloop.json")
  1047  	})
  1048  	t.Run("MappingDelete", func(t *testing.T) {
  1049  		NewSmartContractTest(t, "testdata-istanbul/mapping-delete.json")
  1050  	})
  1051  	t.Run("max-time", func(t *testing.T) {
  1052  		NewSmartContractTest(t, "testdata-istanbul/maxtime.json")
  1053  	})
  1054  	t.Run("Modifier", func(t *testing.T) {
  1055  		NewSmartContractTest(t, "testdata-istanbul/modifiers.json")
  1056  	})
  1057  	t.Run("Multisend", func(t *testing.T) {
  1058  		NewSmartContractTest(t, "testdata-istanbul/multisend.json")
  1059  	})
  1060  	t.Run("NoVariableLengthReturns", func(t *testing.T) {
  1061  		NewSmartContractTest(t, "testdata-istanbul/no-variable-length-returns.json")
  1062  	})
  1063  	t.Run("PublicMapping", func(t *testing.T) {
  1064  		NewSmartContractTest(t, "testdata-istanbul/public-mapping.json")
  1065  	})
  1066  	t.Run("reentry-attack", func(t *testing.T) {
  1067  		NewSmartContractTest(t, "testdata-istanbul/reentry-attack.json")
  1068  	})
  1069  	t.Run("RemoveFromArray", func(t *testing.T) {
  1070  		NewSmartContractTest(t, "testdata-istanbul/remove-from-array.json")
  1071  	})
  1072  	t.Run("SendEth", func(t *testing.T) {
  1073  		NewSmartContractTest(t, "testdata-istanbul/send-eth.json")
  1074  	})
  1075  	t.Run("Sha3", func(t *testing.T) {
  1076  		NewSmartContractTest(t, "testdata-istanbul/sha3.json")
  1077  	})
  1078  	t.Run("storage-test", func(t *testing.T) {
  1079  		NewSmartContractTest(t, "testdata-istanbul/storage-test.json")
  1080  	})
  1081  	t.Run("TailRecursion", func(t *testing.T) {
  1082  		NewSmartContractTest(t, "testdata-istanbul/tail-recursion.json")
  1083  	})
  1084  	t.Run("Tuple", func(t *testing.T) {
  1085  		NewSmartContractTest(t, "testdata-istanbul/tuple.json")
  1086  	})
  1087  	t.Run("wireconnection", func(t *testing.T) {
  1088  		NewSmartContractTest(t, "testdata-istanbul/wireconnection.json")
  1089  	})
  1090  	t.Run("self-destruct", func(t *testing.T) {
  1091  		NewSmartContractTest(t, "testdata-istanbul/self-destruct.json")
  1092  	})
  1093  	t.Run("datacopy", func(t *testing.T) {
  1094  		NewSmartContractTest(t, "testdata-istanbul/datacopy.json")
  1095  	})
  1096  	t.Run("CVE-2021-39137-attack-replay", func(t *testing.T) {
  1097  		NewSmartContractTest(t, "testdata-istanbul/CVE-2021-39137-attack-replay.json")
  1098  	})
  1099  	t.Run("err-write-protection", func(t *testing.T) {
  1100  		NewSmartContractTest(t, "testdata-istanbul/write-protection.json")
  1101  	})
  1102  	t.Run("err-write-protection-twice-delta-0", func(t *testing.T) {
  1103  		// hit errWriteProtection 2 times, delta is 0
  1104  		NewSmartContractTest(t, "testdata-istanbul/write-protection-001.json")
  1105  	})
  1106  	t.Run("err-write-protection-once-delta-0", func(t *testing.T) {
  1107  		// hit errWriteProtection 1 times, delta is 0
  1108  		NewSmartContractTest(t, "testdata-istanbul/write-protection-002.json")
  1109  	})
  1110  	t.Run("err-write-protection-twice-delta-0-0", func(t *testing.T) {
  1111  		// hit errWriteProtection twice, delta is not 0
  1112  		NewSmartContractTest(t, "testdata-istanbul/write-protection-003.json")
  1113  	})
  1114  	t.Run("err-write-protection-twice-delta-0-1", func(t *testing.T) {
  1115  		// hit errWriteProtection twice, first delta is not 0, second delta is 0
  1116  		NewSmartContractTest(t, "testdata-istanbul/write-protection-004.json")
  1117  	})
  1118  	t.Run("err-write-protection-once-delta-1", func(t *testing.T) {
  1119  		// hit errWriteProtection once, delta is not 0,but no revert
  1120  		NewSmartContractTest(t, "testdata-istanbul/write-protection-005.json")
  1121  	})
  1122  	t.Run("err-write-protection-twice-delta-1-1", func(t *testing.T) {
  1123  		// hit errWriteProtection twice,, first delta is not 0, second delta is not 0, no revert
  1124  		NewSmartContractTest(t, "testdata-istanbul/write-protection-006.json")
  1125  	})
  1126  	t.Run("err-write-protection-twice-delta-0-1", func(t *testing.T) {
  1127  		// hit errWriteProtection twice,, first delta is 0, second delta is not 0, no revert
  1128  		NewSmartContractTest(t, "testdata-istanbul/write-protection-007.json")
  1129  	})
  1130  	t.Run("err-write-protection-call-staticcall-revrt", func(t *testing.T) {
  1131  		// call -> staticcall -> revrt
  1132  		NewSmartContractTest(t, "testdata-istanbul/write-protection-008.json")
  1133  	})
  1134  	t.Run("err-write-protection-staticcall-staticcall-revrt", func(t *testing.T) {
  1135  		// staticcall -> staticcall -> revrt
  1136  		NewSmartContractTest(t, "testdata-istanbul/write-protection-009.json")
  1137  	})
  1138  	t.Run("err-write-protection-staticcall-staticcall-revrt-1", func(t *testing.T) {
  1139  		// staticcall -> staticcall -> revrt twice
  1140  		NewSmartContractTest(t, "testdata-istanbul/write-protection-010.json")
  1141  	})
  1142  	t.Run("iip15-manager test", func(t *testing.T) {
  1143  		NewSmartContractTest(t, "testdata-istanbul/iip15-manager.json")
  1144  	})
  1145  }
  1146  
  1147  func TestLondonEVM(t *testing.T) {
  1148  	t.Run("factory", func(t *testing.T) {
  1149  		NewSmartContractTest(t, "testdata-london/factory.json")
  1150  	})
  1151  	t.Run("ArrayReturn", func(t *testing.T) {
  1152  		NewSmartContractTest(t, "testdata-london/array-return.json")
  1153  	})
  1154  	t.Run("BaseFee", func(t *testing.T) {
  1155  		NewSmartContractTest(t, "testdata-london/basefee.json")
  1156  	})
  1157  	t.Run("BasicToken", func(t *testing.T) {
  1158  		NewSmartContractTest(t, "testdata-london/basic-token.json")
  1159  	})
  1160  	t.Run("CallDynamic", func(t *testing.T) {
  1161  		NewSmartContractTest(t, "testdata-london/call-dynamic.json")
  1162  	})
  1163  	t.Run("chainid-selfbalance", func(t *testing.T) {
  1164  		NewSmartContractTest(t, "testdata-london/chainid-selfbalance.json")
  1165  	})
  1166  	t.Run("ChangeState", func(t *testing.T) {
  1167  		NewSmartContractTest(t, "testdata-london/changestate.json")
  1168  	})
  1169  	t.Run("F.value", func(t *testing.T) {
  1170  		NewSmartContractTest(t, "testdata-london/f.value.json")
  1171  	})
  1172  	t.Run("Gas-test", func(t *testing.T) {
  1173  		NewSmartContractTest(t, "testdata-london/gas-test.json")
  1174  	})
  1175  	t.Run("InfiniteLoop", func(t *testing.T) {
  1176  		NewSmartContractTest(t, "testdata-london/infiniteloop.json")
  1177  	})
  1178  	t.Run("MappingDelete", func(t *testing.T) {
  1179  		NewSmartContractTest(t, "testdata-london/mapping-delete.json")
  1180  	})
  1181  	t.Run("max-time", func(t *testing.T) {
  1182  		NewSmartContractTest(t, "testdata-london/maxtime.json")
  1183  	})
  1184  	t.Run("Modifier", func(t *testing.T) {
  1185  		NewSmartContractTest(t, "testdata-london/modifiers.json")
  1186  	})
  1187  	t.Run("Multisend", func(t *testing.T) {
  1188  		NewSmartContractTest(t, "testdata-london/multisend.json")
  1189  	})
  1190  	t.Run("NoVariableLengthReturns", func(t *testing.T) {
  1191  		NewSmartContractTest(t, "testdata-london/no-variable-length-returns.json")
  1192  	})
  1193  	t.Run("PublicMapping", func(t *testing.T) {
  1194  		NewSmartContractTest(t, "testdata-london/public-mapping.json")
  1195  	})
  1196  	t.Run("reentry-attack", func(t *testing.T) {
  1197  		NewSmartContractTest(t, "testdata-london/reentry-attack.json")
  1198  	})
  1199  	t.Run("RemoveFromArray", func(t *testing.T) {
  1200  		NewSmartContractTest(t, "testdata-london/remove-from-array.json")
  1201  	})
  1202  	t.Run("SendEth", func(t *testing.T) {
  1203  		NewSmartContractTest(t, "testdata-london/send-eth.json")
  1204  	})
  1205  	t.Run("Sha3", func(t *testing.T) {
  1206  		NewSmartContractTest(t, "testdata-london/sha3.json")
  1207  	})
  1208  	t.Run("storage-test", func(t *testing.T) {
  1209  		NewSmartContractTest(t, "testdata-london/storage-test.json")
  1210  	})
  1211  	t.Run("TailRecursion", func(t *testing.T) {
  1212  		NewSmartContractTest(t, "testdata-london/tail-recursion.json")
  1213  	})
  1214  	t.Run("Tuple", func(t *testing.T) {
  1215  		NewSmartContractTest(t, "testdata-london/tuple.json")
  1216  	})
  1217  	t.Run("wireconnection", func(t *testing.T) {
  1218  		NewSmartContractTest(t, "testdata-london/wireconnection.json")
  1219  	})
  1220  	t.Run("self-destruct", func(t *testing.T) {
  1221  		NewSmartContractTest(t, "testdata-london/self-destruct.json")
  1222  	})
  1223  	t.Run("datacopy", func(t *testing.T) {
  1224  		NewSmartContractTest(t, "testdata-london/datacopy.json")
  1225  	})
  1226  	t.Run("CVE-2021-39137-attack-replay", func(t *testing.T) {
  1227  		NewSmartContractTest(t, "testdata-london/CVE-2021-39137-attack-replay.json")
  1228  	})
  1229  	t.Run("difficulty", func(t *testing.T) {
  1230  		NewSmartContractTest(t, "testdata-london/difficulty.json")
  1231  	})
  1232  	t.Run("push0-invalid", func(t *testing.T) {
  1233  		NewSmartContractTest(t, "testdata-london/push0.json")
  1234  	})
  1235  }
  1236  
  1237  func TestShanghaiEVM(t *testing.T) {
  1238  	t.Run("array-return", func(t *testing.T) {
  1239  		NewSmartContractTest(t, "testdata-shanghai/array-return.json")
  1240  	})
  1241  	t.Run("basefee", func(t *testing.T) {
  1242  		NewSmartContractTest(t, "testdata-shanghai/basefee.json")
  1243  	})
  1244  	t.Run("basic-token", func(t *testing.T) {
  1245  		NewSmartContractTest(t, "testdata-shanghai/basic-token.json")
  1246  	})
  1247  	t.Run("call-dynamic", func(t *testing.T) {
  1248  		NewSmartContractTest(t, "testdata-shanghai/call-dynamic.json")
  1249  	})
  1250  	t.Run("chainid-selfbalance", func(t *testing.T) {
  1251  		NewSmartContractTest(t, "testdata-shanghai/chainid-selfbalance.json")
  1252  	})
  1253  	t.Run("CVE-2021-39137-attack-replay", func(t *testing.T) {
  1254  		NewSmartContractTest(t, "testdata-shanghai/CVE-2021-39137-attack-replay.json")
  1255  	})
  1256  	t.Run("datacopy", func(t *testing.T) {
  1257  		NewSmartContractTest(t, "testdata-shanghai/datacopy.json")
  1258  	})
  1259  	t.Run("f.value", func(t *testing.T) {
  1260  		NewSmartContractTest(t, "testdata-shanghai/f.value.json")
  1261  	})
  1262  	t.Run("factory", func(t *testing.T) {
  1263  		NewSmartContractTest(t, "testdata-shanghai/factory.json")
  1264  	})
  1265  	t.Run("gas-test", func(t *testing.T) {
  1266  		NewSmartContractTest(t, "testdata-shanghai/gas-test.json")
  1267  	})
  1268  	t.Run("infiniteloop", func(t *testing.T) {
  1269  		NewSmartContractTest(t, "testdata-shanghai/infiniteloop.json")
  1270  	})
  1271  	t.Run("mapping-delete", func(t *testing.T) {
  1272  		NewSmartContractTest(t, "testdata-shanghai/mapping-delete.json")
  1273  	})
  1274  	t.Run("maxtime", func(t *testing.T) {
  1275  		NewSmartContractTest(t, "testdata-shanghai/maxtime.json")
  1276  	})
  1277  	t.Run("modifiers", func(t *testing.T) {
  1278  		NewSmartContractTest(t, "testdata-shanghai/modifiers.json")
  1279  	})
  1280  	t.Run("multisend", func(t *testing.T) {
  1281  		NewSmartContractTest(t, "testdata-shanghai/multisend.json")
  1282  	})
  1283  	t.Run("no-variable-length-returns", func(t *testing.T) {
  1284  		NewSmartContractTest(t, "testdata-shanghai/no-variable-length-returns.json")
  1285  	})
  1286  	t.Run("public-mapping", func(t *testing.T) {
  1287  		NewSmartContractTest(t, "testdata-shanghai/public-mapping.json")
  1288  	})
  1289  	t.Run("reentry-attack", func(t *testing.T) {
  1290  		NewSmartContractTest(t, "testdata-shanghai/reentry-attack.json")
  1291  	})
  1292  	t.Run("remove-from-array", func(t *testing.T) {
  1293  		NewSmartContractTest(t, "testdata-shanghai/remove-from-array.json")
  1294  	})
  1295  	t.Run("self-destruct", func(t *testing.T) {
  1296  		NewSmartContractTest(t, "testdata-shanghai/self-destruct.json")
  1297  	})
  1298  	t.Run("send-eth", func(t *testing.T) {
  1299  		NewSmartContractTest(t, "testdata-shanghai/send-eth.json")
  1300  	})
  1301  	t.Run("sha3", func(t *testing.T) {
  1302  		NewSmartContractTest(t, "testdata-shanghai/sha3.json")
  1303  	})
  1304  	t.Run("storage-test", func(t *testing.T) {
  1305  		NewSmartContractTest(t, "testdata-shanghai/storage-test.json")
  1306  	})
  1307  	t.Run("tail-recursion", func(t *testing.T) {
  1308  		NewSmartContractTest(t, "testdata-shanghai/tail-recursion.json")
  1309  	})
  1310  	t.Run("tuple", func(t *testing.T) {
  1311  		NewSmartContractTest(t, "testdata-shanghai/tuple.json")
  1312  	})
  1313  	t.Run("wireconnection", func(t *testing.T) {
  1314  		NewSmartContractTest(t, "testdata-shanghai/wireconnection.json")
  1315  	})
  1316  	t.Run("prevrandao", func(t *testing.T) {
  1317  		NewSmartContractTest(t, "testdata-shanghai/prevrandao.json")
  1318  	})
  1319  	t.Run("push0-valid", func(t *testing.T) {
  1320  		NewSmartContractTest(t, "testdata-shanghai/push0.json")
  1321  	})
  1322  }
  1323  
  1324  func benchmarkHotContractWithFactory(b *testing.B, async bool) {
  1325  	sct := SmartContractTest{
  1326  		InitBalances: []ExpectedBalance{
  1327  			{
  1328  				Account:    "io1mflp9m6hcgm2qcghchsdqj3z3eccrnekx9p0ms",
  1329  				RawBalance: "1000000000000000000000000000",
  1330  			},
  1331  		},
  1332  		Deployments: []ExecutionConfig{
  1333  			{
  1334  				ContractIndex: 0,
  1335  				RawPrivateKey: "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1",
  1336  				RawByteCode:   "608060405234801561001057600080fd5b506040516040806108018339810180604052810190808051906020019092919080519060200190929190505050816004819055508060058190555050506107a58061005c6000396000f300608060405260043610610078576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680631249c58b1461007d57806327e235e31461009457806353277879146100eb5780636941b84414610142578063810ad50514610199578063a9059cbb14610223575b600080fd5b34801561008957600080fd5b50610092610270565b005b3480156100a057600080fd5b506100d5600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610475565b6040518082815260200191505060405180910390f35b3480156100f757600080fd5b5061012c600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061048d565b6040518082815260200191505060405180910390f35b34801561014e57600080fd5b50610183600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506104a5565b6040518082815260200191505060405180910390f35b3480156101a557600080fd5b506101da600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506104bd565b604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390f35b34801561022f57600080fd5b5061026e600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610501565b005b436004546000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054011115151561032a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f746f6f20736f6f6e20746f206d696e740000000000000000000000000000000081525060200191505060405180910390fd5b436000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550600554600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600081548092919060010191905055503373ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fec61728879a33aa50b55e1f4789dcfc1c680f30a24d7b8694a9f874e242a97b46005546040518082815260200191505060405180910390a3565b60016020528060005260406000206000915090505481565b60026020528060005260406000206000915090505481565b60006020528060005260406000206000915090505481565b60036020528060005260406000206000915090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060010154905082565b80600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054101515156105b8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f696e73756666696369656e742062616c616e636500000000000000000000000081525060200191505060405180910390fd5b80600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555080600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555060408051908101604052803373ffffffffffffffffffffffffffffffffffffffff16815260200182815250600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550602082015181600101559050508173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fec61728879a33aa50b55e1f4789dcfc1c680f30a24d7b8694a9f874e242a97b4836040518082815260200191505060405180910390a350505600a165627a7a7230582047e5e1380e66d6b109548617ae59ff7baf70ee2d4a6734559b8fc5cabca0870b0029000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000186a0",
  1337  				RawAmount:     "0",
  1338  				RawGasLimit:   5000000,
  1339  				RawGasPrice:   "0",
  1340  			},
  1341  		},
  1342  	}
  1343  	r := require.New(b)
  1344  	ctx := context.Background()
  1345  	cfg := config.Default
  1346  	cfg.Genesis.NumSubEpochs = uint64(b.N)
  1347  	cfg.Chain.EnableTrielessStateDB = false
  1348  	if async {
  1349  		cfg.Genesis.GreenlandBlockHeight = 0
  1350  	} else {
  1351  		cfg.Genesis.GreenlandBlockHeight = 10000000000
  1352  	}
  1353  	bc, sf, dao, ap := sct.prepareBlockchain(ctx, cfg, r)
  1354  	defer func() {
  1355  		r.NoError(bc.Stop(ctx))
  1356  	}()
  1357  	contractAddresses := sct.deployContracts(bc, sf, dao, ap, r)
  1358  	r.Equal(1, len(contractAddresses))
  1359  	contractAddr := contractAddresses[0]
  1360  	b.ResetTimer()
  1361  	for i := 0; i < b.N; i++ {
  1362  		receipts, _, err := sct.runExecutions(
  1363  			bc, sf, dao, ap, []*ExecutionConfig{
  1364  				{
  1365  					RawPrivateKey: "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1",
  1366  					RawByteCode:   "1249c58b",
  1367  					RawAmount:     "0",
  1368  					RawGasLimit:   5000000,
  1369  					RawGasPrice:   "0",
  1370  					Failed:        false,
  1371  					Comment:       "mint token",
  1372  				},
  1373  			},
  1374  			[]string{contractAddr},
  1375  		)
  1376  		r.NoError(err)
  1377  		r.Equal(1, len(receipts))
  1378  		r.Equal(uint64(1), receipts[0].Status)
  1379  		ecfgs := []*ExecutionConfig{}
  1380  		contractAddrs := []string{}
  1381  		for j := 0; j < 100; j++ {
  1382  			ecfgs = append(ecfgs, &ExecutionConfig{
  1383  				RawPrivateKey: "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1",
  1384  				RawByteCode:   fmt.Sprintf("a9059cbb000000000000000000000000123456789012345678900987%016x0000000000000000000000000000000000000000000000000000000000000039", 100*i+j),
  1385  				RawAmount:     "0",
  1386  				RawGasLimit:   5000000,
  1387  				RawGasPrice:   "0",
  1388  				Failed:        false,
  1389  				Comment:       "send token",
  1390  			})
  1391  			contractAddrs = append(contractAddrs, contractAddr)
  1392  		}
  1393  		receipts, _, err = sct.runExecutions(bc, sf, dao, ap, ecfgs, contractAddrs)
  1394  		r.NoError(err)
  1395  		for _, receipt := range receipts {
  1396  			r.Equal(uint64(1), receipt.Status)
  1397  		}
  1398  	}
  1399  	b.StopTimer()
  1400  }
  1401  
  1402  func benchmarkHotContractWithStateDB(b *testing.B, cachedStateDBOption bool) {
  1403  	sct := SmartContractTest{
  1404  		InitBalances: []ExpectedBalance{
  1405  			{
  1406  				Account:    "io1mflp9m6hcgm2qcghchsdqj3z3eccrnekx9p0ms",
  1407  				RawBalance: "1000000000000000000000000000",
  1408  			},
  1409  		},
  1410  		Deployments: []ExecutionConfig{
  1411  			{
  1412  				ContractIndex: 0,
  1413  				RawPrivateKey: "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1",
  1414  				RawByteCode:   "608060405234801561001057600080fd5b506040516040806108018339810180604052810190808051906020019092919080519060200190929190505050816004819055508060058190555050506107a58061005c6000396000f300608060405260043610610078576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680631249c58b1461007d57806327e235e31461009457806353277879146100eb5780636941b84414610142578063810ad50514610199578063a9059cbb14610223575b600080fd5b34801561008957600080fd5b50610092610270565b005b3480156100a057600080fd5b506100d5600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610475565b6040518082815260200191505060405180910390f35b3480156100f757600080fd5b5061012c600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061048d565b6040518082815260200191505060405180910390f35b34801561014e57600080fd5b50610183600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506104a5565b6040518082815260200191505060405180910390f35b3480156101a557600080fd5b506101da600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506104bd565b604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390f35b34801561022f57600080fd5b5061026e600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610501565b005b436004546000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054011115151561032a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f746f6f20736f6f6e20746f206d696e740000000000000000000000000000000081525060200191505060405180910390fd5b436000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550600554600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600081548092919060010191905055503373ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fec61728879a33aa50b55e1f4789dcfc1c680f30a24d7b8694a9f874e242a97b46005546040518082815260200191505060405180910390a3565b60016020528060005260406000206000915090505481565b60026020528060005260406000206000915090505481565b60006020528060005260406000206000915090505481565b60036020528060005260406000206000915090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060010154905082565b80600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054101515156105b8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f696e73756666696369656e742062616c616e636500000000000000000000000081525060200191505060405180910390fd5b80600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555080600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555060408051908101604052803373ffffffffffffffffffffffffffffffffffffffff16815260200182815250600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550602082015181600101559050508173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fec61728879a33aa50b55e1f4789dcfc1c680f30a24d7b8694a9f874e242a97b4836040518082815260200191505060405180910390a350505600a165627a7a7230582047e5e1380e66d6b109548617ae59ff7baf70ee2d4a6734559b8fc5cabca0870b0029000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000186a0",
  1415  				RawAmount:     "0",
  1416  				RawGasLimit:   5000000,
  1417  				RawGasPrice:   "0",
  1418  			},
  1419  		},
  1420  	}
  1421  	r := require.New(b)
  1422  	ctx := context.Background()
  1423  	cfg := config.Default
  1424  	cfg.Genesis.NumSubEpochs = uint64(b.N)
  1425  	if cachedStateDBOption {
  1426  		cfg.Chain.EnableStateDBCaching = true
  1427  	} else {
  1428  		cfg.Chain.EnableStateDBCaching = false
  1429  	}
  1430  	bc, sf, dao, ap := sct.prepareBlockchain(ctx, cfg, r)
  1431  	defer func() {
  1432  		r.NoError(bc.Stop(ctx))
  1433  	}()
  1434  	contractAddresses := sct.deployContracts(bc, sf, dao, ap, r)
  1435  	r.Equal(1, len(contractAddresses))
  1436  	contractAddr := contractAddresses[0]
  1437  	b.ResetTimer()
  1438  	for i := 0; i < b.N; i++ {
  1439  		receipts, _, err := sct.runExecutions(
  1440  			bc, sf, dao, ap, []*ExecutionConfig{
  1441  				{
  1442  					RawPrivateKey: "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1",
  1443  					RawByteCode:   "1249c58b",
  1444  					RawAmount:     "0",
  1445  					RawGasLimit:   5000000,
  1446  					RawGasPrice:   "0",
  1447  					Failed:        false,
  1448  					Comment:       "mint token",
  1449  				},
  1450  			},
  1451  			[]string{contractAddr},
  1452  		)
  1453  		r.NoError(err)
  1454  		r.Equal(1, len(receipts))
  1455  		r.Equal(uint64(1), receipts[0].Status)
  1456  		ecfgs := []*ExecutionConfig{}
  1457  		contractAddrs := []string{}
  1458  		for j := 0; j < 100; j++ {
  1459  			ecfgs = append(ecfgs, &ExecutionConfig{
  1460  				RawPrivateKey: "cfa6ef757dee2e50351620dca002d32b9c090cfda55fb81f37f1d26b273743f1",
  1461  				RawByteCode:   fmt.Sprintf("a9059cbb000000000000000000000000123456789012345678900987%016x0000000000000000000000000000000000000000000000000000000000000039", 100*i+j),
  1462  				RawAmount:     "0",
  1463  				RawGasLimit:   5000000,
  1464  				RawGasPrice:   "0",
  1465  				Failed:        false,
  1466  				Comment:       "send token",
  1467  			})
  1468  			contractAddrs = append(contractAddrs, contractAddr)
  1469  		}
  1470  		receipts, _, err = sct.runExecutions(bc, sf, dao, ap, ecfgs, contractAddrs)
  1471  		r.NoError(err)
  1472  		for _, receipt := range receipts {
  1473  			r.Equal(uint64(1), receipt.Status)
  1474  		}
  1475  	}
  1476  	b.StopTimer()
  1477  }
  1478  
  1479  func BenchmarkHotContract(b *testing.B) {
  1480  	b.Run("async mode", func(b *testing.B) {
  1481  		benchmarkHotContractWithFactory(b, true)
  1482  	})
  1483  	b.Run("sync mode", func(b *testing.B) {
  1484  		benchmarkHotContractWithFactory(b, false)
  1485  	})
  1486  	b.Run("cachedStateDB", func(b *testing.B) {
  1487  		benchmarkHotContractWithStateDB(b, true)
  1488  	})
  1489  	b.Run("defaultStateDB", func(b *testing.B) {
  1490  		benchmarkHotContractWithStateDB(b, false)
  1491  	})
  1492  }
  1493  
  1494  func getBlockTimeForTest(h uint64) (time.Time, error) {
  1495  	return fixedTime.Add(time.Duration(h) * 5 * time.Second), nil
  1496  }