Skip to content

Commit

Permalink
feat(GasService): estimateGasFee and payGas (#273)
Browse files Browse the repository at this point in the history
* feat(GasService): estimateGasFee with L2 specific logic

* style(solidity): prettier

* refactor(GasService): method renamed to updateGasInfo

* refactor(GasService): math multiplication and division order

* refactor(GasService): math multiplication and division order

* refactor(GasService): importing gas estimate from SDK

* fix(GasService): PR feedback

* fix(GasService): PR feedback

* fix(GasService): using InterchainGasEstimation

* feat(GasService): new consolidated payGas method

* fix(GasService): removed instant refund

* fix(GasService): better express condition

* fix(GasService): simplifying method

* chore(npm): GMP SDK version bump

* chore(npm): GMP SDK version bump

* Update package.json

Co-authored-by: Milap Sheth <milap@axelar.network>

* Update contracts/interfaces/IAxelarGasService.sol

Co-authored-by: Milap Sheth <milap@axelar.network>

* style(solidity): prettier

* fix(GasService): revert on params

* test(GasService): gas estimation

* style(JS): prettier

---------

Co-authored-by: Milap Sheth <milap@axelar.network>
  • Loading branch information
re1ro and milapsheth authored Mar 26, 2024
1 parent 7c83db9 commit a1ac8ea
Show file tree
Hide file tree
Showing 5 changed files with 192 additions and 380 deletions.
66 changes: 63 additions & 3 deletions contracts/gas-service/AxelarGasService.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,25 @@
pragma solidity ^0.8.0;

import { IERC20 } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IERC20.sol';
import { IAxelarGasService } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/interfaces/IAxelarGasService.sol';
import { InterchainGasEstimation } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/gas-estimation/InterchainGasEstimation.sol';
import { Upgradable } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/upgradable/Upgradable.sol';
import { SafeTokenTransfer, SafeTokenTransferFrom } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/libs/SafeTransfer.sol';
import { SafeNativeTransfer } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/libs/SafeNativeTransfer.sol';
import { IAxelarGasService } from '../interfaces/IAxelarGasService.sol';
import { Upgradable } from '@axelar-network/axelar-gmp-sdk-solidity/contracts/upgradable/Upgradable.sol';

/**
* @title AxelarGasService
* @notice This contract manages gas payments and refunds for cross-chain communication on the Axelar network.
* @dev The owner address of this contract should be the microservice that pays for gas.
* @dev Users pay gas for cross-chain calls, and the gasCollector can collect accumulated fees and/or refund users if needed.
*/
contract AxelarGasService is Upgradable, IAxelarGasService {
contract AxelarGasService is InterchainGasEstimation, Upgradable, IAxelarGasService {
using SafeTokenTransfer for IERC20;
using SafeTokenTransferFrom for IERC20;
using SafeNativeTransfer for address payable;

error InvalidParams();

address public immutable gasCollector;

/**
Expand All @@ -38,6 +41,44 @@ contract AxelarGasService is Upgradable, IAxelarGasService {
_;
}

/**
* @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
*/
function payGas(
address sender,
string calldata destinationChain,
string calldata destinationAddress,
bytes calldata payload,
uint256 executionGasLimit,
bool estimateOnChain,
address refundAddress,
bytes calldata params
) external payable override {
if (params.length > 0) {
revert InvalidParams();
}

if (estimateOnChain) {
uint256 gasEstimate = estimateGasFee(destinationChain, destinationAddress, payload, executionGasLimit, params);

if (gasEstimate > msg.value) {
revert InsufficientGasPayment(gasEstimate, msg.value);
}
}

emit NativeGasPaidForContractCall(sender, destinationChain, destinationAddress, keccak256(payload), msg.value, refundAddress);
}

/**
* @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 Expand Up @@ -348,6 +389,25 @@ contract AxelarGasService is Upgradable, IAxelarGasService {
emit NativeExpressGasAdded(txHash, logIndex, msg.value, refundAddress);
}

/**
* @notice Updates the gas price for a specific chain.
* @dev This function is called by the gas oracle to update the gas prices for a specific chains.
* @param chains Array of chain names
* @param gasUpdates Array of gas updates
*/
function updateGasInfo(string[] calldata chains, GasInfo[] calldata gasUpdates) external onlyCollector {
uint256 chainsLength = chains.length;

if (chainsLength != gasUpdates.length) revert InvalidGasUpdates();

for (uint256 i; i < chainsLength; i++) {
string calldata chain = chains[i];
GasInfo calldata gasUpdate = gasUpdates[i];

_setGasInfo(chain, gasUpdate);
}
}

/**
* @notice Allows the gasCollector to collect accumulated fees from the contract.
* @dev Use address(0) as the token address for native currency.
Expand Down
Loading

0 comments on commit a1ac8ea

Please sign in to comment.