IntroductionEVM RelayerCosmos GMPSolidity UtilitiesSandbox
InterchainTokenServiceInterchainTokenFactoryTokenManagerAxelarGateway AxelarGasServiceAxelarExecutableAxelarJS SDK
Onboard your IBC chainBug Bounty
Crosschain Message FlowaxlUSDCSecurity OverviewInterchain Transaction DurationEVM Contract Governance

On-Chain Gas Estimation (Alpha)

💡

The on-chain gas estimation API is currently only available on testnet.

On-chain gas estimation allows you to estimate interchain transaction gas fees directly from a Solidity contract. You should only use this if you are unable to estimate gas off-chain — for example, if you have a dApp or service that does not have a UI for initiating transactions.

This on-chain API overestimates gas costs using a multiplier for volatility. For more accurate pricing, use the off-chain gas estimation API.

Usage

The on-chain API provided by the IInterchainGasEstimation interface, which is implemented by the AxelarGasService contract. Gas estimates will include a buffer, as they do not have access to real time off-chain gas pricing.

The primary method to invoke is estimateGasFee().

/**
 * @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);

When using on-chain gas estimation, you should pay gas based on the estimate from the new payGas() function on the gas service instead of calling payNativeGasForContractCall().

/**
 * @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;

Full GMP Example

The following is an example GMP contract that can send and receive messages. This contract can be found in the axelar-examples repository on GitHub.

// 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';

/**
 * @title CallContractGasEstimation
 * @notice Send a message from chain A to chain B and stores gmp message
 */
contract CallContractGasEstimation is AxelarExecutable {
    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);

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

    /**
     * @notice Estimate gas for a cross-chain contract call
     * @param destinationChain name of the dest chain
     * @param destinationAddress address on dest chain this tx is going to
     * @param _message message to be sent
     * @return gasEstimate The cross-chain gas estimate
     */
    function estimateGasFee(
        string calldata destinationChain,
        string calldata destinationAddress,
        string calldata _message
    ) external view returns (uint256) {
        bytes memory payload = abi.encode(_message);

        return gasService.estimateGasFee(
            destinationChain,
            destinationAddress,
            payload,
            GAS_LIMIT,
            new bytes(0)
        );
    }

    /**
     * @notice Send message from chain A to chain B
     * @dev message param is passed in as gmp message
     * @param destinationChain name of the dest chain (ex. "Fantom")
     * @param destinationAddress address on dest chain this tx is going to
     * @param _message message to be sent
     */
    function setRemoteValue(
        string calldata destinationChain,
        string calldata destinationAddress,
        string calldata _message
    ) external payable {
        require(msg.value > 0, 'Gas payment is required');

        bytes memory payload = abi.encode(_message);
        gasService.payGas{ value: msg.value }(
            address(this),
            destinationChain,
            destinationAddress,
            payload,
            GAS_LIMIT,
            true,
            msg.sender,
            new bytes(0)
        );
        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 _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 {
        (message) = abi.decode(_payload, (string));
        sourceChain = _sourceChain;
        sourceAddress = _sourceAddress;

        emit Executed(sourceAddress, message);
    }
}

Transaction execution

Transaction execution is not guaranteed with the on-chain gas estimation API. If you wish to guarantee that your transactions will be executed, please contact the Interop Labs team.

Edit this page