Manually relay messages through Amplifier

Chains integrated with Amplifier can pass GMP messages to one another through the following flow:

  1. When a user sends a message to the chain, a callContract event is emitted.
  2. The relayer picks up the event and calls verify_messages on the chain’s Axelar (internal) gateway contract.
  3. For chains that rely on verifier votes, the Axelar gateway calls verify_messages on the voting verifier, which prompts verifiers to begin voting.
  4. Once a threshold of successful votes have been cast for the message, an event is emitted.
  5. A relayer listens for this event and calls route_messages on the chain’s Axelar gateway.
  6. The chain’s Axelar gateway passes the messages to the Amplifier router.
  7. The router passes the message to the destination chain’s Axelar gateway.
  8. A relayer calls construct_proof, which starts the process of creating a signed batch that can be relayed back to the source chain. This method also passes the now-outbound message from the gateway to the prover.
  9. The prover starts a signing session with the multisig contract.
  10. Verifiers participate in the signing session.
  11. Once enough signatures have been submitted, the relayer gets the fully signed proof from the prover and relays the proof to the destination chain to approve the transactions. This relayer can now execute any approved transactions on the destination chain.

The following code samples illustrate a transaction from Avalanche to Ethereum Sepolia. Information for other chains can be found on testnet.json.

verify_messages is a command on the gateway that prompts verifiers to begin voting so that a message can be verified and then routed. It takes a vector of messages to be verified.

Terminal window
export SOURCE_CHAIN_GATEWAY="axelar1vnfn0e4vnn58ydpm05wqcc9zp8t5ztwd5rw5f895lykqaezmuccqujmwl2"
export CHAIN_NAME="avalanche"
export TX_HASH="0x41d08bd627d7be301e0858312b63b3ede840d7fad145a9da333c26adf5d98614"
export TX_EVENT="0"
export DESTINATION_CHAIN="ethereum-sepolia"
export DESTINATION_ADDRESS="0x8f8dedd09E23E22E1555e9D2C25D7c7332291919"
export SOURCE_ADDRESS="0x0a3b8dc7706c47b6dd87d771df63875b1c5cd867"
export PAYLOAD_HASH="220f68445e3cec114bff50cd6b251e3deabc7684b10280c2116b20bcc6795a96"
export RPC="https://tm.axelar-testnet.lava.build:443"
Terminal window
axelard tx wasm execute $SOURCE_CHAIN_GATEWAY \
'{
"verify_messages": [
{
"cc_id": {
"source_chain":"'"$CHAIN_NAME"'",
"message_id":"'"$TX_HASH-$TX_EVENT"'"
},
"destination_chain":"'"$DESTINATION_CHAIN"'",
"destination_address":"'"$DESTINATION_ADDRESS"'",
"source_address":"'"$SOURCE_ADDRESS"'",
"payload_hash":"'"$PAYLOAD_HASH"'"
}
]
}' \
--keyring-backend test \
--from wallet \
--gas auto --gas-adjustment 1.5 --gas-prices 0.007uverifiers \
--chain-id axelar-testnet-lisbon-3 \
--node $RPC

route_messages is a command on the gateway that routes successfully verified messages to the destination chain. It takes a vector of verified messages to be routed.

Terminal window
axelard tx wasm execute $SOURCE_CHAIN_GATEWAY \
'{
"route_messages":[
{
"cc_id": {
"source_chain":"'"$CHAIN_NAME"'",
"message_id":"'"$TX_HASH-$TX_EVENT"'"
},
"destination_chain":"'"$DESTINATION_CHAIN"'",
"destination_address":"'"$DESTINATION_ADDRESS"'",
"source_address":"'"$SOURCE_ADDRESS"'",
"payload_hash":"'"$PAYLOAD_HASH"'"
}
]
}' \
--keyring-backend test \
--from wallet \
--gas auto --gas-adjustment 1.5 --gas-prices 0.007uverifiers \
--chain-id axelar-testnet-lisbon-3 \
--node $RPC

construct_proof takes a vector of CrossChainIDs and builds a proof that includes the messages to be routed so that the message can be relayed to the destination gateway. It also passes the message from the gateway to the prover.

Terminal window
export DESTINATION_CHAIN_MULTISIG_PROVER="axelar1xz4cya4qm2ws6nzperhvc40wdjcq4872fl6d3j2s4cytyx8j80eqenv87g"
Terminal window
axelard tx wasm execute $DESTINATION_CHAIN_MULTISIG_PROVER \
'{
"construct_proof":
[
{
"source_chain":"'"$CHAIN_NAME"'",
"message_id":"'"$TX_HASH-$TX_EVENT"'"
}
]
}' \
--keyring-backend test \
--from wallet \
--gas auto --gas-adjustment 1.5 --gas-prices 0.007uverifiers \
--chain-id axelar-testnet-lisbon-3 \
--node $RPC

get_proof returns the fully signed proof from the multisig prover after verifiers vote.

Terminal window
export MULTISIG_SESSION_ID="3457"
Terminal window
axelard q wasm contract-state smart $DESTINATION_CHAIN_MULTISIG_PROVER \
'{
"get_proof":{
"multisig_session_id":"'"$MULTISIG_SESSION_ID"'"
}
}' \
--node $RPC

Use the Foundry cast command to send the output of get_proof to the destination chain:

Terminal window
export OUTPUT="0x2A8465a312ebBa54D774972f01D64574a5acFC63 0x64f1d85a000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001600000000000000000000000008f8dedd09e23e22e1555e9d2c25d7c7332291919bc36789e7a1e281436464229828f817d6612f7b477d66591ff96a9e064bcc98a00000000000000000000000000000000000000000000000000000000000000096176616c616e636865000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000443078343164303862643632376437626533303165303835383331326236336233656465383430643766616431343561396461333333633236616466356439383631342d3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a30783345373746643142346434313736434139643534644236306631333246624238384246413433434100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000005400000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000b0000000000000000000000000000000000000000000000000000000000212fcc0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000036e007b2f03a6f01af8c99ca1cded439d57007a000000000000000000000000000000000000000000000000000000000000000100000000000000000000000009cc9a35433552080ed235722ff331bcfb533ba700000000000000000000000000000000000000000000000000000000000000010000000000000000000000003a188571605e41ea022304485551dfee11c436d50000000000000000000000000000000000000000000000000000000000000001000000000000000000000000438b7642a57aa47d1a4d290a5e2a046f45c9a6a4000000000000000000000000000000000000000000000000000000000000000100000000000000000000000044b994544df974b36fa75ed80dfb17332dc65fcc0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000467df763dfe6d7608c0d59dff527ad42fe58f29900000000000000000000000000000000000000000000000000000000000000010000000000000000000000004b67ea6cd2728b39e1cc94e48efa988a39cd391f00000000000000000000000000000000000000000000000000000000000000010000000000000000000000005c8d652b996286429c5df2fe604bd5b1299bb26900000000000000000000000000000000000000000000000000000000000000010000000000000000000000006968b2ad7a6d04d57798aebba01ff8bcf5aef5b200000000000000000000000000000000000000000000000000000000000000010000000000000000000000009485acfded01e09aa89d4ae63ec0c4a9f90f42c800000000000000000000000000000000000000000000000000000000000000010000000000000000000000009cd2ebe044c1f87d97d92252507c4363cefdbcf00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000a477a38bd7490fe6a54545dc95240492f89803000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000a56d4a7c6bb8f83b642e057e97de3061020d06c00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000ac46ca659582a66fa9f12e47bb204eda021ddb220000000000000000000000000000000000000000000000000000000000000001000000000000000000000000ea21d376c66903d4c99771650f9e55f7fd7a78c90000000000000000000000000000000000000000000000000000000000000001000000000000000000000000f1e9b98362820cc9257635b1e86dbf00d0bd92090000000000000000000000000000000000000000000000000000000000000001000000000000000000000000f4848a321f7297e1683d188c1383519cf003415c0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000fb13d049c9e0f0d433a09e38c009b697b1039c7c0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000002e0000000000000000000000000000000000000000000000000000000000000036000000000000000000000000000000000000000000000000000000000000003e0000000000000000000000000000000000000000000000000000000000000046000000000000000000000000000000000000000000000000000000000000004e0000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005e000000000000000000000000000000000000000000000000000000000000006600000000000000000000000000000000000000000000000000000000000000041eba2a31ea0eae246e2c0418b9ce6d4c2e5905fbd7e185df77b513c27f2fc4c477b91205725ec25208b7de0d8000116079629941291b0cbf8c0325e91cc64baf61c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041d1160889bb4c83702f294659a17b9a6191adff62efa9c4d677ce3a77c5367ffb78e238b1d2fc622304b9828ab55812499734b33d5dc6ad89fcbca84385dea1cc1b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000411dcd0881bb334167dbe6358263d39b0efe1ab550c384cac620ab2a224e7acf84562eec81fc00ff062ba2077159dd5cc9e89ecfe8eb9356e19dde42a108f0b94f1c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000419dfa1468778d46d2c36d33398971f8c05a501c399984ae437640bb22df50c6070e2e73cc51910bf53527e268ca113156685bd0bbe3e020a0e35a5fbc2a17d4f51b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041bef930be7baa161ad6c71274a7bfb992e6c525a5ae30ba241a9d6d24a287949a61dfb1f639950c0e9d94cb375ced32309ac60542e22f0b56a55020451bb5e5b81b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000417f21fc01777a48f51c1ed19f2a11d148acecce644c0d3de4253c4e9d58df2cd4416336eec7e8787c93ec445d3d985cdb9ce3312974f716cd1acc762ed0bf8d3c1c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041a02d3135ff391b457bcbe39fb25568e80930e2e4e970cfc488d28cfd876dddd64fdda2def8f09e1fd0a2c4d1c225d27a897035491e763b222a2f16c5dddf4eb31c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041382e2e4cbd9eaff8ce466b17a64829c6fcea9af8cde13c1f75763326f3828a383710b82bbf83345c66bbeb7c6d19ccf85d469d9b7524075b2dc96729196ce7c51c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410c702c068f9a679825aadebb8a25932557550653a101a4832cb334e87a2a8a3818615d5754ebb7aaabaec6eb190a262bd0e06804f06f5a87e154797959505ac91b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041cec4908951da8841f7b7b92ec17ed04e5b95c22e2dbd1101b85842631a1b89dd09dd99506848fd3010adc3daad7ad94d275e5ebf9f391abbfa7608d0051061651b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004148c875c4ee50edc3224de13ee4c2aa0f1ac2b2736a075fe59a8c2af810b3f0383c0fcb4373d4dcacc0aced17cb6ede9f2cb7b8cd56a41502dcccccbkbrukgebdtgekutnlvkgecbgelflgtbgfcgfdl
ef8a848c5a5adb71c00000000000000000000000000000000000000000000000000000000000000"
export RPC="https://rpc.ankr.com/eth_sepolia"
Terminal window
cast send $OUTPUT \
--rpc-url $RPC \
--mnemonic-path ./private.mneumonic

Use your MetaMask wallet to send the output of get_proof to the destination chain:

  1. Open your MetaMask wallet.
  2. Click Send.
  3. Get the destination chain’s gateway address from devnet-amplifier.json and paste it in the Send to field.
  4. Paste the output from get_proof in the Hex data field.
  5. Click Next.

The proof should then be sent to the destination chain.

Edit on GitHub