forked from cerc-io/laconicd-deprecated
fix: increase nonce in ante handler for contract creation tx (#809)
Closes: #808 Solution: - move nonce increment to ante handler - revert nonce increment in apply message build(deps): bump github.com/spf13/viper from 1.9.0 to 1.10.0 (#833) Bumps [github.com/spf13/viper](https://github.com/spf13/viper) from 1.9.0 to 1.10.0. - [Release notes](https://github.com/spf13/viper/releases) - [Commits](https://github.com/spf13/viper/compare/v1.9.0...v1.10.0) --- updated-dependencies: - dependency-name: github.com/spf13/viper dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> fix: remove unused code (#834) Co-authored-by: Marko Baricevic <markobaricevic3778@gmail.com> Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com> rm rm pkg Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com>
This commit is contained in:
co-authored by
dependabot[bot]
Marko Baricevic
Federico Kunze Küllmer
parent
514785bd89
commit
e437c4331d
+156
-75
@@ -1,6 +1,7 @@
|
||||
package evm_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"math/big"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -165,6 +166,12 @@ func (suite *EvmTestSuite) SetupTest() {
|
||||
suite.DoSetupTest(suite.T())
|
||||
}
|
||||
|
||||
func (suite *EvmTestSuite) SignTx(tx *types.MsgEthereumTx) {
|
||||
tx.From = suite.from.String()
|
||||
err := tx.Sign(suite.ethSigner, suite.signer)
|
||||
suite.Require().NoError(err)
|
||||
}
|
||||
|
||||
func TestEvmTestSuite(t *testing.T) {
|
||||
suite.Run(t, new(EvmTestSuite))
|
||||
}
|
||||
@@ -182,11 +189,7 @@ func (suite *EvmTestSuite) TestHandleMsgEthereumTx() {
|
||||
func() {
|
||||
to := common.BytesToAddress(suite.to)
|
||||
tx = types.NewTx(suite.chainID, 0, &to, big.NewInt(100), 10_000_000, big.NewInt(10000), nil, nil, nil, nil)
|
||||
tx.From = suite.from.String()
|
||||
|
||||
// sign transaction
|
||||
err := tx.Sign(suite.ethSigner, suite.signer)
|
||||
suite.Require().NoError(err)
|
||||
suite.SignTx(tx)
|
||||
},
|
||||
true,
|
||||
},
|
||||
@@ -194,10 +197,7 @@ func (suite *EvmTestSuite) TestHandleMsgEthereumTx() {
|
||||
"insufficient balance",
|
||||
func() {
|
||||
tx = types.NewTxContract(suite.chainID, 0, big.NewInt(100), 0, big.NewInt(10000), nil, nil, nil, nil)
|
||||
tx.From = suite.from.Hex()
|
||||
// sign transaction
|
||||
err := tx.Sign(suite.ethSigner, suite.signer)
|
||||
suite.Require().NoError(err)
|
||||
suite.SignTx(tx)
|
||||
},
|
||||
false,
|
||||
},
|
||||
@@ -269,10 +269,7 @@ func (suite *EvmTestSuite) TestHandlerLogs() {
|
||||
|
||||
bytecode := common.FromHex("0x6080604052348015600f57600080fd5b5060117f775a94827b8fd9b519d36cd827093c664f93347070a554f65e4a6f56cd73889860405160405180910390a2603580604b6000396000f3fe6080604052600080fdfea165627a7a723058206cab665f0f557620554bb45adf266708d2bd349b8a4314bdff205ee8440e3c240029")
|
||||
tx := types.NewTx(suite.chainID, 1, nil, big.NewInt(0), gasLimit, gasPrice, nil, nil, bytecode, nil)
|
||||
tx.From = suite.from.String()
|
||||
|
||||
err := tx.Sign(suite.ethSigner, suite.signer)
|
||||
suite.Require().NoError(err)
|
||||
suite.SignTx(tx)
|
||||
|
||||
result, err := suite.handler(suite.ctx, tx)
|
||||
suite.Require().NoError(err, "failed to handle eth tx msg")
|
||||
@@ -357,10 +354,7 @@ func (suite *EvmTestSuite) TestDeployAndCallContract() {
|
||||
|
||||
bytecode := common.FromHex("0x608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f342827c97908e5e2f71151c08502a66d44b6f758e3ac2f1de95f02eb95f0a73560405160405180910390a36102c4806100dc6000396000f3fe608060405234801561001057600080fd5b5060043610610053576000357c010000000000000000000000000000000000000000000000000000000090048063893d20e814610058578063a6f9dae1146100a2575b600080fd5b6100606100e6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100e4600480360360208110156100b857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061010f565b005b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146101d1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f43616c6c6572206973206e6f74206f776e65720000000000000000000000000081525060200191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f342827c97908e5e2f71151c08502a66d44b6f758e3ac2f1de95f02eb95f0a73560405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505056fea265627a7a72315820f397f2733a89198bc7fed0764083694c5b828791f39ebcbc9e414bccef14b48064736f6c63430005100032")
|
||||
tx := types.NewTx(suite.chainID, 1, nil, big.NewInt(0), gasLimit, gasPrice, nil, nil, bytecode, nil)
|
||||
tx.From = suite.from.String()
|
||||
|
||||
err := tx.Sign(suite.ethSigner, suite.signer)
|
||||
suite.Require().NoError(err)
|
||||
suite.SignTx(tx)
|
||||
|
||||
result, err := suite.handler(suite.ctx, tx)
|
||||
suite.Require().NoError(err, "failed to handle eth tx msg")
|
||||
@@ -379,10 +373,7 @@ func (suite *EvmTestSuite) TestDeployAndCallContract() {
|
||||
storeAddr := "0xa6f9dae10000000000000000000000006a82e4a67715c8412a9114fbd2cbaefbc8181424"
|
||||
bytecode = common.FromHex(storeAddr)
|
||||
tx = types.NewTx(suite.chainID, 2, &receiver, big.NewInt(0), gasLimit, gasPrice, nil, nil, bytecode, nil)
|
||||
tx.From = suite.from.String()
|
||||
|
||||
err = tx.Sign(suite.ethSigner, suite.signer)
|
||||
suite.Require().NoError(err)
|
||||
suite.SignTx(tx)
|
||||
|
||||
_, err = suite.handler(suite.ctx, tx)
|
||||
suite.Require().NoError(err, "failed to handle eth tx msg")
|
||||
@@ -394,9 +385,7 @@ func (suite *EvmTestSuite) TestDeployAndCallContract() {
|
||||
// query - getOwner
|
||||
bytecode = common.FromHex("0x893d20e8")
|
||||
tx = types.NewTx(suite.chainID, 2, &receiver, big.NewInt(0), gasLimit, gasPrice, nil, nil, bytecode, nil)
|
||||
tx.From = suite.from.String()
|
||||
err = tx.Sign(suite.ethSigner, suite.signer)
|
||||
suite.Require().NoError(err)
|
||||
suite.SignTx(tx)
|
||||
|
||||
_, err = suite.handler(suite.ctx, tx)
|
||||
suite.Require().NoError(err, "failed to handle eth tx msg")
|
||||
@@ -416,9 +405,7 @@ func (suite *EvmTestSuite) TestSendTransaction() {
|
||||
|
||||
// send simple value transfer with gasLimit=21000
|
||||
tx := types.NewTx(suite.chainID, 1, &common.Address{0x1}, big.NewInt(1), gasLimit, gasPrice, nil, nil, nil, nil)
|
||||
tx.From = suite.from.String()
|
||||
err := tx.Sign(suite.ethSigner, suite.signer)
|
||||
suite.Require().NoError(err)
|
||||
suite.SignTx(tx)
|
||||
|
||||
result, err := suite.handler(suite.ctx, tx)
|
||||
suite.Require().NoError(err)
|
||||
@@ -487,10 +474,7 @@ func (suite *EvmTestSuite) TestOutOfGasWhenDeployContract() {
|
||||
|
||||
bytecode := common.FromHex("0x608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f342827c97908e5e2f71151c08502a66d44b6f758e3ac2f1de95f02eb95f0a73560405160405180910390a36102c4806100dc6000396000f3fe608060405234801561001057600080fd5b5060043610610053576000357c010000000000000000000000000000000000000000000000000000000090048063893d20e814610058578063a6f9dae1146100a2575b600080fd5b6100606100e6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100e4600480360360208110156100b857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061010f565b005b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146101d1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f43616c6c6572206973206e6f74206f776e65720000000000000000000000000081525060200191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f342827c97908e5e2f71151c08502a66d44b6f758e3ac2f1de95f02eb95f0a73560405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505056fea265627a7a72315820f397f2733a89198bc7fed0764083694c5b828791f39ebcbc9e414bccef14b48064736f6c63430005100032")
|
||||
tx := types.NewTx(suite.chainID, 1, nil, big.NewInt(0), gasLimit, gasPrice, nil, nil, bytecode, nil)
|
||||
tx.From = suite.from.String()
|
||||
|
||||
err := tx.Sign(suite.ethSigner, suite.signer)
|
||||
suite.Require().NoError(err)
|
||||
suite.SignTx(tx)
|
||||
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
@@ -511,10 +495,7 @@ func (suite *EvmTestSuite) TestErrorWhenDeployContract() {
|
||||
bytecode := common.FromHex("0xa6f9dae10000000000000000000000006a82e4a67715c8412a9114fbd2cbaefbc8181424")
|
||||
|
||||
tx := types.NewTx(suite.chainID, 1, nil, big.NewInt(0), gasLimit, gasPrice, nil, nil, bytecode, nil)
|
||||
tx.From = suite.from.String()
|
||||
|
||||
err := tx.Sign(suite.ethSigner, suite.signer)
|
||||
suite.Require().NoError(err)
|
||||
suite.SignTx(tx)
|
||||
|
||||
result, _ := suite.handler(suite.ctx, tx)
|
||||
var res types.MsgEthereumTxResponse
|
||||
@@ -529,7 +510,7 @@ func (suite *EvmTestSuite) TestErrorWhenDeployContract() {
|
||||
func (suite *EvmTestSuite) deployERC20Contract() common.Address {
|
||||
k := suite.app.EvmKeeper
|
||||
nonce := k.GetNonce(suite.from)
|
||||
ctorArgs, err := types.ERC20Contract.ABI.Pack("", suite.from, big.NewInt(0))
|
||||
ctorArgs, err := types.ERC20Contract.ABI.Pack("", suite.from, big.NewInt(10000000000))
|
||||
suite.Require().NoError(err)
|
||||
msg := ethtypes.NewMessage(
|
||||
suite.from,
|
||||
@@ -550,55 +531,148 @@ func (suite *EvmTestSuite) deployERC20Contract() common.Address {
|
||||
return crypto.CreateAddress(suite.from, nonce)
|
||||
}
|
||||
|
||||
// TestGasRefundWhenReverted check that when transaction reverted, gas refund should still work.
|
||||
func (suite *EvmTestSuite) TestGasRefundWhenReverted() {
|
||||
suite.SetupTest()
|
||||
k := suite.app.EvmKeeper
|
||||
// TestERC20TransferReverted checks:
|
||||
// - when transaction reverted, gas refund works.
|
||||
// - when transaction reverted, nonce is still increased.
|
||||
func (suite *EvmTestSuite) TestERC20TransferReverted() {
|
||||
intrinsicGas := uint64(21572)
|
||||
// test different hooks scenarios
|
||||
testCases := []struct {
|
||||
msg string
|
||||
gasLimit uint64
|
||||
hooks types.EvmHooks
|
||||
expErr string
|
||||
}{
|
||||
{
|
||||
"no hooks",
|
||||
intrinsicGas, // enough for intrinsicGas, but not enough for execution
|
||||
nil,
|
||||
"out of gas",
|
||||
},
|
||||
{
|
||||
"success hooks",
|
||||
intrinsicGas, // enough for intrinsicGas, but not enough for execution
|
||||
&DummyHook{},
|
||||
"out of gas",
|
||||
},
|
||||
{
|
||||
"failure hooks",
|
||||
1000000, // enough gas limit, but hooks fails.
|
||||
&FailureHook{},
|
||||
"failed to execute post processing",
|
||||
},
|
||||
}
|
||||
|
||||
// the bug only reproduce when there are hooks
|
||||
k.SetHooks(&DummyHook{})
|
||||
for _, tc := range testCases {
|
||||
suite.Run(tc.msg, func() {
|
||||
suite.SetupTest()
|
||||
k := suite.app.EvmKeeper
|
||||
k.SetHooks(tc.hooks)
|
||||
|
||||
// add some fund to pay gas fee
|
||||
k.AddBalance(suite.from, big.NewInt(10000000000))
|
||||
// add some fund to pay gas fee
|
||||
k.AddBalance(suite.from, big.NewInt(10000000000))
|
||||
|
||||
contract := suite.deployERC20Contract()
|
||||
contract := suite.deployERC20Contract()
|
||||
|
||||
// the call will fail because no balance
|
||||
data, err := types.ERC20Contract.ABI.Pack("transfer", common.BigToAddress(big.NewInt(1)), big.NewInt(10))
|
||||
suite.Require().NoError(err)
|
||||
data, err := types.ERC20Contract.ABI.Pack("transfer", suite.from, big.NewInt(10))
|
||||
suite.Require().NoError(err)
|
||||
|
||||
tx := types.NewTx(
|
||||
suite.chainID,
|
||||
k.GetNonce(suite.from),
|
||||
&contract,
|
||||
big.NewInt(0),
|
||||
41000,
|
||||
big.NewInt(1),
|
||||
nil,
|
||||
nil,
|
||||
data,
|
||||
nil,
|
||||
)
|
||||
tx.From = suite.from.String()
|
||||
err = tx.Sign(suite.ethSigner, suite.signer)
|
||||
suite.Require().NoError(err)
|
||||
nonce := k.GetNonce(suite.from)
|
||||
tx := types.NewTx(
|
||||
suite.chainID,
|
||||
nonce,
|
||||
&contract,
|
||||
big.NewInt(0),
|
||||
tc.gasLimit,
|
||||
big.NewInt(1),
|
||||
nil,
|
||||
nil,
|
||||
data,
|
||||
nil,
|
||||
)
|
||||
suite.SignTx(tx)
|
||||
|
||||
before := k.GetBalance(suite.from)
|
||||
before := k.GetBalance(suite.from)
|
||||
|
||||
txData, err := types.UnpackTxData(tx.Data)
|
||||
suite.Require().NoError(err)
|
||||
_, err = k.DeductTxCostsFromUserBalance(suite.ctx, *tx, txData, "aphoton", true, true, true)
|
||||
suite.Require().NoError(err)
|
||||
txData, err := types.UnpackTxData(tx.Data)
|
||||
suite.Require().NoError(err)
|
||||
_, err = k.DeductTxCostsFromUserBalance(suite.ctx, *tx, txData, "aphoton", true, true, true)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
res, err := k.EthereumTx(sdk.WrapSDKContext(suite.ctx), tx)
|
||||
suite.Require().NoError(err)
|
||||
suite.Require().True(res.Failed())
|
||||
res, err := k.EthereumTx(sdk.WrapSDKContext(suite.ctx), tx)
|
||||
suite.Require().NoError(err)
|
||||
|
||||
after := k.GetBalance(suite.from)
|
||||
suite.Require().True(res.Failed())
|
||||
suite.Require().Equal(tc.expErr, res.VmError)
|
||||
|
||||
suite.Require().Equal(uint64(23861), res.GasUsed)
|
||||
// check gas refund works
|
||||
suite.Require().Equal(big.NewInt(23861), new(big.Int).Sub(before, after))
|
||||
after := k.GetBalance(suite.from)
|
||||
|
||||
if tc.expErr == "out of gas" {
|
||||
suite.Require().Equal(tc.gasLimit, res.GasUsed)
|
||||
} else {
|
||||
suite.Require().Greater(tc.gasLimit, res.GasUsed)
|
||||
}
|
||||
|
||||
// check gas refund works: only deducted fee for gas used, rather than gas limit.
|
||||
suite.Require().Equal(big.NewInt(int64(res.GasUsed)), new(big.Int).Sub(before, after))
|
||||
|
||||
// nonce should not be increased.
|
||||
suite.Require().Equal(nonce, k.GetNonce(suite.from))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *EvmTestSuite) TestContractDeploymentRevert() {
|
||||
intrinsicGas := uint64(134180)
|
||||
testCases := []struct {
|
||||
msg string
|
||||
gasLimit uint64
|
||||
hooks types.EvmHooks
|
||||
}{
|
||||
{
|
||||
"no hooks",
|
||||
intrinsicGas,
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"success hooks",
|
||||
intrinsicGas,
|
||||
&DummyHook{},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(tc.msg, func() {
|
||||
suite.SetupTest()
|
||||
k := suite.app.EvmKeeper
|
||||
|
||||
// test with different hooks scenarios
|
||||
k.SetHooks(tc.hooks)
|
||||
|
||||
nonce := k.GetNonce(suite.from)
|
||||
ctorArgs, err := types.ERC20Contract.ABI.Pack("", suite.from, big.NewInt(0))
|
||||
suite.Require().NoError(err)
|
||||
|
||||
tx := types.NewTx(
|
||||
nil,
|
||||
nonce,
|
||||
nil, // to
|
||||
nil, // amount
|
||||
tc.gasLimit,
|
||||
nil, nil, nil,
|
||||
append(types.ERC20Contract.Bin, ctorArgs...),
|
||||
nil,
|
||||
)
|
||||
suite.SignTx(tx)
|
||||
|
||||
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))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// DummyHook implements EvmHooks interface
|
||||
@@ -607,3 +681,10 @@ type DummyHook struct{}
|
||||
func (dh *DummyHook) PostTxProcessing(ctx sdk.Context, txHash common.Hash, logs []*ethtypes.Log) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// FailureHook implements EvmHooks interface
|
||||
type FailureHook struct{}
|
||||
|
||||
func (dh *FailureHook) PostTxProcessing(ctx sdk.Context, txHash common.Hash, logs []*ethtypes.Log) error {
|
||||
return errors.New("mock error")
|
||||
}
|
||||
|
||||
@@ -678,6 +678,8 @@ func (suite *KeeperTestSuite) TestTraceTx() {
|
||||
malleate: func() {
|
||||
txIndex = 1
|
||||
traceConfig = nil
|
||||
// increase nonce to avoid address collision
|
||||
suite.app.EvmKeeper.SetNonce(suite.address, suite.app.EvmKeeper.GetNonce(suite.address)+1)
|
||||
|
||||
contractAddr := suite.DeployTestContract(suite.T(), suite.address, sdk.NewIntWithDecimal(1000, 18).BigInt())
|
||||
suite.Commit()
|
||||
@@ -803,6 +805,8 @@ func (suite *KeeperTestSuite) TestTraceBlock() {
|
||||
msg: "tracer with multiple transactions",
|
||||
malleate: func() {
|
||||
traceConfig = nil
|
||||
// increase nonce to avoid address collision
|
||||
suite.app.EvmKeeper.SetNonce(suite.address, suite.app.EvmKeeper.GetNonce(suite.address)+1)
|
||||
contractAddr := suite.DeployTestContract(suite.T(), suite.address, sdk.NewIntWithDecimal(1000, 18).BigInt())
|
||||
suite.Commit()
|
||||
// create multiple transactions in the same block
|
||||
|
||||
@@ -343,7 +343,10 @@ func (k *Keeper) ApplyMessageWithConfig(msg core.Message, tracer vm.Tracer, comm
|
||||
}
|
||||
|
||||
if contractCreation {
|
||||
nonce := k.GetNonce(sender.Address())
|
||||
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)
|
||||
} else {
|
||||
ret, leftoverGas, vmErr = evm.Call(sender, *msg.To(), msg.Data(), leftoverGas, msg.Value())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user