diff --git a/x/cctp/keeper/msg_server_receive_message.go b/x/cctp/keeper/msg_server_receive_message.go index 5803446..b55a1c3 100644 --- a/x/cctp/keeper/msg_server_receive_message.go +++ b/x/cctp/keeper/msg_server_receive_message.go @@ -119,6 +119,14 @@ func (k msgServer) ReceiveMessage(goCtx context.Context, msg *types.MsgReceiveMe return nil, sdkerrors.Wrap(types.ErrReceiveMessage, "corresponding noble mint token not found") } + remoteTokenMessenger, found := k.GetRemoteTokenMessenger(ctx, message.SourceDomain) + if !found { + return nil, sdkerrors.Wrapf(types.ErrReceiveMessage, "could not retrieve remote token messenger for domain %d", message.SourceDomain) + } + if !bytes.Equal(message.Sender, remoteTokenMessenger.Address) { + return nil, sdkerrors.Wrap(types.ErrReceiveMessage, "message sender is not the remote token messenger") + } + // get mint recipient as noble address bech32Prefix := sdk.GetConfig().GetBech32AccountAddrPrefix() mintRecipient, err := sdk.Bech32ifyAddressBytes(bech32Prefix, burnMessage.MintRecipient[12:]) diff --git a/x/cctp/keeper/msg_server_receive_message_test.go b/x/cctp/keeper/msg_server_receive_message_test.go index f7a22ef..b05d3a8 100644 --- a/x/cctp/keeper/msg_server_receive_message_test.go +++ b/x/cctp/keeper/msg_server_receive_message_test.go @@ -90,6 +90,11 @@ func TestReceiveMessageHappyPath(t *testing.T) { } testkeeper.SetSignatureThreshold(ctx, types.SignatureThreshold{Amount: signatureThreshold}) + testkeeper.SetRemoteTokenMessenger(ctx, types.RemoteTokenMessenger{ + DomainId: message.SourceDomain, + Address: message.Sender, + }) + msg := types.MsgReceiveMessage{ From: "random address", Message: messageBytes, @@ -101,6 +106,121 @@ func TestReceiveMessageHappyPath(t *testing.T) { require.True(t, resp.Success) } +func TestReceiveMessageWithoutTokenMessenger(t *testing.T) { + testkeeper, ctx := keepertest.CctpKeeper(t) + server := keeper.NewMsgServerImpl(testkeeper) + + burnMessage := types.BurnMessage{ + Version: 0, + BurnToken: []byte("02345678901234567890123456789012"), + MintRecipient: []byte("message sender567890123456789012"), + Amount: math.NewInt(9876), + MessageSender: []byte("message sender567890123456789012"), + } + + tokenPair := types.TokenPair{ + RemoteDomain: 0, + RemoteToken: burnMessage.BurnToken, + LocalToken: string(crypto.Keccak256([]byte("uusdc"))), + } + testkeeper.SetTokenPair(ctx, tokenPair) + + burnMessageBytes, err := burnMessage.Bytes() + require.Nil(t, err) + + message := types.Message{ + Version: 0, + SourceDomain: 0, + DestinationDomain: 4, + Nonce: 0, + Sender: []byte("01234567890123456789012345678912"), + Recipient: types.PaddedModuleAddress, + DestinationCaller: make([]byte, types.DestinationCallerLen), + MessageBody: burnMessageBytes, + } + messageBytes, err := message.Bytes() + require.Nil(t, err) + + // generate attestation, set attesters, signature threshold + signatureThreshold := uint32(2) + privKeys := generateNPrivateKeys(int(signatureThreshold)) + attesters := getAttestersFromPrivateKeys(privKeys) + attestation := generateAttestation(messageBytes, privKeys) + for _, attester := range attesters { + testkeeper.SetAttester(ctx, attester) + } + testkeeper.SetSignatureThreshold(ctx, types.SignatureThreshold{Amount: signatureThreshold}) + + msg := types.MsgReceiveMessage{ + From: "random address", + Message: messageBytes, + Attestation: attestation, + } + + _, err = server.ReceiveMessage(sdk.WrapSDKContext(ctx), &msg) + require.ErrorContains(t, err, "could not retrieve remote token messenger") +} + +func TestReceiveMessageInvalidTokenMessenger(t *testing.T) { + testkeeper, ctx := keepertest.CctpKeeper(t) + server := keeper.NewMsgServerImpl(testkeeper) + + burnMessage := types.BurnMessage{ + Version: 0, + BurnToken: []byte("02345678901234567890123456789012"), + MintRecipient: []byte("message sender567890123456789012"), + Amount: math.NewInt(9876), + MessageSender: []byte("message sender567890123456789012"), + } + + tokenPair := types.TokenPair{ + RemoteDomain: 0, + RemoteToken: burnMessage.BurnToken, + LocalToken: string(crypto.Keccak256([]byte("uusdc"))), + } + testkeeper.SetTokenPair(ctx, tokenPair) + + burnMessageBytes, err := burnMessage.Bytes() + require.Nil(t, err) + + message := types.Message{ + Version: 0, + SourceDomain: 0, + DestinationDomain: 4, + Nonce: 0, + Sender: []byte("01234567890123456789012345678912"), + Recipient: types.PaddedModuleAddress, + DestinationCaller: make([]byte, types.DestinationCallerLen), + MessageBody: burnMessageBytes, + } + messageBytes, err := message.Bytes() + require.Nil(t, err) + + // generate attestation, set attesters, signature threshold + signatureThreshold := uint32(2) + privKeys := generateNPrivateKeys(int(signatureThreshold)) + attesters := getAttestersFromPrivateKeys(privKeys) + attestation := generateAttestation(messageBytes, privKeys) + for _, attester := range attesters { + testkeeper.SetAttester(ctx, attester) + } + testkeeper.SetSignatureThreshold(ctx, types.SignatureThreshold{Amount: signatureThreshold}) + + testkeeper.SetRemoteTokenMessenger(ctx, types.RemoteTokenMessenger{ + DomainId: message.SourceDomain, + Address: []byte("12345678901234567890123456789123"), + }) + + msg := types.MsgReceiveMessage{ + From: "random address", + Message: messageBytes, + Attestation: attestation, + } + + _, err = server.ReceiveMessage(sdk.WrapSDKContext(ctx), &msg) + require.ErrorContains(t, err, "message sender is not the remote token messenger") +} + func TestReceiveMessageWithDestinationCallerHappyPath(t *testing.T) { testkeeper, ctx := keepertest.CctpKeeper(t) server := keeper.NewMsgServerImpl(testkeeper) @@ -148,6 +268,11 @@ func TestReceiveMessageWithDestinationCallerHappyPath(t *testing.T) { } testkeeper.SetSignatureThreshold(ctx, types.SignatureThreshold{Amount: signatureThreshold}) + testkeeper.SetRemoteTokenMessenger(ctx, types.RemoteTokenMessenger{ + DomainId: message.SourceDomain, + Address: message.Sender, + }) + msg := types.MsgReceiveMessage{ From: destinationCaller.Address, Message: messageBytes, @@ -750,6 +875,11 @@ func TestReceiveMessageMintingFails(t *testing.T) { } testkeeper.SetSignatureThreshold(ctx, types.SignatureThreshold{Amount: signatureThreshold}) + testkeeper.SetRemoteTokenMessenger(ctx, types.RemoteTokenMessenger{ + DomainId: message.SourceDomain, + Address: message.Sender, + }) + msg := types.MsgReceiveMessage{ From: "random address", Message: messageBytes, @@ -805,6 +935,11 @@ func TestReceiveMessageInvalidPrefixForMintRecipient(t *testing.T) { } testkeeper.SetSignatureThreshold(ctx, types.SignatureThreshold{Amount: signatureThreshold}) + testkeeper.SetRemoteTokenMessenger(ctx, types.RemoteTokenMessenger{ + DomainId: message.SourceDomain, + Address: message.Sender, + }) + msg := types.MsgReceiveMessage{ From: "random address", Message: messageBytes,