Axelar Gas Receiver
General Message Passing is a two-step process:
- Approval. Axelar validators approve a message via vote on the message payload hash.
- Execution. Anyone can execute an approved message by posting the payload hash preimage to the destination chain and paying relayer gas fees.
The Axelar network provides approval but not execution. Axelar also provides an optional relayer service called gas receiver that provides execution of approved messages. Anyone can use the gas receiver service by pre-paying the relayer gas fee on the source chain. Axelar relayer services observe use of the gas receiver for a given message and automatically execute the General Message Passing call.
Relayer gas fees are needed only to pay gas costs across chains.
Introduction
An application that wants Axelar to automatically execute contract calls on the destination chain needs to do four things:
- Estimate the
gasLimit
that the contract call will require on the destionation chain. - Query our API to get the
sourceTokenPrice
of the desired token that gas will be paid in, as well asdestinationGasPrice
anddestinationTokenPrice
, the price of the native token, on the destination chain. - Calcualate the amount of token to be paid as
gasLimit * destinationGasPrice * destinationTokenPrice / sourceTokenPrice
. - Pay our
AxelarGasReceiver
smart contract on the source chain that amount. This can be done by the application's smart contracts so no additional transactions are required (except maybe approval in case gas is paid in non-native ERC-20 tokens).
Our service does the following:
- Monitors
AxelarGasReceiver
for receipts of payment, and gets the amount paid asamountPaid
. - Matches those to contract calls.
- Queries our API to get the
sourceTokenPrice
of the token that gas was paid in, as well asdestinationGasPrice
anddestinationTokenPrice
, the price of the native token, on the destination chain. - Calcualate the
gasLimit
asamountPaid * sourceTokenPrice / (destinationGasPrice * gestinationTokenPrice)
. - Executes the specified contract call specifying the
gasLimit
specified above.
We plan to add an option to get refunds in case excessive amounts are paid as gas, but this is not yet implemented.
AxelarGasReceiver
Our smart contract can receive gas in the following ways:
function payGasForContractCall(
address sender,
string calldata destinationChain,
string calldata destinationAddress,
bytes calldata payload,
address gasToken,
uint256 gasFeeAmount,
address refundAddress
) external;
// This is called on the source chain before calling the gateway to execute a remote contract.
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;
// This is called on the source chain before calling the gateway to execute a remote contract.
function payNativeGasForContractCall(
address sender,
string calldata destinationChain,
string calldata destinationAddress,
bytes calldata payload,
address refundAddress
) external payable;
// This is called on the source chain before calling the gateway to execute a remote contract.
function payNativeGasForContractCallWithToken(
address sender,
string calldata destinationChain,
string calldata destinationAddress,
bytes calldata payload,
string calldata symbol,
uint256 amount,
address refundAddress
) external payable;
The function names are prety self explanatory. The following is true for the arguments:
- For all functions
sender
needs to match the address that callscallContract
orcallContractWithToken
on theAxelarGateway
. If theAxelarGasReceiver
is called by the same contract that will call the gateway then simply specifyaddress(this)
assender
.
- For
payGasForContractCall
andpayNativeGasForContractCall
destinationChain
destinationAddress
payload
need to match the arguments of acontractCall
on theAxelarGateway
- For
payGasForContractCallWtihToken
andpayNativeGasForContractCallWithToken
destinationChain
destinationAddress
payload
symbol
amount
need to match the arguments of acontractCallWithToken
on theAxelarGateway
- For
payGasForContractCall
andpayGasForContractCallWtihToken
gasToken
is the address of the token that gas will be paid in. Ensure this token is supported with our API.gasFeeAmount
is the amount ofgasToken
to transfer from the sender. The sender needs to have approved theAxelarGasReceiver
with the appropriate amount togasToken
first.
- For
payNativeGasForContractCall
andpayNativeGasForContractCallWithToken
the amount of funds received is specified bymsg.value
. - For all functions
refundAddress
is the address that will be able to receive excess amount paid for gas.
API
To get the relative gas cost in any token on any of the supported chains you can use the following script. This is subject to change.
const {
constants: { AddressZero },
} = require("ethers");
const axios = require("axios");
async function getGasPrice(
sourceChain,
destinationChain,
tokenAddress,
tokenSymbol
) {
const api_url = "https://devnet.api.gmp.axelarscan.io";
const requester = axios.create({ baseURL: api_url });
const params = {
method: "getGasPrice",
destinationChain: destinationChain,
sourceChain: sourceChain,
};
// set gas token address to params
if (tokenAddress != AddressZero) {
params.sourceTokenAddress = tokenAddress;
} else {
params.sourceTokenSymbol = tokenSymbol;
}
// send request
const response = await requester.get("/", { params }).catch((error) => {
return { data: { error } };
});
const result = response.data.result;
const dest = result.destination_native_token;
const destPrice = 1e18 * dest.gas_price * dest.token_price.usd;
return destPrice / result.source_token.token_price.usd;
}