# SpeedRun ETH Dex Bonus Challenge With Axelar

When building a Web3 application such as a decentralized exchange, cross-chain functionality can offer tremendous growth opportunities. Cross-chain functionality allows more users to interact with the application and more liquidity to enter the application’s ecosystem. It introduces a unique possibility of transferring value from one network to another, which might not have been feasible before. This involves encapsulating and presenting the yield from one network within a new network, where it can serve as collateral or contribute to other productive purposes.

Axelar is a protocol which allows for easy cross-chain compatibility to be built into an application. Axelar is powered by its own blockchain, which it uses to facilitate cross-chain messages and asset transfers. Applications that integrate with Axelar can integrate with any other [chain connected to Axelar](https://axelarscan.io/).

To enhance the DEX challenge you will be adding cross-chain functionality by integrating with Axelar. At this point, you should have completed the basic [Speedrun Eth DEX Challenge](https://speedrunethereum.com/challenge/minimum-viable-exchange). If you want to only do the bonus challenge you can [clone this repository](https://github.com/benjamin852/dex-bonus/tree/main) for the completed DEX challenge

The objective of the bonus challenge will be to conduct a swap on the DEX from a different blockchain. Specifically, you will be swapping [aUSDC](https://axelar.network/blog/what-is-axlusdc-and-how-do-you-get-it) (instead of BALLOONS tokens as done in the initial challenge) as the token for Eth via the `tokenToEth()` function, which is already defined in the DEX.

![Axelar Dex Challenge Overview](https://lh7-us.googleusercontent.com/jh-hYiNLEvGUhWicMObsXmxinlSqOH7PVK120P-zkoUlVNjU5dk0-dpEPM1LYIY-przJr61TRG9-JUyP-NFAQ3RHg1fAk87G5VttKchOGc93fQENT-qcxunoDoO1ma36momLj7VsU_V1d5vIyTZ64yo align="left")

## Contract Setup

First, you must install the necessary dependencies from the cloned repo. To do this run `npm install`. Next, you need to pass your private key into the `.env` file so that you can use it to deploy your contract from your own wallet on testnet.

Now in your `DexBonus.sol` file, you can start with some imports.

```solidity
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';
import {AxelarExecutable} from '@axelar-network/axelar-gmp-sdk-solidity/contracts/executable/AxelarExecutable.sol';
```

* The first import is the interface for the [Axelar Gateway](https://github.com/axelarnetwork/axelar-cgp-solidity/blob/main/contracts/AxelarGateway.sol).
    
    * The Gateway contract executes and receives messages to/from the Axelar network.
        
* Next, is the interface for the Gas Service contract.
    
    * The [Gas Service](https://github.com/axelarnetwork/axelar-cgp-solidity/blob/main/contracts/gas-service/AxelarGasService.sol) was created to assist with the payment for an interchain transaction. It will be used to pay for the entirety of the transaction in the token of the source chain so users don’t need to hold the source chain token, Axelar token, and destination chain token for each transaction.
        
* Lastly, the [Executable](https://github.com/axelarnetwork/axelar-gmp-sdk-solidity/blob/main/contracts/executable/AxelarExecutable.sol) contains the functionality which will be automatically executed by an Axelar relayer on the destination chain.
    

![Axelar General Message Passing (GMP) Overview](https://lh7-us.googleusercontent.com/qhVsYYoWv_-47fIggscgyerpAypymdP9xT73D2TGps74_L9On3VuM9u3DZThTcl9DUEYvuhNeB703uXlGoVxpbhpXngLyOo-wnpzIUXxsITHG0syWrUBrHpB7-Fohm55xM7DiCryOWMHXkHbo_QtuSM align="left")

## Building

### Source Chain Logic

Now that the required functionality is imported into your contract you can begin to write the functionality that will be executed on the source chain of your interchain transaction.

In your DEX contract, create a new function called `interchainSwap()` it will take the following parameters.

```solidity
function interchainSwap(
  string memory _destChain,
  string memory _destContractAddr,
  address _receiver,
  string memory _symbol, 
  uint256 _amount 
) external payable {}
```

The `destChain` is the name of the chain your interchain transaction is sending a message to. The `destContractAddr` is the address on the destination chain that the contract is transacting to. The `receiver` is the end receiver of the transaction on the destination chain. Lastly, the `symbol` and `amount` are the symbol of the token you are sending and the amount of that token you are sending.

Let’s start writing out the `interchainSwap()` functionality.

First, you will need to transfer the ERC20 token you’re swapping to, to this contract.

```solidity
//get token address from symbol
address tokenAddress = gateway.tokenAddresses(_symbol);

//send funds to this contract
IERC20(tokenAddress).transferFrom(msg.sender, address(this), _amount);

//approve gateway to spend funds
IERC20(tokenAddress).approve(address(gateway), _amount);
```

Pass in the symbol of the token you’re transferring to Axelar’s Gateway contract, the Gateway returns the token address. Once you have the address you can call the `transferFrom()` function to send the tokens from your wallet to this contract. NOTE: you must `approve` the contract prior to calling this function to transfer these tokens on your behalf or this function will revert. Lastly, you `approve` the gateway contract to handle the tokens on this contract’s behalf as the tokens will soon be sent out of the custody of this contract.

At this point when the `interchainSwap()` function is called it will have the tokens in its balance and will have approved the Gateway contract to handle the tokens on its behalf. Now you can encode the GMP message that you will be sending along with the token to the destination chain. The message you are sending is simply the address of the receiving address on the destination chain. You also need to pass in a boolean value of `true`, which will be used later in the contract. Axelar requires the GMP message to be sent as a `bytes` type, which is why the message must be encoded.

```solidity
bytes memory encodedMsg = abi.encode(_receiver, true);
```

Now you can begin to interact with the related Axelar functionality, namely the *Gas Service* and the *Gateway*.

To pay for the interchain transaction you will interact with the Gas Service’s [`payNativeGasForContractCallWithToken()`](https://docs.axelar.dev/dev/general-message-passing/gas-services/pay-gas#paynativegasforcontractcallwithtoken) function

```solidity
//pay gas from source chain
gasService.payNativeGasForContractCallWithToken{value: msg.value}(
  address(this),
  _destChain,
  _destContractAddr,
  encodedMsg,
  _symbol,
  _amount,
  msg.sender
);
```

This function takes in the `msg.value` and specifies the parameters related to the interchain transaction, including; the sender of the transaction, the name of the destination chain, the destination address, the data payload, the symbol of the token sent with the call, the amount of tokens sent with the call. Worth noting is the final parameter where you’re passing in the `msg.sender`. If any surplus gas is sent in the `msg.value` then the Gas Service will refund that extra gas amount the `msg.sender` is the address we are choosing to send this refund to.

Now that the gas has been paid you can trigger the interchain transaction by calling the [`callContractWithToken()`](https://github.com/axelarnetwork/axelar-cgp-solidity/blob/4d01eb6ea1b5413520d9ecab804f815103021148/contracts/AxelarGateway.sol#L167) function defined on the Gateway.

```solidity
//send interchain tx
gateway.callContractWithToken(_destChain, destContractAddr, encodedMsg, symbol, _amount);
```

This function similarly requires the name of the destination chain, the target address on the destination chain, the data payload, the symbol of the token, and the amount of the token to be sent.

### Destination Chain Logic

Great! At this point, once the `interchainSwap()` function is called you will be sending a token as well as a GMP message containing an encoded `_receiver` address.

Now once the transaction has been sent through the Axelar blockchain and [confirmed by Axelar’s validators](https://axelar.network/blog/a-technical-introduction-to-the-axelar-network) the transaction will be received at the address you specified on the destination chain. Recall when writing the `interchainSwap()` function the second parameter is the address in which this transaction is going to be received on the destination chain.

Once on the destination chain, your contract will handle this transaction by implementing the [`_executeWithToken()`](https://github.com/axelarnetwork/axelar-gmp-sdk-solidity/blob/ad37802dc6d62fff3ab589f2605f7a3e566977dd/contracts/executable/AxelarExecutable.sol#L61) function

```solidity
function _executeWithToken(
  string calldata,
  string calldata,
  bytes calldata payload,
  string calldata,
  uint256 amount
) internal override {}
```

The `executeWithToken()` is defined in the `AxelarExecutable` contract you inherited earlier. You simply need to override the original definition of the function to implement your own custom logic. The `executeWithToken()` function is a special function that the [Axelar Relayer](https://docs.axelar.dev/learn#relayer-services) knows to execute as soon as it receives the confirmation from the Gateway that an approved interchain transaction was received from the Axelar network.

The function takes several parameters that you can see in the [source code](https://github.com/axelarnetwork/axelar-gmp-sdk-solidity/blob/ad37802dc6d62fff3ab589f2605f7a3e566977dd/contracts/executable/AxelarExecutable.sol#L61). For this challenge, the only two parameters you need to use are the payload and the amount. The payload contains the GMP message that was sent in the `interchainSwap()` function, the amount is the amount that was also sent in the previous function. Note that the payload is of type `bytes` not `address`, that is because in the `interchainSwap()` function the GMP message was encoded to type `bytes` before passing it into the `callContractWithToken()` function. So let’s decode the payload to access the encoded `address` and `boolean` that was passed in earlier.

```solidity
(address receiver, bool isInterchainTx) = abi.decode(payload, (address, bool));
```

Now that the data has been received on the destination chain you can call the already defined `tokenToEth()` function, using the data you received from your GMP message.

The completed function should now look like this

```solidity
function _executeWithToken(
  string calldata,
  string calldata,
  bytes calldata payload,
  string calldata,
  uint256 amount
) internal override {
  (address receiver, bool isInterchainTx) = abi.decode(payload, (address, bool));
  tokenToEth(receiver, isInterchainTx, amount);
}
```

At this point when your interchain transaction is triggered via the `interchainSwap()` function on the src chain your transaction should successfully transfer the tokens and GMP message via Axelar, then on the destination chain `_executeWithToken()` will be triggered, which will in turn trigger the `tokenToEth()` function.

## Interchain vs. Non-Interchain Transaction

Great! At this point the Axelar related functionality is complete. The final thing that needs to be completed is a slight tweak to the existing `tokenToEth()` function to handle the GMP messages you have passed in.

First, make sure to add in two additional parameters; the first being `isInterchainTx` and the second being `tokenInput`.

```solidity
function tokenToEth(
  address recipient,
  bool isInterchainTx,
  uint256 tokenInput
) public returns (uint256 ethOutput) {}
```

Now let’s create a conditional to see if the call to `tokenToEth()` is coming from an interchain call via the `_executeWithToken()` function or if it is being triggered on its own. If the transaction is an interchain transaction, then we can simply send the ETH from this contract’s own balance to the end recipient. Both the end recipient and the conditional are passed in as parameters, which were received via the GMP message sent from the source chain. In the “else” case you can leave the original logic sending the Eth via the `transferFrom()` function. Your function should now look like this.

```solidity
function tokenToEth(
  address recipient,
  bool isInterchainTx,
  uint256 tokenInput
) public returns (uint256 ethOutput) {
 
 require(tokenInput > 0, 'cannot swap 0 tokens');
 
 uint256 token_reserve = token.balanceOf(address(this));

 ethOutput = price(tokenInput, token_reserve, address(this).balance);

  if (isInterchainTx) {
    (bool sent, ) = payable(recipient).call{value: ethOutput}('');
    require(sent, 'tokenToEth: revert in transferring eth to you!');
  } else {
    require(token.transferFrom(msg.sender, address(this), tokenInput), 'tokenToEth(): reverted swap.');
    (bool sent, ) = msg.sender.call{value: ethOutput}('');
    require(sent, 'tokenToEth: revert in transferring eth to you!');
  }

  emit TokenToEthSwap(msg.sender, 'ERC20 to ETH', ethOutput, tokenInput);

  return ethOutput;
}
```

## Contract Deployment & Testing

Now that the contract is complete you can deploy and test it. To do so make use of the helper scripts available in the scripts folder.

To deploy on Polygon run:

```bash
hh run scripts/deployPolygon.ts --network polygon
```

To deploy on Fantom

```bash
hh run scripts/deployFantom.ts --network fantom
```

The output from each of these should be your address on each blockchain.

To interact with the function open your hardhat console by running

```bash
hh console –network fantom
```

Now in the console get access to a live instance of your contract.

```bash
Const Contract = await ethers.getContractFactory(“DexBonus”)
Const contract = await Contract.attach(<YOUR_ADDRESS>)
```

With your contract instance, you can now call the `interchainSwap` function.

```bash
await contract.interchainSwap(“Polygon”, <CONTRACT_ADDRESS_ON_POLYGON>, “aUSDC”, 2000000, {value: “2000000000000000000”})
```

The `interchainSwap` will send 2 aUSDC tokens to the Polygon chain with 2 FTM to cover the gas costs.

Once you execute this, you should see your transaction hash in the console which you can use in the Axelarscan explorer to see your live transaction!

The full execution should look like this in you terminal

![Axelar Dex Challenge Contract Interaction Hardhat CLI](https://lh7-us.googleusercontent.com/L_C53wxtGjspbQSmJbHHm6ckmMXpQaM40uCoEgDM9IhyZm3Uq0zILzPJ5YYZSl_j-ILtbTpOgOCw_SR7t8uWvmMZRi7v9C9xB71fhGWibwChYRxCBkLakeUNsrHHeUN6YUXNmWtBHjIigpIcJyM8CYM align="left")

On Axelarscan the interchain transaction should look like this.

![Axelarscan Live Transaction](https://lh7-us.googleusercontent.com/87a9b4OPXB4g74WHBewalp31s_qVPbqIlS2g56YM-vinKkRHfaIU2VcmsGQ95vSyM3PgOVRt6nE_DE2vkt5KsfvBD6aDLUjpyjJhjE-SU4zULnTjJwD5DT_9AA6LedbliFl5YsyfG_z1gKIy5mrKwd4 align="left")

## Conclusion

At this point, you should have a working contract where you can conduct a cross-chain swap of ERC20 token to a native token on any EVM chain connected to Axelar! For more examples of building interchain applications with Axelar please check out the [Axelar Examples Repo](https://github.com/axelarnetwork/axelar-examples/tree/main/examples/evm) and the [Axelar technical tutorial Youtube playlist](https://www.youtube.com/watch?v=I8m1XGUy8gY&list=PLh_q0hSKS_y23UECn5GJML0BDhJDDiiiL).
