Contract 0xd5678ae1ce712adc945aa8c86a7be2923cbc3c98

 
Txn Hash Method
Block
From
To
Value [Txn Fee]
0x2d47bf6bcecd887492fa37d0169759ca6a85b357111a4d8444abcedfb1b822aa0x60806040186424682022-07-26 20:03:59126 days 4 hrs ago0xdc0d4bdcc70362cedd23d3997c31528ec1502fc4 IN  Create: LiquidityPool0 ETH0.019208124109 ETH
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0xcc45f735cf2d251522199b27dcd619ca75b4e1fbf2b7d9eb15bd914e71b452ed422997932022-11-30 0:32:211 min ago 0x856cb5c3cbbe9e2e21293a644aa1f9363cee11e80xd5678ae1ce712adc945aa8c86a7be2923cbc3c980 ETH
0xc02359a353318dcfdfd39dd0926ff46c17e2cf0f210a08bfeec229b82c9e9bd4422997022022-11-30 0:31:471 min ago 0x856cb5c3cbbe9e2e21293a644aa1f9363cee11e80xd5678ae1ce712adc945aa8c86a7be2923cbc3c980 ETH
0x9795e7b916c3c131eb345d1bbfacf5ad38fb5d2b58545a1ab4076a542d2ec3d5422996842022-11-30 0:31:381 min ago 0x856cb5c3cbbe9e2e21293a644aa1f9363cee11e80xd5678ae1ce712adc945aa8c86a7be2923cbc3c980 ETH
0xca479d1cfbb36e3640085af12c0aac6459b1c0fe386b01d2480d96c1dde9d5ea422995102022-11-30 0:30:362 mins ago 0x856cb5c3cbbe9e2e21293a644aa1f9363cee11e80xd5678ae1ce712adc945aa8c86a7be2923cbc3c980 ETH
0xa12094706b1a22c2227f0d8d0871b9c97bfb1bbf5828c677f17e22c33dc5563a422994422022-11-30 0:30:103 mins ago 0x856cb5c3cbbe9e2e21293a644aa1f9363cee11e80xd5678ae1ce712adc945aa8c86a7be2923cbc3c980 ETH
0xf1d8f6bd7be37dd7148c86af6f4a2a68aa75da61323f9f252bdaad74d1cc289a422994102022-11-30 0:30:003 mins ago 0x856cb5c3cbbe9e2e21293a644aa1f9363cee11e80xd5678ae1ce712adc945aa8c86a7be2923cbc3c980 ETH
0xb391e513fa650b8a623d1a4deb966e095bfa44d1e1f1e91c3c378cd44c84ed27422993372022-11-30 0:29:304 mins ago 0x856cb5c3cbbe9e2e21293a644aa1f9363cee11e80xd5678ae1ce712adc945aa8c86a7be2923cbc3c980 ETH
0xf08bb3d5ac5e5d60b30dcbccc1e9b996e6e4a2e9c1622068d383313df2392f3c422992742022-11-30 0:29:104 mins ago 0x856cb5c3cbbe9e2e21293a644aa1f9363cee11e80xd5678ae1ce712adc945aa8c86a7be2923cbc3c980 ETH
0xa0270e8029c94dfb514f1d3d7de292d50bcc0714a29b2687783babf43a5b9a83422992662022-11-30 0:29:084 mins ago 0x856cb5c3cbbe9e2e21293a644aa1f9363cee11e80xd5678ae1ce712adc945aa8c86a7be2923cbc3c980 ETH
0x5c06571d0d0093c61b1fbd1c9b211a3ed954eeb2cb64c6f703dc3279e2e3f471422991812022-11-30 0:28:344 mins ago 0x856cb5c3cbbe9e2e21293a644aa1f9363cee11e80xd5678ae1ce712adc945aa8c86a7be2923cbc3c980 ETH
0xee79f78f4d62315cbd767575a262765c3d838eeec4a5f6cd6a3ee818868a0056422989972022-11-30 0:27:306 mins ago 0x856cb5c3cbbe9e2e21293a644aa1f9363cee11e80xd5678ae1ce712adc945aa8c86a7be2923cbc3c980 ETH
0x03d89c682e592ff096f9bc77125f2ab5b2309c3e6c6acf6c8921d3daaa678b1e422989822022-11-30 0:27:266 mins ago 0x856cb5c3cbbe9e2e21293a644aa1f9363cee11e80xd5678ae1ce712adc945aa8c86a7be2923cbc3c980 ETH
0x6eaa700caad962d3412115cbc7ce05fc1610aba23f6401eb78e5cd5669859f17422989802022-11-30 0:27:256 mins ago 0x856cb5c3cbbe9e2e21293a644aa1f9363cee11e80xd5678ae1ce712adc945aa8c86a7be2923cbc3c980 ETH
0x6a89b330ec189866f33f12bf47cf7de963ce403a316ca83b660bd033b2492d8e422989802022-11-30 0:27:256 mins ago 0x856cb5c3cbbe9e2e21293a644aa1f9363cee11e80xd5678ae1ce712adc945aa8c86a7be2923cbc3c980 ETH
0x77552d929824972f311db2dc69577c30c478481066b88bef977f48d083c08c07422989792022-11-30 0:27:256 mins ago 0x856cb5c3cbbe9e2e21293a644aa1f9363cee11e80xd5678ae1ce712adc945aa8c86a7be2923cbc3c980 ETH
0x6e343c384197ab1d89b3084a7950819647c074052adb1456dadfe59cdec33237422988762022-11-30 0:26:496 mins ago 0x856cb5c3cbbe9e2e21293a644aa1f9363cee11e80xd5678ae1ce712adc945aa8c86a7be2923cbc3c980 ETH
0x2edcd78e2a57a82028119ce41503cbeaef348907cd362529fb3b27f14d1cae6a422987892022-11-30 0:26:237 mins ago 0x856cb5c3cbbe9e2e21293a644aa1f9363cee11e80xd5678ae1ce712adc945aa8c86a7be2923cbc3c980 ETH
0x6962d7101907a2b306b227099ba14272d9f594c16f70550d3c91530f662bda20422986012022-11-30 0:25:178 mins ago 0x856cb5c3cbbe9e2e21293a644aa1f9363cee11e80xd5678ae1ce712adc945aa8c86a7be2923cbc3c980 ETH
0x3525953d2bb2fa34f9c2457f6ce9087b27eead8c9dfccfd974a11514e1d5ad73422985092022-11-30 0:24:428 mins ago 0x856cb5c3cbbe9e2e21293a644aa1f9363cee11e80xd5678ae1ce712adc945aa8c86a7be2923cbc3c980 ETH
0x47680a68e5b2dcc6a879843d9ebd00c6f7250d67b9d3efd61ec001c2260a69f6422985002022-11-30 0:24:388 mins ago 0x856cb5c3cbbe9e2e21293a644aa1f9363cee11e80xd5678ae1ce712adc945aa8c86a7be2923cbc3c980 ETH
0xa33fb66a571b96717415329fe7a2890fe37c5eb7b20ab8df94edbf8335f88c96422984832022-11-30 0:24:328 mins ago 0x856cb5c3cbbe9e2e21293a644aa1f9363cee11e80xd5678ae1ce712adc945aa8c86a7be2923cbc3c980 ETH
0x928bf937eb45ed53a9b61b335c442b8ff06e17b92aae1d42b613a9e5fecebf3a422984082022-11-30 0:24:069 mins ago 0x856cb5c3cbbe9e2e21293a644aa1f9363cee11e80xd5678ae1ce712adc945aa8c86a7be2923cbc3c980 ETH
0x82379ff82f73777ce5680315837344cb8cf5549f3ead7cb2bb33aa3d183f2291422983322022-11-30 0:23:449 mins ago 0x856cb5c3cbbe9e2e21293a644aa1f9363cee11e80xd5678ae1ce712adc945aa8c86a7be2923cbc3c980 ETH
0x3772555409238f31a17db2bb4336eba22bedbb5754eda35bdc9e0fb2a4ec0f73422981702022-11-30 0:22:4710 mins ago 0x856cb5c3cbbe9e2e21293a644aa1f9363cee11e80xd5678ae1ce712adc945aa8c86a7be2923cbc3c980 ETH
0x232294e660263dc3f3843ab28d03e0d168b9a616ecee0a0909786f6c1d951fd1422980302022-11-30 0:21:4911 mins ago 0x856cb5c3cbbe9e2e21293a644aa1f9363cee11e80xd5678ae1ce712adc945aa8c86a7be2923cbc3c980 ETH
[ Download CSV Export 
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
LiquidityPool

Compiler Version
v0.8.0+commit.c7dfd78e

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 18 : LiquidityPool.sol
// $$\   $$\                     $$\                                 $$$$$$$\                      $$\
// $$ |  $$ |                    $$ |                                $$  __$$\                     $$ |
// $$ |  $$ |$$\   $$\  $$$$$$\  $$$$$$$\   $$$$$$\  $$$$$$$\        $$ |  $$ | $$$$$$\   $$$$$$\  $$ |
// $$$$$$$$ |$$ |  $$ |$$  __$$\ $$  __$$\ $$  __$$\ $$  __$$\       $$$$$$$  |$$  __$$\ $$  __$$\ $$ |
// $$  __$$ |$$ |  $$ |$$ /  $$ |$$ |  $$ |$$$$$$$$ |$$ |  $$ |      $$  ____/ $$ /  $$ |$$ /  $$ |$$ |
// $$ |  $$ |$$ |  $$ |$$ |  $$ |$$ |  $$ |$$   ____|$$ |  $$ |      $$ |      $$ |  $$ |$$ |  $$ |$$ |
// $$ |  $$ |\$$$$$$$ |$$$$$$$  |$$ |  $$ |\$$$$$$$\ $$ |  $$ |      $$ |      \$$$$$$  |\$$$$$$  |$$ |
// \__|  \__| \____$$ |$$  ____/ \__|  \__| \_______|\__|  \__|      \__|       \______/  \______/ \__|
//           $$\   $$ |$$ |
//           \$$$$$$  |$$ |
//            \______/ \__|
//
// SPDX-License-Identifier: MIT

pragma solidity 0.8.0;
pragma abicoder v2;

import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
import "./metatx/ERC2771ContextUpgradeable.sol";
import "../security/Pausable.sol";
import "./structures/TokenConfig.sol";
import "./interfaces/IExecutorManager.sol";
import "./interfaces/ILiquidityProviders.sol";
import "../interfaces/IERC20Permit.sol";
import "./interfaces/ITokenManager.sol";
import "./interfaces/ISwapAdaptor.sol";

contract LiquidityPool is
    Initializable,
    ReentrancyGuardUpgradeable,
    Pausable,
    OwnableUpgradeable,
    ERC2771ContextUpgradeable
{
    address private constant NATIVE = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
    uint256 private constant BASE_DIVISOR = 10000000000; // Basis Points * 100 for better accuracy
    uint256 private constant TOKEN_PRICE_BASE_DIVISOR = 10**28;

    uint256 public baseGas;

    IExecutorManager private executorManager;
    ITokenManager public tokenManager;
    ILiquidityProviders public liquidityProviders;

    struct PermitRequest {
        uint256 nonce;
        uint256 expiry;
        bool allowed;
        uint8 v;
        bytes32 r;
        bytes32 s;
    }

    mapping(bytes32 => bool) public processedHash;
    mapping(address => uint256) public gasFeeAccumulatedByToken;

    // Gas fee accumulated by token address => executor address
    mapping(address => mapping(address => uint256)) public gasFeeAccumulated;

    // Incentive Pool amount per token address
    mapping(address => uint256) public incentivePool;

    mapping(string => address) public swapAdaptorMap;

    event AssetSent(
        address indexed asset,
        uint256 indexed amount,
        uint256 indexed transferredAmount,
        address target,
        bytes depositHash,
        uint256 fromChainId,
        uint256 lpFee,
        uint256 transferFee,
        uint256 gasFee
    );
    event Received(address indexed from, uint256 indexed amount);
    event Deposit(
        address indexed from,
        address indexed tokenAddress,
        address indexed receiver,
        uint256 toChainId,
        uint256 amount,
        uint256 reward,
        string tag
    );
    event GasFeeWithdraw(address indexed tokenAddress, address indexed owner, uint256 indexed amount);
    event LiquidityProvidersChanged(address indexed liquidityProvidersAddress);
    event TokenManagerChanged(address indexed tokenManagerAddress);
    event BaseGasUpdated(uint256 indexed baseGas);
    event EthReceived(address, uint256);
    event DepositAndSwap(
        address indexed from,
        address indexed tokenAddress,
        address indexed receiver,
        uint256 toChainId,
        uint256 amount,
        uint256 reward,
        string tag,
        SwapRequest[] swapRequests
    );
    event SwapAdaptorChanged(string indexed name, address indexed liquidityProvidersAddress);
    event GasFeeCalculated(
        uint256 indexed gasUsed,
        uint256 indexed gasPrice,
        uint256 indexed nativeTokenPriceInTransferredToken,
        uint256 tokenGasBaseFee,
        uint256 gasFeeInTransferredToken
    );

    // MODIFIERS
    modifier onlyExecutor() {
        require(executorManager.getExecutorStatus(_msgSender()), "Only executor is allowed");
        _;
    }

    modifier onlyLiquidityProviders() {
        require(_msgSender() == address(liquidityProviders), "Only liquidityProviders is allowed");
        _;
    }

    modifier tokenChecks(address tokenAddress) {
        (, bool supportedToken, , , ) = tokenManager.tokensInfo(tokenAddress);
        require(supportedToken, "Token not supported");
        _;
    }

    function initialize(
        address _executorManagerAddress,
        address _pauser,
        address _trustedForwarder,
        address _tokenManager,
        address _liquidityProviders
    ) public initializer {
        require(_executorManagerAddress != address(0), "ExecutorManager cannot be 0x0");
        require(_trustedForwarder != address(0), "TrustedForwarder cannot be 0x0");
        require(_liquidityProviders != address(0), "LiquidityProviders cannot be 0x0");
        __ERC2771Context_init(_trustedForwarder);
        __ReentrancyGuard_init();
        __Ownable_init();
        __Pausable_init(_pauser);
        executorManager = IExecutorManager(_executorManagerAddress);
        tokenManager = ITokenManager(_tokenManager);
        liquidityProviders = ILiquidityProviders(_liquidityProviders);
        baseGas = 21000;
    }

    function setSwapAdaptor(string calldata name, address _swapAdaptor) external onlyOwner {
        swapAdaptorMap[name] = _swapAdaptor;
        emit SwapAdaptorChanged(name, _swapAdaptor);
    }

    function setTrustedForwarder(address trustedForwarder) external onlyOwner {
        _setTrustedForwarder(trustedForwarder);
    }

    function setLiquidityProviders(address _liquidityProviders) external onlyOwner {
        require(_liquidityProviders != address(0), "LiquidityProviders can't be 0");
        liquidityProviders = ILiquidityProviders(_liquidityProviders);
        emit LiquidityProvidersChanged(_liquidityProviders);
    }

    function setTokenManager(address _tokenManager) external onlyOwner {
        require(_tokenManager != address(0), "TokenManager can't be 0");
        tokenManager = ITokenManager(_tokenManager);
        emit TokenManagerChanged(_tokenManager);
    }

    function setBaseGas(uint128 gas) external onlyOwner {
        baseGas = gas;
        emit BaseGasUpdated(baseGas);
    }

    function getExecutorManager() external view returns (address) {
        return address(executorManager);
    }

    function setExecutorManager(address _executorManagerAddress) external onlyOwner {
        require(_executorManagerAddress != address(0), "Executor Manager cannot be 0");
        executorManager = IExecutorManager(_executorManagerAddress);
    }

    function getCurrentLiquidity(address tokenAddress) public view returns (uint256 currentLiquidity) {
        uint256 liquidityPoolBalance = liquidityProviders.getCurrentLiquidity(tokenAddress);

        currentLiquidity =
            liquidityPoolBalance -
            liquidityProviders.totalLPFees(tokenAddress) -
            gasFeeAccumulatedByToken[tokenAddress] -
            incentivePool[tokenAddress];
    }

    /**
     * @dev Function used to deposit tokens into pool to initiate a cross chain token transfer.
     * @param toChainId Chain id where funds needs to be transfered
     * @param tokenAddress ERC20 Token address that needs to be transfered
     * @param receiver Address on toChainId where tokens needs to be transfered
     * @param amount Amount of token being transfered
     */
    function depositErc20(
        uint256 toChainId,
        address tokenAddress,
        address receiver,
        uint256 amount,
        string calldata tag
    ) public tokenChecks(tokenAddress) whenNotPaused nonReentrant {
        address sender = _msgSender();
        uint256 rewardAmount = _depositErc20(sender, toChainId, tokenAddress, receiver, amount);

        // Emit (amount + reward amount) in event
        emit Deposit(sender, tokenAddress, receiver, toChainId, amount + rewardAmount, rewardAmount, tag);
    }

    /**
     * @dev Function used to deposit tokens into pool to initiate a cross chain token swap And transfer .
     * @param toChainId Chain id where funds needs to be transfered
     * @param tokenAddress ERC20 Token address that needs to be transfered
     * @param receiver Address on toChainId where tokens needs to be transfered
     * @param amount Amount of token being transfered
     * @param tag Dapp unique identifier
     * @param swapRequest information related to token swap on exit chain
     */
    function depositAndSwapErc20(
        address tokenAddress,
        address receiver,
        uint256 toChainId,
        uint256 amount,
        string calldata tag,
        SwapRequest[] calldata swapRequest
    ) external tokenChecks(tokenAddress) whenNotPaused nonReentrant {
        uint256 totalPercentage = 0;
        {
            uint256 swapArrayLength = swapRequest.length;
            unchecked {
                for (uint256 index = 0; index < swapArrayLength; ++index) {
                    totalPercentage += swapRequest[index].percentage;
                }
            }
        }

        require(totalPercentage <= 100 * BASE_DIVISOR, "Total percentage cannot be > 100");
        address sender = _msgSender();
        uint256 rewardAmount = _depositErc20(sender, toChainId, tokenAddress, receiver, amount);
        // Emit (amount + reward amount) in event
        emit DepositAndSwap(
            sender,
            tokenAddress,
            receiver,
            toChainId,
            amount + rewardAmount,
            rewardAmount,
            tag,
            swapRequest
        );
    }

    function _depositErc20(
        address sender,
        uint256 toChainId,
        address tokenAddress,
        address receiver,
        uint256 amount
    ) internal returns (uint256) {
        require(toChainId != block.chainid, "To chain must be different than current chain");
        require(tokenAddress != NATIVE, "wrong function");
        TokenConfig memory config = tokenManager.getDepositConfig(toChainId, tokenAddress);

        require(config.min <= amount && config.max >= amount, "Deposit amount not in Cap limit");
        require(receiver != address(0), "Receiver address cannot be 0");
        require(amount != 0, "Amount cannot be 0");

        uint256 rewardAmount = getRewardAmount(amount, tokenAddress);
        if (rewardAmount != 0) {
            incentivePool[tokenAddress] = incentivePool[tokenAddress] - rewardAmount;
        }
        liquidityProviders.increaseCurrentLiquidity(tokenAddress, amount);
        SafeERC20Upgradeable.safeTransferFrom(IERC20Upgradeable(tokenAddress), sender, address(this), amount);
        return rewardAmount;
    }

    function getRewardAmount(uint256 amount, address tokenAddress) public view returns (uint256 rewardAmount) {
        uint256 currentLiquidity = getCurrentLiquidity(tokenAddress);
        uint256 providedLiquidity = liquidityProviders.getSuppliedLiquidityByToken(tokenAddress);
        if (currentLiquidity < providedLiquidity) {
            uint256 liquidityDifference = providedLiquidity - currentLiquidity;
            if (amount >= liquidityDifference) {
                rewardAmount = incentivePool[tokenAddress];
            } else {
                // Multiply by 10000000000 to avoid 0 reward amount for small amount and liquidity difference
                rewardAmount = (amount * incentivePool[tokenAddress] * 10000000000) / liquidityDifference;
                rewardAmount = rewardAmount / 10000000000;
            }
        }
    }

    /**
     * DAI permit and Deposit.
     */
    function permitAndDepositErc20(
        address tokenAddress,
        address receiver,
        uint256 amount,
        uint256 toChainId,
        PermitRequest calldata permitOptions,
        string calldata tag
    ) external {
        IERC20Permit(tokenAddress).permit(
            _msgSender(),
            address(this),
            permitOptions.nonce,
            permitOptions.expiry,
            permitOptions.allowed,
            permitOptions.v,
            permitOptions.r,
            permitOptions.s
        );
        depositErc20(toChainId, tokenAddress, receiver, amount, tag);
    }

    /**
     * EIP2612 and Deposit.
     */
    function permitEIP2612AndDepositErc20(
        address tokenAddress,
        address receiver,
        uint256 amount,
        uint256 toChainId,
        PermitRequest calldata permitOptions,
        string calldata tag
    ) external {
        IERC20Permit(tokenAddress).permit(
            _msgSender(),
            address(this),
            amount,
            permitOptions.expiry,
            permitOptions.v,
            permitOptions.r,
            permitOptions.s
        );
        depositErc20(toChainId, tokenAddress, receiver, amount, tag);
    }

    /**
     * @dev Function used to deposit native token into pool to initiate a cross chain token transfer.
     * @param receiver Address on toChainId where tokens needs to be transfered
     * @param toChainId Chain id where funds needs to be transfered
     */
    function depositNative(
        address receiver,
        uint256 toChainId,
        string calldata tag
    ) external payable whenNotPaused nonReentrant {
        uint256 rewardAmount = _depositNative(receiver, toChainId);
        emit Deposit(_msgSender(), NATIVE, receiver, toChainId, msg.value + rewardAmount, rewardAmount, tag);
    }

    function depositNativeAndSwap(
        address receiver,
        uint256 toChainId,
        string calldata tag,
        SwapRequest[] calldata swapRequest
    ) external payable whenNotPaused nonReentrant {
        uint256 totalPercentage = 0;
        {
            uint256 swapArrayLength = swapRequest.length;
            unchecked {
                for (uint256 index = 0; index < swapArrayLength; ++index) {
                    totalPercentage += swapRequest[index].percentage;
                }
            }
        }

        require(totalPercentage <= 100 * BASE_DIVISOR, "Total percentage cannot be > 100");

        uint256 rewardAmount = _depositNative(receiver, toChainId); // TODO: check if need to pass msg.value
        emit DepositAndSwap(
            _msgSender(),
            NATIVE,
            receiver,
            toChainId,
            msg.value + rewardAmount,
            rewardAmount,
            tag,
            swapRequest
        );
    }

    function _depositNative(address receiver, uint256 toChainId) internal returns (uint256) {
        require(toChainId != block.chainid, "To chain must be different than current chain");
        require(
            tokenManager.getDepositConfig(toChainId, NATIVE).min <= msg.value &&
                tokenManager.getDepositConfig(toChainId, NATIVE).max >= msg.value,
            "Deposit amount not in Cap limit"
        );
        require(receiver != address(0), "Receiver address cannot be 0");
        require(msg.value != 0, "Amount cannot be 0");

        uint256 rewardAmount = getRewardAmount(msg.value, NATIVE);
        if (rewardAmount != 0) {
            incentivePool[NATIVE] = incentivePool[NATIVE] - rewardAmount;
        }
        liquidityProviders.increaseCurrentLiquidity(NATIVE, msg.value);
        return rewardAmount;
    }

    function sendFundsToUser(
        address tokenAddress,
        uint256 amount,
        address payable receiver,
        bytes calldata depositHash,
        uint256 tokenGasPrice,
        uint256 fromChainId
    ) external nonReentrant onlyExecutor whenNotPaused {
        uint256 initialGas = gasleft();
        TokenConfig memory config = tokenManager.getTransferConfig(tokenAddress);
        require(config.min <= amount && config.max >= amount, "Withdraw amount not in Cap limit");
        require(receiver != address(0), "Bad receiver address");

        (bytes32 hashSendTransaction, bool status) = checkHashStatus(tokenAddress, amount, receiver, depositHash);

        require(!status, "Already Processed");
        processedHash[hashSendTransaction] = true;

        // uint256 amountToTransfer, uint256 lpFee, uint256 transferFeeAmount, uint256 gasFee
        uint256[4] memory transferDetails = getAmountToTransfer(initialGas, tokenAddress, amount, tokenGasPrice);

        liquidityProviders.decreaseCurrentLiquidity(tokenAddress, transferDetails[0]);

        if (tokenAddress == NATIVE) {
            (bool success, ) = receiver.call{value: transferDetails[0]}("");
            require(success, "Native Transfer Failed");
        } else {
            SafeERC20Upgradeable.safeTransfer(IERC20Upgradeable(tokenAddress), receiver, transferDetails[0]);
        }

        emit AssetSent(
            tokenAddress,
            amount,
            transferDetails[0],
            receiver,
            depositHash,
            fromChainId,
            transferDetails[1],
            transferDetails[2],
            transferDetails[3]
        );
    }

    /**
     * @dev Internal function to calculate amount of token that needs to be transfered afetr deducting all required fees.
     * Fee to be deducted includes gas fee, lp fee and incentive pool amount if needed.
     * @param initialGas Gas provided initially before any calculations began
     * @param tokenAddress Token address for which calculation needs to be done
     * @param amount Amount of token to be transfered before deducting the fee
     * @param tokenGasPrice Gas price in the token being transfered to be used to calculate gas fee
     * @return [ amountToTransfer, lpFee, transferFeeAmount, gasFee ]
     */
    function getAmountToTransfer(
        uint256 initialGas,
        address tokenAddress,
        uint256 amount,
        uint256 tokenGasPrice
    ) internal returns (uint256[4] memory) {
        TokenInfo memory tokenInfo = tokenManager.getTokensInfo(tokenAddress);
        uint256 transferFeePerc = _getTransferFee(tokenAddress, amount, tokenInfo);
        uint256 lpFee;
        if (transferFeePerc > tokenInfo.equilibriumFee) {
            // Here add some fee to incentive pool also
            lpFee = (amount * tokenInfo.equilibriumFee) / BASE_DIVISOR;
            unchecked {
                incentivePool[tokenAddress] += (amount * (transferFeePerc - tokenInfo.equilibriumFee)) / BASE_DIVISOR;
            }
        } else {
            lpFee = (amount * transferFeePerc) / BASE_DIVISOR;
        }
        uint256 transferFeeAmount = (amount * transferFeePerc) / BASE_DIVISOR;

        liquidityProviders.addLPFee(tokenAddress, lpFee);

        uint256 totalGasUsed = initialGas + tokenInfo.transferOverhead + baseGas - gasleft();

        uint256 gasFee = totalGasUsed * tokenGasPrice;
        gasFeeAccumulatedByToken[tokenAddress] += gasFee;
        gasFeeAccumulated[tokenAddress][_msgSender()] += gasFee;
        uint256 amountToTransfer = amount - (transferFeeAmount + gasFee);
        return [amountToTransfer, lpFee, transferFeeAmount, gasFee];
    }

    function sendFundsToUserV2(
        address tokenAddress,
        uint256 amount,
        address payable receiver,
        bytes calldata depositHash,
        uint256 nativeTokenPriceInTransferredToken,
        uint256 fromChainId,
        uint256 tokenGasBaseFee
    ) external nonReentrant onlyExecutor whenNotPaused {
        uint256[4] memory transferDetails = _calculateAmountAndDecreaseAvailableLiquidity(
            tokenAddress,
            amount,
            receiver,
            depositHash,
            nativeTokenPriceInTransferredToken,
            tokenGasBaseFee
        );
        if (tokenAddress == NATIVE) {
            (bool success, ) = receiver.call{value: transferDetails[0]}("");
            require(success, "Native Transfer Failed");
        } else {
            SafeERC20Upgradeable.safeTransfer(IERC20Upgradeable(tokenAddress), receiver, transferDetails[0]);
        }

        emit AssetSent(
            tokenAddress,
            amount,
            transferDetails[0],
            receiver,
            depositHash,
            fromChainId,
            transferDetails[1],
            transferDetails[2],
            transferDetails[3]
        );
    }

    function swapAndSendFundsToUser(
        address tokenAddress,
        uint256 amount,
        address payable receiver,
        bytes calldata depositHash,
        uint256 nativeTokenPriceInTransferredToken,
        uint256 tokenGasBaseFee,
        uint256 fromChainId,
        uint256 swapGasOverhead,
        SwapRequest[] calldata swapRequests,
        string memory swapAdaptor
    ) external nonReentrant onlyExecutor whenNotPaused {
        require(swapRequests.length > 0, "Wrong method call");
        require(swapAdaptorMap[swapAdaptor] != address(0), "Swap adaptor not found");

        uint256[4] memory transferDetails = _calculateAmountAndDecreaseAvailableLiquidity(
            tokenAddress,
            amount,
            receiver,
            depositHash,
            nativeTokenPriceInTransferredToken,
            tokenGasBaseFee
        );

        if (tokenAddress == NATIVE) {
            (bool success, ) = swapAdaptorMap[swapAdaptor].call{value: transferDetails[0]}("");
            require(success, "Native Transfer to Adaptor Failed");
            ISwapAdaptor(swapAdaptorMap[swapAdaptor]).swapNative(transferDetails[0], receiver, swapRequests);
        } else {
            {
                uint256 gasBeforeApproval = gasleft();
                SafeERC20Upgradeable.safeApprove(
                    IERC20Upgradeable(tokenAddress),
                    address(swapAdaptorMap[swapAdaptor]),
                    0
                );
                SafeERC20Upgradeable.safeApprove(
                    IERC20Upgradeable(tokenAddress),
                    address(swapAdaptorMap[swapAdaptor]),
                    transferDetails[0]
                );

                swapGasOverhead += (gasBeforeApproval - gasleft());
            }
            {
                uint256 swapGasFee = calculateGasFee(
                    tokenAddress,
                    nativeTokenPriceInTransferredToken,
                    swapGasOverhead,
                    0,
                    _msgSender()
                );
                transferDetails[0] -= swapGasFee; // Deduct swap gas fee from amount to be sent
                transferDetails[3] += swapGasFee; // Add swap gas fee to gas fee
            }

            ISwapAdaptor(swapAdaptorMap[swapAdaptor]).swap(tokenAddress, transferDetails[0], receiver, swapRequests);
        }

        emit AssetSent(
            tokenAddress,
            amount,
            transferDetails[0],
            receiver,
            depositHash,
            fromChainId,
            transferDetails[1],
            transferDetails[2],
            transferDetails[3]
        );
    }

    function _calculateAmountAndDecreaseAvailableLiquidity(
        address tokenAddress,
        uint256 amount,
        address payable receiver,
        bytes calldata depositHash,
        uint256 nativeTokenPriceInTransferredToken,
        uint256 tokenGasBaseFee
    ) internal returns (uint256[4] memory) {
        uint256 initialGas = gasleft();
        TokenConfig memory config = tokenManager.getTransferConfig(tokenAddress);
        require(config.min <= amount && config.max >= amount, "Withdraw amount not in Cap limit");
        require(receiver != address(0), "Bad receiver address");
        (bytes32 hashSendTransaction, bool status) = checkHashStatus(tokenAddress, amount, receiver, depositHash);

        require(!status, "Already Processed");
        processedHash[hashSendTransaction] = true;
        // uint256 amountToTransfer, uint256 lpFee, uint256 transferFeeAmount, uint256 gasFee
        uint256[4] memory transferDetails = getAmountToTransferV2(
            initialGas,
            tokenAddress,
            amount,
            nativeTokenPriceInTransferredToken,
            tokenGasBaseFee
        );

        liquidityProviders.decreaseCurrentLiquidity(tokenAddress, transferDetails[0]);

        return transferDetails;
    }

    /**
     * @dev Internal function to calculate amount of token that needs to be transfered afetr deducting all required fees.
     * Fee to be deducted includes gas fee, lp fee and incentive pool amount if needed.
     * @param initialGas Gas provided initially before any calculations began
     * @param tokenAddress Token address for which calculation needs to be done
     * @param amount Amount of token to be transfered before deducting the fee
     * @param nativeTokenPriceInTransferredToken Price of native token in terms of the token being transferred (multiplied base div), used to calculate gas fee
     * @return [ amountToTransfer, lpFee, transferFeeAmount, gasFee ]
     */
    function getAmountToTransferV2(
        uint256 initialGas,
        address tokenAddress,
        uint256 amount,
        uint256 nativeTokenPriceInTransferredToken,
        uint256 tokenGasBaseFee
    ) internal returns (uint256[4] memory) {
        TokenInfo memory tokenInfo = tokenManager.getTokensInfo(tokenAddress);
        uint256 transferFeePerc = _getTransferFee(tokenAddress, amount, tokenInfo);
        uint256 lpFee;
        if (transferFeePerc > tokenInfo.equilibriumFee) {
            // Here add some fee to incentive pool also
            lpFee = (amount * tokenInfo.equilibriumFee) / BASE_DIVISOR;
            unchecked {
                incentivePool[tokenAddress] += (amount * (transferFeePerc - tokenInfo.equilibriumFee)) / BASE_DIVISOR;
            }
        } else {
            lpFee = (amount * transferFeePerc) / BASE_DIVISOR;
        }
        uint256 transferFeeAmount = (amount * transferFeePerc) / BASE_DIVISOR;

        liquidityProviders.addLPFee(tokenAddress, lpFee);

        uint256 totalGasUsed = initialGas + tokenInfo.transferOverhead + baseGas - gasleft();
        uint256 gasFee = calculateGasFee(
            tokenAddress,
            nativeTokenPriceInTransferredToken,
            totalGasUsed,
            tokenGasBaseFee,
            _msgSender()
        );
        require(transferFeeAmount + gasFee <= amount, "Insufficient funds to cover transfer fee");
        unchecked {
            uint256 amountToTransfer = amount - (transferFeeAmount + gasFee);
            return [amountToTransfer, lpFee, transferFeeAmount, gasFee];
        }
    }

    function calculateGasFee(
        address tokenAddress,
        uint256 nativeTokenPriceInTransferredToken,
        uint256 gasUsed,
        uint256 tokenGasBaseFee,
        address sender
    ) internal returns (uint256) {
        uint256 gasFee = (gasUsed * nativeTokenPriceInTransferredToken * tx.gasprice) /
            TOKEN_PRICE_BASE_DIVISOR +
            tokenGasBaseFee;
        emit GasFeeCalculated(gasUsed, tx.gasprice, nativeTokenPriceInTransferredToken, tokenGasBaseFee, gasFee);

        gasFeeAccumulatedByToken[tokenAddress] += gasFee;
        gasFeeAccumulated[tokenAddress][sender] += gasFee;
        return gasFee;
    }

    function _getTransferFee(
        address tokenAddress,
        uint256 amount,
        TokenInfo memory tokenInfo
    ) private view returns (uint256) {
        uint256 currentLiquidity = getCurrentLiquidity(tokenAddress);
        uint256 providedLiquidity = liquidityProviders.getSuppliedLiquidityByToken(tokenAddress);

        uint256 resultingLiquidity = currentLiquidity - amount;

        // We return a constant value in excess state
        if (resultingLiquidity > providedLiquidity) {
            return tokenManager.excessStateTransferFeePerc(tokenAddress);
        }

        // Fee is represented in basis points * 10 for better accuracy
        uint256 numerator = providedLiquidity * providedLiquidity * tokenInfo.equilibriumFee * tokenInfo.maxFee; // F(max) * F(e) * L(e) ^ 2
        uint256 denominator = tokenInfo.equilibriumFee *
            providedLiquidity *
            providedLiquidity +
            (tokenInfo.maxFee - tokenInfo.equilibriumFee) *
            resultingLiquidity *
            resultingLiquidity; // F(e) * L(e) ^ 2 + (F(max) - F(e)) * L(r) ^ 2

        uint256 fee;
        if (denominator == 0) {
            fee = 0;
        } else {
            fee = numerator / denominator;
        }
        return fee;
    }

    function getTransferFee(address tokenAddress, uint256 amount) external view returns (uint256) {
        return _getTransferFee(tokenAddress, amount, tokenManager.getTokensInfo(tokenAddress));
    }

    function checkHashStatus(
        address tokenAddress,
        uint256 amount,
        address payable receiver,
        bytes calldata depositHash
    ) public view returns (bytes32 hashSendTransaction, bool status) {
        hashSendTransaction = keccak256(abi.encode(tokenAddress, amount, receiver, keccak256(depositHash)));

        status = processedHash[hashSendTransaction];
    }

    function withdrawErc20GasFee(address tokenAddress) external onlyExecutor whenNotPaused nonReentrant {
        require(tokenAddress != NATIVE, "Can't withdraw native token fee");
        // uint256 gasFeeAccumulated = gasFeeAccumulatedByToken[tokenAddress];
        uint256 _gasFeeAccumulated = gasFeeAccumulated[tokenAddress][_msgSender()];
        require(_gasFeeAccumulated != 0, "Gas Fee earned is 0");
        gasFeeAccumulatedByToken[tokenAddress] = gasFeeAccumulatedByToken[tokenAddress] - _gasFeeAccumulated;
        gasFeeAccumulated[tokenAddress][_msgSender()] = 0;
        SafeERC20Upgradeable.safeTransfer(IERC20Upgradeable(tokenAddress), _msgSender(), _gasFeeAccumulated);
        emit GasFeeWithdraw(tokenAddress, _msgSender(), _gasFeeAccumulated);
    }

    function withdrawNativeGasFee() external onlyExecutor whenNotPaused nonReentrant {
        uint256 _gasFeeAccumulated = gasFeeAccumulated[NATIVE][_msgSender()];
        require(_gasFeeAccumulated != 0, "Gas Fee earned is 0");
        gasFeeAccumulatedByToken[NATIVE] = gasFeeAccumulatedByToken[NATIVE] - _gasFeeAccumulated;
        gasFeeAccumulated[NATIVE][_msgSender()] = 0;
        (bool success, ) = payable(_msgSender()).call{value: _gasFeeAccumulated}("");
        require(success, "Native Transfer Failed");

        emit GasFeeWithdraw(address(this), _msgSender(), _gasFeeAccumulated);
    }

    function transfer(
        address _tokenAddress,
        address receiver,
        uint256 _tokenAmount
    ) external whenNotPaused onlyLiquidityProviders nonReentrant {
        require(receiver != address(0), "Invalid receiver");
        if (_tokenAddress == NATIVE) {
            require(address(this).balance >= _tokenAmount, "ERR__INSUFFICIENT_BALANCE");
            (bool success, ) = receiver.call{value: _tokenAmount}("");
            require(success, "ERR__NATIVE_TRANSFER_FAILED");
        } else {
            IERC20Upgradeable baseToken = IERC20Upgradeable(_tokenAddress);
            require(baseToken.balanceOf(address(this)) >= _tokenAmount, "ERR__INSUFFICIENT_BALANCE");
            SafeERC20Upgradeable.safeTransfer(baseToken, receiver, _tokenAmount);
        }
    }

    function _msgSender()
        internal
        view
        virtual
        override(ContextUpgradeable, ERC2771ContextUpgradeable)
        returns (address sender)
    {
        return ERC2771ContextUpgradeable._msgSender();
    }

    function _msgData()
        internal
        view
        virtual
        override(ContextUpgradeable, ERC2771ContextUpgradeable)
        returns (bytes calldata)
    {
        return ERC2771ContextUpgradeable._msgData();
    }

    receive() external payable {
        emit EthReceived(_msgSender(), msg.value);
    }
}

File 2 of 18 : Initializable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
 * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an
 * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
 * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
 *
 * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
 * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
 *
 * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
 * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
 */
abstract contract Initializable {
    /**
     * @dev Indicates that the contract has been initialized.
     */
    bool private _initialized;

    /**
     * @dev Indicates that the contract is in the process of being initialized.
     */
    bool private _initializing;

    /**
     * @dev Modifier to protect an initializer function from being invoked twice.
     */
    modifier initializer() {
        require(_initializing || !_initialized, "Initializable: contract is already initialized");

        bool isTopLevelCall = !_initializing;
        if (isTopLevelCall) {
            _initializing = true;
            _initialized = true;
        }

        _;

        if (isTopLevelCall) {
            _initializing = false;
        }
    }
}

File 3 of 18 : OwnableUpgradeable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "../utils/ContextUpgradeable.sol";
import "../proxy/utils/Initializable.sol";

/**
 * @dev 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.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    function __Ownable_init() internal initializer {
        __Context_init_unchained();
        __Ownable_init_unchained();
    }

    function __Ownable_init_unchained() internal initializer {
        _setOwner(_msgSender());
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _setOwner(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _setOwner(newOwner);
    }

    function _setOwner(address newOwner) private {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
    uint256[49] private __gap;
}

File 4 of 18 : ReentrancyGuardUpgradeable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;
import "../proxy/utils/Initializable.sol";

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuardUpgradeable is Initializable {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    function __ReentrancyGuard_init() internal initializer {
        __ReentrancyGuard_init_unchained();
    }

    function __ReentrancyGuard_init_unchained() internal initializer {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and make it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        // On the first call to nonReentrant, _notEntered will be true
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;

        _;

        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }
    uint256[49] private __gap;
}

File 5 of 18 : SafeERC20Upgradeable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "../IERC20Upgradeable.sol";
import "../../../utils/AddressUpgradeable.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20Upgradeable {
    using AddressUpgradeable for address;

    function safeTransfer(
        IERC20Upgradeable token,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    function safeTransferFrom(
        IERC20Upgradeable token,
        address from,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(
        IERC20Upgradeable token,
        address spender,
        uint256 value
    ) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        require(
            (value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    function safeIncreaseAllowance(
        IERC20Upgradeable token,
        address spender,
        uint256 value
    ) internal {
        uint256 newAllowance = token.allowance(address(this), spender) + value;
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function safeDecreaseAllowance(
        IERC20Upgradeable token,
        address spender,
        uint256 value
    ) internal {
        unchecked {
            uint256 oldAllowance = token.allowance(address(this), spender);
            require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
            uint256 newAllowance = oldAllowance - value;
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
        }
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20Upgradeable token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
        if (returndata.length > 0) {
            // Return data is optional
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}

File 6 of 18 : IERC20Upgradeable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20Upgradeable {
    /**
     * @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 7 of 18 : ERC2771ContextUpgradeable.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.0;

import "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";

/**
 * @dev Context variant with ERC2771 support.
 * Here _trustedForwarder is made internal instead of private
 * so it can be changed via Child contracts with a setter method.
 */
abstract contract ERC2771ContextUpgradeable is Initializable, ContextUpgradeable {
    event TrustedForwarderChanged(address indexed _tf);

    address internal _trustedForwarder;

    function __ERC2771Context_init(address trustedForwarder) internal initializer {
        __Context_init_unchained();
        __ERC2771Context_init_unchained(trustedForwarder);
    }

    function __ERC2771Context_init_unchained(address trustedForwarder) internal initializer {
        _trustedForwarder = trustedForwarder;
    }

    function isTrustedForwarder(address forwarder) public view virtual returns (bool) {
        return forwarder == _trustedForwarder;
    }

    function _msgSender() internal view virtual override returns (address sender) {
        if (isTrustedForwarder(msg.sender)) {
            // The assembly code is more direct than the Solidity version using `abi.decode`.
            assembly {
                sender := shr(96, calldataload(sub(calldatasize(), 20)))
            }
        } else {
            return super._msgSender();
        }
    }

    function _msgData() internal view virtual override returns (bytes calldata) {
        if (isTrustedForwarder(msg.sender)) {
            return msg.data[:msg.data.length - 20];
        } else {
            return super._msgData();
        }
    }

    function _setTrustedForwarder(address _tf) internal virtual {
        require(_tf != address(0), "TrustedForwarder can't be 0");
        _trustedForwarder = _tf;
        emit TrustedForwarderChanged(_tf);
    }

    uint256[49] private __gap;
}

File 8 of 18 : Pausable.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.0;

import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol";

/**
 * @dev Contract module which allows children to implement an emergency stop
 * mechanism that can be triggered by an authorized account.
 *
 * This module is used through inheritance. It will make available the
 * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
 * the functions of your contract. Note that they will not be pausable by
 * simply including this module, only once the modifiers are put in place.
 */
abstract contract Pausable is Initializable, PausableUpgradeable {
    address private _pauser;

    event PauserChanged(address indexed previousPauser, address indexed newPauser);

    /**
     * @dev The pausable constructor sets the original `pauser` of the contract to the sender
     * account & Initializes the contract in unpaused state..
     */
    function __Pausable_init(address pauser) internal initializer {
        require(pauser != address(0), "Pauser Address cannot be 0");
        __Pausable_init();
        _pauser = pauser;
    }

    /**
     * @return true if `msg.sender` is the owner of the contract.
     */
    function isPauser(address pauser) public view returns (bool) {
        return pauser == _pauser;
    }

    /**
     * @dev Throws if called by any account other than the pauser.
     */
    modifier onlyPauser() {
        require(isPauser(msg.sender), "Only pauser is allowed to perform this operation");
        _;
    }

    /**
     * @dev Allows the current pauser to transfer control of the contract to a newPauser.
     * @param newPauser The address to transfer pauserShip to.
     */
    function changePauser(address newPauser) public onlyPauser whenNotPaused {
        _changePauser(newPauser);
    }

    /**
     * @dev Transfers control of the contract to a newPauser.
     * @param newPauser The address to transfer ownership to.
     */
    function _changePauser(address newPauser) internal {
        require(newPauser != address(0));
        emit PauserChanged(_pauser, newPauser);
        _pauser = newPauser;
    }

    function renouncePauser() external virtual onlyPauser whenNotPaused {
        emit PauserChanged(_pauser, address(0));
        _pauser = address(0);
    }

    function pause() public onlyPauser {
        _pause();
    }

    function unpause() public onlyPauser {
        _unpause();
    }
}

File 9 of 18 : TokenConfig.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.0;

struct TokenInfo {
    uint256 transferOverhead;
    bool supportedToken;
    uint256 equilibriumFee; // Percentage fee Represented in basis points
    uint256 maxFee; // Percentage fee Represented in basis points
    TokenConfig tokenConfig;
}

struct TokenConfig {
    uint256 min;
    uint256 max;
}

File 10 of 18 : IExecutorManager.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.0;

interface IExecutorManager {
    function getExecutorStatus(address executor) external view returns (bool status);

    function getAllExecutors() external view returns (address[] memory);

    //Register new Executors
    function addExecutors(address[] calldata executorArray) external;

    // Register single executor
    function addExecutor(address executorAddress) external;

    //Remove registered Executors
    function removeExecutors(address[] calldata executorArray) external;

    // Remove Register single executor
    function removeExecutor(address executorAddress) external;
}

File 11 of 18 : ILiquidityProviders.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.0;

interface ILiquidityProviders {
    function BASE_DIVISOR() external view returns (uint256);

    function initialize(address _trustedForwarder, address _lpToken) external;

    function addLPFee(address _token, uint256 _amount) external;

    function addNativeLiquidity() external;

    function addTokenLiquidity(address _token, uint256 _amount) external;

    function claimFee(uint256 _nftId) external;

    function getFeeAccumulatedOnNft(uint256 _nftId) external view returns (uint256);

    function getSuppliedLiquidityByToken(address tokenAddress) external view returns (uint256);

    function getTokenPriceInLPShares(address _baseToken) external view returns (uint256);

    function getTotalLPFeeByToken(address tokenAddress) external view returns (uint256);

    function getTotalReserveByToken(address tokenAddress) external view returns (uint256);

    function getSuppliedLiquidity(uint256 _nftId) external view returns (uint256);

    function increaseNativeLiquidity(uint256 _nftId) external;

    function increaseTokenLiquidity(uint256 _nftId, uint256 _amount) external;

    function isTrustedForwarder(address forwarder) external view returns (bool);

    function owner() external view returns (address);

    function paused() external view returns (bool);

    function removeLiquidity(uint256 _nftId, uint256 amount) external;

    function renounceOwnership() external;

    function setLiquidityPool(address _liquidityPool) external;

    function setLpToken(address _lpToken) external;

    function setWhiteListPeriodManager(address _whiteListPeriodManager) external;

    function sharesToTokenAmount(uint256 _shares, address _tokenAddress) external view returns (uint256);

    function totalLPFees(address) external view returns (uint256);

    function totalLiquidity(address) external view returns (uint256);

    function totalReserve(address) external view returns (uint256);

    function totalSharesMinted(address) external view returns (uint256);

    function transferOwnership(address newOwner) external;

    function whiteListPeriodManager() external view returns (address);

    function increaseCurrentLiquidity(address tokenAddress, uint256 amount) external;

    function decreaseCurrentLiquidity(address tokenAddress, uint256 amount) external;

    function getCurrentLiquidity(address tokenAddress) external view returns (uint256);
}

File 12 of 18 : IERC20Permit.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.0;

import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";

interface IERC20Detailed is IERC20Upgradeable {
  function name() external view returns(string memory);
  function decimals() external view returns(uint256);
}

interface IERC20Nonces is IERC20Detailed {
  function nonces(address holder) external view returns(uint);
}

interface IERC20Permit is IERC20Nonces {
  function permit(address holder, address spender, uint256 nonce, uint256 expiry,
                  bool allowed, uint8 v, bytes32 r, bytes32 s) external;

  function permit(address holder, address spender, uint256 value, uint256 expiry,
                  uint8 v, bytes32 r, bytes32 s) external;
}

File 13 of 18 : ITokenManager.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.0;

import "../structures/TokenConfig.sol";

interface ITokenManager {
    function getEquilibriumFee(address tokenAddress) external view returns (uint256);

    function getMaxFee(address tokenAddress) external view returns (uint256);

    function changeFee(
        address tokenAddress,
        uint256 _equilibriumFee,
        uint256 _maxFee
    ) external;

    function tokensInfo(address tokenAddress)
        external
        view
        returns (
            uint256 transferOverhead,
            bool supportedToken,
            uint256 equilibriumFee,
            uint256 maxFee,
            TokenConfig memory config
        );

    function excessStateTransferFeePerc(address tokenAddress) external view returns (uint256);

    function getTokensInfo(address tokenAddress) external view returns (TokenInfo memory);

    function getDepositConfig(uint256 toChainId, address tokenAddress) external view returns (TokenConfig memory);

    function getTransferConfig(address tokenAddress) external view returns (TokenConfig memory);

    function changeExcessStateFee(address _tokenAddress, uint256 _excessStateFeePer) external;
}

File 14 of 18 : ISwapAdaptor.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.0;
import "../structures/SwapRequest.sol";

interface ISwapAdaptor {
    function swap(
        address inputTokenAddress,
        uint256 amountInMaximum,
        address receiver,
        SwapRequest[] calldata swapRequests
    ) external returns (uint256 amountIn);

    function swapNative(
        uint256 amountInMaximum,
        address receiver,
        SwapRequest[] calldata swapRequests
    ) external returns (uint256 amountOut);
}

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

pragma solidity ^0.8.0;
import "../proxy/utils/Initializable.sol";

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract ContextUpgradeable is Initializable {
    function __Context_init() internal initializer {
        __Context_init_unchained();
    }

    function __Context_init_unchained() internal initializer {
    }
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
    uint256[50] private __gap;
}

File 16 of 18 : AddressUpgradeable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Collection of functions related to the address type
 */
library AddressUpgradeable {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        assembly {
            size := extcodesize(account)
        }
        return size > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        require(isContract(target), "Address: call to non-contract");

        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

File 17 of 18 : PausableUpgradeable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "../utils/ContextUpgradeable.sol";
import "../proxy/utils/Initializable.sol";

/**
 * @dev Contract module which allows children to implement an emergency stop
 * mechanism that can be triggered by an authorized account.
 *
 * This module is used through inheritance. It will make available the
 * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
 * the functions of your contract. Note that they will not be pausable by
 * simply including this module, only once the modifiers are put in place.
 */
abstract contract PausableUpgradeable is Initializable, ContextUpgradeable {
    /**
     * @dev Emitted when the pause is triggered by `account`.
     */
    event Paused(address account);

    /**
     * @dev Emitted when the pause is lifted by `account`.
     */
    event Unpaused(address account);

    bool private _paused;

    /**
     * @dev Initializes the contract in unpaused state.
     */
    function __Pausable_init() internal initializer {
        __Context_init_unchained();
        __Pausable_init_unchained();
    }

    function __Pausable_init_unchained() internal initializer {
        _paused = false;
    }

    /**
     * @dev Returns true if the contract is paused, and false otherwise.
     */
    function paused() public view virtual returns (bool) {
        return _paused;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    modifier whenNotPaused() {
        require(!paused(), "Pausable: paused");
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is paused.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    modifier whenPaused() {
        require(paused(), "Pausable: not paused");
        _;
    }

    /**
     * @dev Triggers stopped state.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    function _pause() internal virtual whenNotPaused {
        _paused = true;
        emit Paused(_msgSender());
    }

    /**
     * @dev Returns to normal state.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    function _unpause() internal virtual whenPaused {
        _paused = false;
        emit Unpaused(_msgSender());
    }
    uint256[49] private __gap;
}

File 18 of 18 : SwapRequest.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.0;

enum SwapOperation {ExactOutput, ExactInput}

struct SwapRequest {
    address tokenAddress;
    uint256 percentage;
    uint256 amount;
    SwapOperation operation;
    bytes path;
}

Settings
{
  "evmVersion": "istanbul",
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract ABI

[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"transferredAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"target","type":"address"},{"indexed":false,"internalType":"bytes","name":"depositHash","type":"bytes"},{"indexed":false,"internalType":"uint256","name":"fromChainId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lpFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"transferFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"gasFee","type":"uint256"}],"name":"AssetSent","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"baseGas","type":"uint256"}],"name":"BaseGasUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"tokenAddress","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"toChainId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"},{"indexed":false,"internalType":"string","name":"tag","type":"string"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"tokenAddress","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"toChainId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"},{"indexed":false,"internalType":"string","name":"tag","type":"string"},{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"percentage","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"enum SwapOperation","name":"operation","type":"uint8"},{"internalType":"bytes","name":"path","type":"bytes"}],"indexed":false,"internalType":"struct SwapRequest[]","name":"swapRequests","type":"tuple[]"}],"name":"DepositAndSwap","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"","type":"address"},{"indexed":false,"internalType":"uint256","name":"","type":"uint256"}],"name":"EthReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"gasUsed","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"gasPrice","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"nativeTokenPriceInTransferredToken","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokenGasBaseFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"gasFeeInTransferredToken","type":"uint256"}],"name":"GasFeeCalculated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"tokenAddress","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"GasFeeWithdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"liquidityProvidersAddress","type":"address"}],"name":"LiquidityProvidersChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousPauser","type":"address"},{"indexed":true,"internalType":"address","name":"newPauser","type":"address"}],"name":"PauserChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Received","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"string","name":"name","type":"string"},{"indexed":true,"internalType":"address","name":"liquidityProvidersAddress","type":"address"}],"name":"SwapAdaptorChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"tokenManagerAddress","type":"address"}],"name":"TokenManagerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_tf","type":"address"}],"name":"TrustedForwarderChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"baseGas","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newPauser","type":"address"}],"name":"changePauser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address payable","name":"receiver","type":"address"},{"internalType":"bytes","name":"depositHash","type":"bytes"}],"name":"checkHashStatus","outputs":[{"internalType":"bytes32","name":"hashSendTransaction","type":"bytes32"},{"internalType":"bool","name":"status","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"toChainId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"string","name":"tag","type":"string"},{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"percentage","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"enum SwapOperation","name":"operation","type":"uint8"},{"internalType":"bytes","name":"path","type":"bytes"}],"internalType":"struct SwapRequest[]","name":"swapRequest","type":"tuple[]"}],"name":"depositAndSwapErc20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"toChainId","type":"uint256"},{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"string","name":"tag","type":"string"}],"name":"depositErc20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"toChainId","type":"uint256"},{"internalType":"string","name":"tag","type":"string"}],"name":"depositNative","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"toChainId","type":"uint256"},{"internalType":"string","name":"tag","type":"string"},{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"percentage","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"enum SwapOperation","name":"operation","type":"uint8"},{"internalType":"bytes","name":"path","type":"bytes"}],"internalType":"struct SwapRequest[]","name":"swapRequest","type":"tuple[]"}],"name":"depositNativeAndSwap","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"gasFeeAccumulated","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"gasFeeAccumulatedByToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"}],"name":"getCurrentLiquidity","outputs":[{"internalType":"uint256","name":"currentLiquidity","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getExecutorManager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"tokenAddress","type":"address"}],"name":"getRewardAmount","outputs":[{"internalType":"uint256","name":"rewardAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"getTransferFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"incentivePool","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_executorManagerAddress","type":"address"},{"internalType":"address","name":"_pauser","type":"address"},{"internalType":"address","name":"_trustedForwarder","type":"address"},{"internalType":"address","name":"_tokenManager","type":"address"},{"internalType":"address","name":"_liquidityProviders","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pauser","type":"address"}],"name":"isPauser","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"forwarder","type":"address"}],"name":"isTrustedForwarder","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"liquidityProviders","outputs":[{"internalType":"contract ILiquidityProviders","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"toChainId","type":"uint256"},{"components":[{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"bool","name":"allowed","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct LiquidityPool.PermitRequest","name":"permitOptions","type":"tuple"},{"internalType":"string","name":"tag","type":"string"}],"name":"permitAndDepositErc20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"toChainId","type":"uint256"},{"components":[{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"bool","name":"allowed","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"internalType":"struct LiquidityPool.PermitRequest","name":"permitOptions","type":"tuple"},{"internalType":"string","name":"tag","type":"string"}],"name":"permitEIP2612AndDepositErc20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"processedHash","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renouncePauser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address payable","name":"receiver","type":"address"},{"internalType":"bytes","name":"depositHash","type":"bytes"},{"internalType":"uint256","name":"tokenGasPrice","type":"uint256"},{"internalType":"uint256","name":"fromChainId","type":"uint256"}],"name":"sendFundsToUser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address payable","name":"receiver","type":"address"},{"internalType":"bytes","name":"depositHash","type":"bytes"},{"internalType":"uint256","name":"nativeTokenPriceInTransferredToken","type":"uint256"},{"internalType":"uint256","name":"fromChainId","type":"uint256"},{"internalType":"uint256","name":"tokenGasBaseFee","type":"uint256"}],"name":"sendFundsToUserV2","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"gas","type":"uint128"}],"name":"setBaseGas","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_executorManagerAddress","type":"address"}],"name":"setExecutorManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_liquidityProviders","type":"address"}],"name":"setLiquidityProviders","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"address","name":"_swapAdaptor","type":"address"}],"name":"setSwapAdaptor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenManager","type":"address"}],"name":"setTokenManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"trustedForwarder","type":"address"}],"name":"setTrustedForwarder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"","type":"string"}],"name":"swapAdaptorMap","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address payable","name":"receiver","type":"address"},{"internalType":"bytes","name":"depositHash","type":"bytes"},{"internalType":"uint256","name":"nativeTokenPriceInTransferredToken","type":"uint256"},{"internalType":"uint256","name":"tokenGasBaseFee","type":"uint256"},{"internalType":"uint256","name":"fromChainId","type":"uint256"},{"internalType":"uint256","name":"swapGasOverhead","type":"uint256"},{"components":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"percentage","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"enum SwapOperation","name":"operation","type":"uint8"},{"internalType":"bytes","name":"path","type":"bytes"}],"internalType":"struct SwapRequest[]","name":"swapRequests","type":"tuple[]"},{"internalType":"string","name":"swapAdaptor","type":"string"}],"name":"swapAndSendFundsToUser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"tokenManager","outputs":[{"internalType":"contract ITokenManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"_tokenAmount","type":"uint256"}],"name":"transfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"}],"name":"withdrawErc20GasFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawNativeGasFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

608060405234801561001057600080fd5b50615d0080620000216000396000f3fe6080604052600436106102555760003560e01c80638456cb5911610139578063ca2ba943116100b6578063ea3684211161007a578063ea368421146106db578063ee58591c146106ee578063ef0d45721461070e578063f16c2c251461072e578063f2fde38b1461074e578063fc42b58f1461076e5761029c565b8063ca2ba94314610646578063ccb844e114610666578063da6f679414610686578063da7422281461069b578063e06179fe146106bb5761029c565b8063ab1635b7116100fd578063ab1635b7146105b1578063bcc1f5ad146105c6578063beabacc8146105e6578063bf33e81214610606578063c87e4e25146106265761029c565b80638456cb591461052457806385a25597146105395780638da5cb5b14610567578063a2419a6b1461057c578063a4479b48146105915761029c565b8063583bbc40116101d25780636ef8d66d116101965780636ef8d66d14610487578063715018a61461049c578063760d098a146104b157806376d2cbb4146104d15780637cb2b79c146104e457806383f75fa3146105045761029c565b8063583bbc40146103f057806359ca6c01146104125780635c975abb1461043257806367924a56146104475780636e8ae0a3146104675761029c565b8063316182a311610219578063316182a31461034e5780633f4ba83a1461036e57806346fbf68e1461038357806355d73595146103b0578063572b6c05146103d05761029c565b80631459457a146102a15780631dbb76b3146102c35780631ef6626b146102e35780632a709b14146103035780632cd271e71461032e5761029c565b3661029c577f85177f287940f2f05425a4029951af0e047a7f9c4eaa9a6e6917bcd869f8669561028361078e565b346040516102929291906150d0565b60405180910390a1005b600080fd5b3480156102ad57600080fd5b506102c16102bc366004614660565b61079e565b005b3480156102cf57600080fd5b506102c16102de3660046149ec565b6108f8565b3480156102ef57600080fd5b506102c16102fe3660046148e6565b610ddf565b34801561030f57600080fd5b506103186111a9565b6040516103259190614fa9565b60405180910390f35b34801561033a57600080fd5b506102c161034936600461460c565b6111b8565b34801561035a57600080fd5b506102c1610369366004614965565b61120e565b34801561037a57600080fd5b506102c161142e565b34801561038f57600080fd5b506103a361039e36600461460c565b61145d565b6040516103259190615147565b3480156103bc57600080fd5b506102c16103cb366004614d90565b611474565b3480156103dc57600080fd5b506103a36103eb36600461460c565b6115fe565b3480156103fc57600080fd5b50610405611612565b6040516103259190615a98565b34801561041e57600080fd5b506102c161042d36600461460c565b611618565b34801561043e57600080fd5b506103a36116c7565b34801561045357600080fd5b506102c16104623660046147b4565b6116d0565b34801561047357600080fd5b50610405610482366004614d6c565b611785565b34801561049357600080fd5b506102c16118b4565b3480156104a857600080fd5b506102c1611948565b3480156104bd57600080fd5b506103a36104cc366004614bf8565b611991565b6102c16104df366004614b38565b6119a7565b3480156104f057600080fd5b506102c16104ff36600461460c565b611b08565b34801561051057600080fd5b506102c161051f366004614c10565b611bb7565b34801561053057600080fd5b506102c1611c7b565b34801561054557600080fd5b50610559610554366004614876565b611ca8565b604051610325929190615152565b34801561057357600080fd5b50610318611d0e565b34801561058857600080fd5b50610318611d1d565b34801561059d57600080fd5b506104056105ac36600461460c565b611d2c565b3480156105bd57600080fd5b50610318611d3f565b3480156105d257600080fd5b506102c16105e1366004614710565b611d4e565b3480156105f257600080fd5b506102c16106013660046146d0565b611f46565b34801561061257600080fd5b506102c16106213660046147b4565b612168565b34801561063257600080fd5b506102c161064136600461460c565b6121c2565b34801561065257600080fd5b5061040561066136600461460c565b612414565b34801561067257600080fd5b506102c1610681366004614d2d565b612566565b34801561069257600080fd5b506102c16125e0565b3480156106a757600080fd5b506102c16106b636600461460c565b6128f0565b3480156106c757600080fd5b506104056106d636600461460c565b612938565b6102c16106e9366004614adf565b61294b565b3480156106fa57600080fd5b50610318610709366004614c64565b612a23565b34801561071a57600080fd5b506102c161072936600461460c565b612a4a565b34801561073a57600080fd5b50610405610749366004614628565b612ad1565b34801561075a57600080fd5b506102c161076936600461460c565b612aef565b34801561077a57600080fd5b5061040561078936600461484b565b612b5d565b6000610798612bed565b90505b90565b600054610100900460ff16806107b7575060005460ff16155b6107dc5760405162461bcd60e51b81526004016107d39061553b565b60405180910390fd5b600054610100900460ff16158015610807576000805460ff1961ff0019909116610100171660011790555b6001600160a01b03861661082d5760405162461bcd60e51b81526004016107d39061586c565b6001600160a01b0384166108535760405162461bcd60e51b81526004016107d390615721565b6001600160a01b0382166108795760405162461bcd60e51b81526004016107d390615a63565b61088284612c1b565b61088a612ca2565b610892612d1e565b61089b85612d8e565b60fd80546001600160a01b038089166001600160a01b03199283161790925560fe805486841690831617905560ff80549285169290911691909117905561520860fc5580156108f0576000805461ff00191690555b505050505050565b6002600154141561091b5760405162461bcd60e51b81526004016107d390615924565b600260015560fd546001600160a01b0316630768d65c61093961078e565b6040518263ffffffff1660e01b81526004016109559190614fa9565b60206040518083038186803b15801561096d57600080fd5b505afa158015610981573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109a59190614bdc565b6109c15760405162461bcd60e51b81526004016107d390615195565b6109c96116c7565b156109e65760405162461bcd60e51b81526004016107d3906154cf565b81610a035760405162461bcd60e51b81526004016107d3906157da565b60006001600160a01b031661010482604051610a1f9190614f8d565b908152604051908190036020019020546001600160a01b03161415610a565760405162461bcd60e51b81526004016107d3906153a3565b6000610a678d8d8d8d8d8d8d612e4c565b90506001600160a01b038d16600080516020615cab8339815191521415610bdd57600061010483604051610a9b9190614f8d565b908152604051908190036020019020546001600160a01b03168260006020020151604051610ac89061079b565b60006040518083038185875af1925050503d8060008114610b05576040519150601f19603f3d011682016040523d82523d6000602084013e610b0a565b606091505b5050905080610b2b5760405162461bcd60e51b81526004016107d390615362565b61010483604051610b3c9190614f8d565b908152604051908190036020019020546001600160a01b03166355a4aafb83600060200201518e88886040518563ffffffff1660e01b8152600401610b849493929190615ab8565b602060405180830381600087803b158015610b9e57600080fd5b505af1158015610bb2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bd69190614d54565b5050610d61565b60005a9050610c178e61010485604051610bf79190614f8d565b908152604051908190036020019020546001600160a01b0316600061300e565b610c528e61010485604051610c2c9190614f8d565b908152604051908190036020019020546001600160a01b0316846000602002015161300e565b5a610c5d9082615c18565b610c679087615bc1565b9550506000610c818e8a886000610c7c61078e565b61310d565b825190915081908390610c95908390615c18565b9052508082600360200201818151610cad9190615bc1565b9052505060405161010490610cc3908490614f8d565b908152604051908190036020019020546001600160a01b0316632180777e8e83600060200201518e88886040518663ffffffff1660e01b8152600401610d0d9594939291906150e9565b602060405180830381600087803b158015610d2757600080fd5b505af1158015610d3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d5f9190614d54565b505b80600060200201518c6001600160a01b038f167f6bfd5ee5792d66b151a3fab9f56ee828a0f1c3216d4b752e267cd5590326b15c8e8e8e8c886001602002015189600260200201518a60036020020151604051610dc49796959493929190614fbd565b60405180910390a45050600180555050505050505050505050565b60026001541415610e025760405162461bcd60e51b81526004016107d390615924565b600260015560fd546001600160a01b0316630768d65c610e2061078e565b6040518263ffffffff1660e01b8152600401610e3c9190614fa9565b60206040518083038186803b158015610e5457600080fd5b505afa158015610e68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e8c9190614bdc565b610ea85760405162461bcd60e51b81526004016107d390615195565b610eb06116c7565b15610ecd5760405162461bcd60e51b81526004016107d3906154cf565b60005a60fe546040516302502c3560e31b81529192506000916001600160a01b039091169063128161a890610f06908c90600401614fa9565b604080518083038186803b158015610f1d57600080fd5b505afa158015610f31573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f559190614c96565b905087816000015111158015610f6f575087816020015110155b610f8b5760405162461bcd60e51b81526004016107d390615268565b6001600160a01b038716610fb15760405162461bcd60e51b81526004016107d390615589565b600080610fc18b8b8b8b8b611ca8565b915091508015610fe35760405162461bcd60e51b81526004016107d39061595b565b600082815261010060205260408120805460ff19166001179055611009858d8d8a6131fb565b60ff549091506001600160a01b031663dd8b99238d83600060200201516040518363ffffffff1660e01b81526004016110439291906150d0565b600060405180830381600087803b15801561105d57600080fd5b505af1158015611071573d6000803e3d6000fd5b505050506001600160a01b038c16600080516020615cab83398151915214156111195780516040516000916001600160a01b038d16916110b09061079b565b60006040518083038185875af1925050503d80600081146110ed576040519150601f19603f3d011682016040523d82523d6000602084013e6110f2565b606091505b50509050806111135760405162461bcd60e51b81526004016107d390615805565b5061112c565b61112c8c8b8360005b60200201516134ba565b80600060200201518b6001600160a01b038e167f6bfd5ee5792d66b151a3fab9f56ee828a0f1c3216d4b752e267cd5590326b15c8d8d8d8c886001602002015189600260200201518a6003602002015160405161118f9796959493929190614fbd565b60405180910390a450506001805550505050505050505050565b60fe546001600160a01b031681565b6111c13361145d565b6111dd5760405162461bcd60e51b81526004016107d390615a13565b6111e56116c7565b156112025760405162461bcd60e51b81526004016107d3906154cf565b61120b816134d9565b50565b600260015414156112315760405162461bcd60e51b81526004016107d390615924565b600260015560fd546001600160a01b0316630768d65c61124f61078e565b6040518263ffffffff1660e01b815260040161126b9190614fa9565b60206040518083038186803b15801561128357600080fd5b505afa158015611297573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112bb9190614bdc565b6112d75760405162461bcd60e51b81526004016107d390615195565b6112df6116c7565b156112fc5760405162461bcd60e51b81526004016107d3906154cf565b600061130d89898989898988612e4c565b90506001600160a01b038916600080516020615cab83398151915214156113b35780516040516000916001600160a01b038a169161134a9061079b565b60006040518083038185875af1925050503d8060008114611387576040519150601f19603f3d011682016040523d82523d6000602084013e61138c565b606091505b50509050806113ad5760405162461bcd60e51b81526004016107d390615805565b506113c0565b6113c08988836000611122565b80516020820151604080840151606085015191518c936001600160a01b038f16937f6bfd5ee5792d66b151a3fab9f56ee828a0f1c3216d4b752e267cd5590326b15c93611417938f938f938f938e93909190614fbd565b60405180910390a450506001805550505050505050565b6114373361145d565b6114535760405162461bcd60e51b81526004016107d390615a13565b61145b613548565b565b6097546001600160a01b038281169116145b919050565b60fe54604051635d46df5160e11b815286916000916001600160a01b039091169063ba8dbea2906114a9908590600401614fa9565b60c06040518083038186803b1580156114c157600080fd5b505afa1580156114d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114f99190614df7565b5050509150508061151c5760405162461bcd60e51b81526004016107d3906156f4565b6115246116c7565b156115415760405162461bcd60e51b81526004016107d3906154cf565b600260015414156115645760405162461bcd60e51b81526004016107d390615924565b6002600155600061157361078e565b90506000611584828b8b8b8b6135b6565b9050876001600160a01b0316896001600160a01b0316836001600160a01b03167f522e11fa05593b306c8df10d2b0b8e01eec48f9d0a9427a7a93f21ff90d66fb18d858c6115d29190615bc1565b868c8c6040516115e6959493929190615afb565b60405180910390a45050600180555050505050505050565b60ca546001600160a01b0390811691161490565b60fc5481565b61162061078e565b6001600160a01b0316611631611d0e565b6001600160a01b0316146116575760405162461bcd60e51b81526004016107d39061565c565b6001600160a01b03811661167d5760405162461bcd60e51b81526004016107d390615231565b60ff80546001600160a01b0319166001600160a01b0383169081179091556040517f0988d9952b4295aedfb755253e8d1dcebd105e8a5cf7507e419b544da764706690600090a250565b60655460ff1690565b866001600160a01b0316638fcbaf0c6116e761078e565b30863560208801356116ff60608a0160408b01614bc0565b61170f60808b0160608c01614e4a565b8a608001358b60a001356040518963ffffffff1660e01b815260040161173c989796959493929190615046565b600060405180830381600087803b15801561175657600080fd5b505af115801561176a573d6000803e3d6000fd5b5050505061177c848888888686611474565b50505050505050565b60008061179183612414565b60ff54604051630b3524e360e41b81529192506000916001600160a01b039091169063b3524e30906117c7908790600401614fa9565b60206040518083038186803b1580156117df57600080fd5b505afa1580156117f3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118179190614d54565b9050808210156118ac57600061182d8383615c18565b9050808610611857576001600160a01b0385166000908152610103602052604090205493506118aa565b6001600160a01b03851660009081526101036020526040902054819061187d9088615bf9565b61188c906402540be400615bf9565b6118969190615bd9565b93506118a76402540be40085615bd9565b93505b505b505092915050565b6118bd3361145d565b6118d95760405162461bcd60e51b81526004016107d390615a13565b6118e16116c7565b156118fe5760405162461bcd60e51b81526004016107d3906154cf565b6097546040516000916001600160a01b0316907f95bb211a5a393c4d30c3edc9a745825fba4e6ad3e3bb949e6bf8ccdfe431a811908390a3609780546001600160a01b0319169055565b61195061078e565b6001600160a01b0316611961611d0e565b6001600160a01b0316146119875760405162461bcd60e51b81526004016107d39061565c565b61145b60006137d9565b6101006020526000908152604090205460ff1681565b6119af6116c7565b156119cc5760405162461bcd60e51b81526004016107d3906154cf565b600260015414156119ef5760405162461bcd60e51b81526004016107d390615924565b6002600155600081815b81811015611a4457848482818110611a2157634e487b7160e01b600052603260045260246000fd5b9050602002810190611a339190615b68565b6020013592909201916001016119f9565b50611a5790506402540be4006064615bf9565b811115611a765760405162461bcd60e51b81526004016107d390615758565b6000611a82888861382b565b90506001600160a01b038816600080516020615cab833981519152611aa561078e565b6001600160a01b03167fe0c1647854700a22165488c301138e1e29036e60ec14c1e78653b1e0c918f8748a611ada8634615bc1565b868c8c8c8c604051611af29796959493929190615b21565b60405180910390a4505060018055505050505050565b611b1061078e565b6001600160a01b0316611b21611d0e565b6001600160a01b031614611b475760405162461bcd60e51b81526004016107d39061565c565b6001600160a01b038116611b6d5760405162461bcd60e51b81526004016107d390615986565b60fe80546001600160a01b0319166001600160a01b0383169081179091556040517f331ea0c3b6547bb3d7c5798698a5f25c7b9f5484af90723a847eba9e885a3d7f90600090a250565b611bbf61078e565b6001600160a01b0316611bd0611d0e565b6001600160a01b031614611bf65760405162461bcd60e51b81526004016107d39061565c565b806101048484604051611c0a929190614f7d565b90815260405190819003602001812080546001600160a01b039384166001600160a01b031990911617905590821690611c469085908590614f7d565b604051908190038120907f32987e7b04c960bad9e4a93936f2b82bd108cf13934d9eef41bc48453664e7ea90600090a3505050565b611c843361145d565b611ca05760405162461bcd60e51b81526004016107d390615a13565b61145b613af7565b6000808686868686604051611cbe929190614f7d565b604051908190038120611cd69493929160200161511d565b60408051601f1981840301815291815281516020928301206000818152610100909352912054909860ff909116975095505050505050565b6098546001600160a01b031690565b60ff546001600160a01b031681565b6101036020526000908152604090205481565b60fd546001600160a01b031690565b60fe54604051635d46df5160e11b815289916000916001600160a01b039091169063ba8dbea290611d83908590600401614fa9565b60c06040518083038186803b158015611d9b57600080fd5b505afa158015611daf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dd39190614df7565b50505091505080611df65760405162461bcd60e51b81526004016107d3906156f4565b611dfe6116c7565b15611e1b5760405162461bcd60e51b81526004016107d3906154cf565b60026001541415611e3e5760405162461bcd60e51b81526004016107d390615924565b6002600155600083815b81811015611e9357868682818110611e7057634e487b7160e01b600052603260045260246000fd5b9050602002810190611e829190615b68565b602001359290920191600101611e48565b50611ea690506402540be4006064615bf9565b811115611ec55760405162461bcd60e51b81526004016107d390615758565b6000611ecf61078e565b90506000611ee0828c8f8f8e6135b6565b90508b6001600160a01b03168d6001600160a01b0316836001600160a01b03167fe0c1647854700a22165488c301138e1e29036e60ec14c1e78653b1e0c918f8748e858f611f2e9190615bc1565b868f8f8f8f604051610dc49796959493929190615b21565b611f4e6116c7565b15611f6b5760405162461bcd60e51b81526004016107d3906154cf565b60ff546001600160a01b0316611f7f61078e565b6001600160a01b031614611fa55760405162461bcd60e51b81526004016107d3906154f9565b60026001541415611fc85760405162461bcd60e51b81526004016107d390615924565b60026001556001600160a01b038216611ff35760405162461bcd60e51b81526004016107d3906154a5565b6001600160a01b038316600080516020615cab83398151915214156120b457804710156120325760405162461bcd60e51b81526004016107d3906158a3565b6000826001600160a01b03168260405161204b9061079b565b60006040518083038185875af1925050503d8060008114612088576040519150601f19603f3d011682016040523d82523d6000602084013e61208d565b606091505b50509050806120ae5760405162461bcd60e51b81526004016107d39061529d565b5061215f565b6040516370a0823160e01b8152839082906001600160a01b038316906370a08231906120e4903090600401614fa9565b60206040518083038186803b1580156120fc57600080fd5b505afa158015612110573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121349190614d54565b10156121525760405162461bcd60e51b81526004016107d3906158a3565b61215d8184846134ba565b505b50506001805550565b866001600160a01b031663d505accf61217f61078e565b3088602088013561219660808a0160608b01614e4a565b89608001358a60a001356040518863ffffffff1660e01b815260040161173c979695949392919061508f565b60fd546001600160a01b0316630768d65c6121db61078e565b6040518263ffffffff1660e01b81526004016121f79190614fa9565b60206040518083038186803b15801561220f57600080fd5b505afa158015612223573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122479190614bdc565b6122635760405162461bcd60e51b81526004016107d390615195565b61226b6116c7565b156122885760405162461bcd60e51b81526004016107d3906154cf565b600260015414156122ab5760405162461bcd60e51b81526004016107d390615924565b60026001556001600160a01b038116600080516020615cab83398151915214156122e75760405162461bcd60e51b81526004016107d3906155b7565b6001600160a01b0381166000908152610102602052604081208161230961078e565b6001600160a01b031681526020810191909152604001600020549050806123425760405162461bcd60e51b81526004016107d3906153d3565b6001600160a01b03821660009081526101016020526040902054612367908290615c18565b6001600160a01b0383166000908152610101602090815260408083209390935561010290529081208161239861078e565b6001600160a01b031681526020810191909152604001600020556123c4826123be61078e565b836134ba565b806123cd61078e565b6001600160a01b0316836001600160a01b03167fc129cf8730ce23dfea8953a499f9b276ad5777855ff41fafe198ebc2a0d2324360405160405180910390a4505060018055565b60ff5460405163ca2ba94360e01b815260009182916001600160a01b039091169063ca2ba94390612449908690600401614fa9565b60206040518083038186803b15801561246157600080fd5b505afa158015612475573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124999190614d54565b6001600160a01b0380851660009081526101036020908152604080832054610101909252918290205460ff5492516368da78c960e11b815294955090939092919091169063d1b4f192906124f1908890600401614fa9565b60206040518083038186803b15801561250957600080fd5b505afa15801561251d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125419190614d54565b61254b9084615c18565b6125559190615c18565b61255f9190615c18565b9392505050565b61256e61078e565b6001600160a01b031661257f611d0e565b6001600160a01b0316146125a55760405162461bcd60e51b81526004016107d39061565c565b6001600160801b03811660fc8190556040517f1f7e24d1f8ac9b596a34502db87778da821b5ac198a6738cfb24ab379b969bfe90600090a250565b60fd546001600160a01b0316630768d65c6125f961078e565b6040518263ffffffff1660e01b81526004016126159190614fa9565b60206040518083038186803b15801561262d57600080fd5b505afa158015612641573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126659190614bdc565b6126815760405162461bcd60e51b81526004016107d390615195565b6126896116c7565b156126a65760405162461bcd60e51b81526004016107d3906154cf565b600260015414156126c95760405162461bcd60e51b81526004016107d390615924565b6002600155600080516020615cab83398151915260009081526101026020527f8c843e863d6980427013005c2fd6c559f82753ab35a5ed8f9caaa5df7d58739d8161271261078e565b6001600160a01b0316815260208101919091526040016000205490508061274b5760405162461bcd60e51b81526004016107d3906153d3565b600080516020615cab8339815191526000526101016020527ffc69fe689a10849a4c810115708945edcdce02b4ce0b8911d1cf85d0b30251d554612790908290615c18565b600080516020615cab83398151915260009081527ffc69fe689a10849a4c810115708945edcdce02b4ce0b8911d1cf85d0b30251d5919091556101026020527f8c843e863d6980427013005c2fd6c559f82753ab35a5ed8f9caaa5df7d58739d816127f961078e565b6001600160a01b03166001600160a01b0316815260200190815260200160002081905550600061282761078e565b6001600160a01b03168260405161283d9061079b565b60006040518083038185875af1925050503d806000811461287a576040519150601f19603f3d011682016040523d82523d6000602084013e61287f565b606091505b50509050806128a05760405162461bcd60e51b81526004016107d390615805565b816128a961078e565b6001600160a01b0316306001600160a01b03167fc129cf8730ce23dfea8953a499f9b276ad5777855ff41fafe198ebc2a0d2324360405160405180910390a4505060018055565b6128f861078e565b6001600160a01b0316612909611d0e565b6001600160a01b03161461292f5760405162461bcd60e51b81526004016107d39061565c565b61120b81613b52565b6101016020526000908152604090205481565b6129536116c7565b156129705760405162461bcd60e51b81526004016107d3906154cf565b600260015414156129935760405162461bcd60e51b81526004016107d390615924565b600260015560006129a4858561382b565b90506001600160a01b038516600080516020615cab8339815191526129c761078e565b6001600160a01b03167f522e11fa05593b306c8df10d2b0b8e01eec48f9d0a9427a7a93f21ff90d66fb1876129fc8634615bc1565b868989604051612a10959493929190615afb565b60405180910390a4505060018055505050565b8051602081830181018051610104825292820191909301209152546001600160a01b031681565b612a5261078e565b6001600160a01b0316612a63611d0e565b6001600160a01b031614612a895760405162461bcd60e51b81526004016107d39061565c565b6001600160a01b038116612aaf5760405162461bcd60e51b81526004016107d3906151cc565b60fd80546001600160a01b0319166001600160a01b0392909216919091179055565b61010260209081526000928352604080842090915290825290205481565b612af761078e565b6001600160a01b0316612b08611d0e565b6001600160a01b031614612b2e5760405162461bcd60e51b81526004016107d39061565c565b6001600160a01b038116612b545760405162461bcd60e51b81526004016107d39061531c565b61120b816137d9565b60fe54604051633e978aaf60e21b815260009161255f91859185916001600160a01b039091169063fa5e2abc90612b98908590600401614fa9565b60c06040518083038186803b158015612bb057600080fd5b505afa158015612bc4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612be89190614cb1565b613bc2565b6000612bf8336115fe565b15612c0c575060131936013560601c61079b565b612c14613da0565b905061079b565b600054610100900460ff1680612c34575060005460ff16155b612c505760405162461bcd60e51b81526004016107d39061553b565b600054610100900460ff16158015612c7b576000805460ff1961ff0019909116610100171660011790555b612c83613da4565b612c8c82613e17565b8015612c9e576000805461ff00191690555b5050565b600054610100900460ff1680612cbb575060005460ff16155b612cd75760405162461bcd60e51b81526004016107d39061553b565b600054610100900460ff16158015612d02576000805460ff1961ff0019909116610100171660011790555b612d0a613ea7565b801561120b576000805461ff001916905550565b600054610100900460ff1680612d37575060005460ff16155b612d535760405162461bcd60e51b81526004016107d39061553b565b600054610100900460ff16158015612d7e576000805460ff1961ff0019909116610100171660011790555b612d86613da4565b612d0a613f1f565b600054610100900460ff1680612da7575060005460ff16155b612dc35760405162461bcd60e51b81526004016107d39061553b565b600054610100900460ff16158015612dee576000805460ff1961ff0019909116610100171660011790555b6001600160a01b038216612e145760405162461bcd60e51b81526004016107d390615691565b612e1c613f8f565b609780546001600160a01b0319166001600160a01b0384161790558015612c9e576000805461ff00191690555050565b612e5461448f565b60005a60fe546040516302502c3560e31b81529192506000916001600160a01b039091169063128161a890612e8d908d90600401614fa9565b604080518083038186803b158015612ea457600080fd5b505afa158015612eb8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612edc9190614c96565b905088816000015111158015612ef6575088816020015110155b612f125760405162461bcd60e51b81526004016107d390615268565b6001600160a01b038816612f385760405162461bcd60e51b81526004016107d390615589565b600080612f488c8c8c8c8c611ca8565b915091508015612f6a5760405162461bcd60e51b81526004016107d39061595b565b600082815261010060205260408120805460ff19166001179055612f91858e8e8b8b613fff565b60ff549091506001600160a01b031663dd8b99238e83600060200201516040518363ffffffff1660e01b8152600401612fcb9291906150d0565b600060405180830381600087803b158015612fe557600080fd5b505af1158015612ff9573d6000803e3d6000fd5b50929f9e505050505050505050505050505050565b8015806130965750604051636eb1769f60e11b81526001600160a01b0384169063dd62ed3e906130449030908690600401615008565b60206040518083038186803b15801561305c57600080fd5b505afa158015613070573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130949190614d54565b155b6130b25760405162461bcd60e51b81526004016107d3906159bd565b6131088363095ea7b360e01b84846040516024016130d19291906150d0565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152614250565b505050565b600080836b204fce5e3e250261100000003a6131298989615bf9565b6131339190615bf9565b61313d9190615bd9565b6131479190615bc1565b9050853a867f9b36696d0f99bcef3d9db526d18d2e13abee9741727d7d21128c6079d985c2e1878560405161317d929190615aed565b60405180910390a46001600160a01b03871660009081526101016020526040812080548392906131ae908490615bc1565b90915550506001600160a01b03808816600090815261010260209081526040808320938716835292905290812080548392906131eb908490615bc1565b9091555090979650505050505050565b61320361448f565b60fe54604051633e978aaf60e21b81526000916001600160a01b03169063fa5e2abc90613234908890600401614fa9565b60c06040518083038186803b15801561324c57600080fd5b505afa158015613260573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132849190614cb1565b90506000613293868684613bc2565b905060008260400151821115613318576402540be4008360400151876132b99190615bf9565b6132c39190615bd9565b90506402540be400836040015183038702816132ef57634e487b7160e01b600052601260045260246000fd5b6001600160a01b0389166000908152610103602052604090208054929091049091019055613335565b6402540be4006133288388615bf9565b6133329190615bd9565b90505b60006402540be4006133478489615bf9565b6133519190615bd9565b60ff54604051634993584560e11b81529192506001600160a01b031690639326b08a90613384908b9086906004016150d0565b600060405180830381600087803b15801561339e57600080fd5b505af11580156133b2573d6000803e3d6000fd5b5050505060005a60fc5486516133c8908d615bc1565b6133d29190615bc1565b6133dc9190615c18565b905060006133ea8883615bf9565b6001600160a01b038b1660009081526101016020526040812080549293508392909190613418908490615bc1565b90915550506001600160a01b038a16600090815261010260205260408120829161344061078e565b6001600160a01b03166001600160a01b03168152602001908152602001600020600082825461346f9190615bc1565b90915550600090506134818285615bc1565b61348b908b615c18565b604080516080810182529182526020820196909652948501939093526060840152509098975050505050505050565b6131088363a9059cbb60e01b84846040516024016130d19291906150d0565b6001600160a01b0381166134ec57600080fd5b6097546040516001600160a01b038084169216907f95bb211a5a393c4d30c3edc9a745825fba4e6ad3e3bb949e6bf8ccdfe431a81190600090a3609780546001600160a01b0319166001600160a01b0392909216919091179055565b6135506116c7565b61356c5760405162461bcd60e51b81526004016107d390615203565b6065805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa61359f61078e565b6040516135ac9190614fa9565b60405180910390a1565b6000468514156135d85760405162461bcd60e51b81526004016107d39061578d565b6001600160a01b038416600080516020615cab833981519152141561360f5760405162461bcd60e51b81526004016107d39061547d565b60fe5460405163c0e4d62760e01b81526000916001600160a01b03169063c0e4d627906136429089908990600401615aa1565b604080518083038186803b15801561365957600080fd5b505afa15801561366d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136919190614c96565b9050828160000151111580156136ab575082816020015110155b6136c75760405162461bcd60e51b81526004016107d390615625565b6001600160a01b0384166136ed5760405162461bcd60e51b81526004016107d3906155ee565b8261370a5760405162461bcd60e51b81526004016107d3906156c8565b60006137168487611785565b9050801561375e576001600160a01b03861660009081526101036020526040902054613743908290615c18565b6001600160a01b038716600090815261010360205260409020555b60ff546040516353403fb560e01b81526001600160a01b03909116906353403fb59061379090899088906004016150d0565b600060405180830381600087803b1580156137aa57600080fd5b505af11580156137be573d6000803e3d6000fd5b505050506137ce868930876142df565b979650505050505050565b609880546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60004682141561384d5760405162461bcd60e51b81526004016107d39061578d565b60fe5460405163c0e4d62760e01b815234916001600160a01b03169063c0e4d6279061388d908690600080516020615cab83398151915290600401615aa1565b604080518083038186803b1580156138a457600080fd5b505afa1580156138b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138dc9190614c96565b511180159061397c575060fe5460405163c0e4d62760e01b815234916001600160a01b03169063c0e4d62790613926908690600080516020615cab83398151915290600401615aa1565b604080518083038186803b15801561393d57600080fd5b505afa158015613951573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139759190614c96565b6020015110155b6139985760405162461bcd60e51b81526004016107d390615625565b6001600160a01b0383166139be5760405162461bcd60e51b81526004016107d3906155ee565b346139db5760405162461bcd60e51b81526004016107d3906156c8565b60006139f534600080516020615cab833981519152611785565b90508015613a7d57600080516020615cab8339815191526000526101036020527f56826d040b5c8f3e11711a6f0a85f75994bf6271dc9e6c62c9d3cf2fa418e86054613a42908290615c18565b600080516020615cab8339815191526000526101036020527f56826d040b5c8f3e11711a6f0a85f75994bf6271dc9e6c62c9d3cf2fa418e860555b60ff546040516353403fb560e01b81526001600160a01b03909116906353403fb590613abd90600080516020615cab8339815191529034906004016150d0565b600060405180830381600087803b158015613ad757600080fd5b505af1158015613aeb573d6000803e3d6000fd5b50929695505050505050565b613aff6116c7565b15613b1c5760405162461bcd60e51b81526004016107d3906154cf565b6065805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861359f61078e565b6001600160a01b038116613b785760405162461bcd60e51b81526004016107d390615400565b60ca80546001600160a01b0319166001600160a01b0383169081179091556040517f871264f4293af7d2865ae7eae628b228f4991c57cb45b39c99f0b774ebe2901890600090a250565b600080613bce85612414565b60ff54604051630b3524e360e41b81529192506000916001600160a01b039091169063b3524e3090613c04908990600401614fa9565b60206040518083038186803b158015613c1c57600080fd5b505afa158015613c30573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c549190614d54565b90506000613c628684615c18565b905081811115613cf65760fe54604051630af7c68d60e31b81526001600160a01b03909116906357be346890613c9c908a90600401614fa9565b60206040518083038186803b158015613cb457600080fd5b505afa158015613cc8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cec9190614d54565b935050505061255f565b6000856060015186604001518485613d0e9190615bf9565b613d189190615bf9565b613d229190615bf9565b90506000828388604001518960600151613d3c9190615c18565b613d469190615bf9565b613d509190615bf9565b84858960400151613d619190615bf9565b613d6b9190615bf9565b613d759190615bc1565b9050600081613d8657506000613d93565b613d908284615bd9565b90505b9998505050505050505050565b3390565b600054610100900460ff1680613dbd575060005460ff16155b613dd95760405162461bcd60e51b81526004016107d39061553b565b600054610100900460ff16158015612d0a576000805460ff1961ff001990911661010017166001179055801561120b576000805461ff001916905550565b600054610100900460ff1680613e30575060005460ff16155b613e4c5760405162461bcd60e51b81526004016107d39061553b565b600054610100900460ff16158015613e77576000805460ff1961ff0019909116610100171660011790555b60ca80546001600160a01b0319166001600160a01b0384161790558015612c9e576000805461ff00191690555050565b600054610100900460ff1680613ec0575060005460ff16155b613edc5760405162461bcd60e51b81526004016107d39061553b565b600054610100900460ff16158015613f07576000805460ff1961ff0019909116610100171660011790555b60018055801561120b576000805461ff001916905550565b600054610100900460ff1680613f38575060005460ff16155b613f545760405162461bcd60e51b81526004016107d39061553b565b600054610100900460ff16158015613f7f576000805460ff1961ff0019909116610100171660011790555b612d0a613f8a61078e565b6137d9565b600054610100900460ff1680613fa8575060005460ff16155b613fc45760405162461bcd60e51b81526004016107d39061553b565b600054610100900460ff16158015613fef576000805460ff1961ff0019909116610100171660011790555b613ff7613da4565b612d0a614306565b61400761448f565b60fe54604051633e978aaf60e21b81526000916001600160a01b03169063fa5e2abc90614038908990600401614fa9565b60c06040518083038186803b15801561405057600080fd5b505afa158015614064573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140889190614cb1565b90506000614097878784613bc2565b90506000826040015182111561411c576402540be4008360400151886140bd9190615bf9565b6140c79190615bd9565b90506402540be400836040015183038802816140f357634e487b7160e01b600052601260045260246000fd5b6001600160a01b038a166000908152610103602052604090208054929091049091019055614139565b6402540be40061412c8389615bf9565b6141369190615bd9565b90505b60006402540be40061414b848a615bf9565b6141559190615bd9565b60ff54604051634993584560e11b81529192506001600160a01b031690639326b08a90614188908c9086906004016150d0565b600060405180830381600087803b1580156141a257600080fd5b505af11580156141b6573d6000803e3d6000fd5b5050505060005a60fc5486516141cc908e615bc1565b6141d69190615bc1565b6141e09190615c18565b905060006141f38b8a848b610c7c61078e565b9050896142008285615bc1565b111561421e5760405162461bcd60e51b81526004016107d3906152d4565b604080516080810182528483018c03815260208101959095528401929092525060608201529250505095945050505050565b60006142a5826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166143849092919063ffffffff16565b80519091501561310857808060200190518101906142c39190614bdc565b6131085760405162461bcd60e51b81526004016107d3906158da565b614300846323b872dd60e01b8585856040516024016130d193929190615022565b50505050565b600054610100900460ff168061431f575060005460ff16155b61433b5760405162461bcd60e51b81526004016107d39061553b565b600054610100900460ff16158015614366576000805460ff1961ff0019909116610100171660011790555b6065805460ff19169055801561120b576000805461ff001916905550565b6060614393848460008561439b565b949350505050565b6060824710156143bd5760405162461bcd60e51b81526004016107d390615437565b6143c685614450565b6143e25760405162461bcd60e51b81526004016107d390615835565b600080866001600160a01b031685876040516143fe9190614f8d565b60006040518083038185875af1925050503d806000811461443b576040519150601f19603f3d011682016040523d82523d6000602084013e614440565b606091505b50915091506137ce828286614456565b3b151590565b6060831561446557508161255f565b8251156144755782518084602001fd5b8160405162461bcd60e51b81526004016107d39190615162565b60405180608001604052806004906020820280368337509192915050565b803561146f81615c87565b60008083601f8401126144c9578081fd5b5081356001600160401b038111156144df578182fd5b60208301915083602080830285010111156144f957600080fd5b9250929050565b60008083601f840112614511578182fd5b5081356001600160401b03811115614527578182fd5b6020830191508360208285010111156144f957600080fd5b600082601f83011261454f578081fd5b81356001600160401b038082111561456957614569615c71565b604051601f8301601f19168101602001828111828210171561458d5761458d615c71565b6040528281528483016020018610156145a4578384fd5b82602086016020830137918201602001929092529392505050565b6000604082840312156145d0578081fd5b604051604081018181106001600160401b03821117156145f2576145f2615c71565b604052825181526020928301519281019290925250919050565b60006020828403121561461d578081fd5b813561255f81615c87565b6000806040838503121561463a578081fd5b823561464581615c87565b9150602083013561465581615c87565b809150509250929050565b600080600080600060a08688031215614677578081fd5b853561468281615c87565b9450602086013561469281615c87565b935060408601356146a281615c87565b925060608601356146b281615c87565b915060808601356146c281615c87565b809150509295509295909350565b6000806000606084860312156146e4578283fd5b83356146ef81615c87565b925060208401356146ff81615c87565b929592945050506040919091013590565b60008060008060008060008060c0898b03121561472b578283fd5b883561473681615c87565b9750602089013561474681615c87565b9650604089013595506060890135945060808901356001600160401b038082111561476f578485fd5b61477b8c838d01614500565b909650945060a08b0135915080821115614793578384fd5b506147a08b828c016144b8565b999c989b5096995094979396929594505050565b60008060008060008060008789036101608112156147d0578182fd5b88356147db81615c87565b975060208901356147eb81615c87565b9650604089013595506060890135945060c0607f198201121561480c578182fd5b506080880192506101408801356001600160401b0381111561482c578182fd5b6148388a828b01614500565b989b979a50959850939692959293505050565b6000806040838503121561485d578182fd5b823561486881615c87565b946020939093013593505050565b60008060008060006080868803121561488d578283fd5b853561489881615c87565b94506020860135935060408601356148af81615c87565b925060608601356001600160401b038111156148c9578182fd5b6148d588828901614500565b969995985093965092949392505050565b600080600080600080600060c0888a031215614900578081fd5b873561490b81615c87565b965060208801359550604088013561492281615c87565b945060608801356001600160401b0381111561493c578182fd5b6149488a828b01614500565b989b979a50959895979660808701359660a0013595509350505050565b60008060008060008060008060e0898b031215614980578182fd5b883561498b81615c87565b97506020890135965060408901356149a281615c87565b955060608901356001600160401b038111156149bc578283fd5b6149c88b828c01614500565b999c989b50969996989760808801359760a0810135975060c0013595509350505050565b6000806000806000806000806000806000806101408d8f031215614a0e578586fd5b614a178d6144ad565b9b5060208d01359a50614a2c60408e016144ad565b99506001600160401b0360608e01351115614a45578586fd5b614a558e60608f01358f01614500565b909950975060808d0135965060a08d0135955060c08d0135945060e08d013593506001600160401b036101008e01351115614a8e578283fd5b614a9f8e6101008f01358f016144b8565b90935091506001600160401b036101208e01351115614abc578081fd5b614acd8e6101208f01358f0161453f565b90509295989b509295989b509295989b565b60008060008060608587031215614af4578182fd5b8435614aff81615c87565b93506020850135925060408501356001600160401b03811115614b20578283fd5b614b2c87828801614500565b95989497509550505050565b60008060008060008060808789031215614b50578384fd5b8635614b5b81615c87565b95506020870135945060408701356001600160401b0380821115614b7d578586fd5b614b898a838b01614500565b90965094506060890135915080821115614ba1578384fd5b50614bae89828a016144b8565b979a9699509497509295939492505050565b600060208284031215614bd1578081fd5b813561255f81615c9c565b600060208284031215614bed578081fd5b815161255f81615c9c565b600060208284031215614c09578081fd5b5035919050565b600080600060408486031215614c24578081fd5b83356001600160401b03811115614c39578182fd5b614c4586828701614500565b9094509250506020840135614c5981615c87565b809150509250925092565b600060208284031215614c75578081fd5b81356001600160401b03811115614c8a578182fd5b6143938482850161453f565b600060408284031215614ca7578081fd5b61255f83836145bf565b600060c08284031215614cc2578081fd5b60405160a081018181106001600160401b0382111715614ce457614ce4615c71565b604052825181526020830151614cf981615c9c565b806020830152506040830151604082015260608301516060820152614d2184608085016145bf565b60808201529392505050565b600060208284031215614d3e578081fd5b81356001600160801b038116811461255f578182fd5b600060208284031215614d65578081fd5b5051919050565b60008060408385031215614d7e578182fd5b82359150602083013561465581615c87565b60008060008060008060a08789031215614da8578384fd5b863595506020870135614dba81615c87565b94506040870135614dca81615c87565b93506060870135925060808701356001600160401b03811115614deb578283fd5b614bae89828a01614500565b600080600080600060c08688031215614e0e578283fd5b855194506020860151614e2081615c9c565b6040870151606088015191955093509150614e3e87608088016145bf565b90509295509295909350565b600060208284031215614e5b578081fd5b813560ff8116811461255f578182fd5b60008284526020808501945084818502860184845b87811015614f245783830389528135609e19883603018112614ea0578687fd5b870160a08135614eaf81615c87565b6001600160a01b0316855281870135878601526040808301359086015260608083013560028110614ede57898afd5b614eea82880182614f5b565b50506080614efa81840184615b7d565b93508282880152614f0e8388018583614f31565b9c89019c96505050928601925050600101614e80565b5090979650505050505050565b60008284528282602086013780602084860101526020601f19601f85011685010190509392505050565b60028110614f7957634e487b7160e01b600052602160045260246000fd5b9052565b6000828483379101908152919050565b60008251614f9f818460208701615c2f565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b038816815260c060208201819052600090614fe2908301888a614f31565b90508560408301528460608301528360808301528260a083015298975050505050505050565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b039889168152969097166020870152604086019490945260608501929092521515608084015260ff1660a083015260c082015260e08101919091526101000190565b6001600160a01b0397881681529590961660208601526040850193909352606084019190915260ff16608083015260a082015260c081019190915260e00190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b03868116825260208201869052841660408201526080606082018190526000906137ce9083018486614e6b565b6001600160a01b039485168152602081019390935292166040820152606081019190915260800190565b901515815260200190565b9182521515602082015260400190565b6000602082528251806020840152615181816040850160208701615c2f565b601f01601f19169190910160400192915050565b60208082526018908201527f4f6e6c79206578656375746f7220697320616c6c6f7765640000000000000000604082015260600190565b6020808252601c908201527f4578656375746f72204d616e616765722063616e6e6f74206265203000000000604082015260600190565b60208082526014908201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b604082015260600190565b6020808252601d908201527f4c697175696469747950726f7669646572732063616e27742062652030000000604082015260600190565b6020808252818101527f576974686472617720616d6f756e74206e6f7420696e20436170206c696d6974604082015260600190565b6020808252601b908201527f4552525f5f4e41544956455f5452414e534645525f4641494c45440000000000604082015260600190565b60208082526028908201527f496e73756666696369656e742066756e647320746f20636f766572207472616e604082015267736665722066656560c01b606082015260800190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201526564647265737360d01b606082015260800190565b60208082526021908201527f4e6174697665205472616e7366657220746f2041646170746f72204661696c656040820152601960fa1b606082015260800190565b60208082526016908201527514ddd85c081859185c1d1bdc881b9bdd08199bdd5b9960521b604082015260600190565b602080825260139082015272047617320466565206561726e6564206973203606c1b604082015260600190565b6020808252601b908201527f54727573746564466f727761726465722063616e277420626520300000000000604082015260600190565b60208082526026908201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6040820152651c8818d85b1b60d21b606082015260800190565b6020808252600e908201526d3bb937b73390333ab731ba34b7b760911b604082015260600190565b60208082526010908201526f24b73b30b634b2103932b1b2b4bb32b960811b604082015260600190565b60208082526010908201526f14185d5cd8589b194e881c185d5cd95960821b604082015260600190565b60208082526022908201527f4f6e6c79206c697175696469747950726f76696465727320697320616c6c6f77604082015261195960f21b606082015260800190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b602080825260149082015273426164207265636569766572206164647265737360601b604082015260600190565b6020808252601f908201527f43616e2774207769746864726177206e617469766520746f6b656e2066656500604082015260600190565b6020808252601c908201527f526563656976657220616464726573732063616e6e6f74206265203000000000604082015260600190565b6020808252601f908201527f4465706f73697420616d6f756e74206e6f7420696e20436170206c696d697400604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6020808252601a908201527f50617573657220416464726573732063616e6e6f742062652030000000000000604082015260600190565b6020808252601290820152710416d6f756e742063616e6e6f7420626520360741b604082015260600190565b602080825260139082015272151bdad95b881b9bdd081cdd5c1c1bdc9d1959606a1b604082015260600190565b6020808252601e908201527f54727573746564466f727761726465722063616e6e6f74206265203078300000604082015260600190565b6020808252818101527f546f74616c2070657263656e746167652063616e6e6f74206265203e20313030604082015260600190565b6020808252602d908201527f546f20636861696e206d75737420626520646966666572656e74207468616e2060408201526c31bab93932b73a1031b430b4b760991b606082015260800190565b60208082526011908201527015dc9bdb99c81b595d1a1bd90818d85b1b607a1b604082015260600190565b60208082526016908201527513985d1a5d9948151c985b9cd9995c8811985a5b195960521b604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252601d908201527f4578656375746f724d616e616765722063616e6e6f7420626520307830000000604082015260600190565b60208082526019908201527f4552525f5f494e53554646494349454e545f42414c414e434500000000000000604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b602080825260119082015270105b1c9958591e48141c9bd8d95cdcd959607a1b604082015260600190565b60208082526017908201527f546f6b656e4d616e616765722063616e27742062652030000000000000000000604082015260600190565b60208082526036908201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60408201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b606082015260800190565b60208082526030908201527f4f6e6c792070617573657220697320616c6c6f77656420746f20706572666f7260408201526f36903a3434b99037b832b930ba34b7b760811b606082015260800190565b6020808252818101527f4c697175696469747950726f7669646572732063616e6e6f7420626520307830604082015260600190565b90815260200190565b9182526001600160a01b0316602082015260400190565b8481526001600160a01b0384166020820152606060408201819052600090615ae39083018486614e6b565b9695505050505050565b918252602082015260400190565b6000868252856020830152846040830152608060608301526137ce608083018486614f31565b600088825287602083015286604083015260a06060830152615b4760a083018688614f31565b8281036080840152615b5a818587614e6b565b9a9950505050505050505050565b60008235609e19833603018112614f9f578182fd5b6000808335601e19843603018112615b93578283fd5b83016020810192503590506001600160401b03811115615bb257600080fd5b8036038313156144f957600080fd5b60008219821115615bd457615bd4615c5b565b500190565b600082615bf457634e487b7160e01b81526012600452602481fd5b500490565b6000816000190483118215151615615c1357615c13615c5b565b500290565b600082821015615c2a57615c2a615c5b565b500390565b60005b83811015615c4a578181015183820152602001615c32565b838111156143005750506000910152565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461120b57600080fd5b801515811461120b57600080fdfe000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeea2646970667358221220d8ef70e8bea29deb16bc3508a61ecb7ce66dc12288a87e9eab2f2c034a5e12c764736f6c63430008000033

Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.