Moonbeam was built on Polkadot and shares its interoperability vision, but cross-chain communication doesn’t stop with parachains. The Axelar Network protocol has extended the number of networks to be within Moonbeam’s reach by allowing tokens to be bridged between select Cosmos and EVM networks. In addition to token bridging, Axelar’s general message passing (GMP) allows smart contracts to communicate with each other across chains. This allows developers to build cross-chain connected applications on Moonbeam that can tap into functionality from Polkadot, Ethereum, Avalanche, Cosmos, and beyond.
Multichain dApps are currently unified interfaces for protocols duplicated across multiple EVMs. Protocols will be able to connect their contracts cross-chain using Axelar’s general message passing to become multichain aware, allowing for advanced interoperability and functionality between what would otherwise be isolated ecosystems.
To demonstrate the power of connected contracts, we will walk through a demo that sends and stores a string from one testnet EVM to another. If you don’t have MetaMask set up for it yet, you can add the Moonbase Alpha network on the docs site.
Intro to Axelar Contracts
Axelar is a delegated proof of stake chain that provides secure cross-chain communication. Every validator in Axelar’s network runs light nodes on chains that Axelar supports. These validators work together to confirm that messages are being sent from one chain to another by monitoring each chain’s Axelar Gateway contract, which is one of the two Axelar contracts we will be interacting with later in the demo.
Image from Axelar Network
The other contract we will be working with is the Axelar Gas Receiver microservice. Whenever you use the Axelar Gateway to send a cross-chain transaction, IAxelarGasReceiver lets you pay for the subsequent transaction on the destination chain. While not necessary, it allows the end user to only send one transaction to automatically update the destination chain.
Connected SimpleGeneralMessage Contract
Now let’s try it out in the most basic way possible. To understand what we’re doing, let’s take a look at the contract that we’ll deploy, which has been made available in a Github gist.
If you take a look at the contract’s parent, you’ll find that it inherits from an abstract contract IAxelarExecutable. This pa rent contract contains some code that Axelar’s contracts require to interact with for general message passing.
There are two functions in the parent contract. The first is sendMessage. It sends an encoded string message across chains via Axelar with the option to pay for its gas on the destination chain.
The second function is _execute, which overrides a function inherited by IAxelarExecutable. This function is internal, and can only be called by Axelar’s gateway contract when it receives a message from another chain that is directed at this contract. This is where we parse the string from the message’s payload.
Doing is the best way to learn, so try to follow along with the deployment and message passing yourself on Moonbase Alpha.
Deploying with Remix on Moonbase Alpha
To deploy the script, first copy and paste the contract into Remix. Then compile in the compile tab. Ensure that your MetaMask is connected to the Moonbase Alpha network. Then, in the deploy tab of Remix, set the environment to the Injected Web3, this will use MetaMask as the Web3 provider.
This contract and many connected contracts that use Axelar, will need to know the addresses of two contracts: the Axelar Gateway and the Axelar Gas Receiver. You will have to provide their instances on Moonbase Alpha when constructing SimpleGeneralMessage.sol.
Once your contract has been deployed on Moonbase Alpha, I highly recommend you repeat the process with any of the other EVM testnets that are connected to Axelar. Here are a few of them with a link to a faucet. I’ve also included the SimpleGeneralMessage contracts that were previously deployed if you’re in a major time crunch.
Sending a Cross Chain Message from Moonbase with Axelar
To send a cross-chain message with an automatic destination chain transaction, you first need to know how much gas to spend on the destination chain. In this example, Moonbase Alpha’s native currency DEV is being used to pay for the gas. The testnet treats each testnet’s price as equal to its mainnet’s price (GLMR is the mainnet equivalent of DEV). At the time of writing, ETH is much more expensive than AVAX, so the gas price & conversion from DEV to rETH (Ropsten ETH) will be much higher than DEV to Fuji AVAX.
- Ropsten Testnet: 356806741787800000
- Polygon Mumbai: 3390032863000000
- Avalanche Fuji: 97036323830100000
- Fantom Testnet: 55389864900000
Now that you have the gas fee converted to wei, you can start to use the Remix interface. This example is going to send a cross-chain message to the Fantom testnet, but you can substitute the gas value and chain name for whichever EVM you desire. Check the following things:
- The environment is “Injected Provider – Web3” on network 1287 (Moonbase Alpha)
- You have substantial funds in your wallet from the faucet to cover both the transaction cost and the DEV calculated above
- You have the gas fee calculated in the previous step placed in the value input
- Put a short message of your choice in the message input of the sendMessage call (in this case “ghost of the moon”)
- Put the destination chain’s SimpleGeneralMessage contract address in the destinationAddress input of the sendMessage call. This should be either an address that you deployed (recommended) or one of the listed pre-deployed
- Put “Fantom” (or the canonical name of the mainnet for whichever testnet EVM you want to use) in the destinationChain input of the sendMessage call
Once this is all done, transact the execution and confirm it in MetaMask.
Tracking Cross Chain Messages
After sending your transaction, you should be able to go into the Moonbase block explorer to take a look at the transaction using its transaction hash. If everything went well, it should be confirmed, and you’ll be able to see traces of the input of your transaction at the very bottom when viewing it as UTF-8.
In a typical transaction, you would be able to see the status and data of the transaction on a single page on a single explorer. But, since this is cross-chain messaging, there are really two EVM transactions happening on two chains.
To truly see if your transaction has been successful, go to the Axelarscan testnet explorer and find your transaction. You can search for a transaction by using the same transaction hash as the one outputted by Remix (on the origin chain). You should see something like this:
If everything goes smoothly, your transaction will be approved and you will be able to see the lastMessage updated in the origin chain from your successful cross-chain transaction! If it doesn’t automatically update, don’t worry. On average, it takes a few minutes for confirmations to go through on the testnet. The Axelar team is always working to improve the speed of its network, but keep in mind that in the past it has taken longer, so don’t worry if your transaction doesn’t finish immediately.
If you want to see the message stored in the contract, you can do so through Remix. First, connect to the destination network through Metamask. Make sure that you are on the “Injected Provider” environment and that the contract is still “SimpleGeneralMessage”. Then take the address of the destination contract, and paste it into the “At Address” input. Press it, and you should be able to use the outcome contract to view the last message.
Learn More About Connected Contracts
Moonbeam’s vision for an interoperable hub of networks doesn’t stop here. Learn more about Axelar on their website, general message passing in Axelar’s docs, and read about how Moonbeam is shaping up to be the leader in blockchain interoperability on our connected-contracts page.