GLMR Price: $0.177061 (-4.00%)
Gas: 125 GWei

Contract

0xcb5C784DCf8FF342625DbC53B356ed0Cbb0EBB9b

Overview

GLMR Balance

Moonbeam Chain LogoMoonbeam Chain LogoMoonbeam Chain Logo0 GLMR

GLMR Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To

There are no matching entries

> 10 Internal Transactions found.

Latest 25 internal transactions (View All)

Parent Transaction Hash Block From To
93285932025-01-25 4:41:061 hr ago1737780066
0xcb5C784D...Cbb0EBB9b
3.14529098 GLMR
93245672025-01-24 21:55:307 hrs ago1737755730
0xcb5C784D...Cbb0EBB9b
2.06283376 GLMR
93242132025-01-24 21:19:428 hrs ago1737753582
0xcb5C784D...Cbb0EBB9b
0.05761545 GLMR
93238352025-01-24 20:41:369 hrs ago1737751296
0xcb5C784D...Cbb0EBB9b
0.09425075 GLMR
93236112025-01-24 20:18:549 hrs ago1737749934
0xcb5C784D...Cbb0EBB9b
0.01231876 GLMR
93233352025-01-24 19:51:069 hrs ago1737748266
0xcb5C784D...Cbb0EBB9b
0.09458581 GLMR
93212622025-01-24 16:22:4813 hrs ago1737735768
0xcb5C784D...Cbb0EBB9b
0.0437861 GLMR
93203522025-01-24 14:50:5414 hrs ago1737730254
0xcb5C784D...Cbb0EBB9b
0.00895797 GLMR
93198612025-01-24 14:01:4215 hrs ago1737727302
0xcb5C784D...Cbb0EBB9b
0.1376016 GLMR
93193502025-01-24 13:10:1216 hrs ago1737724212
0xcb5C784D...Cbb0EBB9b
2.08144062 GLMR
93189862025-01-24 12:33:1217 hrs ago1737721992
0xcb5C784D...Cbb0EBB9b
0.21066558 GLMR
93188942025-01-24 12:24:0017 hrs ago1737721440
0xcb5C784D...Cbb0EBB9b
1.75893854 GLMR
93182062025-01-24 11:12:5418 hrs ago1737717174
0xcb5C784D...Cbb0EBB9b
0.01141942 GLMR
93178232025-01-24 10:32:3019 hrs ago1737714750
0xcb5C784D...Cbb0EBB9b
0.07538315 GLMR
93172132025-01-24 9:26:4220 hrs ago1737710802
0xcb5C784D...Cbb0EBB9b
0.13878546 GLMR
93170272025-01-24 9:07:4820 hrs ago1737709668
0xcb5C784D...Cbb0EBB9b
0.19649766 GLMR
93162662025-01-24 7:51:4221 hrs ago1737705102
0xcb5C784D...Cbb0EBB9b
3.1007228 GLMR
93162662025-01-24 7:51:4221 hrs ago1737705102
0xcb5C784D...Cbb0EBB9b
3.1007228 GLMR
93162502025-01-24 7:50:0621 hrs ago1737705006
0xcb5C784D...Cbb0EBB9b
2.88897698 GLMR
93162502025-01-24 7:50:0621 hrs ago1737705006
0xcb5C784D...Cbb0EBB9b
2.8267244 GLMR
93162372025-01-24 7:48:4821 hrs ago1737704928
0xcb5C784D...Cbb0EBB9b
2.24615946 GLMR
93161122025-01-24 7:36:1822 hrs ago1737704178
0xcb5C784D...Cbb0EBB9b
2.17776183 GLMR
93161022025-01-24 7:35:0622 hrs ago1737704106
0xcb5C784D...Cbb0EBB9b
2.84192868 GLMR
93160562025-01-24 7:30:2422 hrs ago1737703824
0xcb5C784D...Cbb0EBB9b
2.17944417 GLMR
93159852025-01-24 7:23:1822 hrs ago1737703398
0xcb5C784D...Cbb0EBB9b
2.17011606 GLMR
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
AxelarGasService

Compiler Version
v0.8.23+commit.f704f362

Optimization Enabled:
Yes with 1000 runs

Other Settings:
london EvmVersion
File 1 of 15 : AxelarGasService.sol
// SPDX-License-Identifier: MIT

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, GasInfo } 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';

/**
 * @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 InterchainGasEstimation, Upgradable, IAxelarGasService {
    using SafeTokenTransfer for IERC20;
    using SafeTokenTransferFrom for IERC20;
    using SafeNativeTransfer for address payable;

    address public immutable gasCollector;

    /**
     * @notice Constructs the AxelarGasService contract.
     * @param gasCollector_ The address of the gas collector
     */
    constructor(address gasCollector_) {
        gasCollector = gasCollector_;
    }

    /**
     * @notice Modifier that ensures the caller is the designated gas collector.
     */
    modifier onlyCollector() {
        if (msg.sender != gasCollector) revert NotCollector();

        _;
    }

    /**
     * @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.
     * @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 gasToken The address of the ERC20 token used to pay for gas
     * @param gasFeeAmount The amount of tokens to pay for gas
     * @param refundAddress The address where refunds, if any, should be sent
     */
    function payGasForContractCall(
        address sender,
        string calldata destinationChain,
        string calldata destinationAddress,
        bytes calldata payload,
        address gasToken,
        uint256 gasFeeAmount,
        address refundAddress
    ) external override {
        emit GasPaidForContractCall(
            sender,
            destinationChain,
            destinationAddress,
            keccak256(payload),
            gasToken,
            gasFeeAmount,
            refundAddress
        );

        IERC20(gasToken).safeTransferFrom(msg.sender, address(this), gasFeeAmount);
    }

    /**
     * @notice Pay for gas using ERC20 tokens for a contract call with tokens on a destination chain.
     * @dev This function is called on the source chain before calling the gateway to execute a remote contract.
     * @param sender The address making the payment
     * @param destinationChain The target chain where the contract call with tokens will be made
     * @param destinationAddress The target address on the destination chain
     * @param payload Data payload for the contract call with tokens
     * @param symbol The symbol of the token to be sent with the call
     * @param amount The amount of tokens to be sent with the call
     * @param gasToken The address of the ERC20 token used to pay for gas
     * @param gasFeeAmount The amount of tokens to pay for gas
     * @param refundAddress The address where refunds, if any, should be sent
     */
    function payGasForContractCallWithToken(
        address sender,
        string calldata destinationChain,
        string calldata destinationAddress,
        bytes calldata payload,
        string memory symbol,
        uint256 amount,
        address gasToken,
        uint256 gasFeeAmount,
        address refundAddress
    ) external override {
        emit GasPaidForContractCallWithToken(
            sender,
            destinationChain,
            destinationAddress,
            keccak256(payload),
            symbol,
            amount,
            gasToken,
            gasFeeAmount,
            refundAddress
        );

        IERC20(gasToken).safeTransferFrom(msg.sender, address(this), gasFeeAmount);
    }

    /**
     * @notice Pay for gas using native currency 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.
     * @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 refundAddress The address where refunds, if any, should be sent
     */
    function payNativeGasForContractCall(
        address sender,
        string calldata destinationChain,
        string calldata destinationAddress,
        bytes calldata payload,
        address refundAddress
    ) external payable override {
        emit NativeGasPaidForContractCall(sender, destinationChain, destinationAddress, keccak256(payload), msg.value, refundAddress);
    }

    /**
     * @notice Pay for gas using native currency for a contract call with tokens on a destination chain.
     * @dev This function is called on the source chain before calling the gateway to execute a remote contract.
     * @param sender The address making the payment
     * @param destinationChain The target chain where the contract call with tokens will be made
     * @param destinationAddress The target address on the destination chain
     * @param payload Data payload for the contract call with tokens
     * @param symbol The symbol of the token to be sent with the call
     * @param amount The amount of tokens to be sent with the call
     * @param refundAddress The address where refunds, if any, should be sent
     */
    function payNativeGasForContractCallWithToken(
        address sender,
        string calldata destinationChain,
        string calldata destinationAddress,
        bytes calldata payload,
        string calldata symbol,
        uint256 amount,
        address refundAddress
    ) external payable override {
        emit NativeGasPaidForContractCallWithToken(
            sender,
            destinationChain,
            destinationAddress,
            keccak256(payload),
            symbol,
            amount,
            msg.value,
            refundAddress
        );
    }

    /**
     * @notice Pay for gas using ERC20 tokens for an express contract call on a destination chain.
     * @dev This function is called on the source chain before calling the gateway to express execute a remote contract.
     * @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 gasToken The address of the ERC20 token used to pay for gas
     * @param gasFeeAmount The amount of tokens to pay for gas
     * @param refundAddress The address where refunds, if any, should be sent
     */
    function payGasForExpressCall(
        address sender,
        string calldata destinationChain,
        string calldata destinationAddress,
        bytes calldata payload,
        address gasToken,
        uint256 gasFeeAmount,
        address refundAddress
    ) external override {
        emit GasPaidForExpressCall(sender, destinationChain, destinationAddress, keccak256(payload), gasToken, gasFeeAmount, refundAddress);

        IERC20(gasToken).safeTransferFrom(msg.sender, address(this), gasFeeAmount);
    }

    /**
     * @notice Pay for gas using ERC20 tokens for an express contract call with tokens on a destination chain.
     * @dev This function is called on the source chain before calling the gateway to express execute a remote contract.
     * @param sender The address making the payment
     * @param destinationChain The target chain where the contract call with tokens will be made
     * @param destinationAddress The target address on the destination chain
     * @param payload Data payload for the contract call with tokens
     * @param symbol The symbol of the token to be sent with the call
     * @param amount The amount of tokens to be sent with the call
     * @param gasToken The address of the ERC20 token used to pay for gas
     * @param gasFeeAmount The amount of tokens to pay for gas
     * @param refundAddress The address where refunds, if any, should be sent
     */
    function payGasForExpressCallWithToken(
        address sender,
        string calldata destinationChain,
        string calldata destinationAddress,
        bytes calldata payload,
        string memory symbol,
        uint256 amount,
        address gasToken,
        uint256 gasFeeAmount,
        address refundAddress
    ) external override {
        emit GasPaidForExpressCallWithToken(
            sender,
            destinationChain,
            destinationAddress,
            keccak256(payload),
            symbol,
            amount,
            gasToken,
            gasFeeAmount,
            refundAddress
        );

        IERC20(gasToken).safeTransferFrom(msg.sender, address(this), gasFeeAmount);
    }

    /**
     * @notice Pay for gas using native currency for an express contract call on a destination chain.
     * @dev This function is called on the source chain before calling the gateway to execute a remote contract.
     * @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 refundAddress The address where refunds, if any, should be sent
     */
    function payNativeGasForExpressCall(
        address sender,
        string calldata destinationChain,
        string calldata destinationAddress,
        bytes calldata payload,
        address refundAddress
    ) external payable override {
        emit NativeGasPaidForExpressCall(sender, destinationChain, destinationAddress, keccak256(payload), msg.value, refundAddress);
    }

    /**
     * @notice Pay for gas using native currency for an express contract call with tokens on a destination chain.
     * @dev This function is called on the source chain before calling the gateway to execute a remote contract.
     * @param sender The address making the payment
     * @param destinationChain The target chain where the contract call with tokens will be made
     * @param destinationAddress The target address on the destination chain
     * @param payload Data payload for the contract call with tokens
     * @param symbol The symbol of the token to be sent with the call
     * @param amount The amount of tokens to be sent with the call
     * @param refundAddress The address where refunds, if any, should be sent
     */
    function payNativeGasForExpressCallWithToken(
        address sender,
        string calldata destinationChain,
        string calldata destinationAddress,
        bytes calldata payload,
        string calldata symbol,
        uint256 amount,
        address refundAddress
    ) external payable override {
        emit NativeGasPaidForExpressCallWithToken(
            sender,
            destinationChain,
            destinationAddress,
            keccak256(payload),
            symbol,
            amount,
            msg.value,
            refundAddress
        );
    }

    /**
     * @notice Add additional gas payment using ERC20 tokens after initiating a cross-chain call.
     * @dev This function can be called on the source chain after calling the gateway to execute a remote contract.
     * @param txHash The transaction hash of the cross-chain call
     * @param logIndex The log index for the cross-chain call
     * @param gasToken The ERC20 token address used to add gas
     * @param gasFeeAmount The amount of tokens to add as gas
     * @param refundAddress The address where refunds, if any, should be sent
     */
    function addGas(
        bytes32 txHash,
        uint256 logIndex,
        address gasToken,
        uint256 gasFeeAmount,
        address refundAddress
    ) external override {
        emit GasAdded(txHash, logIndex, gasToken, gasFeeAmount, refundAddress);

        IERC20(gasToken).safeTransferFrom(msg.sender, address(this), gasFeeAmount);
    }

    /**
     * @notice Add additional gas payment using native currency after initiating a cross-chain call.
     * @dev This function can be called on the source chain after calling the gateway to execute a remote contract.
     * @param txHash The transaction hash of the cross-chain call
     * @param logIndex The log index for the cross-chain call
     * @param refundAddress The address where refunds, if any, should be sent
     */
    function addNativeGas(
        bytes32 txHash,
        uint256 logIndex,
        address refundAddress
    ) external payable override {
        emit NativeGasAdded(txHash, logIndex, msg.value, refundAddress);
    }

    /**
     * @notice Add additional gas payment using ERC20 tokens after initiating an express cross-chain call.
     * @dev This function can be called on the source chain after calling the gateway to express execute a remote contract.
     * @param txHash The transaction hash of the cross-chain call
     * @param logIndex The log index for the cross-chain call
     * @param gasToken The ERC20 token address used to add gas
     * @param gasFeeAmount The amount of tokens to add as gas
     * @param refundAddress The address where refunds, if any, should be sent
     */
    function addExpressGas(
        bytes32 txHash,
        uint256 logIndex,
        address gasToken,
        uint256 gasFeeAmount,
        address refundAddress
    ) external override {
        emit ExpressGasAdded(txHash, logIndex, gasToken, gasFeeAmount, refundAddress);

        IERC20(gasToken).safeTransferFrom(msg.sender, address(this), gasFeeAmount);
    }

    /**
     * @notice Add additional gas payment using native currency after initiating an express cross-chain call.
     * @dev This function can be called on the source chain after calling the gateway to express execute a remote contract.
     * @param txHash The transaction hash of the cross-chain call
     * @param logIndex The log index for the cross-chain call
     * @param refundAddress The address where refunds, if any, should be sent
     */
    function addNativeExpressGas(
        bytes32 txHash,
        uint256 logIndex,
        address refundAddress
    ) external payable override {
        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.
     * @param receiver The address to receive the collected fees
     * @param tokens Array of token addresses to be collected
     * @param amounts Array of amounts to be collected for each respective token address
     */
    function collectFees(
        address payable receiver,
        address[] calldata tokens,
        uint256[] calldata amounts
    ) external onlyCollector {
        if (receiver == address(0)) revert InvalidAddress();

        uint256 tokensLength = tokens.length;
        if (tokensLength != amounts.length) revert InvalidAmounts();

        for (uint256 i; i < tokensLength; i++) {
            address token = tokens[i];
            uint256 amount = amounts[i];
            if (amount == 0) revert InvalidAmounts();

            if (token == address(0)) {
                if (amount <= address(this).balance) receiver.safeNativeTransfer(amount);
            } else {
                // slither-disable-next-line calls-loop
                if (amount <= IERC20(token).balanceOf(address(this))) IERC20(token).safeTransfer(receiver, amount);
            }
        }
    }

    /**
     * @dev Deprecated refund function, kept for backward compatibility.
     */
    function refund(
        address payable receiver,
        address token,
        uint256 amount
    ) external onlyCollector {
        _refund(bytes32(0), 0, receiver, token, amount);
    }

    /**
     * @notice Refunds gas payment to the receiver in relation to a specific cross-chain transaction.
     * @dev Only callable by the gasCollector.
     * @dev Use address(0) as the token address to refund native currency.
     * @param txHash The transaction hash of the cross-chain call
     * @param logIndex The log index for the cross-chain call
     * @param receiver The address to receive the refund
     * @param token The token address to be refunded
     * @param amount The amount to refund
     */
    function refund(
        bytes32 txHash,
        uint256 logIndex,
        address payable receiver,
        address token,
        uint256 amount
    ) external onlyCollector {
        _refund(txHash, logIndex, receiver, token, amount);
    }

    /**
     * @dev Internal function to implement gas refund logic.
     */
    function _refund(
        bytes32 txHash,
        uint256 logIndex,
        address payable receiver,
        address token,
        uint256 amount
    ) private {
        if (receiver == address(0)) revert InvalidAddress();

        emit Refunded(txHash, logIndex, receiver, token, amount);

        if (token == address(0)) {
            receiver.safeNativeTransfer(amount);
        } else {
            IERC20(token).safeTransfer(receiver, amount);
        }
    }

    /**
     * @notice Returns a unique identifier for the contract.
     * @return bytes32 Hash of the contract identifier
     */
    function contractId() external pure returns (bytes32) {
        return keccak256('axelar-gas-service');
    }
}

File 2 of 15 : InterchainGasEstimation.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { GasEstimationType, GasInfo } from '../types/GasEstimationTypes.sol';
import { IInterchainGasEstimation } from '../interfaces/IInterchainGasEstimation.sol';

/**
 * @title InterchainGasEstimation
 * @notice This is an abstract contract that allows for estimating gas fees for cross-chain communication on the Axelar network.
 */
abstract contract InterchainGasEstimation is IInterchainGasEstimation {
    // keccak256('GasEstimate.Slot') - 1
    bytes32 internal constant GAS_SERVICE_SLOT = 0x2fa150da4c9f4c3a28593398c65313dd42f63d0530ec6db4a2b46e6d837a3902;

    // 68 bytes for the TX RLP encoding overhead
    uint256 internal constant TX_ENCODING_OVERHEAD = 68;
    // GMP executeWithToken call parameters
    // 4 bytes for method selector, 32 bytes for the commandId, 96 bytes for the sourceChain, 128 bytes for the sourceAddress, 96 bytes for token symbol, 32 bytes for amount
    // Expecting most of the calldata bytes to be zeroes. So multiplying by 8 as a weighted average of 4 and 16
    uint256 internal constant GMP_CALLDATA_SIZE = 4 + 32 + 96 + 128 + 96 + 32; // 388 bytes

    struct GasServiceStorage {
        mapping(string => GasInfo) gasPrices;
    }

    /**
     * @notice Returns the gas price for a specific chain.
     * @param chain The name of the chain
     * @return gasInfo The gas info for the chain
     */
    function getGasInfo(string calldata chain) external view returns (GasInfo memory) {
        return _storage().gasPrices[chain];
    }

    /**
     * @notice Sets the gas price for a specific chain.
     * @dev This function is called by the gas oracle to update the gas price for a specific chain.
     * @param chain The name of the chain
     * @param gasInfo The gas info for the chain
     */
    function _setGasInfo(string calldata chain, GasInfo calldata gasInfo) internal {
        emit GasInfoUpdated(chain, gasInfo);

        _storage().gasPrices[chain] = gasInfo;
    }

    /**
     * @notice Estimates the gas fee for a contract call on a destination chain.
     * @param destinationChain Axelar registered name of the destination chain
     * param destinationAddress Destination contract address being called
     * @param executionGasLimit The gas limit to be used for the destination contract execution,
     *        e.g. pass in 200k if your app consumes needs upto 200k for this contract call
     * param params Additional parameters for the gas estimation
     * @return gasEstimate The cross-chain gas estimate, in terms of source chain's native gas token that should be forwarded to the gas service.
     */
    function estimateGasFee(
        string calldata destinationChain,
        string calldata, /* destinationAddress */
        bytes calldata payload,
        uint256 executionGasLimit,
        bytes calldata /* params */
    ) public view returns (uint256 gasEstimate) {
        GasInfo storage gasInfo = _storage().gasPrices[destinationChain];
        GasEstimationType gasEstimationType = GasEstimationType(gasInfo.gasEstimationType);

        gasEstimate = gasInfo.axelarBaseFee + (executionGasLimit * gasInfo.relativeGasPrice);

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

            gasEstimate += computeL1DataFee(gasEstimationType, payload, gasInfo, l1GasInfo);
        }
    }

    /**
     * @notice Computes the additional L1 data fee for an L2 destination chain.
     * @param gasEstimationType The gas estimation type
     * @param payload The payload of the contract call
     * @param l1GasInfo The L1 gas info
     * @return l1DataFee The L1 to L2 data fee
     */
    function computeL1DataFee(
        GasEstimationType gasEstimationType,
        bytes calldata payload,
        GasInfo storage gasInfo,
        GasInfo storage l1GasInfo
    ) internal view returns (uint256) {
        if (gasEstimationType == GasEstimationType.OptimismEcotone) {
            return optimismEcotoneL1Fee(payload, gasInfo, l1GasInfo);
        }
        if (gasEstimationType == GasEstimationType.OptimismBedrock) {
            return optimismBedrockL1Fee(payload, gasInfo, l1GasInfo);
        }
        if (gasEstimationType == GasEstimationType.Arbitrum) {
            return arbitrumL1Fee(payload, gasInfo, l1GasInfo);
        }
        if (gasEstimationType == GasEstimationType.Scroll) {
            return scrollL1Fee(payload, gasInfo, l1GasInfo);
        }

        revert UnsupportedEstimationType(gasEstimationType);
    }

    /**
     * @notice Computes the L1 to L2 fee for an OP chain with Ecotone gas model.
     * @param payload The payload of the contract call
     * @param gasInfo Destination chain gas info
     * @param l1GasInfo The L1 gas info
     * @return l1DataFee The L1 to L2 data fee
     */
    function optimismEcotoneL1Fee(
        bytes calldata payload,
        GasInfo storage gasInfo,
        GasInfo storage l1GasInfo
    ) internal view returns (uint256 l1DataFee) {
        /* Optimism Ecotone gas model https://docs.optimism.io/stack/transactions/fees#ecotone
             tx_compressed_size = ((count_zero_bytes(tx_data) * 4 + count_non_zero_bytes(tx_data) * 16)) / 16
             weighted_gas_price = 16 * base_fee_scalar*base_fee + blob_base_fee_scalar * blob_base_fee
             l1_data_fee = tx_compressed_size * weighted_gas_price

           Reference implementation:
             https://github.com/ethereum-optimism/optimism/blob/876e16ad04968f0bb641eb76f98eb77e7e1a3e16/packages/contracts-bedrock/src/L2/GasPriceOracle.sol#L138
        */

        // The new base_fee_scalar is currently set to 0.001368
        // We are setting it to un upper bound of 0.0015 to account for possible fluctuations
        uint256 scalarPrecision = 10**6;

        // The blob_base_fee_scalar is currently set to 0.810949. Setting it to 0.9 as an upper bound
        // https://eips.ethereum.org/EIPS/eip-4844
        uint256 blobBaseFeeScalar = 9 * 10**5; // 0.9 multiplied by scalarPrecision

        // Calculating transaction size in bytes that will later be divided by 16 to compress the size
        uint256 txSize = _l1TxSize(payload);

        uint256 weightedGasPrice = 16 *
            gasInfo.l1FeeScalar *
            l1GasInfo.relativeGasPrice +
            blobBaseFeeScalar *
            l1GasInfo.relativeBlobBaseFee;

        l1DataFee = (weightedGasPrice * txSize) / (16 * scalarPrecision); // 16 for txSize compression and scalar precision conversion
    }

    /**
     * @notice Computes the L1 to L2 fee for an OP chain with Bedrock gas model.
     * @param payload The payload of the contract call
     * @param gasInfo Destination chain gas info
     * @param l1GasInfo The L1 gas info
     * @return l1DataFee The L1 to L2 data fee
     */
    function optimismBedrockL1Fee(
        bytes calldata payload,
        GasInfo storage gasInfo,
        GasInfo storage l1GasInfo
    ) internal view returns (uint256 l1DataFee) {
        // Resembling OP Bedrock gas price model
        // https://docs.optimism.io/stack/transactions/fees#bedrock
        // https://docs-v2.mantle.xyz/devs/concepts/tx-fee/ef
        // Reference https://github.com/mantlenetworkio/mantle-v2/blob/a29f01045191344b0ba89542215e6a02bd5e7fcc/packages/contracts-bedrock/contracts/L2/GasPriceOracle.sol#L98-L105
        uint256 overhead = 188;
        uint256 precision = 1e6;

        uint256 txSize = _l1TxSize(payload) + overhead;

        return (l1GasInfo.relativeGasPrice * txSize * gasInfo.l1FeeScalar) / precision;
    }

    /**
     * @notice Computes the L1 to L2 fee for a contract call on the Arbitrum chain.
     * @param payload The payload of the contract call
     * param gasInfo Destination chain gas info
     * @param l1GasInfo The L1 gas info
     * @return l1DataFee The L1 to L2 data fee
     */
    function arbitrumL1Fee(
        bytes calldata payload,
        GasInfo storage, /* gasInfo */
        GasInfo storage l1GasInfo
    ) internal view returns (uint256 l1DataFee) {
        // https://docs.arbitrum.io/build-decentralized-apps/how-to-estimate-gas
        // https://docs.arbitrum.io/arbos/l1-pricing
        // Reference https://github.com/OffchainLabs/nitro/blob/master/arbos/l1pricing/l1pricing.go#L565-L578
        uint256 oneInBips = 10000;
        uint256 txDataNonZeroGasEIP2028 = 16;
        uint256 estimationPaddingUnits = 16 * txDataNonZeroGasEIP2028;
        uint256 estimationPaddingBasisPoints = 100;

        uint256 l1Bytes = TX_ENCODING_OVERHEAD + GMP_CALLDATA_SIZE + payload.length;
        // Brotli baseline compression rate as 2x
        uint256 units = (txDataNonZeroGasEIP2028 * l1Bytes) / 2;

        return
            (l1GasInfo.relativeGasPrice *
                (units + estimationPaddingUnits) *
                (oneInBips + estimationPaddingBasisPoints)) / oneInBips;
    }

    /**
     * @notice Computes the L1 to L2 fee for a contract call on the Scroll chain.
     * @param payload The payload of the contract call
     * @param gasInfo Destination chain gas info
     * @param l1GasInfo The L1 gas info
     * @return l1DataFee The L1 to L2 data fee
     */
    function scrollL1Fee(
        bytes calldata payload,
        GasInfo storage gasInfo,
        GasInfo storage l1GasInfo
    ) internal view returns (uint256 l1DataFee) {
        // https://docs.scroll.io/en/developers/guides/estimating-gas-and-tx-fees/
        // Reference https://github.com/scroll-tech/scroll/blob/af2913903b181f3492af1c62b4da4c1c99cc552d/contracts/src/L2/predeploys/L1GasPriceOracle.sol#L63-L86
        uint256 overhead = 2500;
        uint256 precision = 1e9;

        uint256 txSize = _l1TxSize(payload) + overhead + (4 * 16);

        return (l1GasInfo.relativeGasPrice * txSize * gasInfo.l1FeeScalar) / precision;
    }

    /**
     * @notice Computes the transaction size for an L1 transaction
     * @param payload The payload of the contract call
     * @return txSize The transaction size
     */
    function _l1TxSize(bytes calldata payload) private pure returns (uint256 txSize) {
        txSize = TX_ENCODING_OVERHEAD * 16;
        // GMP executeWithToken call parameters
        // Expecting most of the calldata bytes to be zeroes. So multiplying by 8 as a weighted average of 4 and 16
        txSize += GMP_CALLDATA_SIZE * 8;

        uint256 length = payload.length;
        for (uint256 i; i < length; ++i) {
            if (payload[i] == 0) {
                txSize += 4; // 4 for each zero byte
            } else {
                txSize += 16; // 16 for each non-zero byte
            }
        }
    }

    /**
     * @notice Get the storage slot for the GasServiceStorage struct
     */
    function _storage() private pure returns (GasServiceStorage storage slot) {
        assembly {
            slot.slot := GAS_SERVICE_SLOT
        }
    }
}

File 3 of 15 : IAxelarGasService.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { GasInfo } from '../types/GasEstimationTypes.sol';
import { IInterchainGasEstimation } from './IInterchainGasEstimation.sol';
import { IUpgradable } from './IUpgradable.sol';

/**
 * @title IAxelarGasService Interface
 * @notice This is an interface for the AxelarGasService contract which manages gas payments
 * and refunds for cross-chain communication on the Axelar network.
 * @dev This interface inherits IUpgradable
 */
interface IAxelarGasService is IInterchainGasEstimation, IUpgradable {
    error InvalidAddress();
    error NotCollector();
    error InvalidAmounts();
    error InvalidGasUpdates();
    error InvalidParams();
    error InsufficientGasPayment(uint256 required, uint256 provided);

    event GasPaidForContractCall(
        address indexed sourceAddress,
        string destinationChain,
        string destinationAddress,
        bytes32 indexed payloadHash,
        address gasToken,
        uint256 gasFeeAmount,
        address refundAddress
    );

    event GasPaidForContractCallWithToken(
        address indexed sourceAddress,
        string destinationChain,
        string destinationAddress,
        bytes32 indexed payloadHash,
        string symbol,
        uint256 amount,
        address gasToken,
        uint256 gasFeeAmount,
        address refundAddress
    );

    event NativeGasPaidForContractCall(
        address indexed sourceAddress,
        string destinationChain,
        string destinationAddress,
        bytes32 indexed payloadHash,
        uint256 gasFeeAmount,
        address refundAddress
    );

    event NativeGasPaidForContractCallWithToken(
        address indexed sourceAddress,
        string destinationChain,
        string destinationAddress,
        bytes32 indexed payloadHash,
        string symbol,
        uint256 amount,
        uint256 gasFeeAmount,
        address refundAddress
    );

    event GasPaidForExpressCall(
        address indexed sourceAddress,
        string destinationChain,
        string destinationAddress,
        bytes32 indexed payloadHash,
        address gasToken,
        uint256 gasFeeAmount,
        address refundAddress
    );

    event GasPaidForExpressCallWithToken(
        address indexed sourceAddress,
        string destinationChain,
        string destinationAddress,
        bytes32 indexed payloadHash,
        string symbol,
        uint256 amount,
        address gasToken,
        uint256 gasFeeAmount,
        address refundAddress
    );

    event NativeGasPaidForExpressCall(
        address indexed sourceAddress,
        string destinationChain,
        string destinationAddress,
        bytes32 indexed payloadHash,
        uint256 gasFeeAmount,
        address refundAddress
    );

    event NativeGasPaidForExpressCallWithToken(
        address indexed sourceAddress,
        string destinationChain,
        string destinationAddress,
        bytes32 indexed payloadHash,
        string symbol,
        uint256 amount,
        uint256 gasFeeAmount,
        address refundAddress
    );

    event GasAdded(
        bytes32 indexed txHash,
        uint256 indexed logIndex,
        address gasToken,
        uint256 gasFeeAmount,
        address refundAddress
    );

    event NativeGasAdded(bytes32 indexed txHash, uint256 indexed logIndex, uint256 gasFeeAmount, address refundAddress);

    event ExpressGasAdded(
        bytes32 indexed txHash,
        uint256 indexed logIndex,
        address gasToken,
        uint256 gasFeeAmount,
        address refundAddress
    );

    event NativeExpressGasAdded(
        bytes32 indexed txHash,
        uint256 indexed logIndex,
        uint256 gasFeeAmount,
        address refundAddress
    );

    event Refunded(
        bytes32 indexed txHash,
        uint256 indexed logIndex,
        address payable receiver,
        address token,
        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. This can be left empty for normal contract call payments.
     */
    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.
     * @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 gasToken The address of the ERC20 token used to pay for gas
     * @param gasFeeAmount The amount of tokens to pay for gas
     * @param refundAddress The address where refunds, if any, should be sent
     */
    function payGasForContractCall(
        address sender,
        string calldata destinationChain,
        string calldata destinationAddress,
        bytes calldata payload,
        address gasToken,
        uint256 gasFeeAmount,
        address refundAddress
    ) external;

    /**
     * @notice Pay for gas using ERC20 tokens for a contract call with tokens on a destination chain.
     * @dev This function is called on the source chain before calling the gateway to execute a remote contract.
     * @param sender The address making the payment
     * @param destinationChain The target chain where the contract call with tokens will be made
     * @param destinationAddress The target address on the destination chain
     * @param payload Data payload for the contract call with tokens
     * @param symbol The symbol of the token to be sent with the call
     * @param amount The amount of tokens to be sent with the call
     * @param gasToken The address of the ERC20 token used to pay for gas
     * @param gasFeeAmount The amount of tokens to pay for gas
     * @param refundAddress The address where refunds, if any, should be sent
     */
    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;

    /**
     * @notice Pay for gas using native currency 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.
     * @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 refundAddress The address where refunds, if any, should be sent
     */
    function payNativeGasForContractCall(
        address sender,
        string calldata destinationChain,
        string calldata destinationAddress,
        bytes calldata payload,
        address refundAddress
    ) external payable;

    /**
     * @notice Pay for gas using native currency for a contract call with tokens on a destination chain.
     * @dev This function is called on the source chain before calling the gateway to execute a remote contract.
     * @param sender The address making the payment
     * @param destinationChain The target chain where the contract call with tokens will be made
     * @param destinationAddress The target address on the destination chain
     * @param payload Data payload for the contract call with tokens
     * @param symbol The symbol of the token to be sent with the call
     * @param amount The amount of tokens to be sent with the call
     * @param refundAddress The address where refunds, if any, should be sent
     */
    function payNativeGasForContractCallWithToken(
        address sender,
        string calldata destinationChain,
        string calldata destinationAddress,
        bytes calldata payload,
        string calldata symbol,
        uint256 amount,
        address refundAddress
    ) external payable;

    /**
     * @notice Pay for gas using ERC20 tokens for an express contract call on a destination chain.
     * @dev This function is called on the source chain before calling the gateway to express execute a remote contract.
     * @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 gasToken The address of the ERC20 token used to pay for gas
     * @param gasFeeAmount The amount of tokens to pay for gas
     * @param refundAddress The address where refunds, if any, should be sent
     */
    function payGasForExpressCall(
        address sender,
        string calldata destinationChain,
        string calldata destinationAddress,
        bytes calldata payload,
        address gasToken,
        uint256 gasFeeAmount,
        address refundAddress
    ) external;

    /**
     * @notice Pay for gas using ERC20 tokens for an express contract call with tokens on a destination chain.
     * @dev This function is called on the source chain before calling the gateway to express execute a remote contract.
     * @param sender The address making the payment
     * @param destinationChain The target chain where the contract call with tokens will be made
     * @param destinationAddress The target address on the destination chain
     * @param payload Data payload for the contract call with tokens
     * @param symbol The symbol of the token to be sent with the call
     * @param amount The amount of tokens to be sent with the call
     * @param gasToken The address of the ERC20 token used to pay for gas
     * @param gasFeeAmount The amount of tokens to pay for gas
     * @param refundAddress The address where refunds, if any, should be sent
     */
    function payGasForExpressCallWithToken(
        address sender,
        string calldata destinationChain,
        string calldata destinationAddress,
        bytes calldata payload,
        string calldata symbol,
        uint256 amount,
        address gasToken,
        uint256 gasFeeAmount,
        address refundAddress
    ) external;

    /**
     * @notice Pay for gas using native currency for an express contract call on a destination chain.
     * @dev This function is called on the source chain before calling the gateway to execute a remote contract.
     * @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 refundAddress The address where refunds, if any, should be sent
     */
    function payNativeGasForExpressCall(
        address sender,
        string calldata destinationChain,
        string calldata destinationAddress,
        bytes calldata payload,
        address refundAddress
    ) external payable;

    /**
     * @notice Pay for gas using native currency for an express contract call with tokens on a destination chain.
     * @dev This function is called on the source chain before calling the gateway to execute a remote contract.
     * @param sender The address making the payment
     * @param destinationChain The target chain where the contract call with tokens will be made
     * @param destinationAddress The target address on the destination chain
     * @param payload Data payload for the contract call with tokens
     * @param symbol The symbol of the token to be sent with the call
     * @param amount The amount of tokens to be sent with the call
     * @param refundAddress The address where refunds, if any, should be sent
     */
    function payNativeGasForExpressCallWithToken(
        address sender,
        string calldata destinationChain,
        string calldata destinationAddress,
        bytes calldata payload,
        string calldata symbol,
        uint256 amount,
        address refundAddress
    ) external payable;

    /**
     * @notice Add additional gas payment using ERC20 tokens after initiating a cross-chain call.
     * @dev This function can be called on the source chain after calling the gateway to execute a remote contract.
     * @param txHash The transaction hash of the cross-chain call
     * @param logIndex The log index for the cross-chain call
     * @param gasToken The ERC20 token address used to add gas
     * @param gasFeeAmount The amount of tokens to add as gas
     * @param refundAddress The address where refunds, if any, should be sent
     */
    function addGas(
        bytes32 txHash,
        uint256 logIndex,
        address gasToken,
        uint256 gasFeeAmount,
        address refundAddress
    ) external;

    /**
     * @notice Add additional gas payment using native currency after initiating a cross-chain call.
     * @dev This function can be called on the source chain after calling the gateway to execute a remote contract.
     * @param txHash The transaction hash of the cross-chain call
     * @param logIndex The log index for the cross-chain call
     * @param refundAddress The address where refunds, if any, should be sent
     */
    function addNativeGas(
        bytes32 txHash,
        uint256 logIndex,
        address refundAddress
    ) external payable;

    /**
     * @notice Add additional gas payment using ERC20 tokens after initiating an express cross-chain call.
     * @dev This function can be called on the source chain after calling the gateway to express execute a remote contract.
     * @param txHash The transaction hash of the cross-chain call
     * @param logIndex The log index for the cross-chain call
     * @param gasToken The ERC20 token address used to add gas
     * @param gasFeeAmount The amount of tokens to add as gas
     * @param refundAddress The address where refunds, if any, should be sent
     */
    function addExpressGas(
        bytes32 txHash,
        uint256 logIndex,
        address gasToken,
        uint256 gasFeeAmount,
        address refundAddress
    ) external;

    /**
     * @notice Add additional gas payment using native currency after initiating an express cross-chain call.
     * @dev This function can be called on the source chain after calling the gateway to express execute a remote contract.
     * @param txHash The transaction hash of the cross-chain call
     * @param logIndex The log index for the cross-chain call
     * @param refundAddress The address where refunds, if any, should be sent
     */
    function addNativeExpressGas(
        bytes32 txHash,
        uint256 logIndex,
        address refundAddress
    ) external payable;

    /**
     * @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;

    /**
     * @notice Allows the gasCollector to collect accumulated fees from the contract.
     * @dev Use address(0) as the token address for native currency.
     * @param receiver The address to receive the collected fees
     * @param tokens Array of token addresses to be collected
     * @param amounts Array of amounts to be collected for each respective token address
     */
    function collectFees(
        address payable receiver,
        address[] calldata tokens,
        uint256[] calldata amounts
    ) external;

    /**
     * @notice Refunds gas payment to the receiver in relation to a specific cross-chain transaction.
     * @dev Only callable by the gasCollector.
     * @dev Use address(0) as the token address to refund native currency.
     * @param txHash The transaction hash of the cross-chain call
     * @param logIndex The log index for the cross-chain call
     * @param receiver The address to receive the refund
     * @param token The token address to be refunded
     * @param amount The amount to refund
     */
    function refund(
        bytes32 txHash,
        uint256 logIndex,
        address payable receiver,
        address token,
        uint256 amount
    ) external;

    /**
     * @notice Returns the address of the designated gas collector.
     * @return address of the gas collector
     */
    function gasCollector() external returns (address);
}

File 4 of 15 : IContractIdentifier.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

// General interface for upgradable contracts
interface IContractIdentifier {
    /**
     * @notice Returns the contract ID. It can be used as a check during upgrades.
     * @dev Meant to be overridden in derived contracts.
     * @return bytes32 The contract ID
     */
    function contractId() external pure returns (bytes32);
}

File 5 of 15 : IERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    error InvalidAccount();

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address sender,
        address recipient,
        uint256 amount
    ) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

File 6 of 15 : IImplementation.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IContractIdentifier } from './IContractIdentifier.sol';

interface IImplementation is IContractIdentifier {
    error NotProxy();

    function setup(bytes calldata data) external;
}

File 7 of 15 : IInterchainGasEstimation.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { GasEstimationType, GasInfo } from '../types/GasEstimationTypes.sol';

/**
 * @title IInterchainGasEstimation Interface
 * @notice This is an interface for the InterchainGasEstimation contract
 * which allows for estimating gas fees for cross-chain communication on the Axelar network.
 */
interface IInterchainGasEstimation {
    error UnsupportedEstimationType(GasEstimationType gasEstimationType);

    /**
     * @notice Event emitted when the gas price for a specific chain is updated.
     * @param chain The name of the chain
     * @param info The gas info for the chain
     */
    event GasInfoUpdated(string chain, GasInfo info);

    /**
     * @notice Returns the gas price for a specific chain.
     * @param chain The name of the chain
     * @return gasInfo The gas info for the chain
     */
    function getGasInfo(string calldata chain) external view returns (GasInfo memory);

    /**
     * @notice Estimates the gas fee for a cross-chain contract call.
     * @param destinationChain Axelar registered name of the destination chain
     * @param destinationAddress Destination contract address being called
     * @param executionGasLimit The gas limit to be used for the destination contract execution,
     *        e.g. pass in 200k if your app consumes needs upto 200k for this contract call
     * @param params Additional parameters for the gas estimation
     * @return gasEstimate The cross-chain gas estimate, in terms of source chain's native gas token that should be forwarded to the gas service.
     */
    function estimateGasFee(
        string calldata destinationChain,
        string calldata destinationAddress,
        bytes calldata payload,
        uint256 executionGasLimit,
        bytes calldata params
    ) external view returns (uint256 gasEstimate);
}

File 8 of 15 : IOwnable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @title IOwnable Interface
 * @notice IOwnable is an interface that abstracts the implementation of a
 * contract with ownership control features. It's commonly used in upgradable
 * contracts and includes the functionality to get current owner, transfer
 * ownership, and propose and accept ownership.
 */
interface IOwnable {
    error NotOwner();
    error InvalidOwner();
    error InvalidOwnerAddress();

    event OwnershipTransferStarted(address indexed newOwner);
    event OwnershipTransferred(address indexed newOwner);

    /**
     * @notice Returns the current owner of the contract.
     * @return address The address of the current owner
     */
    function owner() external view returns (address);

    /**
     * @notice Returns the address of the pending owner of the contract.
     * @return address The address of the pending owner
     */
    function pendingOwner() external view returns (address);

    /**
     * @notice Transfers ownership of the contract to a new address
     * @param newOwner The address to transfer ownership to
     */
    function transferOwnership(address newOwner) external;

    /**
     * @notice Proposes to transfer the contract's ownership to a new address.
     * The new owner needs to accept the ownership explicitly.
     * @param newOwner The address to transfer ownership to
     */
    function proposeOwnership(address newOwner) external;

    /**
     * @notice Transfers ownership to the pending owner.
     * @dev Can only be called by the pending owner
     */
    function acceptOwnership() external;
}

File 9 of 15 : IUpgradable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IOwnable } from './IOwnable.sol';
import { IImplementation } from './IImplementation.sol';

// General interface for upgradable contracts
interface IUpgradable is IOwnable, IImplementation {
    error InvalidCodeHash();
    error InvalidImplementation();
    error SetupFailed();

    event Upgraded(address indexed newImplementation);

    function implementation() external view returns (address);

    function upgrade(
        address newImplementation,
        bytes32 newImplementationCodeHash,
        bytes calldata params
    ) external;
}

File 10 of 15 : SafeNativeTransfer.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

error NativeTransferFailed();

/*
 * @title SafeNativeTransfer
 * @dev This library is used for performing safe native value transfers in Solidity by utilizing inline assembly.
 */
library SafeNativeTransfer {
    /*
     * @notice Perform a native transfer to a given address.
     * @param receiver The recipient address to which the amount will be sent.
     * @param amount The amount of native value to send.
     * @throws NativeTransferFailed error if transfer is not successful.
     */
    function safeNativeTransfer(address receiver, uint256 amount) internal {
        bool success;

        assembly {
            success := call(gas(), receiver, amount, 0, 0, 0, 0)
        }

        if (!success) revert NativeTransferFailed();
    }
}

File 11 of 15 : SafeTransfer.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IERC20 } from '../interfaces/IERC20.sol';

error TokenTransferFailed();

/*
 * @title SafeTokenCall
 * @dev This library is used for performing safe token transfers.
 */
library SafeTokenCall {
    /*
     * @notice Make a safe call to a token contract.
     * @param token The token contract to interact with.
     * @param callData The function call data.
     * @throws TokenTransferFailed error if transfer of token is not successful.
     */
    function safeCall(IERC20 token, bytes memory callData) internal {
        (bool success, bytes memory returnData) = address(token).call(callData);
        bool transferred = success && (returnData.length == uint256(0) || abi.decode(returnData, (bool)));

        if (!transferred || address(token).code.length == 0) revert TokenTransferFailed();
    }
}

/*
 * @title SafeTokenTransfer
 * @dev This library safely transfers tokens from the contract to a recipient.
 */
library SafeTokenTransfer {
    /*
     * @notice Transfer tokens to a recipient.
     * @param token The token contract.
     * @param receiver The recipient of the tokens.
     * @param amount The amount of tokens to transfer.
     */
    function safeTransfer(
        IERC20 token,
        address receiver,
        uint256 amount
    ) internal {
        SafeTokenCall.safeCall(token, abi.encodeWithSelector(IERC20.transfer.selector, receiver, amount));
    }
}

/*
 * @title SafeTokenTransferFrom
 * @dev This library helps to safely transfer tokens on behalf of a token holder.
 */
library SafeTokenTransferFrom {
    /*
     * @notice Transfer tokens on behalf of a token holder.
     * @param token The token contract.
     * @param from The address of the token holder.
     * @param to The address the tokens are to be sent to.
     * @param amount The amount of tokens to be transferred.
     */
    function safeTransferFrom(
        IERC20 token,
        address from,
        address to,
        uint256 amount
    ) internal {
        SafeTokenCall.safeCall(token, abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, amount));
    }
}

File 12 of 15 : GasEstimationTypes.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @title GasEstimationType
 * @notice This enum represents the gas estimation types for different chains.
 */
enum GasEstimationType {
    Default,
    OptimismEcotone,
    OptimismBedrock,
    Arbitrum,
    Scroll
}

/**
 * @title GasInfo
 * @notice This struct represents the gas pricing information for a specific chain.
 * @dev Smaller uint types are used for efficient struct packing to save storage costs.
 */
struct GasInfo {
    /// @dev Custom gas pricing rule, such as L1 data fee on L2s
    uint64 gasEstimationType;
    /// @dev Scalar value needed for specific gas estimation types, expected to be less than 1e10
    uint64 l1FeeScalar;
    /// @dev Axelar base fee for cross-chain message approval on destination, in terms of source native gas token
    uint128 axelarBaseFee;
    /// @dev Gas price of destination chain, in terms of the source chain token, i.e dest_gas_price * dest_token_market_price / src_token_market_price
    uint128 relativeGasPrice;
    /// @dev Needed for specific gas estimation types. Blob base fee of destination chain, in terms of the source chain token, i.e dest_blob_base_fee * dest_token_market_price / src_token_market_price
    uint128 relativeBlobBaseFee;
    /// @dev Axelar express fee for express execution, in terms of source chain token
    uint128 expressFee;
}

File 13 of 15 : Implementation.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IImplementation } from '../interfaces/IImplementation.sol';

/**
 * @title Implementation
 * @notice This contract serves as a base for other contracts and enforces a proxy-first access restriction.
 * @dev Derived contracts must implement the setup function.
 */
abstract contract Implementation is IImplementation {
    address private immutable implementationAddress;

    /**
     * @dev Contract constructor that sets the implementation address to the address of this contract.
     */
    constructor() {
        implementationAddress = address(this);
    }

    /**
     * @dev Modifier to require the caller to be the proxy contract.
     * Reverts if the caller is the current contract (i.e., the implementation contract itself).
     */
    modifier onlyProxy() {
        if (implementationAddress == address(this)) revert NotProxy();
        _;
    }

    /**
     * @notice Initializes contract parameters.
     * This function is intended to be overridden by derived contracts.
     * The overriding function must have the onlyProxy modifier.
     * @param params The parameters to be used for initialization
     */
    function setup(bytes calldata params) external virtual;
}

File 14 of 15 : Upgradable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IImplementation } from '../interfaces/IImplementation.sol';
import { IUpgradable } from '../interfaces/IUpgradable.sol';
import { Ownable } from '../utils/Ownable.sol';
import { Implementation } from './Implementation.sol';

/**
 * @title Upgradable Contract
 * @notice This contract provides an interface for upgradable smart contracts and includes the functionality to perform upgrades.
 */
abstract contract Upgradable is Ownable, Implementation, IUpgradable {
    // bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)
    bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;

    /**
     * @notice Constructor sets the implementation address to the address of the contract itself
     * @dev This is used in the onlyProxy modifier to prevent certain functions from being called directly
     * on the implementation contract itself.
     * @dev The owner is initially set as address(1) because the actual owner is set within the proxy. It is not
     * set as the zero address because Ownable is designed to throw an error for ownership transfers to the zero address.
     */
    constructor() Ownable(address(1)) {}

    /**
     * @notice Returns the address of the current implementation
     * @return implementation_ Address of the current implementation
     */
    function implementation() public view returns (address implementation_) {
        assembly {
            implementation_ := sload(_IMPLEMENTATION_SLOT)
        }
    }

    /**
     * @notice Upgrades the contract to a new implementation
     * @param newImplementation The address of the new implementation contract
     * @param newImplementationCodeHash The codehash of the new implementation contract
     * @param params Optional setup parameters for the new implementation contract
     * @dev This function is only callable by the owner.
     */
    function upgrade(
        address newImplementation,
        bytes32 newImplementationCodeHash,
        bytes calldata params
    ) external override onlyOwner {
        if (IUpgradable(newImplementation).contractId() != IUpgradable(implementation()).contractId())
            revert InvalidImplementation();

        if (newImplementationCodeHash != newImplementation.codehash) revert InvalidCodeHash();

        assembly {
            sstore(_IMPLEMENTATION_SLOT, newImplementation)
        }

        emit Upgraded(newImplementation);

        if (params.length > 0) {
            // slither-disable-next-line controlled-delegatecall
            (bool success, ) = newImplementation.delegatecall(abi.encodeWithSelector(this.setup.selector, params));

            if (!success) revert SetupFailed();
        }
    }

    /**
     * @notice Sets up the contract with initial data
     * @param data Initialization data for the contract
     * @dev This function is only callable by the proxy contract.
     */
    function setup(bytes calldata data) external override(IImplementation, Implementation) onlyProxy {
        _setup(data);
    }

    /**
     * @notice Internal function to set up the contract with initial data
     * @param data Initialization data for the contract
     * @dev This function should be implemented in derived contracts.
     */
    function _setup(bytes calldata data) internal virtual {}
}

File 15 of 15 : Ownable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IOwnable } from '../interfaces/IOwnable.sol';

/**
 * @title Ownable
 * @notice A contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * The owner account is set through ownership transfer. This module makes
 * it possible to transfer the ownership of the contract to a new account in one
 * step, as well as to an interim pending owner. In the second flow the ownership does not
 * change until the pending owner accepts the ownership transfer.
 */
abstract contract Ownable is IOwnable {
    // keccak256('owner')
    bytes32 internal constant _OWNER_SLOT = 0x02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c0;
    // keccak256('ownership-transfer')
    bytes32 internal constant _OWNERSHIP_TRANSFER_SLOT =
        0x9855384122b55936fbfb8ca5120e63c6537a1ac40caf6ae33502b3c5da8c87d1;

    /**
     * @notice Initializes the contract by transferring ownership to the owner parameter.
     * @param _owner Address to set as the initial owner of the contract
     */
    constructor(address _owner) {
        _transferOwnership(_owner);
    }

    /**
     * @notice Modifier that throws an error if called by any account other than the owner.
     */
    modifier onlyOwner() {
        if (owner() != msg.sender) revert NotOwner();

        _;
    }

    /**
     * @notice Returns the current owner of the contract.
     * @return owner_ The current owner of the contract
     */
    function owner() public view returns (address owner_) {
        assembly {
            owner_ := sload(_OWNER_SLOT)
        }
    }

    /**
     * @notice Returns the pending owner of the contract.
     * @return owner_ The pending owner of the contract
     */
    function pendingOwner() public view returns (address owner_) {
        assembly {
            owner_ := sload(_OWNERSHIP_TRANSFER_SLOT)
        }
    }

    /**
     * @notice Transfers ownership of the contract to a new account `newOwner`.
     * @dev Can only be called by the current owner.
     * @param newOwner The address to transfer ownership to
     */
    function transferOwnership(address newOwner) external virtual onlyOwner {
        _transferOwnership(newOwner);
    }

    /**
     * @notice Propose to transfer ownership of the contract to a new account `newOwner`.
     * @dev Can only be called by the current owner. The ownership does not change
     * until the new owner accepts the ownership transfer.
     * @param newOwner The address to transfer ownership to
     */
    function proposeOwnership(address newOwner) external virtual onlyOwner {
        if (newOwner == address(0)) revert InvalidOwnerAddress();

        emit OwnershipTransferStarted(newOwner);

        assembly {
            sstore(_OWNERSHIP_TRANSFER_SLOT, newOwner)
        }
    }

    /**
     * @notice Accepts ownership of the contract.
     * @dev Can only be called by the pending owner
     */
    function acceptOwnership() external virtual {
        address newOwner = pendingOwner();
        if (newOwner != msg.sender) revert InvalidOwner();

        _transferOwnership(newOwner);
    }

    /**
     * @notice Internal function to transfer ownership of the contract to a new account `newOwner`.
     * @dev Called in the constructor to set the initial owner.
     * @param newOwner The address to transfer ownership to
     */
    function _transferOwnership(address newOwner) internal virtual {
        if (newOwner == address(0)) revert InvalidOwnerAddress();

        emit OwnershipTransferred(newOwner);

        assembly {
            sstore(_OWNER_SLOT, newOwner)
            sstore(_OWNERSHIP_TRANSFER_SLOT, 0)
        }
    }
}

Settings
{
  "evmVersion": "london",
  "optimizer": {
    "enabled": true,
    "runs": 1000,
    "details": {
      "peephole": true,
      "inliner": true,
      "jumpdestRemover": true,
      "orderLiterals": true,
      "deduplicate": true,
      "cse": true,
      "constantOptimizer": true,
      "yul": true,
      "yulDetails": {
        "stackAllocation": true
      }
    }
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"gasCollector_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"required","type":"uint256"},{"internalType":"uint256","name":"provided","type":"uint256"}],"name":"InsufficientGasPayment","type":"error"},{"inputs":[],"name":"InvalidAddress","type":"error"},{"inputs":[],"name":"InvalidAmounts","type":"error"},{"inputs":[],"name":"InvalidCodeHash","type":"error"},{"inputs":[],"name":"InvalidGasUpdates","type":"error"},{"inputs":[],"name":"InvalidImplementation","type":"error"},{"inputs":[],"name":"InvalidOwner","type":"error"},{"inputs":[],"name":"InvalidOwnerAddress","type":"error"},{"inputs":[],"name":"InvalidParams","type":"error"},{"inputs":[],"name":"NativeTransferFailed","type":"error"},{"inputs":[],"name":"NotCollector","type":"error"},{"inputs":[],"name":"NotOwner","type":"error"},{"inputs":[],"name":"NotProxy","type":"error"},{"inputs":[],"name":"SetupFailed","type":"error"},{"inputs":[],"name":"TokenTransferFailed","type":"error"},{"inputs":[{"internalType":"enum GasEstimationType","name":"gasEstimationType","type":"uint8"}],"name":"UnsupportedEstimationType","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"txHash","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"logIndex","type":"uint256"},{"indexed":false,"internalType":"address","name":"gasToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"gasFeeAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"refundAddress","type":"address"}],"name":"ExpressGasAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"txHash","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"logIndex","type":"uint256"},{"indexed":false,"internalType":"address","name":"gasToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"gasFeeAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"refundAddress","type":"address"}],"name":"GasAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"chain","type":"string"},{"components":[{"internalType":"uint64","name":"gasEstimationType","type":"uint64"},{"internalType":"uint64","name":"l1FeeScalar","type":"uint64"},{"internalType":"uint128","name":"axelarBaseFee","type":"uint128"},{"internalType":"uint128","name":"relativeGasPrice","type":"uint128"},{"internalType":"uint128","name":"relativeBlobBaseFee","type":"uint128"},{"internalType":"uint128","name":"expressFee","type":"uint128"}],"indexed":false,"internalType":"struct GasInfo","name":"info","type":"tuple"}],"name":"GasInfoUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sourceAddress","type":"address"},{"indexed":false,"internalType":"string","name":"destinationChain","type":"string"},{"indexed":false,"internalType":"string","name":"destinationAddress","type":"string"},{"indexed":true,"internalType":"bytes32","name":"payloadHash","type":"bytes32"},{"indexed":false,"internalType":"address","name":"gasToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"gasFeeAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"refundAddress","type":"address"}],"name":"GasPaidForContractCall","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sourceAddress","type":"address"},{"indexed":false,"internalType":"string","name":"destinationChain","type":"string"},{"indexed":false,"internalType":"string","name":"destinationAddress","type":"string"},{"indexed":true,"internalType":"bytes32","name":"payloadHash","type":"bytes32"},{"indexed":false,"internalType":"string","name":"symbol","type":"string"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"gasToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"gasFeeAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"refundAddress","type":"address"}],"name":"GasPaidForContractCallWithToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sourceAddress","type":"address"},{"indexed":false,"internalType":"string","name":"destinationChain","type":"string"},{"indexed":false,"internalType":"string","name":"destinationAddress","type":"string"},{"indexed":true,"internalType":"bytes32","name":"payloadHash","type":"bytes32"},{"indexed":false,"internalType":"address","name":"gasToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"gasFeeAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"refundAddress","type":"address"}],"name":"GasPaidForExpressCall","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sourceAddress","type":"address"},{"indexed":false,"internalType":"string","name":"destinationChain","type":"string"},{"indexed":false,"internalType":"string","name":"destinationAddress","type":"string"},{"indexed":true,"internalType":"bytes32","name":"payloadHash","type":"bytes32"},{"indexed":false,"internalType":"string","name":"symbol","type":"string"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"gasToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"gasFeeAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"refundAddress","type":"address"}],"name":"GasPaidForExpressCallWithToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"txHash","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"logIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"gasFeeAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"refundAddress","type":"address"}],"name":"NativeExpressGasAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"txHash","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"logIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"gasFeeAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"refundAddress","type":"address"}],"name":"NativeGasAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sourceAddress","type":"address"},{"indexed":false,"internalType":"string","name":"destinationChain","type":"string"},{"indexed":false,"internalType":"string","name":"destinationAddress","type":"string"},{"indexed":true,"internalType":"bytes32","name":"payloadHash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"gasFeeAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"refundAddress","type":"address"}],"name":"NativeGasPaidForContractCall","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sourceAddress","type":"address"},{"indexed":false,"internalType":"string","name":"destinationChain","type":"string"},{"indexed":false,"internalType":"string","name":"destinationAddress","type":"string"},{"indexed":true,"internalType":"bytes32","name":"payloadHash","type":"bytes32"},{"indexed":false,"internalType":"string","name":"symbol","type":"string"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"gasFeeAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"refundAddress","type":"address"}],"name":"NativeGasPaidForContractCallWithToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sourceAddress","type":"address"},{"indexed":false,"internalType":"string","name":"destinationChain","type":"string"},{"indexed":false,"internalType":"string","name":"destinationAddress","type":"string"},{"indexed":true,"internalType":"bytes32","name":"payloadHash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"gasFeeAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"refundAddress","type":"address"}],"name":"NativeGasPaidForExpressCall","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sourceAddress","type":"address"},{"indexed":false,"internalType":"string","name":"destinationChain","type":"string"},{"indexed":false,"internalType":"string","name":"destinationAddress","type":"string"},{"indexed":true,"internalType":"bytes32","name":"payloadHash","type":"bytes32"},{"indexed":false,"internalType":"string","name":"symbol","type":"string"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"gasFeeAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"refundAddress","type":"address"}],"name":"NativeGasPaidForExpressCallWithToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"txHash","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"logIndex","type":"uint256"},{"indexed":false,"internalType":"address payable","name":"receiver","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Refunded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newImplementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"txHash","type":"bytes32"},{"internalType":"uint256","name":"logIndex","type":"uint256"},{"internalType":"address","name":"gasToken","type":"address"},{"internalType":"uint256","name":"gasFeeAmount","type":"uint256"},{"internalType":"address","name":"refundAddress","type":"address"}],"name":"addExpressGas","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"txHash","type":"bytes32"},{"internalType":"uint256","name":"logIndex","type":"uint256"},{"internalType":"address","name":"gasToken","type":"address"},{"internalType":"uint256","name":"gasFeeAmount","type":"uint256"},{"internalType":"address","name":"refundAddress","type":"address"}],"name":"addGas","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"txHash","type":"bytes32"},{"internalType":"uint256","name":"logIndex","type":"uint256"},{"internalType":"address","name":"refundAddress","type":"address"}],"name":"addNativeExpressGas","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"txHash","type":"bytes32"},{"internalType":"uint256","name":"logIndex","type":"uint256"},{"internalType":"address","name":"refundAddress","type":"address"}],"name":"addNativeGas","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address payable","name":"receiver","type":"address"},{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"collectFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"contractId","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"string","name":"destinationChain","type":"string"},{"internalType":"string","name":"","type":"string"},{"internalType":"bytes","name":"payload","type":"bytes"},{"internalType":"uint256","name":"executionGasLimit","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"estimateGasFee","outputs":[{"internalType":"uint256","name":"gasEstimate","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gasCollector","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"chain","type":"string"}],"name":"getGasInfo","outputs":[{"components":[{"internalType":"uint64","name":"gasEstimationType","type":"uint64"},{"internalType":"uint64","name":"l1FeeScalar","type":"uint64"},{"internalType":"uint128","name":"axelarBaseFee","type":"uint128"},{"internalType":"uint128","name":"relativeGasPrice","type":"uint128"},{"internalType":"uint128","name":"relativeBlobBaseFee","type":"uint128"},{"internalType":"uint128","name":"expressFee","type":"uint128"}],"internalType":"struct GasInfo","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"implementation","outputs":[{"internalType":"address","name":"implementation_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"owner_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"string","name":"destinationChain","type":"string"},{"internalType":"string","name":"destinationAddress","type":"string"},{"internalType":"bytes","name":"payload","type":"bytes"},{"internalType":"uint256","name":"executionGasLimit","type":"uint256"},{"internalType":"bool","name":"estimateOnChain","type":"bool"},{"internalType":"address","name":"refundAddress","type":"address"},{"internalType":"bytes","name":"params","type":"bytes"}],"name":"payGas","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"string","name":"destinationChain","type":"string"},{"internalType":"string","name":"destinationAddress","type":"string"},{"internalType":"bytes","name":"payload","type":"bytes"},{"internalType":"address","name":"gasToken","type":"address"},{"internalType":"uint256","name":"gasFeeAmount","type":"uint256"},{"internalType":"address","name":"refundAddress","type":"address"}],"name":"payGasForContractCall","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"string","name":"destinationChain","type":"string"},{"internalType":"string","name":"destinationAddress","type":"string"},{"internalType":"bytes","name":"payload","type":"bytes"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"gasToken","type":"address"},{"internalType":"uint256","name":"gasFeeAmount","type":"uint256"},{"internalType":"address","name":"refundAddress","type":"address"}],"name":"payGasForContractCallWithToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"string","name":"destinationChain","type":"string"},{"internalType":"string","name":"destinationAddress","type":"string"},{"internalType":"bytes","name":"payload","type":"bytes"},{"internalType":"address","name":"gasToken","type":"address"},{"internalType":"uint256","name":"gasFeeAmount","type":"uint256"},{"internalType":"address","name":"refundAddress","type":"address"}],"name":"payGasForExpressCall","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"string","name":"destinationChain","type":"string"},{"internalType":"string","name":"destinationAddress","type":"string"},{"internalType":"bytes","name":"payload","type":"bytes"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"gasToken","type":"address"},{"internalType":"uint256","name":"gasFeeAmount","type":"uint256"},{"internalType":"address","name":"refundAddress","type":"address"}],"name":"payGasForExpressCallWithToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"string","name":"destinationChain","type":"string"},{"internalType":"string","name":"destinationAddress","type":"string"},{"internalType":"bytes","name":"payload","type":"bytes"},{"internalType":"address","name":"refundAddress","type":"address"}],"name":"payNativeGasForContractCall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"string","name":"destinationChain","type":"string"},{"internalType":"string","name":"destinationAddress","type":"string"},{"internalType":"bytes","name":"payload","type":"bytes"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"refundAddress","type":"address"}],"name":"payNativeGasForContractCallWithToken","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"string","name":"destinationChain","type":"string"},{"internalType":"string","name":"destinationAddress","type":"string"},{"internalType":"bytes","name":"payload","type":"bytes"},{"internalType":"address","name":"refundAddress","type":"address"}],"name":"payNativeGasForExpressCall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"string","name":"destinationChain","type":"string"},{"internalType":"string","name":"destinationAddress","type":"string"},{"internalType":"bytes","name":"payload","type":"bytes"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"refundAddress","type":"address"}],"name":"payNativeGasForExpressCallWithToken","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"owner_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"proposeOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"txHash","type":"bytes32"},{"internalType":"uint256","name":"logIndex","type":"uint256"},{"internalType":"address payable","name":"receiver","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"refund","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"receiver","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"refund","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"}],"name":"setup","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string[]","name":"chains","type":"string[]"},{"components":[{"internalType":"uint64","name":"gasEstimationType","type":"uint64"},{"internalType":"uint64","name":"l1FeeScalar","type":"uint64"},{"internalType":"uint128","name":"axelarBaseFee","type":"uint128"},{"internalType":"uint128","name":"relativeGasPrice","type":"uint128"},{"internalType":"uint128","name":"relativeBlobBaseFee","type":"uint128"},{"internalType":"uint128","name":"expressFee","type":"uint128"}],"internalType":"struct GasInfo[]","name":"gasUpdates","type":"tuple[]"}],"name":"updateGasInfo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes32","name":"newImplementationCodeHash","type":"bytes32"},{"internalType":"bytes","name":"params","type":"bytes"}],"name":"upgrade","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60c06040523480156200001157600080fd5b5060405162002f5f38038062002f5f8339810160408190526200003491620000fc565b6001620000418162000058565b50306080526001600160a01b031660a0526200012e565b6001600160a01b0381166200008057604051633649397d60e21b815260040160405180910390fd5b6040516001600160a01b038216907f04dba622d284ed0014ee4b9a6a68386be1a4c08a4913ae272de89199cc68616390600090a27f02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c05560007f9855384122b55936fbfb8ca5120e63c6537a1ac40caf6ae33502b3c5da8c87d155565b6000602082840312156200010f57600080fd5b81516001600160a01b03811681146200012757600080fd5b9392505050565b60805160a051612def62000170600039600081816104240152818161067201528181610afc01528181610ce5015261131f01526000610e190152612def6000f3fe6080604052600436106101c25760003560e01c8063892b5007116100f7578063cd433ada11610095578063edf936f211610064578063edf936f214610594578063f2fde38b146105a7578063f61ed218146105c7578063fd09e3bd146105da57600080fd5b8063cd433ada1461050d578063d3b81f0c14610520578063e30c397814610540578063edb6b3a51461057457600080fd5b8063a3499c73116100d1578063a3499c731461049a578063ab1999ba146104ba578063ba9ddc8d146104da578063c62c2002146104fa57600080fd5b8063892b5007146104125780638da5cb5b146104465780639ded06df1461047a57600080fd5b80634d2384891161016457806379ba50971161013e57806379ba50971461031d5780638291286c1461033257806382ad6f351461036557806386389f021461038557600080fd5b80634d238489146102a25780635c60da1b146102b5578063710bf322146102fd57600080fd5b806317a49f7c116101a057806317a49f7c1461022f5780632e9b74701461024f5780632edd2aa814610262578063365047211461028257600080fd5b80630c93e3bb146101c75780631055eaaf146101dc578063135eaa70146101fc575b600080fd5b6101da6101d5366004611e59565b6105fa565b005b3480156101e857600080fd5b506101da6101f7366004611f5e565b610667565b34801561020857600080fd5b5061021c610217366004611fe1565b610846565b6040519081526020015b60405180910390f35b34801561023b57600080fd5b506101da61024a366004612154565b610980565b6101da61025d366004612272565b610a0c565b34801561026e57600080fd5b506101da61027d366004612365565b610a82565b34801561028e57600080fd5b506101da61029d3660046123bb565b610af1565b6101da6102b036600461240d565b610b46565b3480156102c157600080fd5b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545b6040516001600160a01b039091168152602001610226565b34801561030957600080fd5b506101da610318366004612446565b610b91565b34801561032957600080fd5b506101da610c60565b34801561033e57600080fd5b507ffaa2f015f2ce5aee225904728de2def86eb8837491efd21f1a04fc20d8e923f661021c565b34801561037157600080fd5b506101da61038036600461246a565b610cda565b34801561039157600080fd5b506103a56103a03660046124ab565b610d35565b6040516102269190600060c08201905067ffffffffffffffff8084511683528060208501511660208401525060408301516001600160801b0380821660408501528060608601511660608501528060808601511660808501528060a08601511660a0850152505092915050565b34801561041e57600080fd5b506102e57f000000000000000000000000000000000000000000000000000000000000000081565b34801561045257600080fd5b507f02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c0546102e5565b34801561048657600080fd5b506101da6104953660046124ab565b610e16565b3480156104a657600080fd5b506101da6104b53660046124ed565b610e7c565b3480156104c657600080fd5b506101da6104d5366004612365565b61119c565b3480156104e657600080fd5b506101da6104f5366004612549565b6111eb565b6101da610508366004612272565b611271565b6101da61051b36600461240d565b6112d2565b34801561052c57600080fd5b506101da61053b366004612621565b611314565b34801561054c57600080fd5b507f9855384122b55936fbfb8ca5120e63c6537a1ac40caf6ae33502b3c5da8c87d1546102e5565b34801561058057600080fd5b506101da61058f366004612154565b611405565b6101da6105a23660046126d4565b611466565b3480156105b357600080fd5b506101da6105c2366004612446565b611574565b6101da6105d5366004611e59565b6115c4565b3480156105e657600080fd5b506101da6105f5366004612549565b61161f565b828260405161060a9291906127f0565b6040518091039020886001600160a01b03167f617332c1832058df6ee45fcbdf471251474c9945a8e5d229287a21a5f67ccf0a89898989348860405161065596959493929190612829565b60405180910390a35050505050505050565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146106af57604051623bb10360e91b815260040160405180910390fd5b6001600160a01b0385166106d65760405163e6c4247b60e01b815260040160405180910390fd5b828181146106f757604051636c2b7e2d60e11b815260040160405180910390fd5b60005b8181101561083d57600086868381811061071657610716612873565b905060200201602081019061072b9190612446565b9050600085858481811061074157610741612873565b9050602002013590508060000361076b57604051636c2b7e2d60e11b815260040160405180910390fd5b6001600160a01b03821661079857478111610793576107936001600160a01b038a168261167c565b610833565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa1580156107f5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108199190612889565b8111610833576108336001600160a01b0383168a836116c1565b50506001016106fa565b50505050505050565b6000807f2fa150da4c9f4c3a28593398c65313dd42f63d0530ec6db4a2b46e6d837a390260405161087a908d908d906127f0565b908152604051908190036020019020805490915060009067ffffffffffffffff1660048111156108ac576108ac6128a2565b60018301549091506108c7906001600160801b0316876128ce565b82546108e39190600160801b90046001600160801b03166128e5565b925060008160048111156108f9576108f96128a2565b1461097157604080517f657468657265756d00000000000000000000000000000000000000000000000081527f2fa150da4c9f4c3a28593398c65313dd42f63d0530ec6db4a2b46e6d837a390260088201529051908190036028019020610963828a8a868561176a565b61096d90856128e5565b9350505b50509998505050505050505050565b86866040516109909291906127f0565b60405180910390208c6001600160a01b03167fda4ed638a7ffe9e814722efdb9ad6058c152c19c8564ceffe52e11dda1ca32238d8d8d8d8b8b8b8b8b6040516109e19998979695949392919061291c565b60405180910390a36109fe6001600160a01b038416333085611844565b505050505050505050505050565b8585604051610a1c9291906127f0565b60405180910390208b6001600160a01b03167f8c092067e86e85e8cfbaf187202ef580cdfd7ec37fbec89191607de73ca800058c8c8c8c8a8a8a348b604051610a6d999897969594939291906129a5565b60405180910390a35050505050505050505050565b604080516001600160a01b03808616825260208201859052831691810191909152849086907ff0b09bf969e7958967e0968e22596f647dd6efa09f4778e0393967b881f4b09f906060015b60405180910390a3610aea6001600160a01b038416333085611844565b5050505050565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610b3957604051623bb10360e91b815260040160405180910390fd5b610aea8585858585611895565b604080513481526001600160a01b0383166020820152839185917fb26db521e067acd5c6e345ad92fa1ed06bc7fb2aedd68f35dc7a2e10d636fc9891015b60405180910390a3505050565b33610bba7f02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c05490565b6001600160a01b031614610be1576040516330cd747160e01b815260040160405180910390fd5b6001600160a01b038116610c0857604051633649397d60e21b815260040160405180910390fd5b6040516001600160a01b038216907fd9be0e8e07417e00f2521db636cb53e316fd288f5051f16d2aa2bf0c3938a87690600090a27f9855384122b55936fbfb8ca5120e63c6537a1ac40caf6ae33502b3c5da8c87d155565b6000610c8a7f9855384122b55936fbfb8ca5120e63c6537a1ac40caf6ae33502b3c5da8c87d15490565b90506001600160a01b0381163314610cce576040517f49e27cff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610cd781611945565b50565b336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610d2257604051623bb10360e91b815260040160405180910390fd5b610d30600080858585611895565b505050565b6040805160c081018252600080825260208201819052818301819052606082018190526080820181905260a082015290517f2fa150da4c9f4c3a28593398c65313dd42f63d0530ec6db4a2b46e6d837a390290610d9590859085906127f0565b90815260408051918290036020908101832060c084018352805467ffffffffffffffff808216865268010000000000000000820416928501929092526001600160801b03600160801b92839004811693850193909352600181015480841660608601529190910482166080840152600201541660a082015290505b92915050565b307f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031603610e78576040517fbf10dd3a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b33610ea57f02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c05490565b6001600160a01b031614610ecc576040516330cd747160e01b815260040160405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b0316638291286c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190612889565b846001600160a01b0316638291286c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f8d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fb19190612889565b14610fe8576040517f68155f9a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b836001600160a01b03163f831461102b576040517f8f84fb2400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8490556040516001600160a01b038516907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a28015611196576000846001600160a01b0316639ded06df60e01b84846040516024016110b0929190612a0c565b60408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090941693909317909252905161111b9190612a28565b600060405180830381855af49150503d8060008114611156576040519150601f19603f3d011682016040523d82523d6000602084013e61115b565b606091505b5050905080610aea576040517f97905dfb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050565b604080516001600160a01b03808616825260208201859052831691810191909152849086907f2275e75614080f9782f72563c2c1688c901c5339c7f9f436d323f9386fed700a90606001610acd565b84846040516111fb9291906127f0565b60405180910390208a6001600160a01b03167fd171a7eb157e548ca493dd0a16016d125963a369ac5ae3c275ec12c96d5277028b8b8b8b8989896040516112489796959493929190612a44565b60405180910390a36112656001600160a01b038416333085611844565b50505050505050505050565b85856040516112819291906127f0565b60405180910390208b6001600160a01b03167f999d431b58761213cf53af96262b67a069cbd963499fd8effd1e21556217b8418c8c8c8c8a8a8a348b604051610a6d999897969594939291906129a5565b604080513481526001600160a01b0383166020820152839185917ffeb6b00343feee0f29a1a4345f8bf93ca1c73ee922248a4237a4e50d6447604e9101610b84565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461135c57604051623bb10360e91b815260040160405180910390fd5b82818114611396576040517fa5f1efe300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156113fd573660008787848181106113b6576113b6612873565b90506020028101906113c89190612a98565b91509150368686858181106113df576113df612873565b905060c0020190506113f28383836119e8565b505050600101611399565b505050505050565b86866040516114159291906127f0565b60405180910390208c6001600160a01b03167f8875f9764f28fa82d3e7ff1b80bd5c8f665e1f42fcd8c2faebc7c400a4ba1bbd8d8d8d8d8b8b8b8b8b6040516109e19998979695949392919061291c565b801561149e576040517fa86b651200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83156115035760006114b78c8c8c8c8c8c8c8a8a610846565b905034811115611501576040517f5b1fe5fc000000000000000000000000000000000000000000000000000000008152600481018290523460248201526044015b60405180910390fd5b505b86866040516115139291906127f0565b60405180910390208c6001600160a01b03167f617332c1832058df6ee45fcbdf471251474c9945a8e5d229287a21a5f67ccf0a8d8d8d8d348a60405161155e96959493929190612829565b60405180910390a3505050505050505050505050565b3361159d7f02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c05490565b6001600160a01b031614610cce576040516330cd747160e01b815260040160405180910390fd5b82826040516115d49291906127f0565b6040518091039020886001600160a01b03167f5cf48f121a0fecaa2c4a64b3eaf482c8c308d5387e161535970f3e9e4363eff689898989348860405161065596959493929190612829565b848460405161162f9291906127f0565b60405180910390208a6001600160a01b03167f99206760f0be19dd093729bd35e5924daff5e217bcedc5223ed067b60008cf8a8b8b8b8b8989896040516112489796959493929190612a44565b600080600080600085875af1905080610d30576040517ff4b3b1bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040516001600160a01b038316602482015260448101829052610d309084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611a6e565b60006001866004811115611780576117806128a2565b036117985761179185858585611b45565b905061183b565b60028660048111156117ac576117ac6128a2565b036117bd5761179185858585611c08565b60038660048111156117d1576117d16128a2565b036117e25761179185858585611c7e565b60048660048111156117f6576117f66128a2565b036118075761179185858585611d1a565b856040517f10fcd31f0000000000000000000000000000000000000000000000000000000081526004016114f89190612adf565b95945050505050565b6040516001600160a01b03808516602483015283166044820152606481018290526111969085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611706565b6001600160a01b0383166118bc5760405163e6c4247b60e01b815260040160405180910390fd5b604080516001600160a01b03808616825284166020820152908101829052849086907fd5df103822011013c8c940930e5180419111c65abadd6525ca7e740d56b4703f9060600160405180910390a36001600160a01b0382166119315761192c6001600160a01b0384168261167c565b610aea565b610aea6001600160a01b03831684836116c1565b6001600160a01b03811661196c57604051633649397d60e21b815260040160405180910390fd5b6040516001600160a01b038216907f04dba622d284ed0014ee4b9a6a68386be1a4c08a4913ae272de89199cc68616390600090a27f02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c05560007f9855384122b55936fbfb8ca5120e63c6537a1ac40caf6ae33502b3c5da8c87d155565b7f11415423beab67062fb0f3f22cb2a478e3b5a02a845dd62ddb7c12d11098ff1b838383604051611a1b93929190612b32565b60405180910390a1807f2fa150da4c9f4c3a28593398c65313dd42f63d0530ec6db4a2b46e6d837a3902604051611a5590869086906127f0565b908152604051908190036020019020610aea8282612bf0565b600080836001600160a01b031683604051611a899190612a28565b6000604051808303816000865af19150503d8060008114611ac6576040519150601f19603f3d011682016040523d82523d6000602084013e611acb565b606091505b50915091506000828015611af7575081511580611af7575081806020019051810190611af79190612d33565b9050801580611b0e57506001600160a01b0385163b155b15610aea576040517f045c4b0200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000620f4240620dbba082611b5a8888611d45565b6001860154909150600090611b7f90600160801b90046001600160801b0316846128ce565b600187015488546001600160801b0390911690611bb39068010000000000000000900467ffffffffffffffff166010612d50565b67ffffffffffffffff16611bc79190612d74565b6001600160801b0316611bda91906128e5565b9050611be78460106128ce565b611bf183836128ce565b611bfb9190612d97565b9998505050505050505050565b600060bc620f42408282611c1c8989611d45565b611c2691906128e5565b8654600187015491925083916801000000000000000090910467ffffffffffffffff1690611c5e9084906001600160801b03166128ce565b611c6891906128ce565b611c729190612d97565b98975050505050505050565b6000612710601082611c9082806128ce565b90506064600088611ca461018460446128e5565b611cae91906128e5565b905060006002611cbe83876128ce565b611cc89190612d97565b905085611cd584826128e5565b611cdf86846128e5565b60018b0154611cf791906001600160801b03166128ce565b611d0191906128ce565b611d0b9190612d97565b9b9a5050505050505050505050565b60006109c4633b9aca008282611d308989611d45565b611d3a91906128e5565b611c269060406128e5565b6000611d53604460106128ce565b9050611d6261018460086128ce565b611d6c90826128e5565b90508160005b81811015611de357848482818110611d8c57611d8c612873565b909101357fff00000000000000000000000000000000000000000000000000000000000000166000039050611dcd57611dc66004846128e5565b9250611ddb565b611dd86010846128e5565b92505b600101611d72565b505092915050565b6001600160a01b0381168114610cd757600080fd5b8035611e0b81611deb565b919050565b60008083601f840112611e2257600080fd5b50813567ffffffffffffffff811115611e3a57600080fd5b602083019150836020828501011115611e5257600080fd5b9250929050565b60008060008060008060008060a0898b031215611e7557600080fd5b8835611e8081611deb565b9750602089013567ffffffffffffffff80821115611e9d57600080fd5b611ea98c838d01611e10565b909950975060408b0135915080821115611ec257600080fd5b611ece8c838d01611e10565b909750955060608b0135915080821115611ee757600080fd5b50611ef48b828c01611e10565b9094509250506080890135611f0881611deb565b809150509295985092959890939650565b60008083601f840112611f2b57600080fd5b50813567ffffffffffffffff811115611f4357600080fd5b6020830191508360208260051b8501011115611e5257600080fd5b600080600080600060608688031215611f7657600080fd5b8535611f8181611deb565b9450602086013567ffffffffffffffff80821115611f9e57600080fd5b611faa89838a01611f19565b90965094506040880135915080821115611fc357600080fd5b50611fd088828901611f19565b969995985093965092949392505050565b600080600080600080600080600060a08a8c031215611fff57600080fd5b893567ffffffffffffffff8082111561201757600080fd5b6120238d838e01611e10565b909b50995060208c013591508082111561203c57600080fd5b6120488d838e01611e10565b909950975060408c013591508082111561206157600080fd5b61206d8d838e01611e10565b909750955060608c0135945060808c013591508082111561208d57600080fd5b5061209a8c828d01611e10565b915080935050809150509295985092959850929598565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126120d857600080fd5b813567ffffffffffffffff808211156120f3576120f36120b1565b604051601f8301601f19908116603f0116810190828211818310171561211b5761211b6120b1565b8160405283815286602085880101111561213457600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000806000806000806000806000806101208d8f03121561217757600080fd5b6121808d611e00565b9b5067ffffffffffffffff60208e0135111561219b57600080fd5b6121ab8e60208f01358f01611e10565b909b50995067ffffffffffffffff60408e013511156121c957600080fd5b6121d98e60408f01358f01611e10565b909950975067ffffffffffffffff60608e013511156121f757600080fd5b6122078e60608f01358f01611e10565b909750955067ffffffffffffffff60808e0135111561222557600080fd5b6122358e60808f01358f016120c7565b945060a08d0135935061224a60c08e01611e00565b925060e08d013591506122606101008e01611e00565b90509295989b509295989b509295989b565b600080600080600080600080600080600060e08c8e03121561229357600080fd5b61229c8c611e00565b9a5067ffffffffffffffff8060208e013511156122b857600080fd5b6122c88e60208f01358f01611e10565b909b50995060408d01358110156122de57600080fd5b6122ee8e60408f01358f01611e10565b909950975060608d013581101561230457600080fd5b6123148e60608f01358f01611e10565b909750955060808d013581101561232a57600080fd5b5061233b8d60808e01358e01611e10565b909450925060a08c0135915061235360c08d01611e00565b90509295989b509295989b9093969950565b600080600080600060a0868803121561237d57600080fd5b8535945060208601359350604086013561239681611deb565b92506060860135915060808601356123ad81611deb565b809150509295509295909350565b600080600080600060a086880312156123d357600080fd5b853594506020860135935060408601356123ec81611deb565b925060608601356123fc81611deb565b949793965091946080013592915050565b60008060006060848603121561242257600080fd5b8335925060208401359150604084013561243b81611deb565b809150509250925092565b60006020828403121561245857600080fd5b813561246381611deb565b9392505050565b60008060006060848603121561247f57600080fd5b833561248a81611deb565b9250602084013561249a81611deb565b929592945050506040919091013590565b600080602083850312156124be57600080fd5b823567ffffffffffffffff8111156124d557600080fd5b6124e185828601611e10565b90969095509350505050565b6000806000806060858703121561250357600080fd5b843561250e81611deb565b935060208501359250604085013567ffffffffffffffff81111561253157600080fd5b61253d87828801611e10565b95989497509550505050565b60008060008060008060008060008060e08b8d03121561256857600080fd5b8a3561257381611deb565b995060208b013567ffffffffffffffff8082111561259057600080fd5b61259c8e838f01611e10565b909b50995060408d01359150808211156125b557600080fd5b6125c18e838f01611e10565b909950975060608d01359150808211156125da57600080fd5b506125e78d828e01611e10565b90965094505060808b01356125fb81611deb565b925060a08b0135915061261060c08c01611e00565b90509295989b9194979a5092959850565b6000806000806040858703121561263757600080fd5b843567ffffffffffffffff8082111561264f57600080fd5b61265b88838901611f19565b9096509450602087013591508082111561267457600080fd5b818701915087601f83011261268857600080fd5b81358181111561269757600080fd5b88602060c0830285010111156126ac57600080fd5b95989497505060200194505050565b8015158114610cd757600080fd5b8035611e0b816126bb565b6000806000806000806000806000806000806101008d8f0312156126f757600080fd5b6127008d611e00565b9b5067ffffffffffffffff60208e0135111561271b57600080fd5b61272b8e60208f01358f01611e10565b909b50995067ffffffffffffffff60408e0135111561274957600080fd5b6127598e60408f01358f01611e10565b909950975067ffffffffffffffff60608e0135111561277757600080fd5b6127878e60608f01358f01611e10565b909750955060808d0135945061279f60a08e016126c9565b93506127ad60c08e01611e00565b925067ffffffffffffffff60e08e013511156127c857600080fd5b6127d88e60e08f01358f01611e10565b81935080925050509295989b509295989b509295989b565b8183823760009101908152919050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60808152600061283d60808301888a612800565b8281036020840152612850818789612800565b9150508360408301526001600160a01b0383166060830152979650505050505050565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561289b57600080fd5b5051919050565b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610e1057610e106128b8565b80820180821115610e1057610e106128b8565b60005b838110156129135781810151838201526020016128fb565b50506000910152565b60e08152600061293060e083018b8d612800565b8281036020840152612943818a8c612800565b905082810360408401528751808252612963816020840160208c016128f8565b60608401979097526001600160a01b03958616608084015260a083019490945250921660c0909201919091526020601f909201601f1916010195945050505050565b60c0815260006129b960c083018b8d612800565b82810360208401526129cc818a8c612800565b905082810360408401526129e181888a612800565b6060840196909652505060808101929092526001600160a01b031660a0909101529695505050505050565b602081526000612a20602083018486612800565b949350505050565b60008251612a3a8184602087016128f8565b9190910192915050565b60a081526000612a5860a08301898b612800565b8281036020840152612a6b81888a612800565b6001600160a01b039687166040850152606084019590955250509216608090920191909152949350505050565b6000808335601e19843603018112612aaf57600080fd5b83018035915067ffffffffffffffff821115612aca57600080fd5b602001915036819003821315611e5257600080fd5b6020810160058310612b0157634e487b7160e01b600052602160045260246000fd5b91905290565b67ffffffffffffffff81168114610cd757600080fd5b6001600160801b0381168114610cd757600080fd5b60e081526000612b4660e083018587612800565b90508235612b5381612b07565b67ffffffffffffffff808216602085015260208501359150612b7482612b07565b16604083810191909152830135612b8a81612b1d565b6001600160801b03808216606085015260608501359150612baa82612b1d565b808216608085015260808501359150612bc282612b1d565b1660a083810191909152830135612bd881612b1d565b6001600160801b03811660c084015250949350505050565b8135612bfb81612b07565b67ffffffffffffffff8116905081548167ffffffffffffffff1982161783556020840135612c2881612b07565b6fffffffffffffffff00000000000000008160401b16836fffffffffffffffffffffffffffffffff198416171784555050506040820135612c6881612b1d565b81546001600160801b0316608082901b6fffffffffffffffffffffffffffffffff191617825550600181016060830135612ca181612b1d565b81546fffffffffffffffffffffffffffffffff19166001600160801b038216178255506080830135612cd281612b1d565b81546001600160801b0316608082901b6fffffffffffffffffffffffffffffffff1916178255505060a0820135612d0881612b1d565b6002820180546fffffffffffffffffffffffffffffffff19166001600160801b038316179055505050565b600060208284031215612d4557600080fd5b8151612463816126bb565b67ffffffffffffffff818116838216028082169190828114611de357611de36128b8565b6001600160801b03818116838216028082169190828114611de357611de36128b8565b600082612db457634e487b7160e01b600052601260045260246000fd5b50049056fea2646970667358221220f861469381b22ffcb51c7e8aac64c42df609fa41fe64a670d8f91918c4789d3a64736f6c634300081700330000000000000000000000007ddb2d76b80b0aa19bdea48eb1301182f4ceefbc

Deployed Bytecode

0x6080604052600436106101c25760003560e01c8063892b5007116100f7578063cd433ada11610095578063edf936f211610064578063edf936f214610594578063f2fde38b146105a7578063f61ed218146105c7578063fd09e3bd146105da57600080fd5b8063cd433ada1461050d578063d3b81f0c14610520578063e30c397814610540578063edb6b3a51461057457600080fd5b8063a3499c73116100d1578063a3499c731461049a578063ab1999ba146104ba578063ba9ddc8d146104da578063c62c2002146104fa57600080fd5b8063892b5007146104125780638da5cb5b146104465780639ded06df1461047a57600080fd5b80634d2384891161016457806379ba50971161013e57806379ba50971461031d5780638291286c1461033257806382ad6f351461036557806386389f021461038557600080fd5b80634d238489146102a25780635c60da1b146102b5578063710bf322146102fd57600080fd5b806317a49f7c116101a057806317a49f7c1461022f5780632e9b74701461024f5780632edd2aa814610262578063365047211461028257600080fd5b80630c93e3bb146101c75780631055eaaf146101dc578063135eaa70146101fc575b600080fd5b6101da6101d5366004611e59565b6105fa565b005b3480156101e857600080fd5b506101da6101f7366004611f5e565b610667565b34801561020857600080fd5b5061021c610217366004611fe1565b610846565b6040519081526020015b60405180910390f35b34801561023b57600080fd5b506101da61024a366004612154565b610980565b6101da61025d366004612272565b610a0c565b34801561026e57600080fd5b506101da61027d366004612365565b610a82565b34801561028e57600080fd5b506101da61029d3660046123bb565b610af1565b6101da6102b036600461240d565b610b46565b3480156102c157600080fd5b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545b6040516001600160a01b039091168152602001610226565b34801561030957600080fd5b506101da610318366004612446565b610b91565b34801561032957600080fd5b506101da610c60565b34801561033e57600080fd5b507ffaa2f015f2ce5aee225904728de2def86eb8837491efd21f1a04fc20d8e923f661021c565b34801561037157600080fd5b506101da61038036600461246a565b610cda565b34801561039157600080fd5b506103a56103a03660046124ab565b610d35565b6040516102269190600060c08201905067ffffffffffffffff8084511683528060208501511660208401525060408301516001600160801b0380821660408501528060608601511660608501528060808601511660808501528060a08601511660a0850152505092915050565b34801561041e57600080fd5b506102e57f0000000000000000000000007ddb2d76b80b0aa19bdea48eb1301182f4ceefbc81565b34801561045257600080fd5b507f02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c0546102e5565b34801561048657600080fd5b506101da6104953660046124ab565b610e16565b3480156104a657600080fd5b506101da6104b53660046124ed565b610e7c565b3480156104c657600080fd5b506101da6104d5366004612365565b61119c565b3480156104e657600080fd5b506101da6104f5366004612549565b6111eb565b6101da610508366004612272565b611271565b6101da61051b36600461240d565b6112d2565b34801561052c57600080fd5b506101da61053b366004612621565b611314565b34801561054c57600080fd5b507f9855384122b55936fbfb8ca5120e63c6537a1ac40caf6ae33502b3c5da8c87d1546102e5565b34801561058057600080fd5b506101da61058f366004612154565b611405565b6101da6105a23660046126d4565b611466565b3480156105b357600080fd5b506101da6105c2366004612446565b611574565b6101da6105d5366004611e59565b6115c4565b3480156105e657600080fd5b506101da6105f5366004612549565b61161f565b828260405161060a9291906127f0565b6040518091039020886001600160a01b03167f617332c1832058df6ee45fcbdf471251474c9945a8e5d229287a21a5f67ccf0a89898989348860405161065596959493929190612829565b60405180910390a35050505050505050565b336001600160a01b037f0000000000000000000000007ddb2d76b80b0aa19bdea48eb1301182f4ceefbc16146106af57604051623bb10360e91b815260040160405180910390fd5b6001600160a01b0385166106d65760405163e6c4247b60e01b815260040160405180910390fd5b828181146106f757604051636c2b7e2d60e11b815260040160405180910390fd5b60005b8181101561083d57600086868381811061071657610716612873565b905060200201602081019061072b9190612446565b9050600085858481811061074157610741612873565b9050602002013590508060000361076b57604051636c2b7e2d60e11b815260040160405180910390fd5b6001600160a01b03821661079857478111610793576107936001600160a01b038a168261167c565b610833565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa1580156107f5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108199190612889565b8111610833576108336001600160a01b0383168a836116c1565b50506001016106fa565b50505050505050565b6000807f2fa150da4c9f4c3a28593398c65313dd42f63d0530ec6db4a2b46e6d837a390260405161087a908d908d906127f0565b908152604051908190036020019020805490915060009067ffffffffffffffff1660048111156108ac576108ac6128a2565b60018301549091506108c7906001600160801b0316876128ce565b82546108e39190600160801b90046001600160801b03166128e5565b925060008160048111156108f9576108f96128a2565b1461097157604080517f657468657265756d00000000000000000000000000000000000000000000000081527f2fa150da4c9f4c3a28593398c65313dd42f63d0530ec6db4a2b46e6d837a390260088201529051908190036028019020610963828a8a868561176a565b61096d90856128e5565b9350505b50509998505050505050505050565b86866040516109909291906127f0565b60405180910390208c6001600160a01b03167fda4ed638a7ffe9e814722efdb9ad6058c152c19c8564ceffe52e11dda1ca32238d8d8d8d8b8b8b8b8b6040516109e19998979695949392919061291c565b60405180910390a36109fe6001600160a01b038416333085611844565b505050505050505050505050565b8585604051610a1c9291906127f0565b60405180910390208b6001600160a01b03167f8c092067e86e85e8cfbaf187202ef580cdfd7ec37fbec89191607de73ca800058c8c8c8c8a8a8a348b604051610a6d999897969594939291906129a5565b60405180910390a35050505050505050505050565b604080516001600160a01b03808616825260208201859052831691810191909152849086907ff0b09bf969e7958967e0968e22596f647dd6efa09f4778e0393967b881f4b09f906060015b60405180910390a3610aea6001600160a01b038416333085611844565b5050505050565b336001600160a01b037f0000000000000000000000007ddb2d76b80b0aa19bdea48eb1301182f4ceefbc1614610b3957604051623bb10360e91b815260040160405180910390fd5b610aea8585858585611895565b604080513481526001600160a01b0383166020820152839185917fb26db521e067acd5c6e345ad92fa1ed06bc7fb2aedd68f35dc7a2e10d636fc9891015b60405180910390a3505050565b33610bba7f02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c05490565b6001600160a01b031614610be1576040516330cd747160e01b815260040160405180910390fd5b6001600160a01b038116610c0857604051633649397d60e21b815260040160405180910390fd5b6040516001600160a01b038216907fd9be0e8e07417e00f2521db636cb53e316fd288f5051f16d2aa2bf0c3938a87690600090a27f9855384122b55936fbfb8ca5120e63c6537a1ac40caf6ae33502b3c5da8c87d155565b6000610c8a7f9855384122b55936fbfb8ca5120e63c6537a1ac40caf6ae33502b3c5da8c87d15490565b90506001600160a01b0381163314610cce576040517f49e27cff00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610cd781611945565b50565b336001600160a01b037f0000000000000000000000007ddb2d76b80b0aa19bdea48eb1301182f4ceefbc1614610d2257604051623bb10360e91b815260040160405180910390fd5b610d30600080858585611895565b505050565b6040805160c081018252600080825260208201819052818301819052606082018190526080820181905260a082015290517f2fa150da4c9f4c3a28593398c65313dd42f63d0530ec6db4a2b46e6d837a390290610d9590859085906127f0565b90815260408051918290036020908101832060c084018352805467ffffffffffffffff808216865268010000000000000000820416928501929092526001600160801b03600160801b92839004811693850193909352600181015480841660608601529190910482166080840152600201541660a082015290505b92915050565b307f000000000000000000000000cb5c784dcf8ff342625dbc53b356ed0cbb0ebb9b6001600160a01b031603610e78576040517fbf10dd3a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b33610ea57f02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c05490565b6001600160a01b031614610ecc576040516330cd747160e01b815260040160405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b0316638291286c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f4f9190612889565b846001600160a01b0316638291286c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f8d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fb19190612889565b14610fe8576040517f68155f9a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b836001600160a01b03163f831461102b576040517f8f84fb2400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8490556040516001600160a01b038516907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a28015611196576000846001600160a01b0316639ded06df60e01b84846040516024016110b0929190612a0c565b60408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090941693909317909252905161111b9190612a28565b600060405180830381855af49150503d8060008114611156576040519150601f19603f3d011682016040523d82523d6000602084013e61115b565b606091505b5050905080610aea576040517f97905dfb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050565b604080516001600160a01b03808616825260208201859052831691810191909152849086907f2275e75614080f9782f72563c2c1688c901c5339c7f9f436d323f9386fed700a90606001610acd565b84846040516111fb9291906127f0565b60405180910390208a6001600160a01b03167fd171a7eb157e548ca493dd0a16016d125963a369ac5ae3c275ec12c96d5277028b8b8b8b8989896040516112489796959493929190612a44565b60405180910390a36112656001600160a01b038416333085611844565b50505050505050505050565b85856040516112819291906127f0565b60405180910390208b6001600160a01b03167f999d431b58761213cf53af96262b67a069cbd963499fd8effd1e21556217b8418c8c8c8c8a8a8a348b604051610a6d999897969594939291906129a5565b604080513481526001600160a01b0383166020820152839185917ffeb6b00343feee0f29a1a4345f8bf93ca1c73ee922248a4237a4e50d6447604e9101610b84565b336001600160a01b037f0000000000000000000000007ddb2d76b80b0aa19bdea48eb1301182f4ceefbc161461135c57604051623bb10360e91b815260040160405180910390fd5b82818114611396576040517fa5f1efe300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156113fd573660008787848181106113b6576113b6612873565b90506020028101906113c89190612a98565b91509150368686858181106113df576113df612873565b905060c0020190506113f28383836119e8565b505050600101611399565b505050505050565b86866040516114159291906127f0565b60405180910390208c6001600160a01b03167f8875f9764f28fa82d3e7ff1b80bd5c8f665e1f42fcd8c2faebc7c400a4ba1bbd8d8d8d8d8b8b8b8b8b6040516109e19998979695949392919061291c565b801561149e576040517fa86b651200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83156115035760006114b78c8c8c8c8c8c8c8a8a610846565b905034811115611501576040517f5b1fe5fc000000000000000000000000000000000000000000000000000000008152600481018290523460248201526044015b60405180910390fd5b505b86866040516115139291906127f0565b60405180910390208c6001600160a01b03167f617332c1832058df6ee45fcbdf471251474c9945a8e5d229287a21a5f67ccf0a8d8d8d8d348a60405161155e96959493929190612829565b60405180910390a3505050505050505050505050565b3361159d7f02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c05490565b6001600160a01b031614610cce576040516330cd747160e01b815260040160405180910390fd5b82826040516115d49291906127f0565b6040518091039020886001600160a01b03167f5cf48f121a0fecaa2c4a64b3eaf482c8c308d5387e161535970f3e9e4363eff689898989348860405161065596959493929190612829565b848460405161162f9291906127f0565b60405180910390208a6001600160a01b03167f99206760f0be19dd093729bd35e5924daff5e217bcedc5223ed067b60008cf8a8b8b8b8b8989896040516112489796959493929190612a44565b600080600080600085875af1905080610d30576040517ff4b3b1bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040516001600160a01b038316602482015260448101829052610d309084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611a6e565b60006001866004811115611780576117806128a2565b036117985761179185858585611b45565b905061183b565b60028660048111156117ac576117ac6128a2565b036117bd5761179185858585611c08565b60038660048111156117d1576117d16128a2565b036117e25761179185858585611c7e565b60048660048111156117f6576117f66128a2565b036118075761179185858585611d1a565b856040517f10fcd31f0000000000000000000000000000000000000000000000000000000081526004016114f89190612adf565b95945050505050565b6040516001600160a01b03808516602483015283166044820152606481018290526111969085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611706565b6001600160a01b0383166118bc5760405163e6c4247b60e01b815260040160405180910390fd5b604080516001600160a01b03808616825284166020820152908101829052849086907fd5df103822011013c8c940930e5180419111c65abadd6525ca7e740d56b4703f9060600160405180910390a36001600160a01b0382166119315761192c6001600160a01b0384168261167c565b610aea565b610aea6001600160a01b03831684836116c1565b6001600160a01b03811661196c57604051633649397d60e21b815260040160405180910390fd5b6040516001600160a01b038216907f04dba622d284ed0014ee4b9a6a68386be1a4c08a4913ae272de89199cc68616390600090a27f02016836a56b71f0d02689e69e326f4f4c1b9057164ef592671cf0d37c8040c05560007f9855384122b55936fbfb8ca5120e63c6537a1ac40caf6ae33502b3c5da8c87d155565b7f11415423beab67062fb0f3f22cb2a478e3b5a02a845dd62ddb7c12d11098ff1b838383604051611a1b93929190612b32565b60405180910390a1807f2fa150da4c9f4c3a28593398c65313dd42f63d0530ec6db4a2b46e6d837a3902604051611a5590869086906127f0565b908152604051908190036020019020610aea8282612bf0565b600080836001600160a01b031683604051611a899190612a28565b6000604051808303816000865af19150503d8060008114611ac6576040519150601f19603f3d011682016040523d82523d6000602084013e611acb565b606091505b50915091506000828015611af7575081511580611af7575081806020019051810190611af79190612d33565b9050801580611b0e57506001600160a01b0385163b155b15610aea576040517f045c4b0200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000620f4240620dbba082611b5a8888611d45565b6001860154909150600090611b7f90600160801b90046001600160801b0316846128ce565b600187015488546001600160801b0390911690611bb39068010000000000000000900467ffffffffffffffff166010612d50565b67ffffffffffffffff16611bc79190612d74565b6001600160801b0316611bda91906128e5565b9050611be78460106128ce565b611bf183836128ce565b611bfb9190612d97565b9998505050505050505050565b600060bc620f42408282611c1c8989611d45565b611c2691906128e5565b8654600187015491925083916801000000000000000090910467ffffffffffffffff1690611c5e9084906001600160801b03166128ce565b611c6891906128ce565b611c729190612d97565b98975050505050505050565b6000612710601082611c9082806128ce565b90506064600088611ca461018460446128e5565b611cae91906128e5565b905060006002611cbe83876128ce565b611cc89190612d97565b905085611cd584826128e5565b611cdf86846128e5565b60018b0154611cf791906001600160801b03166128ce565b611d0191906128ce565b611d0b9190612d97565b9b9a5050505050505050505050565b60006109c4633b9aca008282611d308989611d45565b611d3a91906128e5565b611c269060406128e5565b6000611d53604460106128ce565b9050611d6261018460086128ce565b611d6c90826128e5565b90508160005b81811015611de357848482818110611d8c57611d8c612873565b909101357fff00000000000000000000000000000000000000000000000000000000000000166000039050611dcd57611dc66004846128e5565b9250611ddb565b611dd86010846128e5565b92505b600101611d72565b505092915050565b6001600160a01b0381168114610cd757600080fd5b8035611e0b81611deb565b919050565b60008083601f840112611e2257600080fd5b50813567ffffffffffffffff811115611e3a57600080fd5b602083019150836020828501011115611e5257600080fd5b9250929050565b60008060008060008060008060a0898b031215611e7557600080fd5b8835611e8081611deb565b9750602089013567ffffffffffffffff80821115611e9d57600080fd5b611ea98c838d01611e10565b909950975060408b0135915080821115611ec257600080fd5b611ece8c838d01611e10565b909750955060608b0135915080821115611ee757600080fd5b50611ef48b828c01611e10565b9094509250506080890135611f0881611deb565b809150509295985092959890939650565b60008083601f840112611f2b57600080fd5b50813567ffffffffffffffff811115611f4357600080fd5b6020830191508360208260051b8501011115611e5257600080fd5b600080600080600060608688031215611f7657600080fd5b8535611f8181611deb565b9450602086013567ffffffffffffffff80821115611f9e57600080fd5b611faa89838a01611f19565b90965094506040880135915080821115611fc357600080fd5b50611fd088828901611f19565b969995985093965092949392505050565b600080600080600080600080600060a08a8c031215611fff57600080fd5b893567ffffffffffffffff8082111561201757600080fd5b6120238d838e01611e10565b909b50995060208c013591508082111561203c57600080fd5b6120488d838e01611e10565b909950975060408c013591508082111561206157600080fd5b61206d8d838e01611e10565b909750955060608c0135945060808c013591508082111561208d57600080fd5b5061209a8c828d01611e10565b915080935050809150509295985092959850929598565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126120d857600080fd5b813567ffffffffffffffff808211156120f3576120f36120b1565b604051601f8301601f19908116603f0116810190828211818310171561211b5761211b6120b1565b8160405283815286602085880101111561213457600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000806000806000806000806000806101208d8f03121561217757600080fd5b6121808d611e00565b9b5067ffffffffffffffff60208e0135111561219b57600080fd5b6121ab8e60208f01358f01611e10565b909b50995067ffffffffffffffff60408e013511156121c957600080fd5b6121d98e60408f01358f01611e10565b909950975067ffffffffffffffff60608e013511156121f757600080fd5b6122078e60608f01358f01611e10565b909750955067ffffffffffffffff60808e0135111561222557600080fd5b6122358e60808f01358f016120c7565b945060a08d0135935061224a60c08e01611e00565b925060e08d013591506122606101008e01611e00565b90509295989b509295989b509295989b565b600080600080600080600080600080600060e08c8e03121561229357600080fd5b61229c8c611e00565b9a5067ffffffffffffffff8060208e013511156122b857600080fd5b6122c88e60208f01358f01611e10565b909b50995060408d01358110156122de57600080fd5b6122ee8e60408f01358f01611e10565b909950975060608d013581101561230457600080fd5b6123148e60608f01358f01611e10565b909750955060808d013581101561232a57600080fd5b5061233b8d60808e01358e01611e10565b909450925060a08c0135915061235360c08d01611e00565b90509295989b509295989b9093969950565b600080600080600060a0868803121561237d57600080fd5b8535945060208601359350604086013561239681611deb565b92506060860135915060808601356123ad81611deb565b809150509295509295909350565b600080600080600060a086880312156123d357600080fd5b853594506020860135935060408601356123ec81611deb565b925060608601356123fc81611deb565b949793965091946080013592915050565b60008060006060848603121561242257600080fd5b8335925060208401359150604084013561243b81611deb565b809150509250925092565b60006020828403121561245857600080fd5b813561246381611deb565b9392505050565b60008060006060848603121561247f57600080fd5b833561248a81611deb565b9250602084013561249a81611deb565b929592945050506040919091013590565b600080602083850312156124be57600080fd5b823567ffffffffffffffff8111156124d557600080fd5b6124e185828601611e10565b90969095509350505050565b6000806000806060858703121561250357600080fd5b843561250e81611deb565b935060208501359250604085013567ffffffffffffffff81111561253157600080fd5b61253d87828801611e10565b95989497509550505050565b60008060008060008060008060008060e08b8d03121561256857600080fd5b8a3561257381611deb565b995060208b013567ffffffffffffffff8082111561259057600080fd5b61259c8e838f01611e10565b909b50995060408d01359150808211156125b557600080fd5b6125c18e838f01611e10565b909950975060608d01359150808211156125da57600080fd5b506125e78d828e01611e10565b90965094505060808b01356125fb81611deb565b925060a08b0135915061261060c08c01611e00565b90509295989b9194979a5092959850565b6000806000806040858703121561263757600080fd5b843567ffffffffffffffff8082111561264f57600080fd5b61265b88838901611f19565b9096509450602087013591508082111561267457600080fd5b818701915087601f83011261268857600080fd5b81358181111561269757600080fd5b88602060c0830285010111156126ac57600080fd5b95989497505060200194505050565b8015158114610cd757600080fd5b8035611e0b816126bb565b6000806000806000806000806000806000806101008d8f0312156126f757600080fd5b6127008d611e00565b9b5067ffffffffffffffff60208e0135111561271b57600080fd5b61272b8e60208f01358f01611e10565b909b50995067ffffffffffffffff60408e0135111561274957600080fd5b6127598e60408f01358f01611e10565b909950975067ffffffffffffffff60608e0135111561277757600080fd5b6127878e60608f01358f01611e10565b909750955060808d0135945061279f60a08e016126c9565b93506127ad60c08e01611e00565b925067ffffffffffffffff60e08e013511156127c857600080fd5b6127d88e60e08f01358f01611e10565b81935080925050509295989b509295989b509295989b565b8183823760009101908152919050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60808152600061283d60808301888a612800565b8281036020840152612850818789612800565b9150508360408301526001600160a01b0383166060830152979650505050505050565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561289b57600080fd5b5051919050565b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b8082028115828204841417610e1057610e106128b8565b80820180821115610e1057610e106128b8565b60005b838110156129135781810151838201526020016128fb565b50506000910152565b60e08152600061293060e083018b8d612800565b8281036020840152612943818a8c612800565b905082810360408401528751808252612963816020840160208c016128f8565b60608401979097526001600160a01b03958616608084015260a083019490945250921660c0909201919091526020601f909201601f1916010195945050505050565b60c0815260006129b960c083018b8d612800565b82810360208401526129cc818a8c612800565b905082810360408401526129e181888a612800565b6060840196909652505060808101929092526001600160a01b031660a0909101529695505050505050565b602081526000612a20602083018486612800565b949350505050565b60008251612a3a8184602087016128f8565b9190910192915050565b60a081526000612a5860a08301898b612800565b8281036020840152612a6b81888a612800565b6001600160a01b039687166040850152606084019590955250509216608090920191909152949350505050565b6000808335601e19843603018112612aaf57600080fd5b83018035915067ffffffffffffffff821115612aca57600080fd5b602001915036819003821315611e5257600080fd5b6020810160058310612b0157634e487b7160e01b600052602160045260246000fd5b91905290565b67ffffffffffffffff81168114610cd757600080fd5b6001600160801b0381168114610cd757600080fd5b60e081526000612b4660e083018587612800565b90508235612b5381612b07565b67ffffffffffffffff808216602085015260208501359150612b7482612b07565b16604083810191909152830135612b8a81612b1d565b6001600160801b03808216606085015260608501359150612baa82612b1d565b808216608085015260808501359150612bc282612b1d565b1660a083810191909152830135612bd881612b1d565b6001600160801b03811660c084015250949350505050565b8135612bfb81612b07565b67ffffffffffffffff8116905081548167ffffffffffffffff1982161783556020840135612c2881612b07565b6fffffffffffffffff00000000000000008160401b16836fffffffffffffffffffffffffffffffff198416171784555050506040820135612c6881612b1d565b81546001600160801b0316608082901b6fffffffffffffffffffffffffffffffff191617825550600181016060830135612ca181612b1d565b81546fffffffffffffffffffffffffffffffff19166001600160801b038216178255506080830135612cd281612b1d565b81546001600160801b0316608082901b6fffffffffffffffffffffffffffffffff1916178255505060a0820135612d0881612b1d565b6002820180546fffffffffffffffffffffffffffffffff19166001600160801b038316179055505050565b600060208284031215612d4557600080fd5b8151612463816126bb565b67ffffffffffffffff818116838216028082169190828114611de357611de36128b8565b6001600160801b03818116838216028082169190828114611de357611de36128b8565b600082612db457634e487b7160e01b600052601260045260246000fd5b50049056fea2646970667358221220f861469381b22ffcb51c7e8aac64c42df609fa41fe64a670d8f91918c4789d3a64736f6c63430008170033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

0000000000000000000000007ddb2d76b80b0aa19bdea48eb1301182f4ceefbc

-----Decoded View---------------
Arg [0] : gasCollector_ (address): 0x7DdB2d76b80B0AA19bDEa48EB1301182F4CeefbC

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000007ddb2d76b80b0aa19bdea48eb1301182f4ceefbc


Block Transaction Gas Used Reward
view all blocks collator

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.