Skip to content

Commit

Permalink
feat(evm): use gmp executable
Browse files Browse the repository at this point in the history
  • Loading branch information
ahramy committed Aug 29, 2024
1 parent 99af758 commit b21c98f
Show file tree
Hide file tree
Showing 7 changed files with 2,704 additions and 188 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import { AxelarExecutable } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/executable/AxelarExecutable.sol';
import { AxelarGMPExecutable } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/executable/AxelarGMPExecutable.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';
Expand All @@ -10,21 +10,21 @@ import { IERC20 } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interf
* @title CallContractGasEstimation
* @notice Send a message from chain A to chain B and stores gmp message
*/
contract CallContractGasEstimation is AxelarExecutable {
contract CallContractGasEstimation is AxelarGMPExecutable {
string public message;
string public sourceChain;
string public sourceAddress;
IAxelarGasService public immutable gasService;
uint256 public constant GAS_LIMIT = 200000;

event Executed(string _from, string _message);
event Executed(bytes32 commandId, 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) AxelarGMPExecutable(_gateway) {
gasService = IAxelarGasService(_gasReceiver);
}

Expand Down Expand Up @@ -76,7 +76,7 @@ contract CallContractGasEstimation is AxelarExecutable {
msg.sender,
new bytes(0)
);
gateway.callContract(destinationChain, destinationAddress, payload);
gateway().callContract(destinationChain, destinationAddress, payload);
}

/**
Expand All @@ -86,11 +86,11 @@ contract CallContractGasEstimation is AxelarExecutable {
* @param _sourceAddress address on src chain where tx is originating from
* @param _payload encoded gmp message sent from src chain
*/
function _execute(string calldata _sourceChain, string calldata _sourceAddress, bytes calldata _payload) internal override {
function _execute(bytes32 commandId,string calldata _sourceChain, string calldata _sourceAddress, bytes calldata _payload) internal override {
(message) = abi.decode(_payload, (string));
sourceChain = _sourceChain;
sourceAddress = _sourceAddress;

emit Executed(sourceAddress, message);
emit Executed(commandId, sourceAddress, message);
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
//SPDX-License-Identifier: MIT
pragma solidity 0.8.9;
pragma solidity ^0.8.0;

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

contract CallContractWithTokenExpress is AxelarExpressExecutable {
IAxelarGasService public immutable gasService;

event Executed(bytes32 commandId, string sourceChain, string sourceAddress, bytes payload);
event ExecutedWithToken(bytes32 commandId, string sourceChain, string sourceAddress, bytes payload, string tokenSymbol, uint256 amount);

constructor(address gateway_, address gasReceiver_) AxelarExpressExecutable(gateway_) {
gasService = IAxelarGasService(gasReceiver_);
}
Expand All @@ -22,9 +23,9 @@ contract CallContractWithTokenExpress is AxelarExpressExecutable {
string memory symbol,
uint256 amount
) external payable {
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);
if (msg.value > 0) {
gasService.payNativeGasForContractCallWithToken{ value: msg.value }(
Expand All @@ -37,23 +38,35 @@ contract CallContractWithTokenExpress is AxelarExpressExecutable {
msg.sender
);
}
gateway.callContractWithToken(destinationChain, destinationAddress, payload, symbol, amount);
gatewayWithToken().callContractWithToken(destinationChain, destinationAddress, payload, symbol, amount);
}

function _execute(
bytes32 commandId,
string calldata sourceChain,
string calldata sourceAddress,
bytes calldata payload
) internal override {
emit Executed(commandId,sourceChain, sourceAddress, payload);
}

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 ExecutedWithToken(commandId, sourceChain, sourceAddress, payload, tokenSymbol, amount);
}

function contractId() external pure returns (bytes32) {
Expand Down
38 changes: 22 additions & 16 deletions examples/evm/call-contract-with-token/CallContractWithToken.sol
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
//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 { AxelarGMPExecutableWithToken } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/executable/AxelarGMPExecutableWithToken.sol';
import { IAxelarGMPGateway } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarGMPGateway.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
* @title Call Contract With Token
* @notice Send a token along with an Axelar GMP message between two blockchains
*/
contract CallContractWithToken is AxelarExecutable {
contract CallContractWithToken is AxelarGMPExecutableWithToken {
IAxelarGasService public immutable gasService;

event Executed();
event Executed(bytes32 commandId, string sourceChain, string sourceAddress, bytes payload);
event ExecutedWithToken(bytes32 commandId, string sourceChain, string sourceAddress, bytes payload, string tokenSymbol, uint256 amount);

/**
*
*
* @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) AxelarGMPExecutableWithToken(_gateway) {
gasService = IAxelarGasService(_gasReceiver);
}

Expand All @@ -30,7 +30,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 @@ -43,9 +43,9 @@ contract CallContractWithToken is AxelarExecutable {
) external payable {
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 }(
address(this),
Expand All @@ -56,7 +56,11 @@ contract CallContractWithToken is AxelarExecutable {
amount,
msg.sender
);
gateway.callContractWithToken(destinationChain, destinationAddress, payload, symbol, amount);
gatewayWithToken().callContractWithToken(destinationChain, destinationAddress, payload, symbol, amount);
}

function _execute(bytes32 commandId,string calldata sourceChain, string calldata sourceAddress, bytes calldata payload) internal override {
emit Executed(commandId,sourceChain, sourceAddress, payload);
}

/**
Expand All @@ -67,20 +71,22 @@ contract CallContractWithToken is AxelarExecutable {
* @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();
emit ExecutedWithToken(commandId, sourceChain, sourceAddress, payload, tokenSymbol, amount);
}

}
14 changes: 7 additions & 7 deletions examples/evm/call-contract/CallContract.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import { AxelarExecutable } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/executable/AxelarExecutable.sol';
import { AxelarGMPExecutable } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/executable/AxelarGMPExecutable.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';
Expand All @@ -10,20 +10,20 @@ import { IERC20 } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interf
* @title CallContract
* @notice Send a message from chain A to chain B and stores gmp message
*/
contract CallContract is AxelarExecutable {
contract CallContract is AxelarGMPExecutable {
string public message;
string public sourceChain;
string public sourceAddress;
IAxelarGasService public immutable gasService;

event Executed(string _from, string _message);
event Executed(bytes32 commandId, 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) AxelarGMPExecutable(_gateway) {
gasService = IAxelarGasService(_gasReceiver);
}

Expand All @@ -49,7 +49,7 @@ contract CallContract is AxelarExecutable {
payload,
msg.sender
);
gateway.callContract(destinationChain, destinationAddress, payload);
gateway().callContract(destinationChain, destinationAddress, payload);
}

/**
Expand All @@ -59,11 +59,11 @@ contract CallContract is AxelarExecutable {
* @param _sourceAddress address on src chain where tx is originating from
* @param _payload encoded gmp message sent from src chain
*/
function _execute(string calldata _sourceChain, string calldata _sourceAddress, bytes calldata _payload) internal override {
function _execute(bytes32 commandId, string calldata _sourceChain, string calldata _sourceAddress, bytes calldata _payload) internal override {
(message) = abi.decode(_payload, (string));
sourceChain = _sourceChain;
sourceAddress = _sourceAddress;

emit Executed(sourceAddress, message);
emit Executed(commandId, sourceAddress, message);
}
}
2 changes: 1 addition & 1 deletion hardhat.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ require("@nomicfoundation/hardhat-chai-matchers")
*/
module.exports = {
solidity: {
version: '0.8.9',
version: '0.8.19',
settings: {
evmVersion: process.env.EVM_VERSION || 'london',
optimizer: {
Expand Down
Loading

0 comments on commit b21c98f

Please sign in to comment.