Send tokens between Different Blockchain using Axelar General Message Passing - The Basics
Tags: axelar, blockchain, beginners
Published: 2023-04-27 16:54:42

## Howdy!
If you are beginning to explore Blockchain Interoperability , you've come to the right place!
Axelar enables you to make cross chain DApps.
And of course they have their own documentations & videos you can watch. But I'm mainly writing this because when I first started searching for a proper place to learn Axelar, I got confused. Because Axelar does A LOT! So it's easy to get overwhelmed by all the jargans thrown around. So I have compiled what I believe is a good starting point for ANYONE. We'll be using the [**Remix**](https://remix.ethereum.org/) IDE. We'll connect to Meta Mask & actually send a Message from Polygon to Avalanche Blockchain.
Here are the things I will cover accordingly:

- Basic Definitions & Tips

- Resource Websites

- Coding

- Execution

**<u>Basic Definitions</u>**

**General Message Passing**
The first most important service provided by Axelar which allows you to send tokens between blockchains, these tokens can be either messages , nfts etc. 
Basically think of it as two banks exchanging cheques between each other for financial purposes. Now of course when you exchange between two banks, you must pay some amount to the bank in order for the transaction to occure. On to the Next Definition!


**Gas Service**
I think you can kinda guess what the Gas Service is about. Think of the Gas as the fee you pay when sending cheques to another Bank. Now Gas Service serves as the system of payment of that fee. We'll be talking more about this service in the next sections.

**<u>Important Arguments</u>:**

**destinationChain**
Think of destinationChain as the Bank you want to send the cheque to. In our case , we are sending a message from Polygon to Avalanche, so our destinationChain will be Avalanche.

**destinationAddress**
destinationAddress is just the address of your wallet. We'll see more on this later down.


**All Right!**
Now that those things are out of the way, here's some sites that may come in handy:

**[Chainlist](https://chainlist.org/?testnets=true&search=)**
Go to Chainlist & connect to testnet of your choice. For this blog I chose Polygon Mumbai & Avalanche Fuji Testnet.

**Faucets**
Faucets is where you can find Test Gas or in Web2 we call it Fake Money to test your DApp. For our perposes we used the [Polygon Faucet](https://faucet.polygon.technology/) & [Avalanche Faucet](https://faucet.avax.network/)

I used MATIC tokens for Polygon & AVAX for Avalanche.


**<u>Coding Begins!</u>**

Open up [Remix](https://remix.ethereum.org/) & create a new file. Name it anything you like with the .sol extension. I named mine `gmp.sol`. You don't have to set up anything else for this. All necessary package imports will be shown in next parts. 

So as you may have already understood , we are using **Solidity** for this task.

Open up `gmp.sol` & use the code below to use Solidity version:

```
pragma solidity ^0.8.0;
```


**Imports**

Now we'll be exporting some essential packages.
First up is `AxelarExecutable` . This allows us to execute our contracts through Axelar.
**Import Code:**

```
import { AxelarExecutable } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/executable/AxelarExecutable.sol';

```

Next up is `IAxelarGateway` , which is basically a gateway plugin that helps you pay the Gas Service charge.
**Import Code:**

```
import { IAxelarGateway } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarGateway.sol';

```

Finally we import `IAxelarGasService` which is the main service that handles the outgoing & incoming Gas.

**Import Code:**

```
import { IAxelarGasService } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarGasService.sol';

```

**<u>The Contract:</u>**

Now we'll initiate a contract. We'll name our contract `SenderReceiver`. This will allow us to send & receiev messages across blockchains. It's worth mentioning this contract will be an `AxelarExecutable` which will allow us to execute using Axelar's services.
Now let's look at the contract code & we'll explain further below.

```
contract SenderReceiver is AxelarExecutable {
    IAxelarGasService public immutable gasService;
    string public message;
    constructor(address gateway_, address gasService_) AxelarExecutable(gateway_) {
        gasService = IAxelarGasService(gasService_);
    }

```
Here we have defined a state variable `gasService` which is of type `IAxelarGasService`. This has to be declared as public and immutable so that it can't be changed and can be accessed externally.
Now we add a `constructor` function which takes in two arguments `gateway_` &  `gasService_`. Now we must initialize the gateway using `AxelarExecutable` & passing in `gateway_` as an argument.
Finally we initialize the gasService using `IAxelarGasService` & passing in `gasService_` as an argument.

**And Voila!**
Our Contract is ready to go!

**<u>Functions:</u>**

Now we're gonna be writing some simple functions to send & receive the message between blockchains.
The first function we'll write is will send the message to our destination chain. Let's call `sendMessage`. We are going to encode our message using this function. We'll need to take in 3 arguments for this function which are `destinationChain` , `destinationAddress` which I have already explained before & the third one is `message_`. All of them are Strings. The `message_` arguments stores the text message that we'll be sending.
In order to encode the message we'll be making this function an `external payable` which will encode our massage & help us pay the Gas Fee.

**Function Code:**

```
function sendMessage(
        string calldata destinationChain,
        string calldata destinationAddress,
        string calldata message_
    )external payable{
        bytes memory payload = abi.encode(message_);
        gasService.payNativeGasForContractCall{value: msg.value} (
            address(this),
            destinationChain,
            destinationAddress,
            payload,
            msg.sender
        );

        gateway.callContract(destinationChain, destinationAddress, payload);
    }

```
We use the `payNativeGasForContractCall` function from the `gasService` contract to pay for the gas required to execute the transaction. Finally The `gateway.callContract` function is used to initiate the transaction to the `destinationChain` & `destinationAddress` carrying the messaye `payload`.

Done!
Now that we can Send a message to our destination Chain , we need a way to receive the message on our destination.

**<u>On to The Final Function!</u>**

In this function we'll execute our message by decoding it into our destination chain. Let's call it execute function. It will decode the `payload` & show us the string inside.
**Function Code:**

```
    function _execute(
        string calldata sourceChain,
        string calldata sourceAddress,
        bytes calldata payload_
    )internal override{
        message = abi.decode(payload_, (string));
    }
}
```
`message` will decode the payload using `abi.decode` & show you the message.

**And That's About It!**
Here's the Full Code:

```
pragma solidity ^0.8.0;

import { AxelarExecutable } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/executable/AxelarExecutable.sol';
import { IAxelarGateway } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarGateway.sol';
import { IAxelarGasService } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarGasService.sol';


contract SenderReceiver is AxelarExecutable {
    IAxelarGasService public immutable gasService;
    string public message;
    constructor(address gateway_, address gasService_) AxelarExecutable(gateway_) {
        gasService = IAxelarGasService(gasService_);
    }

    function sendMessage(
        string calldata destinationChain,
        string calldata destinationAddress,
        string calldata message_
    )external payable{
        bytes memory payload = abi.encode(message_);
        gasService.payNativeGasForContractCall{value: msg.value} (
            address(this),
            destinationChain,
            destinationAddress,
            payload,
            msg.sender
        );

        gateway.callContract(destinationChain, destinationAddress, payload);
    }

    function _execute(
        string calldata sourceChain,
        string calldata sourceAddress,
        bytes calldata payload_
    )internal override{
        message = abi.decode(payload_, (string));
    }
}
```

**<u>Execution:</u>**

On this part you get to see everything happen! 
Go over to the side menu & click on Solidity Compiler.
Click on Compile gmp.sol.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mmjxg8gublc68asclki9.png)


After Compilation you may see some small warnings about not using sourceChain & sourceAddress in the execute function, these arguments are indicating our source blockchain, in our case polygon. No need to worry too much about these at the moment.

Now click on Deploy & Run Transaction button on the side menu.
 Choose Injected Provider- MetaMask. You will be prompted to connect your MetaMask wallet. If you don't have one yet, you can just create it now.
Here's a links that'll help:
[Download MetaMask for Chrome](https://chrome.google.com/webstore/detail/metamask/nkbihfbeogaeaoehlefnkodbefgpgknn)

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z1zu5t352akxbdziib14.png)



Now after you've connecter MetaMask, check your setting for transaction. Set value to Ether & add 1 Ether.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4gk21iss2e2nyc4sopi3.png)

Now you get to choose your testnets for transaction
Here are the sites you'll need for this part

[Axelar Tesnet Addresses](https://docs.axelar.dev/resources/testnet)

This site has all the gateway & gas service addresses.
Just Copy & paste them on to here:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6dgqxo6scphxxbc5g2sa.png)

I chose Polygon & Avalanche, Make sure whatever testnet you choose is supported by Axelar.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jk3n78klccjyhptvit86.png)

First copy the Polygon Addresses & paste them in.



Now you can click on the `transact` button & your transaction will begin!
Approve your transaction.

Now you have added the Polygon testnet.

For connecting Avalanche, follow the same procedure,
Change your MetaMask profile to Avalanche Fuji.
Got to Avalanche Testnets site. Copy Avalanche chain code & gas service code.
Paste them the same way you pasted Polygon Addresses.
And Click Transact! That's it!
Both Chains are now connected.

Example Image of connecting Polygon:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t46unlyic3c2opforthh.png)

After you click confirm, it will take a little time, keep an eye on the Terminal, it'll show you some information.

Now look at bottom left corner, you will have your hash code for the Source testnet, save it somewhere you can see.
It should look like this:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ba0zaj1hfniozwoewfcc.png)

On the top you can see `SENDERRECIEVER`. This is the `SenderReceiver` function we declared in our code. AND you get an ID . Copy it & Paste it in the destinationAddress field & use Polygon as destinationChain.
Click on sendMessage option to send our Old Hello World! Message to Avalanche. 
Now click on transact again.

Here we'll see the real magic happen!

Head over to [Axelar Gmp Search](https://testnet.axelarscan.io/gmp/search) Site , in here you will see ALL transactions happening LIVE!

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lype2elrtqv5s7y72jta.png)

On the very Top we can see our message along with it's status!

Now for another trick!
You can click on it to see EVERY Detail about our transaction!
Which is pretty freaking cool.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7nkqn55aalms5wpnj54u.png)
Here we can see that our transaction has been approved & executed.

Now for the final part
Go back to Remix.




![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9u72rrxvcf71vzq5ia2c.png)




Under deployed contacts, go to Polygons SenderReceiver & Query the message property, Under they when you click the message option , you will see there, beautifully displayed
 

## Hello World!