Skip to content

Commit

Permalink
feat(nexus): support CallContractWithToken from the nexus gateway con…
Browse files Browse the repository at this point in the history
…tract (#2175)
  • Loading branch information
fish-sammy authored Sep 10, 2024
1 parent d18dcd6 commit 1848c6b
Show file tree
Hide file tree
Showing 7 changed files with 264 additions and 142 deletions.
1 change: 1 addition & 0 deletions docs/proto/proto-docs.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions proto/axelar/nexus/exported/v1beta1/types.proto
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ message WasmMessage {
uint64 source_tx_index = 7 [ (gogoproto.jsontag) = "source_tx_index" ];
bytes sender = 8 [ (gogoproto.casttype) =
"github.com/cosmos/cosmos-sdk/types.AccAddress" ];
string id = 9 [
(gogoproto.customname) = "ID"
];
string id = 9 [ (gogoproto.customname) = "ID" ];
cosmos.base.v1beta1.Coin token = 10
[ (gogoproto.nullable) = true, (gogoproto.customname) = "Asset" ];
}
220 changes: 137 additions & 83 deletions x/nexus/exported/types.pb.go

Large diffs are not rendered by default.

10 changes: 7 additions & 3 deletions x/nexus/keeper/msg_dispatcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,16 +69,20 @@ func (m Messenger) routeMsg(ctx sdk.Context, msg exported.WasmMessage) error {
}

// If message already exists, then this is a no-op to avoid causing an error from reverting the whole message batch being routed in Amplifier
if _, ok := m.Nexus.GetMessage(ctx, msg.ID); ok {
if _, ok := m.GetMessage(ctx, msg.ID); ok {
return nil
}

if msg.Asset != nil && !m.IsAssetRegistered(ctx, destinationChain, msg.Asset.Denom) {
return fmt.Errorf("asset %s is not registered on chain %s", msg.Asset.Denom, destinationChain.Name)
}

sourceChain := exported.Chain{Name: msg.SourceChain, SupportsForeignAssets: false, KeyType: tss.None, Module: wasmtypes.ModuleName}
sender := exported.CrossChainAddress{Chain: sourceChain, Address: msg.SourceAddress}
recipient := exported.CrossChainAddress{Chain: destinationChain, Address: msg.DestinationAddress}

nexusMsg := exported.NewGeneralMessage(fmt.Sprintf("%s-%s", msg.SourceChain, msg.ID), sender, recipient, msg.PayloadHash, msg.SourceTxID, msg.SourceTxIndex, nil)
if err := m.Nexus.SetNewMessage(ctx, nexusMsg); err != nil {
nexusMsg := exported.NewGeneralMessage(fmt.Sprintf("%s-%s", msg.SourceChain, msg.ID), sender, recipient, msg.PayloadHash, msg.SourceTxID, msg.SourceTxIndex, msg.Asset)
if err := m.SetNewMessage(ctx, nexusMsg); err != nil {
return err
}

Expand Down
67 changes: 59 additions & 8 deletions x/nexus/keeper/msg_dispatcher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,65 @@ func TestMessenger_DispatchMsg(t *testing.T) {
Run(t)

givenMessenger.
When("the msg is encoded correctly and the gateway is set correctly", func() {
When("the msg is encoded correctly with token and the gateway is set correctly", func() {
msg = wasmvmtypes.CosmosMsg{
Custom: []byte("{\"source_chain\":\"sourcechain\",\"source_address\":\"0xb860\",\"destination_chain\":\"Axelarnet\",\"destination_address\":\"axelarvaloper1zh9wrak6ke4n6fclj5e8yk397czv430ygs5jz7\",\"payload_hash\":[187,155,85,102,194,244,135,104,99,51,62,72,31,70,152,53,1,84,37,159,254,98,38,226,131,177,108,225,138,100,188,241],\"source_tx_id\":[187,155,85,102,194,244,135,104,99,51,62,72,31,70,152,53,1,84,37,159,254,98,38,226,131,177,108,225,138,100,188,241],\"source_tx_index\":100, \"id\": \"0x73657e3da2e404f474218fe2789462585d7f6060741bd312c862378cf67ca981-1\"}"),
Custom: []byte("{\"source_chain\":\"sourcechain\",\"source_address\":\"0xb860\",\"destination_chain\":\"Axelarnet\",\"destination_address\":\"axelarvaloper1zh9wrak6ke4n6fclj5e8yk397czv430ygs5jz7\",\"payload_hash\":[187,155,85,102,194,244,135,104,99,51,62,72,31,70,152,53,1,84,37,159,254,98,38,226,131,177,108,225,138,100,188,241],\"source_tx_id\":[187,155,85,102,194,244,135,104,99,51,62,72,31,70,152,53,1,84,37,159,254,98,38,226,131,177,108,225,138,100,188,241],\"source_tx_index\":100, \"id\": \"0x73657e3da2e404f474218fe2789462585d7f6060741bd312c862378cf67ca981-1\",\"token\":{\"denom\":\"test\",\"amount\":\"100\"}}"),
}

nexus.GetParamsFunc = func(_ sdk.Context) types.Params {
params := types.DefaultParams()
params.Gateway = contractAddr

return params
}
nexus.GetChainFunc = func(_ sdk.Context, chain exported.ChainName) (exported.Chain, bool) {
switch chain {
case evm.Ethereum.Name:
return evm.Ethereum, true
case axelarnet.Axelarnet.Name:
return axelarnet.Axelarnet, true
default:
return exported.Chain{}, false
}
}
nexus.GetMessageFunc = func(_ sdk.Context, _ string) (exported.GeneralMessage, bool) {
return exported.GeneralMessage{}, false
}
}).
Branch(
When("the asset is not registered for the destination chain", func() {
nexus.IsAssetRegisteredFunc = func(_ sdk.Context, _ exported.Chain, _ string) bool { return false }
}).
Then("should return error", func(t *testing.T) {
_, _, err := messenger.DispatchMsg(ctx, contractAddr, "", msg)

assert.ErrorContains(t, err, "is not registered on chain")
assert.False(t, errors.Is(err, wasmtypes.ErrUnknownMsg))
}),

When("the asset is registered for the destination chain", func() {
nexus.IsAssetRegisteredFunc = func(_ sdk.Context, _ exported.Chain, _ string) bool { return true }
}).
Then("should set new message", func(t *testing.T) {
nexus.SetNewMessageFunc = func(_ sdk.Context, msg exported.GeneralMessage) error {
return msg.ValidateBasic()
}
nexus.RouteMessageFunc = func(ctx sdk.Context, id string, _ ...exported.RoutingContext) error { return nil }

_, _, err := messenger.DispatchMsg(ctx, contractAddr, "", msg)

assert.NoError(t, err)
assert.Len(t, nexus.SetNewMessageCalls(), 1)
assert.Len(t, nexus.RouteMessageCalls(), 1)
assert.NotNil(t, nexus.SetNewMessageCalls()[0].Msg.Asset)
}),
).
Run(t)

givenMessenger.
When("the msg is encoded correctly without token and the gateway is set correctly", func() {
msg = wasmvmtypes.CosmosMsg{
Custom: []byte("{\"source_chain\":\"sourcechain\",\"source_address\":\"0xb860\",\"destination_chain\":\"Axelarnet\",\"destination_address\":\"axelarvaloper1zh9wrak6ke4n6fclj5e8yk397czv430ygs5jz7\",\"payload_hash\":[187,155,85,102,194,244,135,104,99,51,62,72,31,70,152,53,1,84,37,159,254,98,38,226,131,177,108,225,138,100,188,241],\"source_tx_id\":[187,155,85,102,194,244,135,104,99,51,62,72,31,70,152,53,1,84,37,159,254,98,38,226,131,177,108,225,138,100,188,241],\"source_tx_index\":100, \"id\": \"0x73657e3da2e404f474218fe2789462585d7f6060741bd312c862378cf67ca981-1\",\"token\":null}"),
}

nexus.GetParamsFunc = func(_ sdk.Context) types.Params {
Expand Down Expand Up @@ -124,9 +180,6 @@ func TestMessenger_DispatchMsg(t *testing.T) {

}).
When("the msg fails to be set", func() {
nexus.GenerateMessageIDFunc = func(_ sdk.Context) (string, []byte, uint64) {
return "1", []byte("1"), 1
}
nexus.GetMessageFunc = func(_ sdk.Context, _ string) (exported.GeneralMessage, bool) {
return exported.GeneralMessage{}, false
}
Expand Down Expand Up @@ -165,9 +218,6 @@ func TestMessenger_DispatchMsg(t *testing.T) {
}
}).
When("the msg succeeds to be set", func() {
nexus.GenerateMessageIDFunc = func(_ sdk.Context) (string, []byte, uint64) {
return "1", []byte("1"), 1
}
nexus.GetMessageFunc = func(_ sdk.Context, _ string) (exported.GeneralMessage, bool) {
return exported.GeneralMessage{}, false
}
Expand Down Expand Up @@ -231,6 +281,7 @@ func TestMessenger_DispatchMsg(t *testing.T) {
),
).
Run(t)

}

func TestMessenger_DispatchMsg_WasmConnectionNotActivated(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion x/nexus/types/expected_keepers.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,12 @@ type Nexus interface {
GetFeeInfo(ctx sdk.Context, chain exported.Chain, asset string) exported.FeeInfo
SetRateLimit(ctx sdk.Context, chainName exported.ChainName, limit sdk.Coin, window time.Duration) error
RateLimitTransfer(ctx sdk.Context, chain exported.ChainName, asset sdk.Coin, direction exported.TransferDirection) error
GenerateMessageID(ctx sdk.Context) (string, []byte, uint64)
SetNewMessage(ctx sdk.Context, msg exported.GeneralMessage) error
GetMessage(ctx sdk.Context, id string) (exported.GeneralMessage, bool)
SetMessageExecuted(ctx sdk.Context, id string) error
RouteMessage(ctx sdk.Context, id string, routingCtx ...exported.RoutingContext) error
DequeueRouteMessage(ctx sdk.Context) (exported.GeneralMessage, bool)
IsAssetRegistered(ctx sdk.Context, chain exported.Chain, denom string) bool
}

// Snapshotter provides functionality to the snapshot module
Expand Down
100 changes: 56 additions & 44 deletions x/nexus/types/mock/expected_keepers.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 1848c6b

Please sign in to comment.