diff --git a/app/app.go b/app/app.go index ff8b613d10..48e0bdfbdf 100644 --- a/app/app.go +++ b/app/app.go @@ -2,6 +2,7 @@ package app import ( "fmt" + "github.com/kava-labs/kava/precompile/statedb_modifier" "io" stdlog "log" "net/http" @@ -87,7 +88,6 @@ import ( "github.com/evmos/ethermint/x/evm" evmkeeper "github.com/evmos/ethermint/x/evm/keeper" evmtypes "github.com/evmos/ethermint/x/evm/types" - "github.com/evmos/ethermint/x/evm/vm/geth" "github.com/evmos/ethermint/x/feemarket" feemarketkeeper "github.com/evmos/ethermint/x/feemarket/keeper" feemarkettypes "github.com/evmos/ethermint/x/feemarket/types" @@ -546,12 +546,13 @@ func NewApp( evmBankKeeper := evmutilkeeper.NewEvmBankKeeper(app.evmutilKeeper, app.bankKeeper, app.accountKeeper) evmutilWrapper := newEvmutilWrapper(app.evmutilKeeper) + evmConstructor := statedb_modifier.GetEVMConstructor(app.transferKeeper, evmutilWrapper) app.evmKeeper = evmkeeper.NewKeeper( appCodec, keys[evmtypes.StoreKey], tkeys[evmtypes.TransientKey], govAuthorityAddr, - app.accountKeeper, evmBankKeeper, app.stakingKeeper, app.feeMarketKeeper, app.transferKeeper, evmutilWrapper, + app.accountKeeper, evmBankKeeper, app.stakingKeeper, app.feeMarketKeeper, nil, // precompiled contracts - geth.NewEVM, + evmConstructor, options.EVMTrace, evmSubspace, ) diff --git a/go.mod b/go.mod index 1ce60940ef..073783b950 100644 --- a/go.mod +++ b/go.mod @@ -217,7 +217,7 @@ replace ( // Use ethermint fork that respects min-gas-price with NoBaseFee true and london enabled, and includes eip712 support // github.com/evmos/ethermint => /Users/yevheniishcherbina/go/src/github.com/Kava-Labs/ethermint - github.com/evmos/ethermint => github.com/Kava-Labs/ethermint v0.21.1-0.20240313145313-afdacb85073d + github.com/evmos/ethermint => github.com/Kava-Labs/ethermint v0.21.1-0.20240315182528-457e857ecb1e // See https://github.com/cosmos/cosmos-sdk/pull/10401, https://github.com/cosmos/cosmos-sdk/commit/0592ba6158cd0bf49d894be1cef4faeec59e8320 github.com/gin-gonic/gin => github.com/gin-gonic/gin v1.7.0 diff --git a/go.sum b/go.sum index caaa068453..31fd1bacc6 100644 --- a/go.sum +++ b/go.sum @@ -214,8 +214,8 @@ github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d/go.mod h1: github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DataDog/zstd v1.5.0/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= -github.com/Kava-Labs/ethermint v0.21.1-0.20240313145313-afdacb85073d h1:QXMb2a2fG3eElbfzKlRpyf6CL4hBooTFdVHFeTe99M0= -github.com/Kava-Labs/ethermint v0.21.1-0.20240313145313-afdacb85073d/go.mod h1:UsM4MWfvNJbgt3Jpj1VtbWskAERiFpTBUt1ZfezdkfE= +github.com/Kava-Labs/ethermint v0.21.1-0.20240315182528-457e857ecb1e h1:LyohbUkwAR8Wd1PcnolmHjOt86NCdJvwpvJ++/CrPks= +github.com/Kava-Labs/ethermint v0.21.1-0.20240315182528-457e857ecb1e/go.mod h1:UsM4MWfvNJbgt3Jpj1VtbWskAERiFpTBUt1ZfezdkfE= github.com/Kava-Labs/go-ethereum v1.10.27-0.20240308184817-2a5324cb7ce7 h1:upwbx4E9Bt1YdlTmfSpPvPNPFT1x4vcwc+E1bho7FH8= github.com/Kava-Labs/go-ethereum v1.10.27-0.20240308184817-2a5324cb7ce7/go.mod h1:/6CsT5Ceen2WPLI/oCA3xMcZ5sWMF/D46SjM/ayY0Oo= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= diff --git a/precompile/contracts/ibc/token_transfer.go b/precompile/contracts/ibc/token_transfer.go index b4e28a3aa6..4139e144e8 100644 --- a/precompile/contracts/ibc/token_transfer.go +++ b/precompile/contracts/ibc/token_transfer.go @@ -10,7 +10,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/precompile/contract" "github.com/ethereum/go-ethereum/vmerrs" - ethermint_statedb "github.com/evmos/ethermint/x/evm/statedb" + "github.com/kava-labs/kava/precompile/statedb_modifier" "math/big" ) @@ -43,13 +43,17 @@ func tokenTransfer( return nil, remainingGas, err } - stateDB, ok := accessibleState.GetStateDB().(*ethermint_statedb.StateDB) + stateDB, ok := accessibleState.GetStateDB().(*statedb_modifier.ModifiedStateDB) if !ok { return nil, remainingGas, ErrUnsupportedStateDB } + dbContext, err := stateDB.Context() + if err != nil { + return nil, remainingGas, err + } err = stateDB.ConvertERC20ToCoin( - stateDB.Context(), + dbContext, caller.String(), sdk.AccAddress(caller[:]).String(), tokenTransferInput.kavaERC20Address, @@ -59,7 +63,7 @@ func tokenTransfer( return nil, remainingGas, ErrUnsupportedStateDB } - resp, err := stateDB.IBCTransfer(stateDB.Context(), &ibctransfertypes.MsgTransfer{ + resp, err := stateDB.IBCTransfer(dbContext, &ibctransfertypes.MsgTransfer{ SourcePort: tokenTransferInput.sourcePort, SourceChannel: tokenTransferInput.sourceChannel, Token: sdk.Coin{ diff --git a/precompile/contracts/ibc/transfer.go b/precompile/contracts/ibc/transfer.go index 06886b5439..7801d56c62 100644 --- a/precompile/contracts/ibc/transfer.go +++ b/precompile/contracts/ibc/transfer.go @@ -10,7 +10,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/precompile/contract" "github.com/ethereum/go-ethereum/vmerrs" - ethermint_statedb "github.com/evmos/ethermint/x/evm/statedb" + "github.com/kava-labs/kava/precompile/statedb_modifier" "math/big" ) @@ -43,12 +43,16 @@ func transfer( return nil, remainingGas, err } - stateDB, ok := accessibleState.GetStateDB().(*ethermint_statedb.StateDB) + stateDB, ok := accessibleState.GetStateDB().(*statedb_modifier.ModifiedStateDB) if !ok { return nil, remainingGas, ErrUnsupportedStateDB } - resp, err := stateDB.IBCTransfer(stateDB.Context(), &ibctransfertypes.MsgTransfer{ + dbContext, err := stateDB.Context() + if err != nil { + return nil, remainingGas, err + } + resp, err := stateDB.IBCTransfer(dbContext, &ibctransfertypes.MsgTransfer{ SourcePort: transferInput.sourcePort, SourceChannel: transferInput.sourceChannel, Token: sdk.Coin{ diff --git a/precompile/contracts/ibc/transfer_kava.go b/precompile/contracts/ibc/transfer_kava.go index 38231e6b89..218d2a7996 100644 --- a/precompile/contracts/ibc/transfer_kava.go +++ b/precompile/contracts/ibc/transfer_kava.go @@ -10,7 +10,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/precompile/contract" "github.com/ethereum/go-ethereum/vmerrs" - ethermint_statedb "github.com/evmos/ethermint/x/evm/statedb" + "github.com/kava-labs/kava/precompile/statedb_modifier" "math/big" ) @@ -43,12 +43,16 @@ func transferKava( return nil, remainingGas, err } - stateDB, ok := accessibleState.GetStateDB().(*ethermint_statedb.StateDB) + stateDB, ok := accessibleState.GetStateDB().(*statedb_modifier.ModifiedStateDB) if !ok { return nil, remainingGas, ErrUnsupportedStateDB } - resp, err := stateDB.IBCTransfer(stateDB.Context(), &ibctransfertypes.MsgTransfer{ + dbContext, err := stateDB.Context() + if err != nil { + return nil, remainingGas, err + } + resp, err := stateDB.IBCTransfer(dbContext, &ibctransfertypes.MsgTransfer{ SourcePort: transferKavaInput.sourcePort, SourceChannel: transferKavaInput.sourceChannel, Token: sdk.Coin{ diff --git a/precompile/statedb_modifier/statedb.go b/precompile/statedb_modifier/statedb.go new file mode 100644 index 0000000000..5c7a6f1187 --- /dev/null +++ b/precompile/statedb_modifier/statedb.go @@ -0,0 +1,89 @@ +package statedb_modifier + +import ( + "context" + "errors" + "github.com/ethereum/go-ethereum/params" + evm "github.com/evmos/ethermint/x/evm/vm" + "github.com/evmos/ethermint/x/evm/vm/geth" + + sdk "github.com/cosmos/cosmos-sdk/types" + ibctransfertypes "github.com/cosmos/ibc-go/v6/modules/apps/transfer/types" + "github.com/ethereum/go-ethereum/core/vm" + ethermint_statedb "github.com/evmos/ethermint/x/evm/statedb" +) + +var ErrUnsupportedStateDB = errors.New("unsupported statedb") + +type IBCTransferKeeper interface { + Transfer(goCtx context.Context, msg *ibctransfertypes.MsgTransfer) (*ibctransfertypes.MsgTransferResponse, error) +} + +type EvmutilKeeper interface { + ConvertERC20ToCoin( + goCtx context.Context, + initiator string, + receiver string, + kavaERC20Address string, + amount sdk.Int, + ) error +} + +type ModifiedStateDB struct { + vm.StateDB + ibcTransferKeeper IBCTransferKeeper + evmutilKeeper EvmutilKeeper +} + +func NewModifiedStateDB(stateDB vm.StateDB, ibcTransferKeeper IBCTransferKeeper, evmutilKeeper EvmutilKeeper) *ModifiedStateDB { + return &ModifiedStateDB{ + StateDB: stateDB, + ibcTransferKeeper: ibcTransferKeeper, + evmutilKeeper: evmutilKeeper, + } +} + +func GetEVMConstructor( + ibcTransferKeeper IBCTransferKeeper, + evmutilKeeper EvmutilKeeper, +) evm.Constructor { + return func( + blockCtx vm.BlockContext, + txCtx vm.TxContext, + stateDB vm.StateDB, + chainConfig *params.ChainConfig, + config vm.Config, + customPrecompiles evm.PrecompiledContracts, + ) evm.EVM { + customStateDB := NewModifiedStateDB(stateDB, ibcTransferKeeper, evmutilKeeper) + return geth.NewEVM(blockCtx, txCtx, customStateDB, chainConfig, config, customPrecompiles) + } +} + +func (s *ModifiedStateDB) Context() (context.Context, error) { + stateDB, ok := s.StateDB.(*ethermint_statedb.StateDB) + if !ok { + return nil, ErrUnsupportedStateDB + } + + return stateDB.Context(), nil +} + +func (s *ModifiedStateDB) IBCTransfer(goCtx context.Context, msg *ibctransfertypes.MsgTransfer) (*ibctransfertypes.MsgTransferResponse, error) { + resp, err := s.ibcTransferKeeper.Transfer(goCtx, msg) + if err != nil { + return nil, err + } + + return resp, nil +} + +func (s *ModifiedStateDB) ConvertERC20ToCoin( + goCtx context.Context, + initiator string, + receiver string, + kavaERC20Address string, + amount sdk.Int, +) error { + return s.evmutilKeeper.ConvertERC20ToCoin(goCtx, initiator, receiver, kavaERC20Address, amount) +}