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 on GitHub