package types import ( "bytes" "fmt" "math/big" "testing" "github.com/cosmos/ethermint/crypto" ethcmn "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/rlp" "github.com/stretchr/testify/require" ) func TestMsgEthereumTx(t *testing.T) { addr := GenerateEthAddress() msg1 := NewEthereumTxMsg(0, addr, nil, 100000, nil, []byte("test")) require.NotNil(t, msg1) require.Equal(t, *msg1.Data.Recipient, addr) msg2 := NewEthereumTxMsgContract(0, nil, 100000, nil, []byte("test")) require.NotNil(t, msg2) require.Nil(t, msg2.Data.Recipient) msg3 := NewEthereumTxMsg(0, addr, nil, 100000, nil, []byte("test")) require.Equal(t, msg3.Route(), RouteEthereumTxMsg) require.Equal(t, msg3.Type(), TypeEthereumTxMsg) require.Panics(t, func() { msg3.GetSigners() }) require.Panics(t, func() { msg3.GetSignBytes() }) } func TestMsgEthereumTxValidation(t *testing.T) { testCases := []struct { nonce uint64 to ethcmn.Address amount *big.Int gasLimit uint64 gasPrice *big.Int payload []byte expectPass bool }{ {amount: big.NewInt(100), gasPrice: big.NewInt(100000), expectPass: true}, {amount: big.NewInt(-1), gasPrice: big.NewInt(100000), expectPass: false}, {amount: big.NewInt(100), gasPrice: big.NewInt(-1), expectPass: false}, } for i, tc := range testCases { msg := NewEthereumTxMsg(tc.nonce, tc.to, tc.amount, tc.gasLimit, tc.gasPrice, tc.payload) if tc.expectPass { require.Nil(t, msg.ValidateBasic(), "test: %v", i) } else { require.NotNil(t, msg.ValidateBasic(), "test: %v", i) } } } func TestMsgEthereumTxRLPSignBytes(t *testing.T) { addr := ethcmn.BytesToAddress([]byte("test_address")) chainID := big.NewInt(3) msg := NewEthereumTxMsg(0, addr, nil, 100000, nil, []byte("test")) hash := msg.RLPSignBytes(chainID) require.Equal(t, "5BD30E35AD27449390B14C91E6BCFDCAADF8FE44EF33680E3BC200FC0DC083C7", fmt.Sprintf("%X", hash)) } func TestMsgEthereumTxRLPEncode(t *testing.T) { addr := ethcmn.BytesToAddress([]byte("test_address")) msg := NewEthereumTxMsg(0, addr, nil, 100000, nil, []byte("test")) raw, err := rlp.EncodeToBytes(msg) require.NoError(t, err) require.Equal(t, ethcmn.FromHex("E48080830186A0940000000000000000746573745F61646472657373808474657374808080"), raw) } func TestMsgEthereumTxRLPDecode(t *testing.T) { var msg EthereumTxMsg raw := ethcmn.FromHex("E48080830186A0940000000000000000746573745F61646472657373808474657374808080") addr := ethcmn.BytesToAddress([]byte("test_address")) expectedMsg := NewEthereumTxMsg(0, addr, nil, 100000, nil, []byte("test")) err := rlp.Decode(bytes.NewReader(raw), &msg) require.NoError(t, err) require.Equal(t, expectedMsg.Data, msg.Data) } func TestMsgEthereumTxHash(t *testing.T) { addr := ethcmn.BytesToAddress([]byte("test_address")) msg := NewEthereumTxMsg(0, addr, nil, 100000, nil, []byte("test")) hash := msg.Hash() require.Equal(t, "E2AA2E68E7586AE9700F1D3D643330866B6AC2B6CA4C804F7C85ECB11D0B0B29", fmt.Sprintf("%X", hash)) } func TestMsgEthereumTxSig(t *testing.T) { chainID := big.NewInt(3) priv1, _ := crypto.GenerateKey() priv2, _ := crypto.GenerateKey() addr1 := ethcmn.BytesToAddress(priv1.PubKey().Address().Bytes()) addr2 := ethcmn.BytesToAddress(priv2.PubKey().Address().Bytes()) // require valid signature passes validation msg := NewEthereumTxMsg(0, addr1, nil, 100000, nil, []byte("test")) msg.Sign(chainID, priv1.ToECDSA()) signer, err := msg.VerifySig(chainID) require.NoError(t, err) require.Equal(t, addr1, signer) require.NotEqual(t, addr2, signer) // require invalid chain ID fail validation msg = NewEthereumTxMsg(0, addr1, nil, 100000, nil, []byte("test")) msg.Sign(chainID, priv1.ToECDSA()) signer, err = msg.VerifySig(big.NewInt(4)) require.Error(t, err) require.Equal(t, ethcmn.Address{}, signer) } func TestMsgEthereumTxAmino(t *testing.T) { addr := GenerateEthAddress() msg := NewEthereumTxMsg(0, addr, nil, 100000, nil, []byte("test")) raw, err := ModuleCdc.MarshalBinaryBare(msg) require.NoError(t, err) var msg2 EthereumTxMsg err = ModuleCdc.UnmarshalBinaryBare(raw, &msg2) require.NoError(t, err) require.Equal(t, msg.Data, msg2.Data) }