Manually relay messages through Amplifier
Chains integrated with Amplifier can pass GMP messages to one another through the following flow:
- When a user sends a message to the chain, a
callContract
event is emitted. - The relayer picks up the event and calls
verify_messages
on the chain’s Axelar (internal) gateway contract. - For chains that rely on verifier votes, the Axelar gateway calls
verify_messages
on the voting verifier, which prompts verifiers to begin voting. - Once a threshold of successful votes have been cast for the message, an event is emitted.
- A relayer listens for this event and calls
route_messages
on the chain’s Axelar gateway. - The chain’s Axelar gateway passes the messages to the Amplifier router.
- The router passes the message to the destination chain’s Axelar gateway.
- 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. - The prover starts a signing session with the multisig contract.
- Verifiers participate in the signing session.
- 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.
Live Axelar contract deployments
Verify messages
Once a call has been executed on an external chain such as Ethereum, the first step is to get that message verified with your integration’s unique Verifier Contract
The verify_messages
command on the gateway prompts verifiers (in the case of a VotingVerifier verification choice) to begin voting so that a message can be verified and then routed. It takes a vector of messages to be verified. This example will trigger the verify_messages function in the Voting Verifier contract.
Note: A Voting Verifier verification is just one of many possibilities to verify messages. Other options include but are not limited to the use of ZK Proofs or light clients.
export SOURCE_CHAIN_GATEWAY="axelar1exenpcymaxz5gpkl0lmv85kxzgm6rk0czn9ysxn0ssf8j7c4rkts8ltcvw" # Chain integrations unique gatewayexport CHAIN_NAME="toronto" # Chain nameexport TX_HASH="0x4f5b0ed0dc717b317f16c841a407c79226deba7bc15e82ba98b4d4aab1169baf" # Hash of tx on Toronto chainexport TX_EVENT="1" # Index of call-contract event on Toronto chainexport DESTINATION_CHAIN="avalanche-fuji" # Name of dest chain as indicated in devnet-deployments.json fileexport DESTINATION_ADDRESS="0x8f8dedd09E23E22E1555e9D2C25D7c7332291919" # Receiving dapp address on Avalancheexport SOURCE_ADDRESS="0x4501dc2E5Da9C3c8Eb6A68ecdE7a351229AA3134" # Sending dapp address on Torontoexport PAYLOAD_HASH="510904852D8E69EBFD1F84DC0DD0BF7A75C97A8C7EF873BF5BEF26DC41AD1C0F" # Hash of GMP payload sentexport RPC="http://devnet-amplifier.axelar.dev:26657" # Devnet RPCexport GAS_PRICE="0.007uamplifier" # Gas price for devnet txexport CHAIN_ID="devnet-amplifier" # Devnet chain id
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"export GAS_PRICE="0.007uverifiers"export CHAIN_ID="axelar-testnet-lisbon-3 "
Running this command will trigger a vote among the chain’s registered verifiers to come to consensus about the message that was sent.
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 $GAS_PRICE \ --chain-id $CHAIN_ID \ --node $RPC
Route messages
With the message now verified, the next step is to route the message to the destination chain’s Prover contract. To do this you can run the route_messages
command on the gateway. It takes a vector of verified messages to be routed.
export SOURCE_CHAIN_GATEWAY="axelar1exenpcymaxz5gpkl0lmv85kxzgm6rk0czn9ysxn0ssf8j7c4rkts8ltcvw" # Chain integrations unique gatewayexport CHAIN_NAME="toronto" # Chain nameexport TX_HASH="0x4f5b0ed0dc717b317f16c841a407c79226deba7bc15e82ba98b4d4aab1169baf" # Hash of tx on Toronto chainexport TX_EVENT="1" # Index of call-contract event on Toronto chainexport DESTINATION_CHAIN="avalanche-fuji" # Name of dest chain as indicated in devnet-deployments.json fileexport DESTINATION_ADDRESS="0x8f8dedd09E23E22E1555e9D2C25D7c7332291919" # Receiving dapp address on Avalancheexport SOURCE_ADDRESS="0x4501dc2E5Da9C3c8Eb6A68ecdE7a351229AA3134" # Sending dapp address on Torontoexport PAYLOAD_HASH="510904852D8E69EBFD1F84DC0DD0BF7A75C97A8C7EF873BF5BEF26DC41AD1C0F" # Hash of GMP payload sentexport RPC="http://devnet-amplifier.axelar.dev:26657" # Devnet RPCexport GAS_PRICE="0.007uamplifier" # Gas price for devnet txexport CHAIN_ID="devnet-amplifier" # Devnet chain id
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"export GAS_PRICE="0.007uverifiers"export CHAIN_ID="axelar-testnet-lisbon-3"
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 $GAS_PRICE \ --chain-id $CHAIN_ID \ --node $RPC
Construct a proof
Now that the message has been routed, the Prover of the destination chain can construct the proof for it.
construct_proof
takes a vector of CrossChainID
s 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.
export DESTINATION_CHAIN_MULTISIG_PROVER="axelar14smpvv72hkaajh7rqzuhxum5vj3yh5smftaescucdmfsh9eednyqdme35j" # Chain integrations unique proverexport CHAIN_NAME="toronto" # Chain nameexport TX_HASH="0x4f5b0ed0dc717b317f16c841a407c79226deba7bc15e82ba98b4d4aab1169baf" # Hash of tx on Toronto chainexport TX_EVENT="1" # Index of call-contract event on Toronto chainexport RPC="http://devnet-amplifier.axelar.dev:26657" # Devnet RPCexport GAS_PRICE="0.007uamplifier" # Gas price for devnet txexport CHAIN_ID="devnet-amplifier" # Devnet chain id
export DESTINATION_CHAIN_MULTISIG_PROVER="axelar1xz4cya4qm2ws6nzperhvc40wdjcq4872fl6d3j2s4cytyx8j80eqenv87g"export CHAIN_NAME="avalanche"export TX_HASH="0x41d08bd627d7be301e0858312b63b3ede840d7fad145a9da333c26adf5d98614"export TX_EVENT="0"export RPC="https://tm.axelar-testnet.lava.build:443"export GAS_PRICE="0.007uverifiers"export CHAIN_ID="axelar-testnet-lisbon-3"
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 $GAS_PRICE \ --chain-id $CHAIN_ID \ --node $RPC
Get the proof
Now that the proof has been submitted you can run get_proof
to return the fully signed proof from the multisig prover.
export DESTINATION_CHAIN_MULTISIG_PROVER="axelar14smpvv72hkaajh7rqzuhxum5vj3yh5smftaescucdmfsh9eednyqdme35j" # Chain integrations unique proverexport MULTISIG_SESSION_ID="1742" # Unique value for each proof generationexport RPC="http://devnet-amplifier.axelar.dev:26657" # Devnet RPC
export DESTINATION_CHAIN_MULTISIG_PROVER="axelar1xz4cya4qm2ws6nzperhvc40wdjcq4872fl6d3j2s4cytyx8j80eqenv87g"export MULTISIG_SESSION_ID="3457"export RPC="https://tm.axelar-testnet.lava.build:443"
axelard q wasm contract-state smart $DESTINATION_CHAIN_MULTISIG_PROVER \ '{ "get_proof":{ "multisig_session_id":"'"$MULTISIG_SESSION_ID"'" } }' \ --node $RPC
Send the proof to the destination chain
Use the Foundry cast
command to send the output of get_proof
to the destination chain:
export OUTPUT="0x2A8465a312ebBa54D774972f01D64574a5acFC63 0x64f1d85a000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000001600000000000000000000000008f8dedd09e23e22e1555e9d2c25d7c7332291919bc36789e7a1e281436464229828f817d6612f7b477d66591ff96a9e064bcc98a00000000000000000000000000000000000000000000000000000000000000096176616c616e636865000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000443078343164303862643632376437626533303165303835383331326236336233656465383430643766616431343561396461333333633236616466356439383631342d3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002a30783345373746643142346434313736434139643534644236306631333246624238384246413433434100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000005400000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000b0000000000000000000000000000000000000000000000000000000000212fcc0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000036e007b2f03a6f01af8c99ca1cded439d57007a000000000000000000000000000000000000000000000000000000000000000100000000000000000000000009cc9a35433552080ed235722ff331bcfb533ba700000000000000000000000000000000000000000000000000000000000000010000000000000000000000003a188571605e41ea022304485551dfee11c436d50000000000000000000000000000000000000000000000000000000000000001000000000000000000000000438b7642a57aa47d1a4d290a5e2a046f45c9a6a4000000000000000000000000000000000000000000000000000000000000000100000000000000000000000044b994544df974b36fa75ed80dfb17332dc65fcc0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000467df763dfe6d7608c0d59dff527ad42fe58f29900000000000000000000000000000000000000000000000000000000000000010000000000000000000000004b67ea6cd2728b39e1cc94e48efa988a39cd391f00000000000000000000000000000000000000000000000000000000000000010000000000000000000000005c8d652b996286429c5df2fe604bd5b1299bb26900000000000000000000000000000000000000000000000000000000000000010000000000000000000000006968b2ad7a6d04d57798aebba01ff8bcf5aef5b200000000000000000000000000000000000000000000000000000000000000010000000000000000000000009485acfded01e09aa89d4ae63ec0c4a9f90f42c800000000000000000000000000000000000000000000000000000000000000010000000000000000000000009cd2ebe044c1f87d97d92252507c4363cefdbcf00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000a477a38bd7490fe6a54545dc95240492f89803000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000a56d4a7c6bb8f83b642e057e97de3061020d06c00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000ac46ca659582a66fa9f12e47bb204eda021ddb220000000000000000000000000000000000000000000000000000000000000001000000000000000000000000ea21d376c66903d4c99771650f9e55f7fd7a78c90000000000000000000000000000000000000000000000000000000000000001000000000000000000000000f1e9b98362820cc9257635b1e86dbf00d0bd92090000000000000000000000000000000000000000000000000000000000000001000000000000000000000000f4848a321f7297e1683d188c1383519cf003415c0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000fb13d049c9e0f0d433a09e38c009b697b1039c7c0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000026000000000000000000000000000000000000000000000000000000000000002e0000000000000000000000000000000000000000000000000000000000000036000000000000000000000000000000000000000000000000000000000000003e0000000000000000000000000000000000000000000000000000000000000046000000000000000000000000000000000000000000000000000000000000004e0000000000000000000000000000000000000000000000000000000000000056000000000000000000000000000000000000000000000000000000000000005e000000000000000000000000000000000000000000000000000000000000006600000000000000000000000000000000000000000000000000000000000000041eba2a31ea0eae246e2c0418b9ce6d4c2e5905fbd7e185df77b513c27f2fc4c477b91205725ec25208b7de0d8000116079629941291b0cbf8c0325e91cc64baf61c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041d1160889bb4c83702f294659a17b9a6191adff62efa9c4d677ce3a77c5367ffb78e238b1d2fc622304b9828ab55812499734b33d5dc6ad89fcbca84385dea1cc1b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000411dcd0881bb334167dbe6358263d39b0efe1ab550c384cac620ab2a224e7acf84562eec81fc00ff062ba2077159dd5cc9e89ecfe8eb9356e19dde42a108f0b94f1c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000419dfa1468778d46d2c36d33398971f8c05a501c399984ae437640bb22df50c6070e2e73cc51910bf53527e268ca113156685bd0bbe3e020a0e35a5fbc2a17d4f51b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041bef930be7baa161ad6c71274a7bfb992e6c525a5ae30ba241a9d6d24a287949a61dfb1f639950c0e9d94cb375ced32309ac60542e22f0b56a55020451bb5e5b81b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000417f21fc01777a48f51c1ed19f2a11d148acecce644c0d3de4253c4e9d58df2cd4416336eec7e8787c93ec445d3d985cdb9ce3312974f716cd1acc762ed0bf8d3c1c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041a02d3135ff391b457bcbe39fb25568e80930e2e4e970cfc488d28cfd876dddd64fdda2def8f09e1fd0a2c4d1c225d27a897035491e763b222a2f16c5dddf4eb31c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041382e2e4cbd9eaff8ce466b17a64829c6fcea9af8cde13c1f75763326f3828a383710b82bbf83345c66bbeb7c6d19ccf85d469d9b7524075b2dc96729196ce7c51c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000410c702c068f9a679825aadebb8a25932557550653a101a4832cb334e87a2a8a3818615d5754ebb7aaabaec6eb190a262bd0e06804f06f5a87e154797959505ac91b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041cec4908951da8841f7b7b92ec17ed04e5b95c22e2dbd1101b85842631a1b89dd09dd99506848fd3010adc3daad7ad94d275e5ebf9f391abbfa7608d0051061651b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004148c875c4ee50edc3224de13ee4c2aa0f1ac2b2736a075fe59a8c2af810b3f0383c0fcb4373d4dcacc0aced17cb6ede9f2cb7b8cd56a41502dcccccbkbrukgebdtgekutnlvkgecbgelflgtbgfcgfdlef8a848c5a5adb71c00000000000000000000000000000000000000000000000000000000000000"export RPC="https://rpc.ankr.com/eth_sepolia"
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:
- Open your MetaMask wallet.
- Click Send.
- Get the destination chain’s gateway address from
devnet-amplifier.json
and paste it in the Send to field. - Paste the output from
get_proof
in the Hex data field. - Click Next.
The proof should then be sent to the destination chain.