Post-Dispatch Interchain Gas Payment
During the post-dispatch hook, the InterchainGasPaymaster
contract will revert if payment is insufficient to cover the relayer's anticipated costs. The gas quote calculated at dispatch
time must align with the relayer’s anticipated costs.
Gas Limit
The gasLimit
is set based on the cost of calling handle
on the destination chain for a given message. This can vary depending on message content and the logic of the handler.
The default gasLimit
for metering the handle call is a static default of 50_000
gas. This is sufficient for simple operations but may not be enough for more complex handle
functions.
If your handle
function performs complex operations or requires more gas, you must override the default gasLimit
in metadata to avoid transaction reverts. Benchmark your handle
implementations in unit tests to determine a reasonable gasLimit
to use.
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;
}
The StandardHookMetadata
struct defines the fields required for metadata encoding:
variant
: Specifies the metadata format version.msgValue
: Amount of native token sent with the message.gasLimit
: Gas limit for thehandle
function on the destination chain. Ensure this matches your simulation results.refundAddress
: Address to refund unused gas payments.
To encode this metadata, use the StandardHookMetadata.formatMetadata
library function. Direct encoding of the struct with abi.encodePacked
is not supported in Solidity.
Example Usage
- Solidity
// Example: Encoding metadata using StandardHookMetadata
bytes memory metadata = StandardHookMetadata.formatMetadata(
0, // ETH message value
200000, // Custom gas limit
address(this), // Refund address
bytes("") // Optional custom metadata
);
Determine and Override the Gas Limit
- Simulate and Benchmark Gas Usage:
- Use tools like Tenderly or Foundry to simulate the
handle
function on your message recipient. Ensure thefrom
address is set to the Mailbox contract on your chain. - If gas usage exceeds
50,000
gas, calculate an appropriategasLimit
and update your metadata. - Use the call-to-action in the Hyperlane Explorer to simulate transactions from the message details.
- Update Your Metadata:
- Calculate the required
gasLimit
based on the simulation. - Pass the updated
gasLimit
in your metadata to ensure the relayer will deliver your message.
Destination Gas Config
For each remote domain, the InterchainGasPaymaster sets the domain gas config.
struct DomainGasConfig {
IGasOracle gasOracle;
uint96 gasOverhead;
}
Gas overhead
The gas overhead is set as part of the destination gas configuration. This corresponds to the operational cost of processing a message on the destination chain.
- You should ensure the
gasOverhead
sufficiently covers the range of ISMs on your destination chain. - As you can configure different ISMs for different message types, you may have different gas overheads for each ISM's
verify
function.
Gas Oracles
Interchain Gas Payment requirements are calculated using oraclized gas prices and exchange rates between the origin and destination chains.
IGP contracts may be configured with gas oracles, which are responsible for tracking remote token gas prices and exchange rates. Developers should use the quoteDispatch
function on the Mailbox contract to calculate gas fees. The quoteDispatch
accounts for system-level overhead and ensures accurate fee calculation for the entire dispatch
process.
- Exchange rates and gas prices are up to the relayer to decide. A spread may be charged to account for drift and operating costs.
Eventually, a relayer will be able to automatically update their gas oracles in order to ensure that their IGP always quotes a fair price for remote gas.
getExchangeRateAndGasPrice
- Solidity
function getExchangeRateAndGasPrice(
uint32 _destinationDomain
)
public
view
override
returns (uint128 tokenExchangeRate, uint128 gasPrice)
{
IGasOracle _gasOracle = destinationGasConfigs[_destinationDomain]
.gasOracle;
if (address(_gasOracle) == address(0)) {
revert(
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
quoteGasPayment
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. This issue often occurs due to insufficient gas payment during the initial dispatch
.
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
Using the Hyperlane Explorer for Debugging
The Hyperlane Explorer is a powerful tool to debug cross-chain message issues, including gas payments and relayer behavior.
Key Features
- Message Status: View the current status of your message (e.g., "Retry: GasPaymentRequirementNotMet").
- Gas Payment Details: Check the gas amount paid (Origin IGP gas amount) and the amount required by the relayer.
- Simulate Calldata: Use the "View calldata details" option to simulate transactions on tools like Tenderly.
Troubleshooting
This section covers common issues developers encounter with Interchain Gas Payments, along with potential solutions.
GasPaymentRequirementNotMet
Warning
-
Reason: This occurs when the gas payment provided during
dispatch
does not meet the relayer's calculated requirement. -
Solution:
- Use
quoteDispatch
to calculate the aggregate fee required for adispatch
call to be successful. - Verify that
msg.value
in your metadata covers the relayer’s quoted fee. - Check the message status in the Hyperlane Explorer. Look for:
Retry(GasPaymentRequirementNotMet)
.
- Use
Fallback Routing and Overpayment Warning
-
Reason:
msg.value
exceeds the required gas payment, triggering the fallback routing hook. -
Solution:
- Verify that your quoting logic (
quoteDispatch
) matches the relayer's anticipated fees. - Avoid overestimating
gasLimit
values without first benchmarking thehandle
function. - Simulate the transaction to confirm appropriate payment.
- Verify that your quoting logic (
Unexpectedly Large Gas Quotes
-
Reason: A very high
gasLimit
was set, leading to excessively large gas quotes. -
Solution:
- Double-check the
gasLimit
specified in your metadata. - Verify that your quoting logic (
quoteDispatch
) matches the relayer's anticipated fees. - Adjust the
gasLimit
to match the estimated gas consumption of yourhandle
function.
- Double-check the