github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/vmbridge/keeper/evm_test.go (about)

     1  package keeper_test
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/hex"
     6  	"errors"
     7  	"fmt"
     8  
     9  	"github.com/ethereum/go-ethereum/accounts/abi"
    10  	"github.com/ethereum/go-ethereum/common"
    11  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
    12  	sdkerrors "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types/errors"
    13  	keeper2 "github.com/fibonacci-chain/fbc/x/vmbridge/keeper"
    14  	"github.com/fibonacci-chain/fbc/x/vmbridge/types"
    15  	wasmtypes "github.com/fibonacci-chain/fbc/x/wasm/types"
    16  
    17  	"math/big"
    18  )
    19  
    20  func (suite *KeeperTestSuite) TestKeeper_SendToEvm() {
    21  
    22  	caller := suite.wasmContract.String()
    23  	contract := suite.evmContract.String()
    24  	recipient := sdk.AccAddress(common.BigToAddress(big.NewInt(1)).Bytes()).String()
    25  	amount := sdk.NewInt(1)
    26  
    27  	reset := func() {
    28  		caller = suite.wasmContract.String()
    29  		contract = suite.evmContract.String()
    30  		recipient = common.BigToAddress(big.NewInt(1)).String()
    31  		amount = sdk.NewInt(1)
    32  	}
    33  	testCases := []struct {
    34  		msg       string
    35  		malleate  func()
    36  		postcheck func()
    37  		error     error
    38  		success   bool
    39  	}{
    40  		{
    41  			"caller(ex wasm),contract(0x),recipient(0x),amount(1)",
    42  			func() {
    43  
    44  			},
    45  			func() {
    46  				aimAddr, err := sdk.AccAddressFromBech32(recipient)
    47  				suite.Require().NoError(err)
    48  				balance := suite.queryBalance(common.BytesToAddress(aimAddr.Bytes()))
    49  				suite.Require().Equal(amount.Int64(), balance.Int64())
    50  			},
    51  			nil,
    52  			true,
    53  		},
    54  		{
    55  			"caller(ex wasm),contract(ex),recipient(0x),amount(1)",
    56  			func() {
    57  				temp, err := sdk.AccAddressFromBech32(contract)
    58  				suite.Require().NoError(err)
    59  				contract = temp.String()
    60  			},
    61  			func() {
    62  				aimAddr, err := sdk.AccAddressFromBech32(recipient)
    63  				suite.Require().NoError(err)
    64  				balance := suite.queryBalance(common.BytesToAddress(aimAddr.Bytes()))
    65  				suite.Require().Equal(amount.Int64(), balance.Int64())
    66  			},
    67  			types.ErrIsNotETHAddr,
    68  			true,
    69  		},
    70  		{
    71  			"caller(ex wasm),contract(0x),recipient(ex),amount(1)",
    72  			func() {
    73  				temp, err := sdk.AccAddressFromBech32(recipient)
    74  				suite.Require().NoError(err)
    75  				recipient = temp.String()
    76  			},
    77  			func() {
    78  				aimAddr, err := sdk.AccAddressFromBech32(recipient)
    79  				suite.Require().NoError(err)
    80  				balance := suite.queryBalance(common.BytesToAddress(aimAddr.Bytes()))
    81  				suite.Require().Equal(amount.Int64(), balance.Int64())
    82  			},
    83  			types.ErrIsNotETHAddr,
    84  			true,
    85  		},
    86  		{
    87  			"caller(ex wasm),contract(0x),recipient(0x),amount(0)",
    88  			func() {
    89  				amount = sdk.NewInt(0)
    90  			},
    91  			func() {
    92  				aimAddr, err := sdk.AccAddressFromBech32(recipient)
    93  				suite.Require().NoError(err)
    94  				balance := suite.queryBalance(common.BytesToAddress(aimAddr.Bytes()))
    95  				suite.Require().Equal(amount.Int64(), balance.Int64())
    96  			},
    97  			nil,
    98  			true,
    99  		},
   100  		{
   101  			"caller(ex wasm),contract(0x),recipient(0x),amount(-1)",
   102  			func() {
   103  				amount = sdk.NewInt(-1)
   104  			},
   105  			func() {
   106  
   107  			},
   108  			errors.New("[\"execution reverted\",\"0x4e487b710000000000000000000000000000000000000000000000000000000000000011\",\"HexData\",\"0x4e487b710000000000000000000000000000000000000000000000000000000000000011\"]"),
   109  			true,
   110  		},
   111  		{
   112  			"caller(ex wasm),contract(0x),recipient(0x wasm),amount(1)", // recipent is not wasm addr but is check in SendToEvmEvent Check.
   113  			func() {
   114  				buffer := make([]byte, 32)
   115  				buffer[31] = 0x1
   116  				recipient = "0x" + hex.EncodeToString(buffer)
   117  			},
   118  			func() {
   119  				aimAddr, err := sdk.AccAddressFromBech32(recipient)
   120  				suite.Require().NoError(err)
   121  				balance := suite.queryBalance(common.BytesToAddress(aimAddr.Bytes()))
   122  				suite.Require().Equal(amount.Int64(), balance.Int64())
   123  			},
   124  			nil,
   125  			//errors.New("[\"execution reverted\",\"execution reverted:ERC20: mint to the zero address\",\"HexData\",\"0x08c379a00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000001f45524332303a206d696e7420746f20746865207a65726f206164647265737300\"]"),
   126  			true,
   127  		},
   128  		{
   129  			"caller(ex wasm),contract(0x wasm),recipient(0x),amount(1)",
   130  			func() {
   131  				buffer := make([]byte, 32)
   132  				buffer[31] = 0x1
   133  				contract = "0x" + hex.EncodeToString(buffer)
   134  			},
   135  			func() {
   136  			},
   137  			errors.New("abi: attempting to unmarshall an empty string while arguments are expected"),
   138  			true,
   139  		},
   140  		{
   141  			"caller(ex nowasm),contract(0x),recipient(0x),amount(1)",
   142  			func() {
   143  				buffer := make([]byte, 20)
   144  				buffer[19] = 0x1
   145  				caller = sdk.AccAddress(buffer).String()
   146  			},
   147  			func() {
   148  			},
   149  			errors.New("execution reverted"),
   150  			true,
   151  		},
   152  		{
   153  			"caller(ex wasm is no exist in erc20 contrat),contract(ex),recipient(0x),amount(1)",
   154  			func() {
   155  				buffer := make([]byte, 32)
   156  				buffer[19] = 0x1
   157  				caller = sdk.AccAddress(buffer).String()
   158  			},
   159  			func() {
   160  			},
   161  			errors.New("execution reverted"),
   162  			true,
   163  		},
   164  		{
   165  			"caller(0x wasm),contract(0x),recipient(ex),amount(1)",
   166  			func() {
   167  				wasmAddr, err := sdk.AccAddressFromBech32(caller)
   168  				suite.Require().NoError(err)
   169  				temp := hex.EncodeToString(wasmAddr.Bytes())
   170  				suite.T().Log(temp)
   171  				caller = "0x" + temp
   172  			},
   173  			func() {
   174  			},
   175  			errors.New("execution reverted"),
   176  			true,
   177  		},
   178  	}
   179  	for _, tc := range testCases {
   180  		suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
   181  			suite.SetupTest()
   182  			reset()
   183  			tc.malleate()
   184  
   185  			success, err := suite.app.VMBridgeKeeper.SendToEvm(suite.ctx, caller, contract, recipient, amount)
   186  			if tc.error != nil {
   187  				suite.Require().EqualError(err, tc.error.Error())
   188  			} else {
   189  				suite.Require().NoError(err)
   190  				suite.Require().Equal(tc.success, success)
   191  				tc.postcheck()
   192  			}
   193  		})
   194  	}
   195  }
   196  
   197  func (suite *KeeperTestSuite) TestSendToWasmEventHandler_Handle() {
   198  	contractAccAddr, err := sdk.AccAddressFromBech32("fb1fnkz39vpxmukf6mp78essh8g0hrzp3gy9zqj7f")
   199  	suite.Require().NoError(err)
   200  	contract := common.BytesToAddress(contractAccAddr.Bytes())
   201  	//addr := sdk.AccAddress{0x1}
   202  	ethAddr := common.BigToAddress(big.NewInt(1))
   203  	var data []byte
   204  
   205  	testCases := []struct {
   206  		msg       string
   207  		malleate  func()
   208  		postcheck func()
   209  		error     error
   210  	}{
   211  		{
   212  			"normal topic,recipient is 0x",
   213  			func() {
   214  				wasmAddrStr := suite.wasmContract.String()
   215  				input, err := getSendToWasmEventData(wasmAddrStr, ethAddr.String(), big.NewInt(1))
   216  				suite.Require().NoError(err)
   217  				data = input
   218  			},
   219  			func() {
   220  				queryAddr := sdk.AccAddress(ethAddr.Bytes())
   221  				result, err := suite.app.WasmKeeper.QuerySmart(suite.ctx, suite.wasmContract, []byte(fmt.Sprintf("{\"balance\":{\"address\":\"%s\"}}", queryAddr.String())))
   222  				suite.Require().NoError(err)
   223  				suite.Require().Equal("{\"balance\":\"1\"}", string(result))
   224  			},
   225  			types.ErrIsNotFBCAddr,
   226  		},
   227  		{
   228  			"normal topic,recipient is ex",
   229  			func() {
   230  				wasmAddrStr := suite.wasmContract.String()
   231  				queryAddr := sdk.AccAddress(ethAddr.Bytes())
   232  				input, err := getSendToWasmEventData(wasmAddrStr, queryAddr.String(), big.NewInt(1))
   233  				suite.Require().NoError(err)
   234  				data = input
   235  			},
   236  			func() {
   237  				queryAddr := sdk.AccAddress(ethAddr.Bytes())
   238  				result, err := suite.app.WasmKeeper.QuerySmart(suite.ctx, suite.wasmContract, []byte(fmt.Sprintf("{\"balance\":{\"address\":\"%s\"}}", queryAddr.String())))
   239  				suite.Require().NoError(err)
   240  				suite.Require().Equal("{\"balance\":\"1\"}", string(result))
   241  			},
   242  			nil,
   243  		},
   244  		{
   245  			"normal topic,amount is zero",
   246  			func() {
   247  				wasmAddrStr := suite.wasmContract.String()
   248  				queryAddr := sdk.AccAddress(ethAddr.Bytes())
   249  				input, err := getSendToWasmEventData(wasmAddrStr, queryAddr.String(), big.NewInt(0))
   250  				suite.Require().NoError(err)
   251  				data = input
   252  			},
   253  			func() {
   254  				queryAddr := sdk.AccAddress(ethAddr.Bytes())
   255  				result, err := suite.app.WasmKeeper.QuerySmart(suite.ctx, suite.wasmContract, []byte(fmt.Sprintf("{\"balance\":{\"address\":\"%s\"}}", queryAddr.String())))
   256  				suite.Require().NoError(err)
   257  				suite.Require().Equal("{\"balance\":\"0\"}", string(result))
   258  			},
   259  			nil,
   260  		},
   261  		{
   262  			"error input",
   263  			func() {
   264  				data = []byte("ddddddd")
   265  			},
   266  			func() {
   267  			},
   268  			nil,
   269  		},
   270  		{
   271  			"wasmAddStr is not wasm",
   272  			func() {
   273  				wasmAddrStr := sdk.AccAddress(make([]byte, 20)).String()
   274  				input, err := getSendToWasmEventData(wasmAddrStr, sdk.AccAddress(ethAddr.Bytes()).String(), big.NewInt(1))
   275  				suite.Require().NoError(err)
   276  				data = input
   277  			},
   278  			func() {
   279  			},
   280  			types.ErrIsNotWasmAddr,
   281  		},
   282  		{
   283  			"wasmAddStr is not exist",
   284  			func() {
   285  				wasmAddrStr := sdk.AccAddress(make([]byte, 32)).String()
   286  				input, err := getSendToWasmEventData(wasmAddrStr, sdk.AccAddress(ethAddr.Bytes()).String(), big.NewInt(1))
   287  				suite.Require().NoError(err)
   288  				data = input
   289  			},
   290  			func() {
   291  			},
   292  			sdkerrors.Wrap(wasmtypes.ErrNotFound, "contract"),
   293  		},
   294  		{
   295  			"recipient  is a error addr",
   296  			func() {
   297  				wasmAddrStr := suite.wasmContract.String()
   298  				input, err := getSendToWasmEventData(wasmAddrStr, "fb111", big.NewInt(1))
   299  				suite.Require().NoError(err)
   300  				data = input
   301  			},
   302  			func() {
   303  			},
   304  			errors.New("decoding bech32 failed: invalid bech32 string length 5"),
   305  		},
   306  		{
   307  			"caller is not expect",
   308  			func() {
   309  				contract = common.BigToAddress(big.NewInt(1000))
   310  				wasmAddrStr := suite.wasmContract.String()
   311  				input, err := getSendToWasmEventData(wasmAddrStr, sdk.AccAddress(ethAddr.Bytes()).String(), big.NewInt(1))
   312  				suite.Require().NoError(err)
   313  				data = input
   314  			},
   315  			func() {
   316  			},
   317  			errors.New("execute wasm contract failed: The Contract addr is not expect)"),
   318  		},
   319  	}
   320  	for _, tc := range testCases {
   321  		suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
   322  			suite.SetupTest()
   323  
   324  			handler := keeper2.NewSendToWasmEventHandler(*suite.keeper)
   325  			tc.malleate()
   326  			err := handler.Handle(suite.ctx, contract, data)
   327  			if tc.error != nil {
   328  				suite.Require().EqualError(err, tc.error.Error())
   329  			} else {
   330  				suite.Require().NoError(err)
   331  				tc.postcheck()
   332  			}
   333  		})
   334  	}
   335  }
   336  
   337  func (suite *KeeperTestSuite) TestSendToWasmEvent_Unpack() {
   338  	ethAddr := common.BigToAddress(big.NewInt(1))
   339  	var data []byte
   340  
   341  	testCases := []struct {
   342  		msg       string
   343  		malleate  func()
   344  		postcheck func(wasmAddr string, recipient string, amount sdk.Int, err error)
   345  		error     error
   346  	}{
   347  		{
   348  			"normal topic",
   349  			func() {
   350  				wasmAddrStr := suite.wasmContract.String()
   351  				input, err := getSendToWasmEventData(wasmAddrStr, ethAddr.String(), big.NewInt(1))
   352  				suite.Require().NoError(err)
   353  				data = input
   354  			},
   355  			func(wasmAddr string, recipient string, amount sdk.Int, err error) {
   356  				suite.Require().NoError(err)
   357  				suite.Require().Equal(suite.wasmContract.String(), wasmAddr)
   358  				suite.Require().Equal(ethAddr.String(), recipient)
   359  				suite.Require().Equal(big.NewInt(1), amount.BigInt())
   360  			},
   361  			nil,
   362  		},
   363  		{
   364  			"recipient is bytes",
   365  			func() {
   366  				testABIJson := "[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"wasmAddr\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"recipient\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"__OKCSendToWasm\",\"type\":\"event\"}]"
   367  
   368  				testABIEvent, err := abi.JSON(bytes.NewReader([]byte(testABIJson)))
   369  				suite.Require().NoError(err)
   370  
   371  				ethAddrAcc, err := sdk.AccAddressFromBech32(ethAddr.String())
   372  				suite.Require().NoError(err)
   373  				input, err := testABIEvent.Events[types.SendToWasmEventName].Inputs.Pack(suite.wasmContract.String(), []byte(ethAddrAcc.String()), big.NewInt(1))
   374  				suite.Require().NoError(err)
   375  				data = input
   376  			},
   377  			func(wasmAddr string, recipient string, amount sdk.Int, err error) {
   378  				suite.Require().NoError(err)
   379  				suite.Require().NotEqual(ethAddr.String(), recipient)
   380  				suite.Require().Equal(big.NewInt(1), amount.BigInt())
   381  			},
   382  			nil,
   383  		},
   384  		{
   385  			"wasmAddr is bytes",
   386  			func() {
   387  				testABIJson := "[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"wasmAddr\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"recipient\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"__OKCSendToWasm\",\"type\":\"event\"}]"
   388  
   389  				testABIEvent, err := abi.JSON(bytes.NewReader([]byte(testABIJson)))
   390  				suite.Require().NoError(err)
   391  				input, err := testABIEvent.Events[types.SendToWasmEventName].Inputs.Pack([]byte(suite.wasmContract.String()), ethAddr.String(), big.NewInt(1))
   392  				suite.Require().NoError(err)
   393  				data = input
   394  			},
   395  			func(wasmAddr string, recipient string, amount sdk.Int, err error) {
   396  				suite.Require().NoError(err)
   397  				suite.Require().Equal(suite.wasmContract.String(), wasmAddr)
   398  				suite.Require().Equal(ethAddr.String(), recipient)
   399  				suite.Require().Equal(big.NewInt(1), amount.BigInt())
   400  			},
   401  			nil,
   402  		},
   403  		{
   404  			"event __OKCSendToWasm(string,uint256) ",
   405  			func() {
   406  				testABIJson := "[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"recipient\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"__OKCSendToWasm\",\"type\":\"event\"}]"
   407  
   408  				testABIEvent, err := abi.JSON(bytes.NewReader([]byte(testABIJson)))
   409  				suite.Require().NoError(err)
   410  				input, err := testABIEvent.Events[types.SendToWasmEventName].Inputs.Pack(ethAddr.String(), big.NewInt(1))
   411  				suite.Require().NoError(err)
   412  				data = input
   413  			},
   414  			func(wasmAddr string, recipient string, amount sdk.Int, err error) {
   415  			},
   416  			errors.New("abi: cannot marshal in to go type: length insufficient 160 require 16417"),
   417  		},
   418  		{
   419  			"event __OKCSendToWasm(string,string,string,uint256) ",
   420  			func() {
   421  				testABIJson := "[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"recipient2\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"recipient1\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"recipient\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"__OKCSendToWasm\",\"type\":\"event\"}]"
   422  
   423  				testABIEvent, err := abi.JSON(bytes.NewReader([]byte(testABIJson)))
   424  				suite.Require().NoError(err)
   425  				input, err := testABIEvent.Events[types.SendToWasmEventName].Inputs.Pack("1", "2", "3", big.NewInt(1))
   426  				suite.Require().NoError(err)
   427  				data = input
   428  			},
   429  			func(wasmAddr string, recipient string, amount sdk.Int, err error) {
   430  				suite.Require().Equal("1", wasmAddr)
   431  				suite.Require().Equal("2", recipient)
   432  				suite.Require().NotEqual(big.NewInt(1), amount.BigInt())
   433  			},
   434  			nil,
   435  			//errors.New("argument count mismatch: got 2 for 4"),
   436  		},
   437  		{
   438  			"amount is negative",
   439  			func() {
   440  				testABIJson := "[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"wasmAddr\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"recipient\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"int8\",\"name\":\"amount\",\"type\":\"int8\"}],\"name\":\"__OKCSendToWasm\",\"type\":\"event\"}]\n"
   441  
   442  				testABIEvent, err := abi.JSON(bytes.NewReader([]byte(testABIJson)))
   443  				suite.Require().NoError(err)
   444  				input, err := testABIEvent.Events[types.SendToWasmEventName].Inputs.Pack(suite.wasmContract.String(), ethAddr.String(), int8(-1))
   445  				suite.T().Log(testABIEvent.Events[types.SendToWasmEventName].ID, types.SendToWasmEvent.ID)
   446  				suite.Require().NoError(err)
   447  				data = input
   448  			},
   449  			func(wasmAddr string, recipient string, amount sdk.Int, err error) {
   450  				suite.Require().Equal(errors.New("recover err: NewIntFromBigInt() out of bound"), err)
   451  				suite.Require().Equal(suite.wasmContract.String(), wasmAddr)
   452  				suite.Require().Equal(ethAddr.String(), recipient)
   453  			},
   454  			nil,
   455  		},
   456  	}
   457  
   458  	for _, tc := range testCases {
   459  		suite.Run(fmt.Sprintf("Case %s", tc.msg), func() {
   460  			suite.SetupTest()
   461  
   462  			tc.malleate()
   463  			unpacked, err := types.SendToWasmEvent.Inputs.Unpack(data)
   464  			if tc.error != nil {
   465  				suite.Require().EqualError(err, tc.error.Error())
   466  			} else {
   467  				suite.Require().NoError(err)
   468  				feild1, field2, feild3, err := getUnpack(unpacked)
   469  				tc.postcheck(feild1, field2, feild3, err)
   470  			}
   471  		})
   472  	}
   473  }
   474  
   475  func getUnpack(unpacked []interface{}) (wasmAddr string, recipient string, amount sdk.Int, err error) {
   476  	defer func() {
   477  		if r := recover(); r != nil {
   478  			err = fmt.Errorf("recover err: %v", r)
   479  		}
   480  	}()
   481  	wasmAddr, ok := unpacked[0].(string)
   482  	if !ok {
   483  		return wasmAddr, recipient, amount, errors.New("the 1 feild is not string")
   484  	}
   485  
   486  	recipient, ok = unpacked[1].(string)
   487  	if !ok {
   488  		return wasmAddr, recipient, amount, errors.New("the 2 feild is not string")
   489  	}
   490  
   491  	temp, ok := unpacked[2].(*big.Int)
   492  	if !ok {
   493  		return wasmAddr, recipient, amount, errors.New("the 3 feild is not *big.Int")
   494  	}
   495  	amount = sdk.NewIntFromBigInt(temp)
   496  	return
   497  }
   498  func getSendToWasmEventData(wasmAddr, recipient string, amount *big.Int) ([]byte, error) {
   499  	return types.SendToWasmEvent.Inputs.Pack(wasmAddr, recipient, amount)
   500  }