Skip to content

Commit

Permalink
feat(nexus): add the wasm message route
Browse files Browse the repository at this point in the history
  • Loading branch information
fish-sammy committed Nov 9, 2023
1 parent 4929397 commit be784b9
Show file tree
Hide file tree
Showing 9 changed files with 1,017 additions and 4 deletions.
8 changes: 6 additions & 2 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,6 @@ func NewAxelarApp(
messageRouter := nexusTypes.NewMessageRouter().
AddRoute(evmTypes.ModuleName, evmKeeper.NewMessageRoute()).
AddRoute(axelarnetTypes.ModuleName, axelarnetKeeper.NewMessageRoute(getKeeper[axelarnetKeeper.Keeper](keepers), getKeeper[axelarnetKeeper.IBCKeeper](keepers), getKeeper[feegrantkeeper.Keeper](keepers), axelarbankkeeper.NewBankKeeper(getKeeper[bankkeeper.BaseKeeper](keepers)), getKeeper[nexusKeeper.Keeper](keepers), getKeeper[authkeeper.AccountKeeper](keepers)))
getKeeperAsRef[nexusKeeper.Keeper](keepers).SetMessageRouter(messageRouter)

axelarnetModule := axelarnet.NewAppModule(getKeeper[axelarnetKeeper.Keeper](keepers), getKeeper[nexusKeeper.Keeper](keepers), axelarbankkeeper.NewBankKeeper(getKeeper[bankkeeper.BaseKeeper](keepers)), getKeeper[authkeeper.AccountKeeper](keepers), getKeeper[axelarnetKeeper.IBCKeeper](keepers), transferStack, rateLimiter, logger)

Expand Down Expand Up @@ -355,10 +354,15 @@ func NewAxelarApp(
ibcRouter.AddRoute(wasm.ModuleName, wasmStack)

// set the contract keeper for the Ics20WasmHooks
wasmHooks.ContractKeeper = wasmkeeper.NewDefaultPermissionKeeper(wasmK)
contractKeeper := wasmkeeper.NewDefaultPermissionKeeper(wasmK)
wasmHooks.ContractKeeper = contractKeeper
setKeeper(keepers, wasmK)

messageRouter.AddRoute(wasm.ModuleName, nexusKeeper.NewMessageRoute(getKeeperAsRef[nexusKeeper.Keeper](keepers), getKeeper[authkeeper.AccountKeeper](keepers), contractKeeper))
}

getKeeperAsRef[nexusKeeper.Keeper](keepers).SetMessageRouter(messageRouter)

// Finalize the IBC router
getKeeperAsRef[ibckeeper.Keeper](keepers).SetRouter(ibcRouter)

Expand Down
1 change: 1 addition & 0 deletions x/axelarnet/keeper/message_route.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
// for IBC execution
const gasCost = storetypes.Gas(1000000)

// NewMessageRoute creates a new message route
func NewMessageRoute(
keeper Keeper,
ibcK types.IBCKeeper,
Expand Down
1 change: 1 addition & 0 deletions x/evm/keeper/message_route.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
// for commands approval
const gasCost = storetypes.Gas(10000000)

// NewMessageRoute creates a new message route
func NewMessageRoute() nexus.MessageRoute {
return func(ctx sdk.Context, _ nexus.RoutingContext, _ nexus.GeneralMessage) error {
ctx.GasMeter().ConsumeGas(gasCost, "execute-message")
Expand Down
13 changes: 13 additions & 0 deletions x/nexus/exported/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -336,3 +336,16 @@ func (m GeneralMessage) Type() MessageType {

return TypeGeneralMessageWithToken
}

// FromGeneralMessage returns a WasmMessage from a GeneralMessage
func FromGeneralMessage(msg GeneralMessage) WasmMessage {
return WasmMessage{
SourceChain: msg.GetSourceChain(),
SourceAddress: msg.GetSourceAddress(),
DestinationChain: msg.GetDestinationChain(),
DestinationAddress: msg.GetDestinationAddress(),
PayloadHash: msg.PayloadHash,
SourceTxID: msg.SourceTxID,
SourceTxIndex: msg.SourceTxIndex,
}
}
2 changes: 1 addition & 1 deletion x/nexus/keeper/msg_dispatcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func (m Messenger) DispatchMsg(ctx sdk.Context, contractAddr sdk.AccAddress, _ s

gateway := m.GetParams(ctx).Gateway

if len(gateway) == 0 {
if gateway.Empty() {
return nil, nil, fmt.Errorf("gateway is not set")
}

Expand Down
36 changes: 36 additions & 0 deletions x/nexus/keeper/wasm_message_route.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package keeper

import (
"encoding/json"
"fmt"

sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/axelarnetwork/axelar-core/x/nexus/exported"
types "github.com/axelarnetwork/axelar-core/x/nexus/types"
)

// NewMessageRoute creates a new message route
func NewMessageRoute(nexus types.Nexus, account types.AccountKeeper, wasm types.WasmKeeper) exported.MessageRoute {
return func(ctx sdk.Context, _ exported.RoutingContext, msg exported.GeneralMessage) error {
if msg.Asset != nil {
return fmt.Errorf("asset is not supported")
}

gateway := nexus.GetParams(ctx).Gateway
if gateway.Empty() {
return fmt.Errorf("gateway is not set")
}

bz, err := json.Marshal(exported.FromGeneralMessage(msg))
if err != nil {
return nil
}

if _, err := wasm.Execute(ctx, gateway, account.GetModuleAddress(types.ModuleName), bz, sdk.NewCoins()); err != nil {
return err
}

return nil
}
}
96 changes: 96 additions & 0 deletions x/nexus/keeper/wasm_message_route_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package keeper_test

import (
"encoding/json"
"testing"

"github.com/axelarnetwork/axelar-core/testutils/fake"
"github.com/axelarnetwork/axelar-core/testutils/rand"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/assert"
"github.com/tendermint/tendermint/libs/log"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"

nexus "github.com/axelarnetwork/axelar-core/x/nexus/exported"
"github.com/axelarnetwork/axelar-core/x/nexus/keeper"
"github.com/axelarnetwork/axelar-core/x/nexus/types"
"github.com/axelarnetwork/axelar-core/x/nexus/types/mock"
. "github.com/axelarnetwork/utils/test"
)

func TestNewMessageRoute(t *testing.T) {
var (
ctx sdk.Context
route nexus.MessageRoute
msg nexus.GeneralMessage

nexusK *mock.NexusMock
accountK *mock.AccountKeeperMock
wasmK *mock.WasmKeeperMock
gateway sdk.AccAddress
)

givenMessageRoute := Given("the message route", func() {
ctx = sdk.NewContext(fake.NewMultiStore(), tmproto.Header{}, false, log.TestingLogger())

nexusK = &mock.NexusMock{}
accountK = &mock.AccountKeeperMock{}
wasmK = &mock.WasmKeeperMock{}

route = keeper.NewMessageRoute(nexusK, accountK, wasmK)
})

givenMessageRoute.
When("the gateway is not set", func() {
nexusK.GetParamsFunc = func(ctx sdk.Context) types.Params { return types.DefaultParams() }
}).
Then("should return error", func(t *testing.T) {
assert.ErrorContains(t, route(ctx, nexus.RoutingContext{}, msg), "gateway is not set")
}).
Run(t)

givenMessageRoute.
When("the gateway is set", func() {
nexusK.GetParamsFunc = func(ctx sdk.Context) types.Params {
gateway = rand.AccAddr()

params := types.DefaultParams()
params.Gateway = gateway

return params
}
}).
Branch(
When("the message has an asset", func() {
msg = randMsg(nexus.Processing, true)
}).
Then("should return error", func(t *testing.T) {
assert.ErrorContains(t, route(ctx, nexus.RoutingContext{}, msg), "asset is not supported")
}),

When("the message has no asset", func() {
msg = randMsg(nexus.Processing)
}).
Then("should execute the wasm message", func(t *testing.T) {
moduleAddr := rand.AccAddr()
accountK.GetModuleAddressFunc = func(_ string) sdk.AccAddress { return moduleAddr }

wasmK.ExecuteFunc = func(_ sdk.Context, _, _ sdk.AccAddress, _ []byte, _ sdk.Coins) ([]byte, error) {
return nil, nil
}

assert.NoError(t, route(ctx, nexus.RoutingContext{}, msg))

assert.Len(t, wasmK.ExecuteCalls(), 1)
assert.Equal(t, wasmK.ExecuteCalls()[0].ContractAddress, gateway)
assert.Equal(t, wasmK.ExecuteCalls()[0].Caller, moduleAddr)
assert.Empty(t, wasmK.ExecuteCalls()[0].Coins)

var actual nexus.WasmMessage
assert.NoError(t, json.Unmarshal(wasmK.ExecuteCalls()[0].Msg, &actual))
assert.Equal(t, nexus.FromGeneralMessage(msg), actual)
}),
).
Run(t)

}
13 changes: 12 additions & 1 deletion x/nexus/types/expected_keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package types
import (
"time"

wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types"
sdk "github.com/cosmos/cosmos-sdk/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
"github.com/tendermint/tendermint/libs/log"
Expand All @@ -13,7 +14,7 @@ import (
snapshot "github.com/axelarnetwork/axelar-core/x/snapshot/exported"
)

//go:generate moq -out ./mock/expected_keepers.go -pkg mock . Nexus Snapshotter AxelarnetKeeper RewardKeeper SlashingKeeper
//go:generate moq -out ./mock/expected_keepers.go -pkg mock . Nexus Snapshotter AxelarnetKeeper RewardKeeper SlashingKeeper WasmKeeper AccountKeeper

// Nexus provides functionality to manage cross-chain transfers
type Nexus interface {
Expand Down Expand Up @@ -73,3 +74,13 @@ type RewardKeeper interface {
type SlashingKeeper interface {
IsTombstoned(ctx sdk.Context, consAddr sdk.ConsAddress) bool
}

// WasmKeeper provides functionality to manage wasm contracts
type WasmKeeper interface {
wasmtypes.ContractOpsKeeper
}

// AccountKeeper provides functionality to get account keeper
type AccountKeeper interface {
GetModuleAddress(moduleName string) sdk.AccAddress
}
Loading

0 comments on commit be784b9

Please sign in to comment.