Skip to content

Commit

Permalink
Merge branch 'main' into releases/v2.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
k-yang committed Jan 21, 2025
2 parents 63b2be4 + 0e3ab43 commit a58899e
Show file tree
Hide file tree
Showing 19 changed files with 465 additions and 33 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,18 @@ JSON encoding for the `EIP55Addr` struct was not following the Go conventions an
needed to include double quotes around the hexadecimal string.
- [#2156](https://github.com/NibiruChain/nibiru/pull/2156) - test(evm-e2e): add E2E test using the Nibiru Oracle's ChainLink impl
- [#2157](https://github.com/NibiruChain/nibiru/pull/2157) - fix(evm): Fix unit inconsistency related to AuthInfo.Fee and txData.Fee using effective fee
- [#2159](https://github.com/NibiruChain/nibiru/pull/2159) - chore(evm): Augment the Wasm msg handler so that wasm contracts cannot send MsgEthereumTx
- [#2160](https://github.com/NibiruChain/nibiru/pull/2160) - fix(evm-precompile): use bank.MsgServer Send in precompile IFunToken.bankMsgSend
- [#2161](https://github.com/NibiruChain/nibiru/pull/2161) - fix(evm): added tx logs events to the funtoken related txs
- [#2162](https://github.com/NibiruChain/nibiru/pull/2162) - test(testutil): try retrying for 'panic: pebbledb: closed'
- [#2167](https://github.com/NibiruChain/nibiru/pull/2167) - refactor(evm): removed blockGasUsed transient variable
- [#2168](https://github.com/NibiruChain/nibiru/pull/2168) - chore(evm-solidity): Move unrelated docs, gen-embeds, and add Solidity docs
- [#2165](https://github.com/NibiruChain/nibiru/pull/2165) - fix(evm): use Singleton StateDB pattern for EVM txs
- [#2169](https://github.com/NibiruChain/nibiru/pull/2169) - fix(evm): Better handling erc20 metadata
- [#2170](https://github.com/NibiruChain/nibiru/pull/2170) - chore: Remove redundant allowUnprotectedTxs
- [#2172](https://github.com/NibiruChain/nibiru/pull/2172) - chore: close iterator in IterateEpochInfo
- [#2173](https://github.com/NibiruChain/nibiru/pull/2173) - fix(evm): clear `StateDB` between calls

#### Nibiru EVM | Before Audit 2 - 2024-12-06

The codebase went through a third-party [Code4rena
Expand Down
7 changes: 6 additions & 1 deletion app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,11 @@ func init() {
}

// GetWasmOpts build wasm options
func GetWasmOpts(nibiru NibiruApp, appOpts servertypes.AppOptions) []wasmkeeper.Option {
func GetWasmOpts(
nibiru NibiruApp,
appOpts servertypes.AppOptions,
wasmMsgHandlerArgs wasmext.MsgHandlerArgs,
) []wasmkeeper.Option {
var wasmOpts []wasmkeeper.Option
if cast.ToBool(appOpts.Get("telemetry.enabled")) {
wasmOpts = append(wasmOpts, wasmkeeper.WithVMCacheMetrics(prometheus.DefaultRegisterer))
Expand All @@ -122,6 +126,7 @@ func GetWasmOpts(nibiru NibiruApp, appOpts servertypes.AppOptions) []wasmkeeper.
return append(wasmOpts, wasmext.NibiruWasmOptions(
nibiru.GRPCQueryRouter(),
nibiru.appCodec,
wasmMsgHandlerArgs,
)...)
}

Expand Down
3 changes: 1 addition & 2 deletions app/evmante/evmante_sigverify.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,8 @@ func (esvd EthSigVerificationDecorator) AnteHandle(
)
}

allowUnprotectedTxs := false
ethTx := msgEthTx.AsTransaction()
if !allowUnprotectedTxs && !ethTx.Protected() {
if !ethTx.Protected() {
return ctx, errors.Wrapf(
sdkerrors.ErrNotSupported,
"rejected unprotected Ethereum transaction. "+
Expand Down
24 changes: 18 additions & 6 deletions app/keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ import (
// Nibiru Custom Modules

"github.com/NibiruChain/nibiru/v2/app/keepers"
"github.com/NibiruChain/nibiru/v2/app/wasmext"
"github.com/NibiruChain/nibiru/v2/eth"
"github.com/NibiruChain/nibiru/v2/x/common"
"github.com/NibiruChain/nibiru/v2/x/devgas/v1"
Expand Down Expand Up @@ -451,25 +452,36 @@ func (app *NibiruApp) InitKeepers(
// For example, if there are bindings for the x/inflation module, then the app
// passed to GetWasmOpts must already have a non-nil InflationKeeper.
supportedFeatures := strings.Join(wasmdapp.AllCapabilities(), ",")

wmha := wasmext.MsgHandlerArgs{
Router: app.MsgServiceRouter(),
Ics4Wrapper: app.ibcFeeKeeper,
ChannelKeeper: app.ibcKeeper.ChannelKeeper,
CapabilityKeeper: app.ScopedWasmKeeper,
BankKeeper: app.BankKeeper,
Unpacker: appCodec,
PortSource: app.ibcTransferKeeper,
}
app.WasmMsgHandlerArgs = wmha
app.WasmKeeper = wasmkeeper.NewKeeper(
appCodec,
keys[wasmtypes.StoreKey],
app.AccountKeeper,
app.BankKeeper,
app.StakingKeeper,
distrkeeper.NewQuerier(app.DistrKeeper),
app.ibcFeeKeeper, // ISC4 Wrapper: fee IBC middleware
app.ibcKeeper.ChannelKeeper,
wmha.Ics4Wrapper, // ISC4 Wrapper: fee IBC middleware
wmha.ChannelKeeper,
&app.ibcKeeper.PortKeeper,
app.ScopedWasmKeeper,
app.ibcTransferKeeper,
app.MsgServiceRouter(),
wmha.CapabilityKeeper,
wmha.PortSource,
wmha.Router,
app.GRPCQueryRouter(),
wasmDir,
wasmConfig,
supportedFeatures,
govModuleAddr,
GetWasmOpts(*app, appOpts)...,
GetWasmOpts(*app, appOpts, wmha)...,
)

// DevGas uses WasmKeeper
Expand Down
5 changes: 4 additions & 1 deletion app/keepers/all_keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
// ---------------------------------------------------------------
// Nibiru Custom Modules

"github.com/NibiruChain/nibiru/v2/app/wasmext"
devgaskeeper "github.com/NibiruChain/nibiru/v2/x/devgas/v1/keeper"
epochskeeper "github.com/NibiruChain/nibiru/v2/x/epochs/keeper"
evmkeeper "github.com/NibiruChain/nibiru/v2/x/evm/keeper"
Expand Down Expand Up @@ -66,6 +67,8 @@ type PublicKeepers struct {
EvmKeeper *evmkeeper.Keeper

// WASM keepers
WasmKeeper wasmkeeper.Keeper
WasmKeeper wasmkeeper.Keeper
WasmMsgHandlerArgs wasmext.MsgHandlerArgs

ScopedWasmKeeper capabilitykeeper.ScopedKeeper
}
4 changes: 2 additions & 2 deletions app/wasmext/stargate_query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package wasmext_test
import (
"fmt"
"strings"
"testing"

"github.com/cosmos/gogoproto/proto"
"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -36,7 +35,8 @@ Given only the `PB_MSG.PACKAGE` and the `PB_MSG.NAME` of either the query
request or response, we should know the `QueryRequest::Stargate.path`
deterministically.
*/
func TestWasmAcceptedStargateQueries(t *testing.T) {
func (s *Suite) TestWasmAcceptedStargateQueries() {
t := s.T()
t.Log("stargateQueryPaths: Add nibiru query paths from GRPC service descriptions")
queryServiceDescriptions := []grpc.ServiceDesc{
epochs.GrpcQueryServiceDesc(),
Expand Down
116 changes: 115 additions & 1 deletion app/wasmext/wasm.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
package wasmext

import (
"github.com/NibiruChain/nibiru/v2/x/evm"

"cosmossdk.io/errors"
wasmkeeper "github.com/CosmWasm/wasmd/x/wasm/keeper"
wasm "github.com/CosmWasm/wasmd/x/wasm/types"
wasmvmtypes "github.com/CosmWasm/wasmvm/types"
"github.com/cosmos/cosmos-sdk/baseapp"
"github.com/cosmos/cosmos-sdk/codec"
sdkcodec "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)

// NibiruWasmOptions: Wasm Options are extension points to instantiate the Wasm
// keeper with non-default values
func NibiruWasmOptions(
grpcQueryRouter *baseapp.GRPCQueryRouter,
appCodec codec.Codec,
msgHandlerArgs MsgHandlerArgs,
) []wasmkeeper.Option {
wasmQueryOption := wasmkeeper.WithQueryPlugins(&wasmkeeper.QueryPlugins{
Stargate: wasmkeeper.AcceptListStargateQuerier(
Expand All @@ -20,5 +29,110 @@ func NibiruWasmOptions(
),
})

return []wasmkeeper.Option{wasmQueryOption}
wasmMsgHandlerOption := wasmkeeper.WithMessageHandler(WasmMessageHandler(msgHandlerArgs))

return []wasmkeeper.Option{
wasmQueryOption,
wasmMsgHandlerOption,
}
}

func (h SDKMessageHandler) handleSdkMessage(ctx sdk.Context, contractAddr sdk.Address, msg sdk.Msg) (*sdk.Result, error) {
if err := msg.ValidateBasic(); err != nil {
return nil, err
}

// make sure this account can send it
for _, acct := range msg.GetSigners() {
if !acct.Equals(contractAddr) {
return nil, errors.Wrap(sdkerrors.ErrUnauthorized, "contract doesn't have permission")
}
}

msgTypeUrl := sdk.MsgTypeURL(msg)
if msgTypeUrl == sdk.MsgTypeURL(new(evm.MsgEthereumTx)) {
return nil, errors.Wrap(sdkerrors.ErrUnauthorized, "Wasm VM to EVM call pattern is not yet supported")
}

// find the handler and execute it
if handler := h.router.Handler(msg); handler != nil {
// ADR 031 request type routing
msgResult, err := handler(ctx, msg)
return msgResult, err
}
// legacy sdk.Msg routing
// Assuming that the app developer has migrated all their Msgs to
// proto messages and has registered all `Msg services`, then this
// path should never be called, because all those Msgs should be
// registered within the `msgServiceRouter` already.
return nil, errors.Wrapf(sdkerrors.ErrUnknownRequest, "can't route message %+v", msg)
}

type MsgHandlerArgs struct {
Router MessageRouter
Ics4Wrapper wasm.ICS4Wrapper
ChannelKeeper wasm.ChannelKeeper
CapabilityKeeper wasm.CapabilityKeeper
BankKeeper wasm.Burner
Unpacker sdkcodec.AnyUnpacker
PortSource wasm.ICS20TransferPortSource
}

// SDKMessageHandler can handles messages that can be encoded into sdk.Message types and routed.
type SDKMessageHandler struct {
router MessageRouter
encoders msgEncoder
}

// MessageRouter ADR 031 request type routing
type MessageRouter interface {
Handler(msg sdk.Msg) baseapp.MsgServiceHandler
}

// msgEncoder is an extension point to customize encodings
type msgEncoder interface {
// Encode converts wasmvm message to n cosmos message types
Encode(ctx sdk.Context, contractAddr sdk.AccAddress, contractIBCPortID string, msg wasmvmtypes.CosmosMsg) ([]sdk.Msg, error)
}

// WasmMessageHandler is a replacement constructor for
// [wasmkeeper.NewDefaultMessageHandler] inside of [wasmkeeper.NewKeeper].
func WasmMessageHandler(
args MsgHandlerArgs,
) wasmkeeper.Messenger {
encoders := wasmkeeper.DefaultEncoders(args.Unpacker, args.PortSource)
return wasmkeeper.NewMessageHandlerChain(
NewSDKMessageHandler(args.Router, encoders),
wasmkeeper.NewIBCRawPacketHandler(args.Ics4Wrapper, args.ChannelKeeper, args.CapabilityKeeper),
wasmkeeper.NewBurnCoinMessageHandler(args.BankKeeper),
)
}

func NewSDKMessageHandler(router MessageRouter, encoders msgEncoder) SDKMessageHandler {
return SDKMessageHandler{
router: router,
encoders: encoders,
}
}

func (h SDKMessageHandler) DispatchMsg(ctx sdk.Context, contractAddr sdk.AccAddress, contractIBCPortID string, msg wasmvmtypes.CosmosMsg) (events []sdk.Event, data [][]byte, err error) {
sdkMsgs, err := h.encoders.Encode(ctx, contractAddr, contractIBCPortID, msg)
if err != nil {
return nil, nil, err
}
for _, sdkMsg := range sdkMsgs {
res, err := h.handleSdkMessage(ctx, contractAddr, sdkMsg)
if err != nil {
return nil, nil, err
}
// append data
data = append(data, res.Data)
// append events
sdkEvents := make([]sdk.Event, len(res.Events))
for i := range res.Events {
sdkEvents[i] = sdk.Event(res.Events[i])
}
events = append(events, sdkEvents...)
}
return
}
98 changes: 98 additions & 0 deletions app/wasmext/wasmext_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package wasmext_test

import (
"math/big"
"testing"

wasmvm "github.com/CosmWasm/wasmvm/types"
sdkcodec "github.com/cosmos/cosmos-sdk/codec/types"
sdk "github.com/cosmos/cosmos-sdk/types"
bank "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/stretchr/testify/suite"

"github.com/NibiruChain/nibiru/v2/app/wasmext"
"github.com/NibiruChain/nibiru/v2/x/common/testutil/testapp"
"github.com/NibiruChain/nibiru/v2/x/evm"
"github.com/NibiruChain/nibiru/v2/x/evm/evmtest"
)

type Suite struct {
suite.Suite
}

func TestWasmExtSuite(t *testing.T) {
suite.Run(t, new(Suite))
}

// WasmVM to EVM call pattern is not yet supported. This test verifies the
// Nibiru's [wasmkeeper.Option] function as expected.
func (s *Suite) TestEvmFilter() {
deps := evmtest.NewTestDeps()
// wk := wasmkeeper.NewDefaultPermissionKeeper(deps.App.WasmKeeper)
wasmMsgHandler := wasmext.WasmMessageHandler(deps.App.WasmMsgHandlerArgs)

s.T().Log("Create a valid Ethereum tx msg")

to := evmtest.NewEthPrivAcc()
ethTxMsg, err := evmtest.TxTransferWei{
Deps: &deps,
To: to.EthAddr,
AmountWei: evm.NativeToWei(big.NewInt(420)),
}.Build()
s.NoError(err)

s.T().Log("Validate Eth tx msg proto encoding as wasmvm.StargateMsg")
wasmContractAddr := deps.Sender.NibiruAddr
protoValueBz, err := deps.EncCfg.Codec.Marshal(ethTxMsg)
s.Require().NoError(err, "expect ethTxMsg to proto marshal", protoValueBz)

_, ok := deps.EncCfg.Codec.(sdkcodec.AnyUnpacker)
s.Require().True(ok, "codec must be an AnyUnpacker")

pbAny, err := sdkcodec.NewAnyWithValue(ethTxMsg)
s.NoError(err)
pbAnyBz, err := pbAny.Marshal()
s.NoError(err, pbAnyBz)

var sdkMsg sdk.Msg
err = deps.EncCfg.Codec.UnpackAny(pbAny, &sdkMsg)
s.Require().NoError(err)
s.Equal("/eth.evm.v1.MsgEthereumTx", sdk.MsgTypeURL(sdkMsg))

s.T().Log("Dispatch the Eth tx msg from Wasm (unsuccessfully)")
_, _, err = wasmMsgHandler.DispatchMsg(
deps.Ctx,
wasmContractAddr,
"ibcport-unused",
wasmvm.CosmosMsg{
Stargate: &wasmvm.StargateMsg{
TypeURL: sdk.MsgTypeURL(ethTxMsg),
Value: protoValueBz,
},
},
)
s.Require().ErrorContains(err, "Wasm VM to EVM call pattern is not yet supported")

coins := sdk.NewCoins(sdk.NewInt64Coin(evm.EVMBankDenom, 420)) // arbitrary constant
err = testapp.FundAccount(deps.App.BankKeeper, deps.Ctx, deps.Sender.NibiruAddr, coins)
s.NoError(err)
txMsg := &bank.MsgSend{
FromAddress: deps.Sender.NibiruAddr.String(),
ToAddress: evmtest.NewEthPrivAcc().NibiruAddr.String(),
Amount: []sdk.Coin{sdk.NewInt64Coin(evm.EVMBankDenom, 20)},
}
protoValueBz, err = deps.EncCfg.Codec.Marshal(txMsg)
s.NoError(err)
_, _, err = wasmMsgHandler.DispatchMsg(
deps.Ctx,
wasmContractAddr,
"ibcport-unused",
wasmvm.CosmosMsg{
Stargate: &wasmvm.StargateMsg{
TypeURL: sdk.MsgTypeURL(txMsg),
Value: protoValueBz,
},
},
)
s.Require().NoError(err)
}
1 change: 1 addition & 0 deletions x/epochs/keeper/epoch.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ func (k Keeper) IterateEpochInfo(
iterate := k.Epochs.Iterate(ctx, &collections.Range[string]{})
i := int64(0)

defer iterate.Close()
for ; iterate.Valid(); iterate.Next() {
epoch := iterate.Value()
stop := fn(i, epoch)
Expand Down
Loading

0 comments on commit a58899e

Please sign in to comment.