Interchain Gas Payment
To deliver a message, a transaction must be included on the destination chain that calls the Mailbox process
function with the encoded message and ISM metadata.
For convenience, a relayer watches for dispatched messages and will submit process transactions on behalf of the message sender if they receive sufficient payment on the origin chain. We refer to this as interchain gas payment.
Because messages can trigger arbitrary code execution, the relayer must meter the handle
call with a gasLimit
to charge appropriately at message dispatch time.
Destination Gas Config
For each remote domain, you can set the domain gas config.
struct DomainGasConfig {
IGasOracle gasOracle;
uint96 gasOverhead;
}
gasOracle
The gasOracle
is a contract containing the exchange rates between supported origin and destination chains.
gasOverhead
The gasOverhead
is the operational cost of processing a message on the destination chain. When returning a quote for the cost of dispatching a message, the IGP contract will add this gasOverhead
to the gasLimit
.
Post Dispatch
During the post-dispatch hook, the InterchainGasPaymaster
contract will revert if payment is insufficient to cover the relayer's anticipated costs. The relayer will honor quotes from dispatch
time.
Gas Limit
When none is specified, the gasLimit
for metering the handle
call uses a static default of 50_000
.
We recommend developers benchmark their handle
implementations in unit tests to determine a reasonable gasLimit
to use.
If you expect the handle
function to consume more than this default, you should override the default gasLimit
in metadata.
Metadata
This hook expects metadata in a packed encoding of StandardHookMetadata
. See the Mailbox dispatch overloads for how to pass metadata overrides.
- Solidity
struct StandardHookMetadata {
uint16 variant;
uint256 msgValue;
uint256 gasLimit;
address refundAddress;
}
Examples
bytes memory metadata = abi.encodePacked(
StandardHookMetadata({
variant: 1, // only variant supported by this hook
msgValue: 0, // unused by this hook
gasLimit: 100000, // override default gas limit
refundAddress: msg.sender // override default refund address
})
);
Gas Oracles
The interchain gas payment requirement is calculated using oraclized gas price and exchange rates between supported origin and destination chains.
Exchange rates and gas prices are up to the relayer to decide. A spread may be charged to account for drift and operating costs.
- Solidity
function getExchangeRateAndGasPrice(
uint32 _destinationDomain
)
public
view
override
returns (uint128 tokenExchangeRate, uint128 gasPrice)
{
IGasOracle _gasOracle = destinationGasConfigs[_destinationDomain]
.gasOracle;
require(
address(_gasOracle) != address(0),
string.concat(
"Configured IGP doesn't support domain ",
Strings.toString(_destinationDomain)
)
);
return _gasOracle.getExchangeRateAndGasPrice(_destinationDomain);
}
Parameters
destinationDomain
: The message's destination domain
Returns
tokenExchangeRate
: The exchange rate between the origin and destination chain's gas tokensgasPrice
: The gas price for the destination chain
The quoteGasPayment
function calculates fees for the relayer's anticipated costs.
- Solidity
function quoteGasPayment(
uint32 _destinationDomain,
uint256 _gasLimit
) public view virtual override returns (uint256) {
// Get the gas data for the destination domain.
(
uint128 _tokenExchangeRate,
uint128 _gasPrice
) = getExchangeRateAndGasPrice(_destinationDomain);
// The total cost quoted in destination chain's native token.
uint256 _destinationGasCost = _gasLimit * uint256(_gasPrice);
// Convert to the local native token.
return
(_destinationGasCost * _tokenExchangeRate) /
TOKEN_EXCHANGE_RATE_SCALE;
}
Parameters
destinationDomain
: The message's destination domaingasLimit
: The gas limit to meter thehandle
call with
Returns
fee
: The payment required for thepostDispatch
to succeed
Retrying
If the handle
call consumes more gas than quoted, the relayer will not submit a process transaction. In this case, additional gas can be paid for with the payForGas
function.
- Solidity
function payForGas(
bytes32 _messageId,
uint32 _destinationDomain,
uint256 _gasAmount,
address _refundAddress
) external payable;
Parameters
messageId
: The message identifier returned fromdispatch
calldestinationDomain
: The message's destination domaingasAmount
: The additional gas amount to pay forrefundAddress
: The address to refund excess payment to