// Source: contracts/utils/GatewayCaller.sol pragma solidity ^0.8.0; // SPDX-License-Identifier: MIT // File @axelar-network/axelar-gmp-sdk-solidity/contracts/types/GasEstimationTypes.sol@v6.0.4 /** * @title GasEstimationType * @notice This enum represents the gas estimation types for different chains. */ enum GasEstimationType { Default, OptimismEcotone, OptimismBedrock, Arbitrum, Scroll } /** * @title GasInfo * @notice This struct represents the gas pricing information for a specific chain. * @dev Smaller uint types are used for efficient struct packing to save storage costs. */ struct GasInfo { /// @dev Custom gas pricing rule, such as L1 data fee on L2s uint64 gasEstimationType; /// @dev Scalar value needed for specific gas estimation types, expected to be less than 1e10 uint64 l1FeeScalar; /// @dev Axelar base fee for cross-chain message approval on destination, in terms of source native gas token uint128 axelarBaseFee; /// @dev Gas price of destination chain, in terms of the source chain token, i.e dest_gas_price * dest_token_market_price / src_token_market_price uint128 relativeGasPrice; /// @dev Needed for specific gas estimation types. Blob base fee of destination chain, in terms of the source chain token, i.e dest_blob_base_fee * dest_token_market_price / src_token_market_price uint128 relativeBlobBaseFee; /// @dev Axelar express fee for express execution, in terms of source chain token uint128 expressFee; } // File @axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IInterchainGasEstimation.sol@v6.0.4 /** * @title IInterchainGasEstimation Interface * @notice This is an interface for the InterchainGasEstimation contract * which allows for estimating gas fees for cross-chain communication on the Axelar network. */ interface IInterchainGasEstimation { error UnsupportedEstimationType(GasEstimationType gasEstimationType); /** * @notice Event emitted when the gas price for a specific chain is updated. * @param chain The name of the chain * @param info The gas info for the chain */ event GasInfoUpdated(string chain, GasInfo info); /** * @notice Returns the gas price for a specific chain. * @param chain The name of the chain * @return gasInfo The gas info for the chain */ function getGasInfo(string calldata chain) external view returns (GasInfo memory); /** * @notice Estimates the gas fee for a cross-chain contract call. * @param destinationChain Axelar registered name of the destination chain * @param destinationAddress Destination contract address being called * @param executionGasLimit The gas limit to be used for the destination contract execution, * e.g. pass in 200k if your app consumes needs upto 200k for this contract call * @param params Additional parameters for the gas estimation * @return gasEstimate The cross-chain gas estimate, in terms of source chain's native gas token that should be forwarded to the gas service. */ function estimateGasFee( string calldata destinationChain, string calldata destinationAddress, bytes calldata payload, uint256 executionGasLimit, bytes calldata params ) external view returns (uint256 gasEstimate); } // File @axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IContractIdentifier.sol@v6.0.4 // General interface for upgradable contracts interface IContractIdentifier { /** * @notice Returns the contract ID. It can be used as a check during upgrades. * @dev Meant to be overridden in derived contracts. * @return bytes32 The contract ID */ function contractId() external pure returns (bytes32); } // File @axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IImplementation.sol@v6.0.4 interface IImplementation is IContractIdentifier { error NotProxy(); function setup(bytes calldata data) external; } // File @axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IOwnable.sol@v6.0.4 /** * @title IOwnable Interface * @notice IOwnable is an interface that abstracts the implementation of a * contract with ownership control features. It's commonly used in upgradable * contracts and includes the functionality to get current owner, transfer * ownership, and propose and accept ownership. */ interface IOwnable { error NotOwner(); error InvalidOwner(); error InvalidOwnerAddress(); event OwnershipTransferStarted(address indexed newOwner); event OwnershipTransferred(address indexed newOwner); /** * @notice Returns the current owner of the contract. * @return address The address of the current owner */ function owner() external view returns (address); /** * @notice Returns the address of the pending owner of the contract. * @return address The address of the pending owner */ function pendingOwner() external view returns (address); /** * @notice Transfers ownership of the contract to a new address * @param newOwner The address to transfer ownership to */ function transferOwnership(address newOwner) external; /** * @notice Proposes to transfer the contract's ownership to a new address. * The new owner needs to accept the ownership explicitly. * @param newOwner The address to transfer ownership to */ function proposeOwnership(address newOwner) external; /** * @notice Transfers ownership to the pending owner. * @dev Can only be called by the pending owner */ function acceptOwnership() external; } // File @axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IUpgradable.sol@v6.0.4 // General interface for upgradable contracts interface IUpgradable is IOwnable, IImplementation { error InvalidCodeHash(); error InvalidImplementation(); error SetupFailed(); event Upgraded(address indexed newImplementation); function implementation() external view returns (address); function upgrade(address newImplementation, bytes32 newImplementationCodeHash, bytes calldata params) external; } // File @axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarGasService.sol@v6.0.4 /** * @title IAxelarGasService Interface * @notice This is an interface for the AxelarGasService contract which manages gas payments * and refunds for cross-chain communication on the Axelar network. * @dev This interface inherits IUpgradable */ interface IAxelarGasService is IInterchainGasEstimation, IUpgradable { error InvalidAddress(); error NotCollector(); error InvalidAmounts(); error InvalidGasUpdates(); error InvalidParams(); error InsufficientGasPayment(uint256 required, uint256 provided); event GasPaidForContractCall( address indexed sourceAddress, string destinationChain, string destinationAddress, bytes32 indexed payloadHash, address gasToken, uint256 gasFeeAmount, address refundAddress ); event GasPaidForContractCallWithToken( address indexed sourceAddress, string destinationChain, string destinationAddress, bytes32 indexed payloadHash, string symbol, uint256 amount, address gasToken, uint256 gasFeeAmount, address refundAddress ); event NativeGasPaidForContractCall( address indexed sourceAddress, string destinationChain, string destinationAddress, bytes32 indexed payloadHash, uint256 gasFeeAmount, address refundAddress ); event NativeGasPaidForContractCallWithToken( address indexed sourceAddress, string destinationChain, string destinationAddress, bytes32 indexed payloadHash, string symbol, uint256 amount, uint256 gasFeeAmount, address refundAddress ); event GasPaidForExpressCall( address indexed sourceAddress, string destinationChain, string destinationAddress, bytes32 indexed payloadHash, address gasToken, uint256 gasFeeAmount, address refundAddress ); event GasPaidForExpressCallWithToken( address indexed sourceAddress, string destinationChain, string destinationAddress, bytes32 indexed payloadHash, string symbol, uint256 amount, address gasToken, uint256 gasFeeAmount, address refundAddress ); event NativeGasPaidForExpressCall( address indexed sourceAddress, string destinationChain, string destinationAddress, bytes32 indexed payloadHash, uint256 gasFeeAmount, address refundAddress ); event NativeGasPaidForExpressCallWithToken( address indexed sourceAddress, string destinationChain, string destinationAddress, bytes32 indexed payloadHash, string symbol, uint256 amount, uint256 gasFeeAmount, address refundAddress ); event GasAdded(bytes32 indexed txHash, uint256 indexed logIndex, address gasToken, uint256 gasFeeAmount, address refundAddress); event NativeGasAdded(bytes32 indexed txHash, uint256 indexed logIndex, uint256 gasFeeAmount, address refundAddress); event ExpressGasAdded(bytes32 indexed txHash, uint256 indexed logIndex, address gasToken, uint256 gasFeeAmount, address refundAddress); event NativeExpressGasAdded(bytes32 indexed txHash, uint256 indexed logIndex, uint256 gasFeeAmount, address refundAddress); event Refunded(bytes32 indexed txHash, uint256 indexed logIndex, address payable receiver, address token, uint256 amount); /** * @notice Pay for gas for any type of contract execution on a destination chain. * @dev This function is called on the source chain before calling the gateway to execute a remote contract. * @dev If estimateOnChain is true, the function will estimate the gas cost and revert if the payment is insufficient. * @param sender The address making the payment * @param destinationChain The target chain where the contract call will be made * @param destinationAddress The target address on the destination chain * @param payload Data payload for the contract call * @param executionGasLimit The gas limit for the contract call * @param estimateOnChain Flag to enable on-chain gas estimation * @param refundAddress The address where refunds, if any, should be sent * @param params Additional parameters for gas payment. This can be left empty for normal contract call payments. */ function payGas( address sender, string calldata destinationChain, string calldata destinationAddress, bytes calldata payload, uint256 executionGasLimit, bool estimateOnChain, address refundAddress, bytes calldata params ) external payable; /** * @notice Pay for gas using ERC20 tokens for a contract call on a destination chain. * @dev This function is called on the source chain before calling the gateway to execute a remote contract. * @param sender The address making the payment * @param destinationChain The target chain where the contract call will be made * @param destinationAddress The target address on the destination chain * @param payload Data payload for the contract call * @param gasToken The address of the ERC20 token used to pay for gas * @param gasFeeAmount The amount of tokens to pay for gas * @param refundAddress The address where refunds, if any, should be sent */ function payGasForContractCall( address sender, string calldata destinationChain, string calldata destinationAddress, bytes calldata payload, address gasToken, uint256 gasFeeAmount, address refundAddress ) external; /** * @notice Pay for gas using ERC20 tokens for a contract call with tokens on a destination chain. * @dev This function is called on the source chain before calling the gateway to execute a remote contract. * @param sender The address making the payment * @param destinationChain The target chain where the contract call with tokens will be made * @param destinationAddress The target address on the destination chain * @param payload Data payload for the contract call with tokens * @param symbol The symbol of the token to be sent with the call * @param amount The amount of tokens to be sent with the call * @param gasToken The address of the ERC20 token used to pay for gas * @param gasFeeAmount The amount of tokens to pay for gas * @param refundAddress The address where refunds, if any, should be sent */ function payGasForContractCallWithToken( address sender, string calldata destinationChain, string calldata destinationAddress, bytes calldata payload, string calldata symbol, uint256 amount, address gasToken, uint256 gasFeeAmount, address refundAddress ) external; /** * @notice Pay for gas using native currency for a contract call on a destination chain. * @dev This function is called on the source chain before calling the gateway to execute a remote contract. * @param sender The address making the payment * @param destinationChain The target chain where the contract call will be made * @param destinationAddress The target address on the destination chain * @param payload Data payload for the contract call * @param refundAddress The address where refunds, if any, should be sent */ function payNativeGasForContractCall( address sender, string calldata destinationChain, string calldata destinationAddress, bytes calldata payload, address refundAddress ) external payable; /** * @notice Pay for gas using native currency for a contract call with tokens on a destination chain. * @dev This function is called on the source chain before calling the gateway to execute a remote contract. * @param sender The address making the payment * @param destinationChain The target chain where the contract call with tokens will be made * @param destinationAddress The target address on the destination chain * @param payload Data payload for the contract call with tokens * @param symbol The symbol of the token to be sent with the call * @param amount The amount of tokens to be sent with the call * @param refundAddress The address where refunds, if any, should be sent */ function payNativeGasForContractCallWithToken( address sender, string calldata destinationChain, string calldata destinationAddress, bytes calldata payload, string calldata symbol, uint256 amount, address refundAddress ) external payable; /** * @notice Pay for gas using ERC20 tokens for an express contract call on a destination chain. * @dev This function is called on the source chain before calling the gateway to express execute a remote contract. * @param sender The address making the payment * @param destinationChain The target chain where the contract call will be made * @param destinationAddress The target address on the destination chain * @param payload Data payload for the contract call * @param gasToken The address of the ERC20 token used to pay for gas * @param gasFeeAmount The amount of tokens to pay for gas * @param refundAddress The address where refunds, if any, should be sent */ function payGasForExpressCall( address sender, string calldata destinationChain, string calldata destinationAddress, bytes calldata payload, address gasToken, uint256 gasFeeAmount, address refundAddress ) external; /** * @notice Pay for gas using ERC20 tokens for an express contract call with tokens on a destination chain. * @dev This function is called on the source chain before calling the gateway to express execute a remote contract. * @param sender The address making the payment * @param destinationChain The target chain where the contract call with tokens will be made * @param destinationAddress The target address on the destination chain * @param payload Data payload for the contract call with tokens * @param symbol The symbol of the token to be sent with the call * @param amount The amount of tokens to be sent with the call * @param gasToken The address of the ERC20 token used to pay for gas * @param gasFeeAmount The amount of tokens to pay for gas * @param refundAddress The address where refunds, if any, should be sent */ function payGasForExpressCallWithToken( address sender, string calldata destinationChain, string calldata destinationAddress, bytes calldata payload, string calldata symbol, uint256 amount, address gasToken, uint256 gasFeeAmount, address refundAddress ) external; /** * @notice Pay for gas using native currency for an express contract call on a destination chain. * @dev This function is called on the source chain before calling the gateway to execute a remote contract. * @param sender The address making the payment * @param destinationChain The target chain where the contract call will be made * @param destinationAddress The target address on the destination chain * @param payload Data payload for the contract call * @param refundAddress The address where refunds, if any, should be sent */ function payNativeGasForExpressCall( address sender, string calldata destinationChain, string calldata destinationAddress, bytes calldata payload, address refundAddress ) external payable; /** * @notice Pay for gas using native currency for an express contract call with tokens on a destination chain. * @dev This function is called on the source chain before calling the gateway to execute a remote contract. * @param sender The address making the payment * @param destinationChain The target chain where the contract call with tokens will be made * @param destinationAddress The target address on the destination chain * @param payload Data payload for the contract call with tokens * @param symbol The symbol of the token to be sent with the call * @param amount The amount of tokens to be sent with the call * @param refundAddress The address where refunds, if any, should be sent */ function payNativeGasForExpressCallWithToken( address sender, string calldata destinationChain, string calldata destinationAddress, bytes calldata payload, string calldata symbol, uint256 amount, address refundAddress ) external payable; /** * @notice Add additional gas payment using ERC20 tokens after initiating a cross-chain call. * @dev This function can be called on the source chain after calling the gateway to execute a remote contract. * @param txHash The transaction hash of the cross-chain call * @param logIndex The log index for the cross-chain call * @param gasToken The ERC20 token address used to add gas * @param gasFeeAmount The amount of tokens to add as gas * @param refundAddress The address where refunds, if any, should be sent */ function addGas(bytes32 txHash, uint256 logIndex, address gasToken, uint256 gasFeeAmount, address refundAddress) external; /** * @notice Add additional gas payment using native currency after initiating a cross-chain call. * @dev This function can be called on the source chain after calling the gateway to execute a remote contract. * @param txHash The transaction hash of the cross-chain call * @param logIndex The log index for the cross-chain call * @param refundAddress The address where refunds, if any, should be sent */ function addNativeGas(bytes32 txHash, uint256 logIndex, address refundAddress) external payable; /** * @notice Add additional gas payment using ERC20 tokens after initiating an express cross-chain call. * @dev This function can be called on the source chain after calling the gateway to express execute a remote contract. * @param txHash The transaction hash of the cross-chain call * @param logIndex The log index for the cross-chain call * @param gasToken The ERC20 token address used to add gas * @param gasFeeAmount The amount of tokens to add as gas * @param refundAddress The address where refunds, if any, should be sent */ function addExpressGas(bytes32 txHash, uint256 logIndex, address gasToken, uint256 gasFeeAmount, address refundAddress) external; /** * @notice Add additional gas payment using native currency after initiating an express cross-chain call. * @dev This function can be called on the source chain after calling the gateway to express execute a remote contract. * @param txHash The transaction hash of the cross-chain call * @param logIndex The log index for the cross-chain call * @param refundAddress The address where refunds, if any, should be sent */ function addNativeExpressGas(bytes32 txHash, uint256 logIndex, address refundAddress) external payable; /** * @notice Updates the gas price for a specific chain. * @dev This function is called by the gas oracle to update the gas prices for a specific chains. * @param chains Array of chain names * @param gasUpdates Array of gas updates */ function updateGasInfo(string[] calldata chains, GasInfo[] calldata gasUpdates) external; /** * @notice Allows the gasCollector to collect accumulated fees from the contract. * @dev Use address(0) as the token address for native currency. * @param receiver The address to receive the collected fees * @param tokens Array of token addresses to be collected * @param amounts Array of amounts to be collected for each respective token address */ function collectFees(address payable receiver, address[] calldata tokens, uint256[] calldata amounts) external; /** * @notice Refunds gas payment to the receiver in relation to a specific cross-chain transaction. * @dev Only callable by the gasCollector. * @dev Use address(0) as the token address to refund native currency. * @param txHash The transaction hash of the cross-chain call * @param logIndex The log index for the cross-chain call * @param receiver The address to receive the refund * @param token The token address to be refunded * @param amount The amount to refund */ function refund(bytes32 txHash, uint256 logIndex, address payable receiver, address token, uint256 amount) external; /** * @notice Returns the address of the designated gas collector. * @return address of the gas collector */ function gasCollector() external returns (address); } // File @axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarGateway.sol@v6.0.4 /** * @title IAxelarGateway * @dev Interface for the Axelar Gateway that supports general message passing and contract call execution. */ interface IAxelarGateway { /** * @notice Emitted when a contract call is made through the gateway. * @dev Logs the attempt to call a contract on another chain. * @param sender The address of the sender who initiated the contract call. * @param destinationChain The name of the destination chain. * @param destinationContractAddress The address of the contract on the destination chain. * @param payloadHash The keccak256 hash of the sent payload data. * @param payload The payload data used for the contract call. */ event ContractCall( address indexed sender, string destinationChain, string destinationContractAddress, bytes32 indexed payloadHash, bytes payload ); /** * @notice Sends a contract call to another chain. * @dev Initiates a cross-chain contract call through the gateway to the specified destination chain and contract. * @param destinationChain The name of the destination chain. * @param contractAddress The address of the contract on the destination chain. * @param payload The payload data to be used in the contract call. */ function callContract(string calldata destinationChain, string calldata contractAddress, bytes calldata payload) external; /** * @notice Checks if a contract call is approved. * @dev Determines whether a given contract call, identified by the commandId and payloadHash, is approved. * @param commandId The identifier of the command to check. * @param sourceChain The name of the source chain. * @param sourceAddress The address of the sender on the source chain. * @param contractAddress The address of the contract where the call will be executed. * @param payloadHash The keccak256 hash of the payload data. * @return True if the contract call is approved, false otherwise. */ function isContractCallApproved( bytes32 commandId, string calldata sourceChain, string calldata sourceAddress, address contractAddress, bytes32 payloadHash ) external view returns (bool); /** * @notice Validates and approves a contract call. * @dev Validates the given contract call information and marks it as approved if valid. * @param commandId The identifier of the command to validate. * @param sourceChain The name of the source chain. * @param sourceAddress The address of the sender on the source chain. * @param payloadHash The keccak256 hash of the payload data. * @return True if the contract call is validated and approved, false otherwise. */ function validateContractCall( bytes32 commandId, string calldata sourceChain, string calldata sourceAddress, bytes32 payloadHash ) external returns (bool); /** * @notice Checks if a command has been executed. * @dev Determines whether a command, identified by the commandId, has been executed. * @param commandId The identifier of the command to check. * @return True if the command has been executed, false otherwise. */ function isCommandExecuted(bytes32 commandId) external view returns (bool); } // File contracts/interfaces/IGatewayCaller.sol /** * @title IGatewayCaller interface * @dev Interface for the GatewayCaller contract */ interface IGatewayCaller { /** * @dev Enum representing different metadata versions */ enum MetadataVersion { CONTRACT_CALL, EXPRESS_CALL } /** * @dev Error thrown when an invalid metadata version is provided */ error InvalidMetadataVersion(uint32 metadataVersion); /** * @notice Call the Axelar gateway to send a payload to a destination contract on a specific destination chain * @param destinationChain The target chain where the contract will be called * @param destinationAddress The address of the contract to be called on the destination chain * @param payload The data payload for the transaction * @param metadataVersion The version of metadata to be used * @param gasValue The amount of gas to be paid for the cross-chain message. If this is 0, then gas payment is skipped. `msg.value` must be at least gasValue. */ function callContract( string calldata destinationChain, string calldata destinationAddress, bytes calldata payload, MetadataVersion metadataVersion, uint256 gasValue ) external payable; } // File contracts/utils/GatewayCaller.sol /** * @title GatewayCaller contract * @dev This contract is used to handle cross-chain ITS calls via the Axelar gateway. */ contract GatewayCaller is IGatewayCaller { IAxelarGateway public immutable gateway; IAxelarGasService public immutable gasService; /** * @dev Constructor to initialize the GatewayCaller contract * @param gateway_ The address of the AxelarGateway contract * @param gasService_ The address of the AxelarGasService contract */ constructor(address gateway_, address gasService_) { gateway = IAxelarGateway(gateway_); gasService = IAxelarGasService(gasService_); } /** * @dev Calls a contract on a specific destination chain with the given payload * @param destinationChain The target chain where the contract will be called * @param destinationAddress The address of the contract to be called on the destination chain * @param payload The data payload for the transaction * @param metadataVersion The version of metadata to be used * @param gasValue The amount of gas to be paid for the cross-chain message. If this is 0, then gas payment is skipped. `msg.value` must be at least gasValue. */ function callContract( string calldata destinationChain, string calldata destinationAddress, bytes calldata payload, MetadataVersion metadataVersion, uint256 gasValue ) external payable override { if (gasValue > 0) { if (metadataVersion == MetadataVersion.CONTRACT_CALL) { // slither-disable-next-line arbitrary-send-eth gasService.payNativeGasForContractCall{ value: gasValue }( address(this), destinationChain, destinationAddress, payload, // solhint-disable-next-line avoid-tx-origin tx.origin ); } else if (metadataVersion == MetadataVersion.EXPRESS_CALL) { // slither-disable-next-line arbitrary-send-eth gasService.payNativeGasForExpressCall{ value: gasValue }( address(this), destinationChain, destinationAddress, payload, // solhint-disable-next-line avoid-tx-origin tx.origin ); } else { revert InvalidMetadataVersion(uint32(metadataVersion)); } } gateway.callContract(destinationChain, destinationAddress, payload); } }