Skip to content

Commit

Permalink
implement GoFastHandler contract
Browse files Browse the repository at this point in the history
  • Loading branch information
thal0x committed Nov 4, 2024
1 parent a95690a commit 863d421
Show file tree
Hide file tree
Showing 5 changed files with 356 additions and 34 deletions.
7 changes: 7 additions & 0 deletions AxelarHandler/remappings.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
lib/axelar-gmp-sdk-solidity/=lib/axelar-gmp-sdk-solidity/
lib/ds-test/=lib/forge-std/lib/ds-test/src/
lib/erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/
lib/forge-std/=lib/forge-std
lib/openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/
lib/openzeppelin-contracts/=lib/openzeppelin-contracts/
lib/openzeppelin/=lib/openzeppelin-contracts-upgradeable/contracts/
45 changes: 11 additions & 34 deletions AxelarHandler/src/AxelarExecutableUpgradeable.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,11 @@ contract AxelarExecutableUpgradeable is IAxelarExecutable, Initializable {
_disableInitializers();
}

function __AxelarExecutable_init(
address axelarGateway
) internal onlyInitializing {
function __AxelarExecutable_init(address axelarGateway) internal onlyInitializing {
__AxelarExecutable_init_unchained(axelarGateway);
}

function __AxelarExecutable_init_unchained(
address axelarGateway
) internal onlyInitializing {
function __AxelarExecutable_init_unchained(address axelarGateway) internal onlyInitializing {
gateway = IAxelarGateway(axelarGateway);
}

Expand All @@ -40,14 +36,9 @@ contract AxelarExecutableUpgradeable is IAxelarExecutable, Initializable {
) external {
bytes32 payloadHash = keccak256(payload);

if (
!gateway.validateContractCall(
commandId,
sourceChain,
sourceAddress,
payloadHash
)
) revert NotApprovedByGateway();
if (!gateway.validateContractCall(commandId, sourceChain, sourceAddress, payloadHash)) {
revert NotApprovedByGateway();
}

_execute(sourceChain, sourceAddress, payload);
}
Expand All @@ -63,30 +54,16 @@ contract AxelarExecutableUpgradeable is IAxelarExecutable, Initializable {
bytes32 payloadHash = keccak256(payload);

if (
!gateway.validateContractCallAndMint(
commandId,
sourceChain,
sourceAddress,
payloadHash,
tokenSymbol,
amount
)
!gateway.validateContractCallAndMint(commandId, sourceChain, sourceAddress, payloadHash, tokenSymbol, amount)
) revert NotApprovedByGateway();

_executeWithToken(
sourceChain,
sourceAddress,
payload,
tokenSymbol,
amount
);
_executeWithToken(sourceChain, sourceAddress, payload, tokenSymbol, amount);
}

function _execute(
string calldata sourceChain,
string calldata sourceAddress,
bytes calldata payload
) internal virtual {}
function _execute(string calldata sourceChain, string calldata sourceAddress, bytes calldata payload)
internal
virtual
{}

function _executeWithToken(
string calldata sourceChain,
Expand Down
73 changes: 73 additions & 0 deletions AxelarHandler/src/GoFastHandler.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

import {IERC20} from "lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol";

import {ISwapRouter02} from "./interfaces/ISwapRouter02.sol";
import {IFastTransferGateway} from "./interfaces/IFastTransferGateway.sol";

contract GoFastHandler {
using SafeERC20 for IERC20;

ISwapRouter02 public swapRouter;
IFastTransferGateway public fastTransferGateway;

constructor(address _swapRouter, address _fastTransferGateway) {
swapRouter = ISwapRouter02(_swapRouter);
fastTransferGateway = IFastTransferGateway(_fastTransferGateway);
}

function swapAndSubmitOrder(
address tokenIn,
uint256 swapAmountIn,
bytes memory swapCalldata,
uint256 feeAmount,
bytes32 sender,
bytes32 recipient,
uint32 destinationDomain,
uint64 timeoutTimestamp,
bytes calldata destinationCalldata
) public payable returns (bytes32) {
require(feeAmount != 0, "fast transfer fee cannot be zero");

uint256 swapAmountOut = _swap(tokenIn, swapAmountIn, swapCalldata);

require(swapAmountOut >= feeAmount, "amount received from swap is less than fast transfer fee");

// this is the amount that the recipient will receive on the destination chain
uint256 swapAmountOutAfterFee = swapAmountOut - feeAmount;

return fastTransferGateway.submitOrder(
sender,
recipient,
swapAmountOut,
swapAmountOutAfterFee,
destinationDomain,
timeoutTimestamp,
destinationCalldata
);
}

function _swap(address tokenIn, uint256 amountIn, bytes memory swapCalldata) internal returns (uint256 amountOut) {
address tokenOut = fastTransferGateway.token();

uint256 tokenOutBalanceBefore = IERC20(tokenOut).balanceOf(address(this));

if (tokenIn != address(0)) {
IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);

IERC20(tokenIn).safeApprove(address(swapRouter), amountIn);
}

(bool success,) = address(swapRouter).call{value: msg.value}(swapCalldata);
if (!success) {
assembly {
returndatacopy(0, 0, returndatasize())
revert(0, returndatasize())
}
}

amountOut = IERC20(tokenOut).balanceOf(address(this)) - tokenOutBalanceBefore;
}
}
16 changes: 16 additions & 0 deletions AxelarHandler/src/interfaces/IFastTransferGateway.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

interface IFastTransferGateway {
function submitOrder(
bytes32 sender,
bytes32 recipient,
uint256 amountIn,
uint256 amountOut,
uint32 destinationDomain,
uint64 timeoutTimestamp,
bytes calldata data
) external returns (bytes32);

function token() external view returns (address);
}
Loading

0 comments on commit 863d421

Please sign in to comment.