Skip to content

Commit

Permalink
feat(evm)!: update evm examples with AxelarExecutable and AxelarExecu…
Browse files Browse the repository at this point in the history
…tableWithToken (#198)
  • Loading branch information
ahramy authored Oct 24, 2024
1 parent edd8396 commit 502d741
Show file tree
Hide file tree
Showing 33 changed files with 381 additions and 272 deletions.
Original file line number Diff line number Diff line change
@@ -1,26 +1,28 @@
//SPDX-License-Identifier: MIT
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 { IERC20 } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IERC20.sol';
import { IAxelarGasService } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarGasService.sol';
import {AxelarExecutableWithToken} from "@axelar-network/axelar-gmp-sdk-solidity/contracts/executable/AxelarExecutableWithToken.sol";
import {IERC20} from "@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IERC20.sol";
import {IAxelarGasService} from "@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarGasService.sol";

/**
* @title Call Contract With Token Contract
* @notice Send a token along with an Axelar GMP message between two blockchains
*/
contract CallContractWithToken is AxelarExecutable {
contract CallContractWithToken is AxelarExecutableWithToken {
IAxelarGasService public immutable gasService;

event Executed();

/**
*
*
* @param _gateway address of axl gateway on deployed chain
* @param _gasReceiver address of axl gas service on deployed chain
*/
constructor(address _gateway, address _gasReceiver) AxelarExecutable(_gateway) {
constructor(
address _gateway,
address _gasReceiver
) AxelarExecutableWithToken(_gateway) {
gasService = IAxelarGasService(_gasReceiver);
}

Expand All @@ -29,7 +31,7 @@ contract CallContractWithToken is AxelarExecutable {
* @dev destinationAddresses will be passed in as gmp message in this tx
* @param destinationChain name of the dest chain (ex. "Fantom")
* @param destinationAddress address on dest chain this tx is going to
* @param destinationAddresses recipient addresses receiving sent funds
* @param destinationAddresses recipient addresses receiving sent funds
* @param symbol symbol of token being sent
* @param amount amount of tokens being sent
*/
Expand All @@ -40,13 +42,13 @@ contract CallContractWithToken is AxelarExecutable {
string memory symbol,
uint256 amount
) external payable {
require(msg.value > 0, 'Gas payment is required');
require(msg.value > 0, "Gas payment is required");

address tokenAddress = gateway.tokenAddresses(symbol);
address tokenAddress = gatewayWithToken().tokenAddresses(symbol);
IERC20(tokenAddress).transferFrom(msg.sender, address(this), amount);
IERC20(tokenAddress).approve(address(gateway), amount);
IERC20(tokenAddress).approve(address(gatewayWithToken()), amount);
bytes memory payload = abi.encode(destinationAddresses);
gasService.payNativeGasForContractCallWithToken{ value: msg.value }(
gasService.payNativeGasForContractCallWithToken{value: msg.value}(
address(this),
destinationChain,
destinationAddress,
Expand All @@ -55,34 +57,47 @@ contract CallContractWithToken is AxelarExecutable {
amount,
msg.sender
);
gateway.callContractWithToken(destinationChain, destinationAddress, payload, symbol, amount);
gatewayWithToken().callContractWithToken(
destinationChain,
destinationAddress,
payload,
symbol,
amount
);
}



/**
* @notice logic to be executed on dest chain
* @dev this is triggered automatically by relayer
* @param
* @param
* @param
* @param payload encoded gmp message sent from src chain
* @param tokenSymbol symbol of token sent from src chain
* @param amount amount of tokens sent from src chain
*/
function _executeWithToken(
string calldata,
string calldata,
bytes32 /*commandId*/,
string calldata /*sourceChain*/,
string calldata /*sourceAddress*/,
bytes calldata payload,
string calldata tokenSymbol,
uint256 amount
) internal override {
address[] memory recipients = abi.decode(payload, (address[]));
address tokenAddress = gateway.tokenAddresses(tokenSymbol);
address tokenAddress = gatewayWithToken().tokenAddresses(tokenSymbol);

uint256 sentAmount = amount / recipients.length;
for (uint256 i = 0; i < recipients.length; i++) {
IERC20(tokenAddress).transfer(recipients[i], sentAmount);
}
emit Executed();
}

function _execute(
bytes32 commandId,
string calldata sourceChain,
string calldata sourceAddress,
bytes calldata payload
) internal virtual override {}
}
26 changes: 14 additions & 12 deletions examples-web/contracts/call-contract/CallContract.sol
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
// SPDX-License-Identifier: MIT
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';
import { IERC20 } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IERC20.sol';
import {AxelarExecutable} from "@axelar-network/axelar-gmp-sdk-solidity/contracts/executable/AxelarExecutable.sol";
import {IAxelarGasService} from "@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarGasService.sol";
import {IERC20} from "@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IERC20.sol";

/**
* @title CallContract
* @notice Send a message from chain A to chain B and stores gmp message */
contract CallContract is AxelarExecutable {

string public message;

string public sourceChain;
Expand All @@ -20,11 +18,14 @@ contract CallContract is AxelarExecutable {
event Executed(string _from, string _message);

/**
*
*
* @param _gateway address of axl gateway on deployed chain
* @param _gasReceiver address of axl gas service on deployed chain
*/
constructor(address _gateway, address _gasReceiver) AxelarExecutable(_gateway) {
constructor(
address _gateway,
address _gasReceiver
) AxelarExecutable(_gateway) {
gasService = IAxelarGasService(_gasReceiver);
}

Expand All @@ -40,27 +41,29 @@ contract CallContract is AxelarExecutable {
string calldata destinationAddress,
string calldata _message
) external payable {
require(msg.value > 0, 'Gas payment is required');
require(msg.value > 0, "Gas payment is required");

bytes memory payload = abi.encode(_message);
gasService.payNativeGasForContractCall{ value: msg.value }(
gasService.payNativeGasForContractCall{value: msg.value}(
address(this),
destinationChain,
destinationAddress,
payload,
msg.sender
);
gateway.callContract(destinationChain, destinationAddress, payload);
gateway().callContract(destinationChain, destinationAddress, payload);
}

/**
* @notice logic to be executed on dest chain
* @dev this is triggered automatically by relayer
* @param _sourceChain blockchain where tx is originating from
* @param
* @param _sourceChain blockchain where tx is originating from
* @param _sourceAddress address on src chain where tx is originating from
* @param _payload encoded gmp message sent from src chain
*/
function _execute(
bytes32 /*commandId*/,
string calldata _sourceChain,
string calldata _sourceAddress,
bytes calldata _payload
Expand All @@ -70,6 +73,5 @@ contract CallContract is AxelarExecutable {
sourceAddress = _sourceAddress;

emit Executed(sourceAddress, message);

}
}
17 changes: 8 additions & 9 deletions examples-web/contracts/nft-linker/NFTLinker.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ pragma solidity ^0.8.0;

import {IERC20} from "@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IERC20.sol";
import {IAxelarGasService} from "@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarGasService.sol";
import {IAxelarGateway} from "@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarGateway.sol";
import {AxelarExecutable} from "@axelar-network/axelar-gmp-sdk-solidity/contracts/executable/AxelarExecutable.sol";
import {Upgradable} from "@axelar-network/axelar-gmp-sdk-solidity/contracts/upgradable/Upgradable.sol";
import {StringToAddress, AddressToString} from "@axelar-network/axelar-gmp-sdk-solidity/contracts/libs/AddressString.sol";
Expand All @@ -24,7 +23,7 @@ contract NftLinker is ERC721URIStorage, AxelarExecutable, Upgradable {
error AlreadyInitialized();

/**
*
*
* @param _gateway address of axl gateway on deployed chain
* @param _gasReceiver address of axl gas service on deployed chain
*/
Expand All @@ -49,7 +48,7 @@ contract NftLinker is ERC721URIStorage, AxelarExecutable, Upgradable {
* @notice send nft from src chain to dest chain
* @param operator contract handling the nft briding
* @param tokenId id of the token being sent
* @param destinationChain name of the dest chain
* @param destinationChain name of the dest chain
* @param destinationAddress address on dest chain tx is going to
*/
function sendNFT(
Expand Down Expand Up @@ -81,7 +80,7 @@ contract NftLinker is ERC721URIStorage, AxelarExecutable, Upgradable {
* @notice Burns and sends interchain nft tx
* @dev Used when sending nft back to origin chain
* @param tokenId id of nft to be bridged
* @param destinationChain name of the dest chain
* @param destinationChain name of the dest chain
* @param destinationAddress address on dest chain tx is going to
*/
function _sendMintedToken(
Expand Down Expand Up @@ -115,16 +114,15 @@ contract NftLinker is ERC721URIStorage, AxelarExecutable, Upgradable {
msg.sender
);
//Call the remote contract.
gateway.callContract(destinationChain, stringAddress, payload);
gateway().callContract(destinationChain, stringAddress, payload);
}


/**
* @notice Locks and sends a token from src to dest chain.
* @dev Used when sending from original chain to dest
* @param operator contract handling the nft briding
* @param tokenId id of nft to be bridged
* @param destinationChain name of the dest chain
* @param destinationChain name of the dest chain
* @param destinationAddress address on dest chain tx is going to
*/
function _sendNativeToken(
Expand Down Expand Up @@ -152,17 +150,18 @@ contract NftLinker is ERC721URIStorage, AxelarExecutable, Upgradable {
msg.sender
);
//Call remote contract.
gateway.callContract(destinationChain, stringAddress, payload);
gateway().callContract(destinationChain, stringAddress, payload);
}

/**
/**
* @notice logic to be executed on dest chain
* @dev this is triggered automatically by relayer since gas was paid for
* @param
* @param sourceAddress address on src chain where tx is originating from
* @param payload encoded gmp message sent from src chain
*/
function _execute(
bytes32 /*commandId*/,
string calldata /*sourceChain*/,
string calldata sourceAddress,
bytes calldata payload
Expand Down
46 changes: 38 additions & 8 deletions examples-web/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion examples-web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"contracts:clean": "rm -rf artifacts src/types"
},
"dependencies": {
"@axelar-network/axelar-gmp-sdk-solidity": "^5.3.1",
"@axelar-network/axelar-gmp-sdk-solidity": "^6.0.0",
"@axelar-network/axelar-local-dev": "^2.1.1",
"@axelar-network/axelarjs-sdk": "^0.15.0",
"@openzeppelin/contracts": "^4.8.1",
Expand Down
Loading

0 comments on commit 502d741

Please sign in to comment.