diff --git a/go.mod b/go.mod index 70b0be5eb..cea90f719 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,7 @@ require ( github.com/spf13/afero v1.2.2 // indirect github.com/spf13/cobra v1.0.0 github.com/spf13/viper v1.7.0 - github.com/status-im/keycard-go v0.0.0-20190424133014-d95853db0f48 // indirect + github.com/status-im/keycard-go v0.0.0-20190424133014-d95853db0f48 github.com/stretchr/testify v1.6.1 github.com/tendermint/tendermint v0.33.4 github.com/tendermint/tm-db v0.5.1 diff --git a/x/evm/handler_test.go b/x/evm/handler_test.go index 9d1feae65..79e781ce9 100644 --- a/x/evm/handler_test.go +++ b/x/evm/handler_test.go @@ -4,9 +4,12 @@ import ( "crypto/ecdsa" "fmt" "math/big" + "strings" "testing" "time" + "github.com/status-im/keycard-go/hexutils" + "github.com/stretchr/testify/suite" "github.com/ethereum/go-ethereum/common" @@ -291,6 +294,112 @@ func (suite *EvmTestSuite) TestQueryTxLogs() { suite.Require().Equal(txLogs.Logs[0], resultData.Logs[0]) } +func (suite *EvmTestSuite) TestDeployAndCallContract() { + // Test contract: + //http://remix.ethereum.org/#optimize=false&evmVersion=istanbul&version=soljson-v0.5.15+commit.6a57276f.js + //2_Owner.sol + // + //pragma solidity >=0.4.22 <0.7.0; + // + ///** + // * @title Owner + // * @dev Set & change owner + // */ + //contract Owner { + // + // address private owner; + // + // // event for EVM logging + // event OwnerSet(address indexed oldOwner, address indexed newOwner); + // + // // modifier to check if caller is owner + // modifier isOwner() { + // // If the first argument of 'require' evaluates to 'false', execution terminates and all + // // changes to the state and to Ether balances are reverted. + // // This used to consume all gas in old EVM versions, but not anymore. + // // It is often a good idea to use 'require' to check if functions are called correctly. + // // As a second argument, you can also provide an explanation about what went wrong. + // require(msg.sender == owner, "Caller is not owner"); + // _; + //} + // + // /** + // * @dev Set contract deployer as owner + // */ + // constructor() public { + // owner = msg.sender; // 'msg.sender' is sender of current call, contract deployer for a constructor + // emit OwnerSet(address(0), owner); + //} + // + // /** + // * @dev Change owner + // * @param newOwner address of new owner + // */ + // function changeOwner(address newOwner) public isOwner { + // emit OwnerSet(owner, newOwner); + // owner = newOwner; + //} + // + // /** + // * @dev Return owner address + // * @return address of owner + // */ + // function getOwner() external view returns (address) { + // return owner; + //} + //} + + // Deploy contract - Owner.sol + gasLimit := uint64(100000000) + gasPrice := big.NewInt(10000) + + priv, err := crypto.GenerateKey() + suite.Require().NoError(err, "failed to create key") + + bytecode := common.FromHex("0x608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f342827c97908e5e2f71151c08502a66d44b6f758e3ac2f1de95f02eb95f0a73560405160405180910390a36102c4806100dc6000396000f3fe608060405234801561001057600080fd5b5060043610610053576000357c010000000000000000000000000000000000000000000000000000000090048063893d20e814610058578063a6f9dae1146100a2575b600080fd5b6100606100e6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100e4600480360360208110156100b857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061010f565b005b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146101d1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f43616c6c6572206973206e6f74206f776e65720000000000000000000000000081525060200191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f342827c97908e5e2f71151c08502a66d44b6f758e3ac2f1de95f02eb95f0a73560405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505056fea265627a7a72315820f397f2733a89198bc7fed0764083694c5b828791f39ebcbc9e414bccef14b48064736f6c63430005100032") + tx := types.NewMsgEthereumTx(1, nil, big.NewInt(0), gasLimit, gasPrice, bytecode) + tx.Sign(big.NewInt(3), priv.ToECDSA()) + suite.Require().NoError(err) + + result, err := suite.handler(suite.ctx, tx) + suite.Require().NoError(err, "failed to handle eth tx msg") + + resultData, err := types.DecodeResultData(result.Data) + suite.Require().NoError(err, "failed to decode result data") + + // store - changeOwner + gasLimit = uint64(100000000000) + gasPrice = big.NewInt(100) + receiver := common.HexToAddress(resultData.ContractAddress.String()) + + storeAddr := "0xa6f9dae10000000000000000000000006a82e4a67715c8412a9114fbd2cbaefbc8181424" + bytecode = common.FromHex(storeAddr) + tx = types.NewMsgEthereumTx(2, &receiver, big.NewInt(0), gasLimit, gasPrice, bytecode) + tx.Sign(big.NewInt(3), priv.ToECDSA()) + suite.Require().NoError(err) + + result, err = suite.handler(suite.ctx, tx) + suite.Require().NoError(err, "failed to handle eth tx msg") + + resultData, err = types.DecodeResultData(result.Data) + suite.Require().NoError(err, "failed to decode result data") + + // query - getOwner + bytecode = common.FromHex("0x893d20e8") + tx = types.NewMsgEthereumTx(2, &receiver, big.NewInt(0), gasLimit, gasPrice, bytecode) + tx.Sign(big.NewInt(3), priv.ToECDSA()) + suite.Require().NoError(err) + + result, err = suite.handler(suite.ctx, tx) + suite.Require().NoError(err, "failed to handle eth tx msg") + + resultData, err = types.DecodeResultData(result.Data) + suite.Require().NoError(err, "failed to decode result data") + + getAddr := strings.ToLower(hexutils.BytesToHex(resultData.Ret)) + suite.Require().Equal(true, strings.HasSuffix(storeAddr, getAddr), "Fail to query the address") +} + func (suite *EvmTestSuite) TestSendTransaction() { gasLimit := uint64(21000) gasPrice := big.NewInt(0x55ae82600)