diff --git a/CHANGELOG.md b/CHANGELOG.md index 769b4f51..afdf8af4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,6 +43,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ - (feemarket) [tharsis#822](https://github.com/tharsis/ethermint/pull/822) Update EIP1559 base fee in `BeginBlock`. - (evm) [tharsis#817](https://github.com/tharsis/ethermint/pull/817) Use `effectiveGasPrice` in ante handler, add `effectiveGasPrice` to tx receipt. - (evm) [tharsis#808](https://github.com/tharsis/ethermint/issues/808) increase nonce in ante handler for contract creation transaction. +- (evm) [tharsis#851](https://github.com/tharsis/ethermint/pull/851) fix contract address used in EVM, this issue is caused by [tharsis#808](https://github.com/tharsis/ethermint/issues/808). - (evm) [tharsis#N/A]() reject invalid `MsgEthereumTx` wrapping tx - (evm) [tharsis#N/A]() Fix SelfDestruct opcode by deleting account code and state diff --git a/tests/rpc/rpc_test.go b/tests/rpc/rpc_test.go index 4d020f52..483c10fa 100644 --- a/tests/rpc/rpc_test.go +++ b/tests/rpc/rpc_test.go @@ -26,6 +26,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" ethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto" ) const ( @@ -634,18 +635,21 @@ func deployTestContract(t *testing.T) (hexutil.Bytes, map[string]interface{}) { } func TestEth_GetTransactionReceipt_ContractDeployment(t *testing.T) { - hash, _ := deployTestContract(t) + nonce := getNonce(t) + _, receipt := deployTestContract(t) - param := []string{hash.String()} - rpcRes := call(t, "eth_getTransactionReceipt", param) - - receipt := make(map[string]interface{}) - err := json.Unmarshal(rpcRes.Result, &receipt) + addrBz, err := hexutil.Decode(receipt["contractAddress"].(string)) require.NoError(t, err) - require.Equal(t, "0x1", receipt["status"].(string)) - require.NotEqual(t, common.Address{}.String(), receipt["contractAddress"].(string)) - require.NotNil(t, receipt["logs"]) + addr := common.BytesToAddress(addrBz) + require.Equal(t, crypto.CreateAddress(common.BytesToAddress(from), uint64(nonce)), addr) + require.Greater(t, len(receipt["logs"].([]interface{})), 0) + + rpcRes := call(t, "eth_getCode", []string{addr.Hex(), "latest"}) + var code hexutil.Bytes + err = code.UnmarshalJSON(rpcRes.Result) + require.NoError(t, err) + require.NotEmpty(t, code) } func getTransactionReceipt(t *testing.T, hash hexutil.Bytes) map[string]interface{} { diff --git a/x/evm/handler_test.go b/x/evm/handler_test.go index a64388ea..480ea06f 100644 --- a/x/evm/handler_test.go +++ b/x/evm/handler_test.go @@ -665,12 +665,15 @@ func (suite *EvmTestSuite) TestContractDeploymentRevert() { ) suite.SignTx(tx) + // simulate nonce increment in ante handler + k.SetNonce(suite.from, nonce+1) + rsp, err := k.EthereumTx(sdk.WrapSDKContext(suite.ctx), tx) suite.Require().NoError(err) suite.Require().True(rsp.Failed()) - // nonce don't increase, it's increased in ante handler. - suite.Require().Equal(nonce, k.GetNonce(suite.from)) + // nonce don't change + suite.Require().Equal(nonce+1, k.GetNonce(suite.from)) }) } } diff --git a/x/evm/keeper/keeper_test.go b/x/evm/keeper/keeper_test.go index beddeb1c..c60c6198 100644 --- a/x/evm/keeper/keeper_test.go +++ b/x/evm/keeper/keeper_test.go @@ -208,10 +208,13 @@ func (suite *KeeperTestSuite) DeployTestContract(t require.TestingT, owner commo ctorArgs, err := types.ERC20Contract.ABI.Pack("", owner, supply) require.NoError(t, err) + nonce := suite.app.EvmKeeper.GetNonce(suite.address) + data := append(types.ERC20Contract.Bin, ctorArgs...) args, err := json.Marshal(&types.TransactionArgs{ - From: &suite.address, - Data: (*hexutil.Bytes)(&data), + From: &suite.address, + Data: (*hexutil.Bytes)(&data), + Nonce: (*hexutil.Uint64)(&nonce), }) require.NoError(t, err) @@ -221,8 +224,6 @@ func (suite *KeeperTestSuite) DeployTestContract(t require.TestingT, owner commo }) require.NoError(t, err) - nonce := suite.app.EvmKeeper.GetNonce(suite.address) - var erc20DeployTx *types.MsgEthereumTx if suite.dynamicTxFee { erc20DeployTx = types.NewTxContract( diff --git a/x/evm/keeper/state_transition.go b/x/evm/keeper/state_transition.go index 93065087..b7c977d9 100644 --- a/x/evm/keeper/state_transition.go +++ b/x/evm/keeper/state_transition.go @@ -343,10 +343,12 @@ func (k *Keeper) ApplyMessageWithConfig(msg core.Message, tracer vm.Tracer, comm } if contractCreation { - nonce := k.GetNonce(sender.Address()) + // take over the nonce management from evm: + // - reset sender's nonce to msg.Nonce() before calling evm. + // - increase sender's nonce by one no matter the result. + k.SetNonce(sender.Address(), msg.Nonce()) ret, _, leftoverGas, vmErr = evm.Create(sender, msg.Data(), leftoverGas, msg.Value()) - // revert nonce increment, because it's increased in ante handler - k.SetNonce(sender.Address(), nonce) + k.SetNonce(sender.Address(), msg.Nonce()+1) } else { ret, leftoverGas, vmErr = evm.Call(sender, *msg.To(), msg.Data(), leftoverGas, msg.Value()) } diff --git a/x/evm/keeper/state_transition_test.go b/x/evm/keeper/state_transition_test.go index c5d07e39..eea8ff3b 100644 --- a/x/evm/keeper/state_transition_test.go +++ b/x/evm/keeper/state_transition_test.go @@ -511,3 +511,9 @@ func (suite *KeeperTestSuite) TestEVMConfig() { suite.Require().Equal(suite.address, cfg.CoinBase) suite.Require().Equal(types.DefaultParams().ChainConfig.EthereumConfig(big.NewInt(9000)), cfg.ChainConfig) } + +func (suite *KeeperTestSuite) TestContractDeployment() { + suite.SetupTest() + contractAddress := suite.DeployTestContract(suite.T(), suite.address, big.NewInt(10000000000000)) + suite.Require().Greater(suite.app.EvmKeeper.GetCodeSize(contractAddress), 0) +} diff --git a/x/evm/types/tx_args.go b/x/evm/types/tx_args.go index 24e16f60..525a008f 100644 --- a/x/evm/types/tx_args.go +++ b/x/evm/types/tx_args.go @@ -215,7 +215,13 @@ func (args *TransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int) (e if args.AccessList != nil { accessList = *args.AccessList } - msg := ethtypes.NewMessage(addr, args.To, 0, value, gas, gasPrice, gasFeeCap, gasTipCap, data, accessList, true) + + nonce := uint64(0) + if args.Nonce != nil { + nonce = uint64(*args.Nonce) + } + + msg := ethtypes.NewMessage(addr, args.To, nonce, value, gas, gasPrice, gasFeeCap, gasTipCap, data, accessList, true) return msg, nil }