GMP Message Verification

Axelar enables messages to be sent between two different blockchains. When a message is sent from a source chain to a destination chain, Axelar verifies that the incoming message on the destination chain is the authentic message that was sent on the source chain, having passed through the Axelar blockchain and confirmed by Axelar’s validators.

Ethereum Virtual Machine (EVM)

On EVM based chains such as Ethereum or Avalanche, connections to Axelar are initiated via the Gateway Contract. The Gateway is used on both the source and the destination chain. On the source chain it is used to trigger the interchain transaction, on the destination chain it is triggered by the Axelar Executable to validate an incoming GMP message.

Validate Contract Call

The validateContractCall() function is called on every inbound GMP message to ensure that the incoming message is authentic. This function receives the relevant parameters of a GMP call including;

  1. CommandId: A unique id for interchain messages
  2. SourceChain: The source chain of the GMP message
  3. SourceAddress: The source address of the contract call
  4. PayloadHash: A hash of the GMP message that was sent with the call

Using this information it confirms that the inbound call has indeed been verified by the Axelar network and that this data is the authentic data passed in from the source chain rather than a malicious execution with invalid data on the destination chain.

Once this function has been called the transaction is marked as Executed on the destination chain to avoid double execution.

Please watch here for more information on validating incoming messages.

Cosmos

On Cosmos, validation is conducted on Axelar before calling a destination contract.

Evm -> Cosmos

For messages coming from EVM to Cosmos, Axelar users a unique sender to handle communication axelar1dv4u5k73pzqrxlzujxg3qp8kvc3pje7jtdvu72npnt5zhq05ejcsn5qme5. Then on the destination chain itself Axelar derives a unique caller to execute the transaction. On your contract you simply must ensure that the address triggering the transaction is the unique Axelar address to know that this is the authentic call coming from the Axelar network. The Axelar account is derived via the DeriveIntermediateSender sender function.

func DeriveIntermediateSender(channel, originalSender, bech32Prefix string) (string, error) {
senderStr := fmt.Sprintf("%s/%s", channel, originalSender)
senderHash32 := address.Hash(types.SenderPrefix, []byte(senderStr))
sender := sdk.AccAddress(senderHash32[:])
return sdk.Bech32ifyAddressBytes(bech32Prefix, sender)
}

For the Neutron blockchain for example to derive the Axelar account you pass in channel-2, axelar1dv4u5k73pzqrxlzujxg3qp8kvc3pje7jtdvu72npnt5zhq05ejcsn5qme5 , neutron to the DeriveIntermediateSender function.

IBC Hooks

If you’re using IBC hooks (iirc) to trigger wasm contracts, it will derive the sender for the wasm call itself (rather than just the plain IBC sender). In this instance as well you can require the contract to expect this specific derived sender address.

Edit on GitHub