github.com/iotexproject/iotex-core@v1.14.1-rc1/ioctl/newcmd/action/action_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 action
     7  
     8  import (
     9  	"math/big"
    10  	"testing"
    11  
    12  	"github.com/ethereum/go-ethereum/accounts/keystore"
    13  	"github.com/golang/mock/gomock"
    14  	"github.com/iotexproject/iotex-address/address"
    15  	"github.com/iotexproject/iotex-proto/golang/iotexapi"
    16  	"github.com/iotexproject/iotex-proto/golang/iotexapi/mock_iotexapi"
    17  	"github.com/iotexproject/iotex-proto/golang/iotextypes"
    18  	"github.com/pkg/errors"
    19  	"github.com/stretchr/testify/require"
    20  
    21  	"github.com/iotexproject/iotex-core/ioctl/config"
    22  	"github.com/iotexproject/iotex-core/ioctl/util"
    23  	"github.com/iotexproject/iotex-core/test/identityset"
    24  	"github.com/iotexproject/iotex-core/test/mock/mock_ioctlclient"
    25  )
    26  
    27  func TestSigner(t *testing.T) {
    28  	require := require.New(t)
    29  	ctrl := gomock.NewController(t)
    30  	client := mock_ioctlclient.NewMockClient(ctrl)
    31  	client.EXPECT().SelectTranslation(gomock.Any()).Return("mockTranslationString", config.English).Times(2)
    32  	client.EXPECT().SetEndpointWithFlag(gomock.Any())
    33  	client.EXPECT().SetInsecureWithFlag(gomock.Any())
    34  
    35  	t.Run("returns signer's address", func(t *testing.T) {
    36  		client.EXPECT().AddressWithDefaultIfNotExist(gomock.Any()).Return("test", nil).AnyTimes()
    37  
    38  		cmd := NewActionCmd(client)
    39  		registerSignerFlag(client, cmd)
    40  		_, err := util.ExecuteCmd(cmd, "--signer", "test")
    41  		require.NoError(err)
    42  		signer, err := cmd.Flags().GetString(signerFlagLabel)
    43  		require.NoError(err)
    44  		result, err := Signer(client, signer)
    45  		require.NoError(err)
    46  		require.Equal(result, "test")
    47  	})
    48  }
    49  
    50  func TestSendRaw(t *testing.T) {
    51  	require := require.New(t)
    52  	ctrl := gomock.NewController(t)
    53  	client := mock_ioctlclient.NewMockClient(ctrl)
    54  	apiServiceClient := mock_iotexapi.NewMockAPIServiceClient(ctrl)
    55  	selp := &iotextypes.Action{}
    56  
    57  	client.EXPECT().SelectTranslation(gomock.Any()).Return("mockTranslationString", config.English).Times(3)
    58  	client.EXPECT().APIServiceClient().Return(apiServiceClient, nil).Times(7)
    59  
    60  	for _, test := range []struct {
    61  		endpoint string
    62  		insecure bool
    63  	}{
    64  		{
    65  			endpoint: "111:222:333:444:5678",
    66  			insecure: false,
    67  		},
    68  		{
    69  			endpoint: "",
    70  			insecure: true,
    71  		},
    72  	} {
    73  		callbackEndpoint := func(cb func(*string, string, string, string)) {
    74  			cb(&test.endpoint, "endpoint", test.endpoint, "endpoint usage")
    75  		}
    76  		callbackInsecure := func(cb func(*bool, string, bool, string)) {
    77  			cb(&test.insecure, "insecure", !test.insecure, "insecure usage")
    78  		}
    79  		client.EXPECT().SetEndpointWithFlag(gomock.Any()).Do(callbackEndpoint).AnyTimes()
    80  		client.EXPECT().SetInsecureWithFlag(gomock.Any()).Do(callbackInsecure).AnyTimes()
    81  
    82  		t.Run("sends raw action to blockchain", func(t *testing.T) {
    83  			response := &iotexapi.SendActionResponse{}
    84  
    85  			apiServiceClient.EXPECT().SendAction(gomock.Any(), gomock.Any()).Return(response, nil).Times(3)
    86  
    87  			cmd := NewActionCmd(client)
    88  			_, err := util.ExecuteCmd(cmd)
    89  			require.NoError(err)
    90  
    91  			t.Run("endpoint iotexscan", func(t *testing.T) {
    92  				client.EXPECT().Config().Return(config.Config{
    93  					Explorer: "iotexscan",
    94  					Endpoint: "testnet1",
    95  				}).Times(2)
    96  
    97  				err = SendRaw(client, cmd, selp)
    98  				require.NoError(err)
    99  			})
   100  
   101  			t.Run("endpoint iotxplorer", func(t *testing.T) {
   102  				client.EXPECT().Config().Return(config.Config{
   103  					Explorer: "iotxplorer",
   104  				}).Times(2)
   105  
   106  				err := SendRaw(client, cmd, selp)
   107  				require.NoError(err)
   108  			})
   109  
   110  			t.Run("endpoint default", func(t *testing.T) {
   111  				client.EXPECT().Config().Return(config.Config{
   112  					Explorer: "test",
   113  				}).Times(2)
   114  
   115  				err := SendRaw(client, cmd, selp)
   116  				require.NoError(err)
   117  			})
   118  		})
   119  	}
   120  
   121  	t.Run("failed to invoke SendAction api", func(t *testing.T) {
   122  		expectedErr := errors.New("failed to invoke SendAction api")
   123  		apiServiceClient.EXPECT().SendAction(gomock.Any(), gomock.Any()).Return(nil, expectedErr)
   124  
   125  		cmd := NewActionCmd(client)
   126  		_, err := util.ExecuteCmd(cmd)
   127  		require.NoError(err)
   128  		err = SendRaw(client, cmd, selp)
   129  		require.Contains(err.Error(), expectedErr.Error())
   130  	})
   131  }
   132  
   133  func TestSendAction(t *testing.T) {
   134  	require := require.New(t)
   135  	ctrl := gomock.NewController(t)
   136  	client := mock_ioctlclient.NewMockClient(ctrl)
   137  	apiServiceClient := mock_iotexapi.NewMockAPIServiceClient(ctrl)
   138  	passwd := "123456"
   139  
   140  	ks := keystore.NewKeyStore(t.TempDir(), 2, 1)
   141  	acc, err := ks.NewAccount(passwd)
   142  	require.NoError(err)
   143  	accAddr, err := address.FromBytes(acc.Address.Bytes())
   144  	require.NoError(err)
   145  
   146  	chainMetaResponse := &iotexapi.GetChainMetaResponse{ChainMeta: &iotextypes.ChainMeta{}}
   147  	elp := createEnvelope(0)
   148  	cost, err := elp.Cost()
   149  	require.NoError(err)
   150  	accountResponse := &iotexapi.GetAccountResponse{AccountMeta: &iotextypes.AccountMeta{
   151  		Address:      accAddr.String(),
   152  		PendingNonce: 1,
   153  		Balance:      cost.String(),
   154  	}}
   155  
   156  	client.EXPECT().SelectTranslation(gomock.Any()).Return("action", config.English).AnyTimes()
   157  	client.EXPECT().SetEndpointWithFlag(gomock.Any()).AnyTimes()
   158  	client.EXPECT().SetInsecureWithFlag(gomock.Any()).AnyTimes()
   159  	client.EXPECT().IsCryptoSm2().Return(false).AnyTimes()
   160  	client.EXPECT().NewKeyStore().Return(ks).AnyTimes()
   161  
   162  	t.Run("failed to get privateKey", func(t *testing.T) {
   163  		expectedErr := errors.New("failed to get privateKey")
   164  		client.EXPECT().ReadSecret().Return("", expectedErr).Times(1)
   165  
   166  		cmd := NewActionCmd(client)
   167  		err = SendAction(client, cmd, elp, accAddr.String(), "", 0, false)
   168  		require.Contains(err.Error(), expectedErr.Error())
   169  	})
   170  
   171  	client.EXPECT().APIServiceClient().Return(apiServiceClient, nil).AnyTimes()
   172  	client.EXPECT().ReadSecret().Return(passwd, nil).AnyTimes()
   173  	client.EXPECT().Address(gomock.Any()).Return(accAddr.String(), nil).AnyTimes()
   174  	client.EXPECT().Alias(gomock.Any()).Return("producer", nil).AnyTimes()
   175  	client.EXPECT().ReadInput().Return("confirm", nil).AnyTimes()
   176  	client.EXPECT().AskToConfirm(gomock.Any()).Return(true, nil).Times(2)
   177  	client.EXPECT().Config().Return(config.Config{
   178  		Explorer: "iotexscan",
   179  		Endpoint: "testnet1",
   180  	}).AnyTimes()
   181  
   182  	apiServiceClient.EXPECT().GetChainMeta(gomock.Any(), gomock.Any()).Return(chainMetaResponse, nil).Times(6)
   183  	apiServiceClient.EXPECT().GetAccount(gomock.Any(), gomock.Any()).Return(accountResponse, nil).Times(4)
   184  	apiServiceClient.EXPECT().SendAction(gomock.Any(), gomock.Any()).Return(&iotexapi.SendActionResponse{}, nil).AnyTimes()
   185  
   186  	t.Run("sends signed action to blockchain", func(t *testing.T) {
   187  		cmd := NewActionCmd(client)
   188  		err = SendAction(client, cmd, elp, accAddr.String(), passwd, 1, false)
   189  		require.NoError(err)
   190  	})
   191  
   192  	t.Run("send action with nonce", func(t *testing.T) {
   193  		mnemonic := "lake stove quarter shove dry matrix hire split wide attract argue core"
   194  		client.EXPECT().HdwalletMnemonic(gomock.Any()).Return(mnemonic, nil)
   195  
   196  		cmd := NewActionCmd(client)
   197  		err = SendAction(client, cmd, elp, "hdw::1/2", passwd, 1, false)
   198  		require.NoError(err)
   199  	})
   200  
   201  	t.Run("quit action command", func(t *testing.T) {
   202  		client.EXPECT().AskToConfirm(gomock.Any()).Return(false, nil)
   203  
   204  		cmd := NewActionCmd(client)
   205  		err = SendAction(client, cmd, elp, accAddr.String(), passwd, 1, false)
   206  		require.NoError(err)
   207  	})
   208  
   209  	t.Run("failed to ask confirm", func(t *testing.T) {
   210  		expectedErr := errors.New("failed to ask confirm")
   211  		client.EXPECT().AskToConfirm(gomock.Any()).Return(false, expectedErr)
   212  
   213  		cmd := NewActionCmd(client)
   214  		err = SendAction(client, cmd, elp, accAddr.String(), passwd, 1, false)
   215  		require.Contains(err.Error(), expectedErr.Error())
   216  	})
   217  
   218  	t.Run("failed to pass balance check", func(t *testing.T) {
   219  		expectedErr := errors.New("failed to pass balance check")
   220  		apiServiceClient.EXPECT().GetAccount(gomock.Any(), gomock.Any()).Return(nil, expectedErr)
   221  
   222  		cmd := NewActionCmd(client)
   223  		err = SendAction(client, cmd, elp, accAddr.String(), passwd, 1, false)
   224  		require.Contains(err.Error(), expectedErr.Error())
   225  	})
   226  
   227  	t.Run("failed to get nonce", func(t *testing.T) {
   228  		mnemonic := "lake stove quarter shove dry matrix hire split wide attract argue core"
   229  		expectedErr := errors.New("failed to get nonce")
   230  		client.EXPECT().HdwalletMnemonic(gomock.Any()).Return(mnemonic, nil)
   231  		apiServiceClient.EXPECT().GetAccount(gomock.Any(), gomock.Any()).Return(nil, expectedErr)
   232  
   233  		cmd := NewActionCmd(client)
   234  		err = SendAction(client, cmd, elp, "hdw::1/2", passwd, 1, false)
   235  		require.Contains(err.Error(), expectedErr.Error())
   236  	})
   237  	t.Run("failed to get chain meta", func(t *testing.T) {
   238  		expectedErr := errors.New("failed to get chain meta")
   239  		apiServiceClient.EXPECT().GetChainMeta(gomock.Any(), gomock.Any()).Return(nil, expectedErr)
   240  		apiServiceClient.EXPECT().GetAccount(gomock.Any(), gomock.Any()).Return(accountResponse, nil).AnyTimes()
   241  
   242  		cmd := NewActionCmd(client)
   243  		err = SendAction(client, cmd, elp, accAddr.String(), passwd, 1, false)
   244  		require.Contains(err.Error(), expectedErr.Error())
   245  	})
   246  }
   247  func TestExecute(t *testing.T) {
   248  	require := require.New(t)
   249  	ctrl := gomock.NewController(t)
   250  	client := mock_ioctlclient.NewMockClient(ctrl)
   251  	apiServiceClient := mock_iotexapi.NewMockAPIServiceClient(ctrl)
   252  	passwd := "123456"
   253  	bytecode := "608060405234801561001057600080fd5b506040516040806108018339810180604052810190808051906020019092919080519060200190929190505050816004819055508060058190555050506107a58061005c6000396000f300608060405260043610610078576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680631249c58b1461007d57806327e235e31461009457806353277879146100eb5780636941b84414610142578063810ad50514610199578063a9059cbb14610223575b600080fd5b34801561008957600080fd5b50610092610270565b005b3480156100a057600080fd5b506100d5600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610475565b6040518082815260200191505060405180910390f35b3480156100f757600080fd5b5061012c600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061048d565b6040518082815260200191505060405180910390f35b34801561014e57600080fd5b50610183600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506104a5565b6040518082815260200191505060405180910390f35b3480156101a557600080fd5b506101da600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506104bd565b604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390f35b34801561022f57600080fd5b5061026e600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610501565b005b436004546000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054011115151561032a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f746f6f20736f6f6e20746f206d696e740000000000000000000000000000000081525060200191505060405180910390fd5b436000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550600554600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600081548092919060010191905055503373ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fec61728879a33aa50b55e1f4789dcfc1c680f30a24d7b8694a9f874e242a97b46005546040518082815260200191505060405180910390a3565b60016020528060005260406000206000915090505481565b60026020528060005260406000206000915090505481565b60006020528060005260406000206000915090505481565b60036020528060005260406000206000915090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060010154905082565b80600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054101515156105b8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f696e73756666696369656e742062616c616e636500000000000000000000000081525060200191505060405180910390fd5b80600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555080600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555060408051908101604052803373ffffffffffffffffffffffffffffffffffffffff16815260200182815250600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550602082015181600101559050508173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fec61728879a33aa50b55e1f4789dcfc1c680f30a24d7b8694a9f874e242a97b4836040518082815260200191505060405180910390a350505600a165627a7a7230582047e5e1380e66d6b109548617ae59ff7baf70ee2d4a6734559b8fc5cabca0870b0029000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000186a0"
   254  
   255  	ks := keystore.NewKeyStore(t.TempDir(), 2, 1)
   256  	acc, err := ks.NewAccount(passwd)
   257  	require.NoError(err)
   258  	accAddr, err := address.FromBytes(acc.Address.Bytes())
   259  	require.NoError(err)
   260  
   261  	chainMetaResponse := &iotexapi.GetChainMetaResponse{ChainMeta: &iotextypes.ChainMeta{}}
   262  	elp := createEnvelope(0)
   263  	cost, err := elp.Cost()
   264  	require.NoError(err)
   265  	accountResponse := &iotexapi.GetAccountResponse{AccountMeta: &iotextypes.AccountMeta{
   266  		Address:      accAddr.String(),
   267  		PendingNonce: 1,
   268  		Balance:      cost.String(),
   269  	}}
   270  
   271  	client.EXPECT().APIServiceClient().Return(apiServiceClient, nil).Times(13)
   272  	client.EXPECT().Address(gomock.Any()).Return(accAddr.String(), nil).Times(2)
   273  	client.EXPECT().Alias(gomock.Any()).Return("producer", nil).Times(4)
   274  	client.EXPECT().Config().Return(config.Config{
   275  		Explorer: "iotexscan",
   276  		Endpoint: "testnet1",
   277  	}).Times(4)
   278  
   279  	apiServiceClient.EXPECT().GetChainMeta(gomock.Any(), gomock.Any()).Return(chainMetaResponse, nil).Times(2)
   280  	apiServiceClient.EXPECT().GetAccount(gomock.Any(), gomock.Any()).Return(accountResponse, nil).Times(5)
   281  	apiServiceClient.EXPECT().SendAction(gomock.Any(), gomock.Any()).Return(&iotexapi.SendActionResponse{}, nil).Times(2)
   282  
   283  	client.EXPECT().SelectTranslation(gomock.Any()).Return("action", config.English).Times(7)
   284  	client.EXPECT().SetEndpointWithFlag(gomock.Any()).Times(7)
   285  	client.EXPECT().SetInsecureWithFlag(gomock.Any()).Times(7)
   286  	client.EXPECT().IsCryptoSm2().Return(false).Times(10)
   287  	client.EXPECT().NewKeyStore().Return(ks).Times(4)
   288  
   289  	t.Run("failed to get signer address", func(t *testing.T) {
   290  		expectedErr := errors.New("failed to get signer address")
   291  		client.EXPECT().AddressWithDefaultIfNotExist(gomock.Any()).Return("", expectedErr)
   292  		cmd := NewActionCmd(client)
   293  		err = Execute(client, cmd, "test", big.NewInt(100), []byte(bytecode), "100", accAddr.String(), passwd, 0, 100, true)
   294  		require.Error(err, expectedErr)
   295  	})
   296  
   297  	client.EXPECT().AddressWithDefaultIfNotExist(gomock.Any()).Return(accAddr.String(), nil).Times(4)
   298  
   299  	t.Run("sends signed execution's transaction to blockchain", func(t *testing.T) {
   300  		cmd := NewActionCmd(client)
   301  		err = Execute(client, cmd, "test", big.NewInt(100), []byte(bytecode), "100", accAddr.String(), passwd, 0, 100, true)
   302  		require.NoError(err)
   303  	})
   304  
   305  	t.Run("gas limit equals to 0", func(t *testing.T) {
   306  		t.Run("sends signed execution's transaction to blockchain", func(t *testing.T) {
   307  			cmd := NewActionCmd(client)
   308  			apiServiceClient.EXPECT().EstimateActionGasConsumption(gomock.Any(), gomock.Any()).Return(&iotexapi.EstimateActionGasConsumptionResponse{
   309  				Gas: uint64(100),
   310  			}, nil)
   311  			err = Execute(client, cmd, "test", big.NewInt(100), []byte(bytecode), "100", accAddr.String(), passwd, 0, 0, true)
   312  			require.NoError(err)
   313  		})
   314  
   315  		t.Run("failed to fix Execution gas limit", func(t *testing.T) {
   316  			expectedErr := errors.New("failed to fix Execution gas limit")
   317  			apiServiceClient.EXPECT().EstimateActionGasConsumption(gomock.Any(), gomock.Any()).Return(nil, expectedErr)
   318  			cmd := NewActionCmd(client)
   319  			err = Execute(client, cmd, "test", big.NewInt(100), []byte(bytecode), "100", accAddr.String(), passwd, 0, 0, true)
   320  			require.Error(err, expectedErr)
   321  		})
   322  	})
   323  
   324  	t.Run("failed to get nonce", func(t *testing.T) {
   325  		expectedErr := errors.New("failed to get nonce")
   326  		apiServiceClient.EXPECT().GetAccount(gomock.Any(), gomock.Any()).Return(nil, expectedErr)
   327  		cmd := NewActionCmd(client)
   328  		err = Execute(client, cmd, "test", big.NewInt(100), []byte(bytecode), "100", accAddr.String(), passwd, 0, 100, true)
   329  		require.Error(err, expectedErr)
   330  	})
   331  
   332  	t.Run("failed to get gas price", func(t *testing.T) {
   333  		expectedErr := errors.New("failed to get gas price")
   334  		apiServiceClient.EXPECT().SuggestGasPrice(gomock.Any(), gomock.Any()).Return(nil, expectedErr)
   335  		cmd := NewActionCmd(client)
   336  		err = Execute(client, cmd, "test", big.NewInt(100), []byte(bytecode), "", accAddr.String(), passwd, 0, 100, true)
   337  		require.Error(err, expectedErr)
   338  	})
   339  
   340  	t.Run("failed to deploy contract with empty bytecode", func(t *testing.T) {
   341  		expectedErr := errors.New("failed to deploy contract with empty bytecode")
   342  		cmd := NewActionCmd(client)
   343  		err = Execute(client, cmd, "", big.NewInt(100), []byte(""), "100", accAddr.String(), passwd, 0, 100, true)
   344  		require.Error(err, expectedErr)
   345  	})
   346  }
   347  
   348  func TestRead(t *testing.T) {
   349  	require := require.New(t)
   350  	ctrl := gomock.NewController(t)
   351  	client := mock_ioctlclient.NewMockClient(ctrl)
   352  	apiServiceClient := mock_iotexapi.NewMockAPIServiceClient(ctrl)
   353  	accAddr := identityset.Address(0)
   354  	bytecode := "608060405234801561001057600080fd5b506040516040806108018339810180604052810190808051906020019092919080519060200190929190505050816004819055508060058190555050506107a58061005c6000396000f300608060405260043610610078576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680631249c58b1461007d57806327e235e31461009457806353277879146100eb5780636941b84414610142578063810ad50514610199578063a9059cbb14610223575b600080fd5b34801561008957600080fd5b50610092610270565b005b3480156100a057600080fd5b506100d5600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610475565b6040518082815260200191505060405180910390f35b3480156100f757600080fd5b5061012c600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061048d565b6040518082815260200191505060405180910390f35b34801561014e57600080fd5b50610183600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506104a5565b6040518082815260200191505060405180910390f35b3480156101a557600080fd5b506101da600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506104bd565b604051808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018281526020019250505060405180910390f35b34801561022f57600080fd5b5061026e600480360381019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610501565b005b436004546000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054011115151561032a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f746f6f20736f6f6e20746f206d696e740000000000000000000000000000000081525060200191505060405180910390fd5b436000803373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550600554600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282540192505081905550600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600081548092919060010191905055503373ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fec61728879a33aa50b55e1f4789dcfc1c680f30a24d7b8694a9f874e242a97b46005546040518082815260200191505060405180910390a3565b60016020528060005260406000206000915090505481565b60026020528060005260406000206000915090505481565b60006020528060005260406000206000915090505481565b60036020528060005260406000206000915090508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060010154905082565b80600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054101515156105b8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f696e73756666696369656e742062616c616e636500000000000000000000000081525060200191505060405180910390fd5b80600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555080600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555060408051908101604052803373ffffffffffffffffffffffffffffffffffffffff16815260200182815250600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550602082015181600101559050508173ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fec61728879a33aa50b55e1f4789dcfc1c680f30a24d7b8694a9f874e242a97b4836040518082815260200191505060405180910390a350505600a165627a7a7230582047e5e1380e66d6b109548617ae59ff7baf70ee2d4a6734559b8fc5cabca0870b0029000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000186a0"
   355  
   356  	client.EXPECT().SelectTranslation(gomock.Any()).Return("action", config.English).AnyTimes()
   357  	client.EXPECT().SetEndpointWithFlag(gomock.Any()).AnyTimes()
   358  	client.EXPECT().SetInsecureWithFlag(gomock.Any()).AnyTimes()
   359  	client.EXPECT().APIServiceClient().Return(apiServiceClient, nil).Times(2)
   360  
   361  	t.Run("reads smart contract on IoTeX blockchain", func(t *testing.T) {
   362  		client.EXPECT().AddressWithDefaultIfNotExist(gomock.Any()).Return("test", nil)
   363  		apiServiceClient.EXPECT().ReadContract(gomock.Any(), gomock.Any()).Return(&iotexapi.ReadContractResponse{
   364  			Data: "test",
   365  		}, nil)
   366  
   367  		result, err := Read(client, accAddr, "100", []byte(bytecode), "test", 100)
   368  		require.NoError(err)
   369  		require.Equal("test", result)
   370  	})
   371  
   372  	t.Run("failed to get signer address", func(t *testing.T) {
   373  		expectErr := errors.New("failed to get signer address")
   374  		client.EXPECT().AddressWithDefaultIfNotExist(gomock.Any()).Return("", expectErr)
   375  		_, err := Read(client, accAddr, "100", []byte(bytecode), "test", 100)
   376  		require.Contains(err.Error(), expectErr.Error())
   377  	})
   378  }