Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(GasEstimation): adding support for express fee #146

Merged
merged 8 commits into from
Mar 23, 2024
18 changes: 12 additions & 6 deletions contracts/gas-estimation/InterchainGasEstimation.sol
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,18 @@ abstract contract InterchainGasEstimation is IInterchainGasEstimation {
string calldata destinationChain,
string calldata, /* destinationAddress */
bytes calldata payload,
uint256 executionGasLimit
) external view returns (uint256 gasEstimate) {
uint256 executionGasLimit,
bool isExpress
) public view returns (uint256 gasEstimate) {
GasServiceStorage storage slot = _gasServiceStorage();
GasInfo storage gasInfo = slot.gasPrices[destinationChain];

gasEstimate = gasInfo.axelarBaseFee + (executionGasLimit * gasInfo.relativeGasPrice);
gasEstimate =
(executionGasLimit * gasInfo.relativeGasPrice) +
(isExpress ? gasInfo.expressFee : gasInfo.axelarBaseFee);

// if chain is L2, compute L1 data fee using L1 gas price info
if (gasInfo.gasEstimationType != GasEstimationType.Default) {
if (gasInfo.gasEstimationType != 0) {
GasInfo storage l1GasInfo = slot.gasPrices['ethereum'];

gasEstimate += computeL1DataFee(
Expand All @@ -77,12 +80,15 @@ abstract contract InterchainGasEstimation is IInterchainGasEstimation {
* @return l1DataFee The L1 to L2 data fee
*/
function computeL1DataFee(
GasEstimationType gasEstimationType,
uint256 gasEstimationType,
bytes calldata payload,
uint256 relativeGasPrice,
uint256 relativeBlobBaseFee
) internal pure returns (uint256) {
if (gasEstimationType == GasEstimationType.OptimismEcotone) {
if (gasEstimationType > uint256(type(GasEstimationType).max))
revert UnsupportedEstimationType(gasEstimationType);

if (GasEstimationType(gasEstimationType) == GasEstimationType.OptimismEcotone) {
return optimismEcotoneL1Fee(payload, relativeGasPrice, relativeBlobBaseFee);
}

Expand Down
25 changes: 25 additions & 0 deletions contracts/interfaces/IAxelarGasService.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ interface IAxelarGasService is IInterchainGasEstimation, IUpgradable {
error NotCollector();
error InvalidAmounts();
error InvalidGasUpdates();
error InsufficientGasPayment(uint256 required, uint256 provided);

event GasPaidForContractCall(
address indexed sourceAddress,
Expand Down Expand Up @@ -134,6 +135,30 @@ interface IAxelarGasService is IInterchainGasEstimation, IUpgradable {
uint256 amount
);

/**
* @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
re1ro marked this conversation as resolved.
Show resolved Hide resolved
*/
function payGas(
address sender,
string calldata destinationChain,
string calldata destinationAddress,
bytes calldata payload,
uint256 executionGasLimit,
bool estimateOnChain,
address refundAddress,
bytes calldata params
) external payable;

/**
* @notice Pay for gas using ERC20 tokens for a contract call on a destination chain.
* @dev This function is called on the source chain before calling the gateway to execute a remote contract.
Expand Down
14 changes: 8 additions & 6 deletions contracts/interfaces/IInterchainGasEstimation.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ pragma solidity ^0.8.0;
* which allows for estimating gas fees for cross-chain communication on the Axelar network.
*/
interface IInterchainGasEstimation {
error UnsupportedEstimationType(GasEstimationType feeType);
error UnsupportedEstimationType(uint256 feeType);

/**
* @notice Event emitted when the gas price for a specific chain is updated.
Expand All @@ -23,10 +23,11 @@ interface IInterchainGasEstimation {
}

struct GasInfo {
GasEstimationType gasEstimationType; // Custom gas pricing rule, such as L1 data fee on L2s
milapsheth marked this conversation as resolved.
Show resolved Hide resolved
uint256 axelarBaseFee; // destination axelar base fee for cross-chain message approval (in terms of src native gas token)
uint256 relativeGasPrice; // dest_gas_price * dest_token_market_price / src_token_market_price
uint256 relativeBlobBaseFee; // dest_blob_base_fee * dest_token_market_price / src_token_market_price
uint128 gasEstimationType; // Custom gas pricing rule, such as L1 data fee on L2s
uint128 axelarBaseFee; // axelar base fee for cross-chain message approval (in terms of src native gas token)
uint128 expressFee; // axelar express fee for cross-chain message approval and express execution
uint128 relativeGasPrice; // dest_gas_price * dest_token_market_price / src_token_market_price
uint128 relativeBlobBaseFee; // dest_blob_base_fee * dest_token_market_price / src_token_market_price
}

/**
Expand All @@ -48,6 +49,7 @@ interface IInterchainGasEstimation {
string calldata destinationChain,
string calldata destinationAddress,
bytes calldata payload,
uint256 executionGasLimit
uint256 executionGasLimit,
bool isExpress
milapsheth marked this conversation as resolved.
Show resolved Hide resolved
) external view returns (uint256 gasEstimate);
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,16 @@ describe('InterchainGasEstimation', () => {
});

it('should compute gas estimate correctly', async () => {
await gasEstimate.updateGasInfo(sourceChain, [0, 90000000000, 50000000000, 1]).then((tx) => tx.wait());
await gasEstimate.updateGasInfo(destinationChain, [1, 90000, 5000, 0]).then((tx) => tx.wait());
await gasEstimate
.updateGasInfo(sourceChain, [0, 90000000000, 190000000000, 50000000000, 1])
.then((tx) => tx.wait());
await gasEstimate.updateGasInfo(destinationChain, [1, 90000, 190000, 5000, 0]).then((tx) => tx.wait());
const estimate = await gasEstimate.estimateGasFee(
destinationChain,
destinationAddress,
'0x2534d1533c9ffce84d3174c1f846a4041d07b56d1e7b5cb7138e06fb42086325',
120000,
false,
);

expect(estimate).to.equal(353400090264);
Expand Down
Loading