Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(evm)!: update evm examples with AxelarExecutable and AxelarExecutableWithToken #198

Merged
merged 11 commits into from
Oct 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading