APE Price: $1.16 (-6.32%)

Contract

0x2f7FF71FE4F0a8bC3B708F883F2aAdF89290ab09

Overview

APE Balance

Apechain LogoApechain LogoApechain Logo0 APE

APE Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Set Market Borro...62745602024-12-06 9:52:4220 days ago1733478762IN
0x2f7FF71F...89290ab09
0 APE0.001755725.42069
Set Market Suppl...62745562024-12-06 9:52:2720 days ago1733478747IN
0x2f7FF71F...89290ab09
0 APE0.00168625.42069
Set Market Borro...62745302024-12-06 9:51:0820 days ago1733478668IN
0x2f7FF71F...89290ab09
0 APE0.001755725.42069
Set Market Suppl...62745222024-12-06 9:50:5420 days ago1733478654IN
0x2f7FF71F...89290ab09
0 APE0.0017571725.42069
Set Market Borro...62745162024-12-06 9:50:3520 days ago1733478635IN
0x2f7FF71F...89290ab09
0 APE0.001755725.42069
Set Market Suppl...62744892024-12-06 9:49:4320 days ago1733478583IN
0x2f7FF71F...89290ab09
0 APE0.0017571725.42069
Set Market Suppl...61033402024-12-03 8:34:3923 days ago1733214879IN
0x2f7FF71F...89290ab09
0 APE0.0017571525.42069
Set Market Suppl...60203862024-12-02 9:00:1724 days ago1733130017IN
0x2f7FF71F...89290ab09
0 APE0.0017571725.42069
Set Market Suppl...60203652024-12-02 8:59:5324 days ago1733129993IN
0x2f7FF71F...89290ab09
0 APE0.0017571725.42069
Configure Market...57030562024-11-28 9:51:5028 days ago1732787510IN
0x2f7FF71F...89290ab09
0 APE0.0018305625.42069
Configure Market...57030242024-11-28 9:51:0528 days ago1732787465IN
0x2f7FF71F...89290ab09
0 APE0.0018305625.42069
Configure Market...57029852024-11-28 9:50:1928 days ago1732787419IN
0x2f7FF71F...89290ab09
0 APE0.0018305625.42069
Set Market Suppl...57027602024-11-28 9:45:4928 days ago1732787149IN
0x2f7FF71F...89290ab09
0 APE0.0021849825.42069
Set Market Suppl...57027152024-11-28 9:45:0128 days ago1732787101IN
0x2f7FF71F...89290ab09
0 APE0.0021849825.42069
Set Market Suppl...57026592024-11-28 9:44:0128 days ago1732787041IN
0x2f7FF71F...89290ab09
0 APE0.0021852825.42069
List Market57022472024-11-28 9:35:3628 days ago1732786536IN
0x2f7FF71F...89290ab09
0 APE0.0061791325.42069
List Market57017182024-11-28 9:26:4028 days ago1732786000IN
0x2f7FF71F...89290ab09
0 APE0.0061791325.42069
List Market56970362024-11-28 7:59:2728 days ago1732780767IN
0x2f7FF71F...89290ab09
0 APE0.0067358225.42069
Accept Ownership55119432024-11-26 9:16:4930 days ago1732612609IN
0x2f7FF71F...89290ab09
0 APE0.0006505425.42069
Transfer Ownersh...55119432024-11-26 9:16:4930 days ago1732612609IN
0x2f7FF71F...89290ab09
0 APE0.0012162525.42069

Parent Transaction Hash Block From To
View All Internal Transactions

Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
MarketConfigurator

Compiler Version
v0.8.10+commit.fc410830

Optimization Enabled:
Yes with 200 runs

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

pragma solidity ^0.8.0;

import "openzeppelin-contracts/contracts/access/Ownable2Step.sol";
import "openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import "./Constants.sol";
import "../../interfaces/IApeFinance.sol";
import "../../interfaces/IAToken.sol";
import "../../interfaces/IDebtToken.sol";
import "../../interfaces/IPToken.sol";
import "../../libraries/DataTypes.sol";
import "../../libraries/PauseFlags.sol";

contract MarketConfigurator is Ownable2Step, Constants {
    using PauseFlags for DataTypes.MarketConfig;

    /// @notice The ApeFinance contract
    IApeFinance public immutable apeFinance;

    /// @notice The address of the guardian
    address public guardian;

    event GuardianSet(address guardian);
    event MarketListed(
        address market,
        address aToken,
        address debtToken,
        address interestRateModel,
        uint16 reserveFactor,
        bool isPToken
    );
    event MarketDelisted(address market);
    event MarketCollateralFactorSet(address market, uint16 collateralFactor);
    event MarketLiquidationThresholdSet(address market, uint16 liquidationThreshold);
    event MarketLiquidationBonusSet(address market, uint16 liquidationBonus);
    event MarketReserveFactorSet(address market, uint16 reserveFactor);
    event MarketInterestRateModelSet(address market, address interestRateModel);
    event MarketSupplyCapSet(address market, uint256 cap);
    event MarketBorrowCapSet(address market, uint256 cap);
    event MarketPausedSet(address market, string action, bool paused);
    event MarketFrozen(address market, bool state);
    event MarketConfiguredAsPToken(address market);

    constructor(address apeFinance_) {
        apeFinance = IApeFinance(apeFinance_);
    }

    /**
     * @notice Check if the caller is the owner or the guardian.
     */
    modifier onlyOwnerOrGuardian() {
        _checkOwnerOrGuardian();
        _;
    }

    /* ========== VIEW FUNCTIONS ========== */

    /**
     * @notice Get the market configuration of a market.
     * @return The market configuration
     */
    function getMarketConfiguration(address market) public view returns (DataTypes.MarketConfig memory) {
        return apeFinance.getMarketConfiguration(market);
    }

    /* ========== RESTRICTED FUNCTIONS ========== */

    /**
     * @notice Set the guardian of market configurator.
     * @param _guardian The address of the guardian
     */
    function setGuardian(address _guardian) external onlyOwner {
        guardian = _guardian;

        emit GuardianSet(guardian);
    }

    /**
     * @notice List a market to ApeFinance.
     * @param market The market to be listed
     * @param aTokenAddress The address of the aToken
     * @param debtTokenAddress The address of the debtToken
     * @param interestRateModelAddress The address of the interest rate model
     * @param reserveFactor The reserve factor of the market
     */
    function listMarket(
        address market,
        address aTokenAddress,
        address debtTokenAddress,
        address interestRateModelAddress,
        uint16 reserveFactor
    ) external onlyOwner {
        _listMarket(market, aTokenAddress, debtTokenAddress, interestRateModelAddress, reserveFactor, false);
    }

    /**
     * @notice List a pToken market to ApeFinance.
     * @param market The market to be listed
     * @param aTokenAddress The address of the aToken
     * @param interestRateModelAddress The address of the interest rate model
     * @param reserveFactor The reserve factor of the market
     */
    function listPTokenMarket(
        address market,
        address aTokenAddress,
        address interestRateModelAddress,
        uint16 reserveFactor
    ) external onlyOwner {
        _listMarket(market, aTokenAddress, address(0), interestRateModelAddress, reserveFactor, true);
    }

    /**
     * @notice Configure a market as collateral.
     * @dev This function is used for the first time to configure a market as collateral.
     * @param market The market to be configured
     * @param collateralFactor The collateral factor of the market
     * @param liquidationThreshold The liquidation threshold of the market
     * @param liquidationBonus The liquidation bonus of the market
     */
    function configureMarketAsCollateral(
        address market,
        uint16 collateralFactor,
        uint16 liquidationThreshold,
        uint16 liquidationBonus
    ) external onlyOwner {
        DataTypes.MarketConfig memory config = getMarketConfiguration(market);
        require(config.isListed, "not listed");
        require(
            config.collateralFactor == 0 && config.liquidationThreshold == 0 && config.liquidationBonus == 0,
            "already configured"
        );
        require(collateralFactor > 0 && collateralFactor <= MAX_COLLATERAL_FACTOR, "invalid collateral factor");
        require(
            liquidationThreshold > 0 && liquidationThreshold <= MAX_LIQUIDATION_THRESHOLD
                && liquidationThreshold >= collateralFactor,
            "invalid liquidation threshold"
        );
        require(
            liquidationBonus > MIN_LIQUIDATION_BONUS && liquidationBonus <= MAX_LIQUIDATION_BONUS,
            "invalid liquidation bonus"
        );
        require(
            uint256(liquidationThreshold) * uint256(liquidationBonus) / FACTOR_SCALE
                <= MAX_LIQUIDATION_THRESHOLD_X_BONUS,
            "liquidation threshold * liquidation bonus larger than 100%"
        );

        config.collateralFactor = collateralFactor;
        config.liquidationThreshold = liquidationThreshold;
        config.liquidationBonus = liquidationBonus;
        apeFinance.setMarketConfiguration(market, config);

        emit MarketCollateralFactorSet(market, collateralFactor);
        emit MarketLiquidationThresholdSet(market, liquidationThreshold);
        emit MarketLiquidationBonusSet(market, liquidationBonus);
    }

    /**
     * @notice Adjust the collateral factor of a market.
     * @param market The market to be adjusted
     * @param collateralFactor The new collateral factor of the market
     */
    function adjustMarketCollateralFactor(address market, uint16 collateralFactor) external onlyOwner {
        DataTypes.MarketConfig memory config = getMarketConfiguration(market);
        require(config.isListed, "not listed");
        if (collateralFactor > 0) {
            require(collateralFactor <= MAX_COLLATERAL_FACTOR, "invalid collateral factor");
            require(
                collateralFactor <= config.liquidationThreshold, "collateral factor larger than liquidation threshold"
            );
        }

        config.collateralFactor = collateralFactor;
        apeFinance.setMarketConfiguration(market, config);

        emit MarketCollateralFactorSet(market, collateralFactor);
    }

    /**
     * @notice Adjust the reserve factor of a market.
     * @param market The market to be adjusted
     * @param reserveFactor The new reserve factor of the market
     */
    function adjustMarketReserveFactor(address market, uint16 reserveFactor) external onlyOwner {
        DataTypes.MarketConfig memory config = getMarketConfiguration(market);
        require(config.isListed, "not listed");
        require(reserveFactor <= MAX_RESERVE_FACTOR, "invalid reserve factor");

        // Accrue interests before changing reserve factor.
        apeFinance.accrueInterest(market);

        config.reserveFactor = reserveFactor;
        apeFinance.setMarketConfiguration(market, config);

        emit MarketReserveFactorSet(market, reserveFactor);
    }

    /**
     * @notice Adjust the liquidation threshold of a market.
     * @param market The market to be adjusted
     * @param liquidationThreshold The new liquidation threshold of the market
     */
    function adjustMarketLiquidationThreshold(address market, uint16 liquidationThreshold) external onlyOwner {
        DataTypes.MarketConfig memory config = getMarketConfiguration(market);
        require(config.isListed, "not listed");
        if (liquidationThreshold > 0) {
            require(liquidationThreshold <= MAX_LIQUIDATION_THRESHOLD, "invalid liquidation threshold");
            require(
                liquidationThreshold >= config.collateralFactor, "liquidation threshold smaller than collateral factor"
            );
            require(
                uint256(liquidationThreshold) * uint256(config.liquidationBonus) / FACTOR_SCALE
                    <= MAX_LIQUIDATION_THRESHOLD_X_BONUS,
                "liquidation threshold * liquidation bonus larger than 100%"
            );
        } else {
            require(config.collateralFactor == 0, "collateral factor not zero");
        }

        config.liquidationThreshold = liquidationThreshold;
        apeFinance.setMarketConfiguration(market, config);

        emit MarketLiquidationThresholdSet(market, liquidationThreshold);
    }

    /**
     * @notice Adjust the liquidation bonus of a market.
     * @param market The market to be adjusted
     * @param liquidationBonus The new liquidation bonus of the market
     */
    function adjustMarketLiquidationBonus(address market, uint16 liquidationBonus) external onlyOwner {
        DataTypes.MarketConfig memory config = getMarketConfiguration(market);
        require(config.isListed, "not listed");
        if (liquidationBonus > 0) {
            require(
                liquidationBonus > MIN_LIQUIDATION_BONUS && liquidationBonus <= MAX_LIQUIDATION_BONUS,
                "invalid liquidation bonus"
            );
            require(
                uint256(config.liquidationThreshold) * uint256(liquidationBonus) / FACTOR_SCALE
                    <= MAX_LIQUIDATION_THRESHOLD_X_BONUS,
                "liquidation threshold * liquidation bonus larger than 100%"
            );
        } else {
            require(
                config.collateralFactor == 0 && config.liquidationThreshold == 0,
                "collateral factor or liquidation threshold not zero"
            );
        }

        config.liquidationBonus = liquidationBonus;
        apeFinance.setMarketConfiguration(market, config);

        emit MarketLiquidationBonusSet(market, liquidationBonus);
    }

    /**
     * @notice Change the interest rate model of a market.
     * @param market The market to be changed
     * @param interestRateModelAddress The new interest rate model of the market
     */
    function changeMarketInterestRateModel(address market, address interestRateModelAddress) external onlyOwner {
        DataTypes.MarketConfig memory config = getMarketConfiguration(market);
        require(config.isListed, "not listed");

        // Accrue interests before changing IRM.
        apeFinance.accrueInterest(market);

        config.interestRateModelAddress = interestRateModelAddress;
        apeFinance.setMarketConfiguration(market, config);

        emit MarketInterestRateModelSet(market, interestRateModelAddress);
    }

    /**
     * @notice Soft delist a market.
     * @dev Soft delisting a market means that the supply and borrow will be paused and the reserve factor will be set to 100%.
     * @param market The market to be soft delisted
     */
    function softDelistMarket(address market) external onlyOwner {
        DataTypes.MarketConfig memory config = getMarketConfiguration(market);
        require(config.isListed, "not listed");

        if (!config.isSupplyPaused()) {
            config.setSupplyPaused(true);
            emit MarketPausedSet(market, "supply", true);
        }
        if (!config.isBorrowPaused()) {
            config.setBorrowPaused(true);
            emit MarketPausedSet(market, "borrow", true);
        }
        if (config.reserveFactor != MAX_RESERVE_FACTOR) {
            // Accrue interests before changing reserve factor.
            apeFinance.accrueInterest(market);

            config.reserveFactor = MAX_RESERVE_FACTOR;
            emit MarketReserveFactorSet(market, MAX_RESERVE_FACTOR);
        }
        apeFinance.setMarketConfiguration(market, config);
    }

    /**
     * @notice Hard delist a market.
     * @param market The market to be hard delisted
     */
    function hardDelistMarket(address market) external onlyOwner {
        DataTypes.MarketConfig memory config = getMarketConfiguration(market);
        require(config.isListed, "not listed");
        require(config.isSupplyPaused() && config.isBorrowPaused(), "not paused");
        require(config.reserveFactor == MAX_RESERVE_FACTOR, "reserve factor not max");
        require(
            config.collateralFactor == 0 && config.liquidationThreshold == 0,
            "collateral factor or liquidation threshold not zero"
        );

        apeFinance.delistMarket(market);

        emit MarketDelisted(market);
    }

    /**
     * @notice Pause or unpause the transfer of a market's aToken.
     * @param market The market's aToken to be paused or unpaused
     * @param paused Pause or unpause
     */
    function setMarketTransferPaused(address market, bool paused) external onlyOwner {
        DataTypes.MarketConfig memory config = getMarketConfiguration(market);
        require(config.isListed, "not listed");

        config.setTransferPaused(paused);
        apeFinance.setMarketConfiguration(market, config);

        emit MarketPausedSet(market, "transfer", paused);
    }

    struct MarketCap {
        address market;
        uint256 cap;
    }

    /**
     * @notice Set the supply cap of a list of markets.
     * @param marketCaps The list of markets and their supply caps
     */
    function setMarketSupplyCaps(MarketCap[] calldata marketCaps) external onlyOwnerOrGuardian {
        uint256 length = marketCaps.length;
        for (uint256 i = 0; i < length;) {
            address market = marketCaps[i].market;
            uint256 cap = marketCaps[i].cap;
            DataTypes.MarketConfig memory config = getMarketConfiguration(market);
            require(config.isListed, "not listed");

            config.supplyCap = cap;
            apeFinance.setMarketConfiguration(market, config);

            emit MarketSupplyCapSet(market, cap);

            unchecked {
                i++;
            }
        }
    }

    /**
     * @notice Set the borrow cap of a list of markets.
     * @param marketCaps The list of markets and their borrow caps
     */
    function setMarketBorrowCaps(MarketCap[] calldata marketCaps) external onlyOwnerOrGuardian {
        uint256 length = marketCaps.length;
        for (uint256 i = 0; i < length;) {
            address market = marketCaps[i].market;
            uint256 cap = marketCaps[i].cap;
            DataTypes.MarketConfig memory config = getMarketConfiguration(market);
            require(config.isListed, "not listed");
            require(!config.isPToken, "cannot set borrow cap for pToken");

            config.borrowCap = cap;
            apeFinance.setMarketConfiguration(market, config);

            emit MarketBorrowCapSet(market, cap);

            unchecked {
                i++;
            }
        }
    }

    /**
     * @notice Pause or unpause the supply of a market.
     * @param market The market to be paused or unpaused
     * @param paused Pause or unpause
     */
    function setMarketSupplyPaused(address market, bool paused) external onlyOwnerOrGuardian {
        DataTypes.MarketConfig memory config = getMarketConfiguration(market);
        require(config.isListed, "not listed");

        config.setSupplyPaused(paused);
        apeFinance.setMarketConfiguration(market, config);

        emit MarketPausedSet(market, "supply", paused);
    }

    /**
     * @notice Pause or unpause the borrow of a market.
     * @param market The market to be paused or unpaused
     * @param paused Pause or unpause
     */
    function setMarketBorrowPaused(address market, bool paused) external onlyOwnerOrGuardian {
        DataTypes.MarketConfig memory config = getMarketConfiguration(market);
        require(config.isListed, "not listed");
        require(!config.isPToken, "cannot set borrow paused for pToken");

        config.setBorrowPaused(paused);
        apeFinance.setMarketConfiguration(market, config);

        emit MarketPausedSet(market, "borrow", paused);
    }

    /**
     * @notice Configure a market as a pToken.
     * @dev This function can be called when the pToken was accidentally listed by using `listMarket` function.
     * @param market The market to be configured as a pToken
     */
    function configureMarketAsPToken(address market) external onlyOwnerOrGuardian {
        // Simple sanity check to make sure the market is a pToken.
        IPToken(market).getUnderlying();

        DataTypes.MarketConfig memory config = getMarketConfiguration(market);
        require(config.isListed, "not listed");
        require(!config.isPToken, "already a pToken");

        config.isPToken = true;
        config.setBorrowPaused(true);
        // Set the borrow cap to a very small amount (1 Wei) to prevent borrowing.
        config.borrowCap = 1;

        apeFinance.setMarketConfiguration(market, config);

        emit MarketConfiguredAsPToken(market);
    }

    /* ========== INTERNAL FUNCTIONS ========== */

    /**
     * @dev Check if the caller is the owner or guardian.
     */
    function _checkOwnerOrGuardian() internal view {
        require(msg.sender == owner() || msg.sender == guardian, "!authorized");
    }

    /**
     * @dev List a vanilla market or a pToken market. Markets that were delisted can't be listed again.
     * @param market The market to be listed
     * @param aTokenAddress The aToken of the market
     * @param debtTokenAddress The debtToken of the market
     * @param interestRateModelAddress The interest rate model of the market
     * @param reserveFactor The reserve factor of the market
     * @param isPToken Whether the market is a pToken market
     */
    function _listMarket(
        address market,
        address aTokenAddress,
        address debtTokenAddress,
        address interestRateModelAddress,
        uint16 reserveFactor,
        bool isPToken
    ) internal {
        DataTypes.MarketConfig memory config = getMarketConfiguration(market);
        require(!config.isListed, "already listed");
        require(!config.isDelisted, "already delisted");
        require(IAToken(aTokenAddress).asset() == market, "mismatch market");
        if (!isPToken) {
            require(IDebtToken(debtTokenAddress).asset() == market, "mismatch market");
        }
        require(reserveFactor <= MAX_RESERVE_FACTOR, "invalid reserve factor");

        uint8 underlyingDecimals = IERC20Metadata(market).decimals();
        require(underlyingDecimals <= 18, "nonstandard token decimals");

        config.isListed = true;
        config.aTokenAddress = aTokenAddress;
        config.interestRateModelAddress = interestRateModelAddress;
        config.reserveFactor = reserveFactor;
        config.initialExchangeRate = 10 ** underlyingDecimals;
        if (isPToken) {
            config.isPToken = true;
            config.setBorrowPaused(true);
            // Set the borrow cap to a very small amount (1 Wei) to prevent borrowing.
            config.borrowCap = 1;
        } else {
            config.debtTokenAddress = debtTokenAddress;
        }

        apeFinance.listMarket(market, config);

        emit MarketListed(market, aTokenAddress, debtTokenAddress, interestRateModelAddress, reserveFactor, isPToken);
    }
}

File 2 of 13 : Ownable2Step.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (access/Ownable2Step.sol)

pragma solidity ^0.8.0;

import "./Ownable.sol";

/**
 * @dev Contract module which provides 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} and {acceptOwnership}.
 *
 * This module is used through inheritance. It will make available all functions
 * from parent (Ownable).
 */
abstract contract Ownable2Step is Ownable {
    address private _pendingOwner;

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

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

    /**
     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual override onlyOwner {
        _pendingOwner = newOwner;
        emit OwnershipTransferStarted(owner(), newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual override {
        delete _pendingOwner;
        super._transferOwnership(newOwner);
    }

    /**
     * @dev The new owner accepts the ownership transfer.
     */
    function acceptOwnership() external {
        address sender = _msgSender();
        require(pendingOwner() == sender, "Ownable2Step: caller is not the new owner");
        _transferOwnership(sender);
    }
}

File 3 of 13 : IERC20Metadata.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.0;

import "../IERC20.sol";

/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 *
 * _Available since v4.1._
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}

File 4 of 13 : Constants.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

abstract contract Constants {
    uint256 internal constant INITIAL_BORROW_INDEX = 1e18;
    uint256 internal constant INITIAL_EXCHANGE_RATE = 1e18;
    uint256 internal constant FACTOR_SCALE = 10000;

    uint16 internal constant MAX_COLLATERAL_FACTOR = 9000; // 90%
    uint16 internal constant MAX_LIQUIDATION_THRESHOLD = 10000; // 100%
    uint16 internal constant MIN_LIQUIDATION_BONUS = 10000; // 100%
    uint16 internal constant MAX_LIQUIDATION_BONUS = 12500; // 125%
    uint16 internal constant MAX_LIQUIDATION_THRESHOLD_X_BONUS = 10000; // 100%
    uint16 internal constant MAX_RESERVE_FACTOR = 10000; // 100%

    uint8 internal constant LIQUIDITY_CHECK_NORMAL = 0;
    uint8 internal constant LIQUIDITY_CHECK_DEFERRED = 1;
    uint8 internal constant LIQUIDITY_CHECK_DIRTY = 2;
}

File 5 of 13 : IApeFinance.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "../libraries/DataTypes.sol";

interface IApeFinance {
    /* ========== USER INTERFACES ========== */

    function accrueInterest(address market) external;

    function supply(address from, address to, address market, uint256 amount) external;

    function borrow(address from, address to, address asset, uint256 amount) external;

    function redeem(address from, address to, address asset, uint256 amount) external returns (uint256);

    function repay(address from, address to, address asset, uint256 amount) external returns (uint256);

    function liquidate(
        address liquidator,
        address borrower,
        address marketBorrow,
        address marketCollateral,
        uint256 repayAmount
    ) external returns (uint256, uint256);

    function deferLiquidityCheck(address user, bytes memory data) external;

    function getBorrowBalance(address user, address market) external view returns (uint256);

    function getATokenBalance(address user, address market) external view returns (uint256);

    function getSupplyBalance(address user, address market) external view returns (uint256);

    function isMarketListed(address market) external view returns (bool);

    function getExchangeRate(address market) external view returns (uint256);

    function getTotalSupply(address market) external view returns (uint256);

    function getTotalBorrow(address market) external view returns (uint256);

    function getTotalCash(address market) external view returns (uint256);

    function getTotalReserves(address market) external view returns (uint256);

    function getAccountLiquidity(address user) external view returns (uint256, uint256, uint256);

    function isAllowedExtension(address user, address extension) external view returns (bool);

    function transferAToken(address market, address from, address to, uint256 amount) external;

    function setSubAccountExtension(address primary, uint256 subAccountId, bool allowed) external;

    /* ========== MARKET CONFIGURATOR INTERFACES ========== */

    function getMarketConfiguration(address market) external view returns (DataTypes.MarketConfig memory);

    function listMarket(address market, DataTypes.MarketConfig calldata config) external;

    function delistMarket(address market) external;

    function setMarketConfiguration(address market, DataTypes.MarketConfig calldata config) external;

    /* ========== CREDIT LIMIT MANAGER INTERFACES ========== */

    function getCreditLimit(address user, address market) external view returns (uint256);

    function getUserCreditMarkets(address user) external view returns (address[] memory);

    function isCreditAccount(address user) external view returns (bool);

    function setCreditLimit(address user, address market, uint256 credit) external;

    /* ========== RESERVE MANAGER INTERFACES ========== */

    function absorbToReserves(address market) external;

    function reduceReserves(address market, uint256 aTokenAmount, address recipient) external;
}

File 6 of 13 : IAToken.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

interface IAToken {
    function mint(address account, uint256 amount) external;

    function burn(address account, uint256 amount) external;

    function seize(address from, address to, uint256 amount) external;

    function asset() external view returns (address);
}

File 7 of 13 : IDebtToken.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
import "openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol";

interface IDebtToken is IERC20, IERC20Metadata {
    function asset() external view returns (address);
}

File 8 of 13 : IPToken.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";

interface IPToken is IERC20 {
    function getUnderlying() external view returns (address);

    function wrap(uint256 amount) external;

    function unwrap(uint256 amount) external;

    function absorb(address user) external;
}

File 9 of 13 : DataTypes.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

library DataTypes {
    struct UserBorrow {
        uint256 borrowBalance;
        uint256 borrowIndex;
    }

    struct MarketConfig {
        // 1 + 1 + 2 + 2 + 2 + 2 + 1 + 1 = 12
        bool isListed;
        uint8 pauseFlags;
        uint16 collateralFactor;
        uint16 liquidationThreshold;
        uint16 liquidationBonus;
        uint16 reserveFactor;
        bool isPToken;
        bool isDelisted;
        // 20 + 20 + 20 + 32 + 32 + 32
        address aTokenAddress;
        address debtTokenAddress;
        address interestRateModelAddress;
        uint256 supplyCap;
        uint256 borrowCap;
        uint256 initialExchangeRate;
    }

    struct Market {
        MarketConfig config;
        uint40 lastUpdateTimestamp;
        uint256 totalCash;
        uint256 totalBorrow;
        uint256 totalSupply;
        uint256 totalReserves;
        uint256 borrowIndex;
        mapping(address => UserBorrow) userBorrows;
        mapping(address => uint256) userSupplies;
    }
}

File 10 of 13 : PauseFlags.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./DataTypes.sol";

library PauseFlags {
    /// @dev Mask for specific actions in the pause flag bit array
    uint8 internal constant PAUSE_SUPPLY_MASK = 0xFE;
    uint8 internal constant PAUSE_BORROW_MASK = 0xFD;
    uint8 internal constant PAUSE_TRANSFER_MASK = 0xFB;

    /// @dev Offsets for specific actions in the pause flag bit array
    uint8 internal constant PAUSE_SUPPLY_OFFSET = 0;
    uint8 internal constant PAUSE_BORROW_OFFSET = 1;
    uint8 internal constant PAUSE_TRANSFER_OFFSET = 2;

    /// @dev Sets the market supply paused.
    function setSupplyPaused(DataTypes.MarketConfig memory self, bool paused) internal pure {
        self.pauseFlags = (self.pauseFlags & PAUSE_SUPPLY_MASK) | (toUInt8(paused) << PAUSE_SUPPLY_OFFSET);
    }

    /// @dev Returns true if the market supply is paused, and false otherwise.
    function isSupplyPaused(DataTypes.MarketConfig memory self) internal pure returns (bool) {
        return toBool(self.pauseFlags & ~PAUSE_SUPPLY_MASK);
    }

    /// @dev Sets the market borrow paused.
    function setBorrowPaused(DataTypes.MarketConfig memory self, bool paused) internal pure {
        self.pauseFlags = (self.pauseFlags & PAUSE_BORROW_MASK) | (toUInt8(paused) << PAUSE_BORROW_OFFSET);
    }

    /// @dev Returns true if the market borrow is paused, and false otherwise.
    function isBorrowPaused(DataTypes.MarketConfig memory self) internal pure returns (bool) {
        return toBool(self.pauseFlags & ~PAUSE_BORROW_MASK);
    }

    /// @dev Sets the market transfer paused.
    function setTransferPaused(DataTypes.MarketConfig memory self, bool paused) internal pure {
        self.pauseFlags = (self.pauseFlags & PAUSE_TRANSFER_MASK) | (toUInt8(paused) << PAUSE_TRANSFER_OFFSET);
    }

    /// @dev Returns true if the market transfer is paused, and false otherwise.
    function isTransferPaused(DataTypes.MarketConfig memory self) internal pure returns (bool) {
        return toBool(self.pauseFlags & ~PAUSE_TRANSFER_MASK);
    }

    /// @dev Casts a boolean to uint8.
    function toUInt8(bool x) internal pure returns (uint8) {
        return x ? 1 : 0;
    }

    /// @dev Casts a uint8 to boolean.
    function toBool(uint8 x) internal pure returns (bool) {
        return x != 0;
    }
}

File 11 of 13 : Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)

pragma solidity ^0.8.0;

import "../utils/Context.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 Ownable is Context {
    address private _owner;

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

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

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

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        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 {
        _transferOwnership(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");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

File 12 of 13 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @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);

    /**
     * @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 `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, 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 `from` to `to` 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 from,
        address to,
        uint256 amount
    ) external returns (bool);
}

File 13 of 13 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @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 Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

Settings
{
  "remappings": [
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "forge-std/=lib/forge-std/src/",
    "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs"
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "london",
  "viaIR": false,
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"apeFinance_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"guardian","type":"address"}],"name":"GuardianSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"market","type":"address"},{"indexed":false,"internalType":"uint256","name":"cap","type":"uint256"}],"name":"MarketBorrowCapSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"market","type":"address"},{"indexed":false,"internalType":"uint16","name":"collateralFactor","type":"uint16"}],"name":"MarketCollateralFactorSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"market","type":"address"}],"name":"MarketConfiguredAsPToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"market","type":"address"}],"name":"MarketDelisted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"market","type":"address"},{"indexed":false,"internalType":"bool","name":"state","type":"bool"}],"name":"MarketFrozen","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"market","type":"address"},{"indexed":false,"internalType":"address","name":"interestRateModel","type":"address"}],"name":"MarketInterestRateModelSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"market","type":"address"},{"indexed":false,"internalType":"uint16","name":"liquidationBonus","type":"uint16"}],"name":"MarketLiquidationBonusSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"market","type":"address"},{"indexed":false,"internalType":"uint16","name":"liquidationThreshold","type":"uint16"}],"name":"MarketLiquidationThresholdSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"market","type":"address"},{"indexed":false,"internalType":"address","name":"aToken","type":"address"},{"indexed":false,"internalType":"address","name":"debtToken","type":"address"},{"indexed":false,"internalType":"address","name":"interestRateModel","type":"address"},{"indexed":false,"internalType":"uint16","name":"reserveFactor","type":"uint16"},{"indexed":false,"internalType":"bool","name":"isPToken","type":"bool"}],"name":"MarketListed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"market","type":"address"},{"indexed":false,"internalType":"string","name":"action","type":"string"},{"indexed":false,"internalType":"bool","name":"paused","type":"bool"}],"name":"MarketPausedSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"market","type":"address"},{"indexed":false,"internalType":"uint16","name":"reserveFactor","type":"uint16"}],"name":"MarketReserveFactorSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"market","type":"address"},{"indexed":false,"internalType":"uint256","name":"cap","type":"uint256"}],"name":"MarketSupplyCapSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","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"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"market","type":"address"},{"internalType":"uint16","name":"collateralFactor","type":"uint16"}],"name":"adjustMarketCollateralFactor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"market","type":"address"},{"internalType":"uint16","name":"liquidationBonus","type":"uint16"}],"name":"adjustMarketLiquidationBonus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"market","type":"address"},{"internalType":"uint16","name":"liquidationThreshold","type":"uint16"}],"name":"adjustMarketLiquidationThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"market","type":"address"},{"internalType":"uint16","name":"reserveFactor","type":"uint16"}],"name":"adjustMarketReserveFactor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"apeFinance","outputs":[{"internalType":"contract IApeFinance","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"market","type":"address"},{"internalType":"address","name":"interestRateModelAddress","type":"address"}],"name":"changeMarketInterestRateModel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"market","type":"address"},{"internalType":"uint16","name":"collateralFactor","type":"uint16"},{"internalType":"uint16","name":"liquidationThreshold","type":"uint16"},{"internalType":"uint16","name":"liquidationBonus","type":"uint16"}],"name":"configureMarketAsCollateral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"market","type":"address"}],"name":"configureMarketAsPToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"market","type":"address"}],"name":"getMarketConfiguration","outputs":[{"components":[{"internalType":"bool","name":"isListed","type":"bool"},{"internalType":"uint8","name":"pauseFlags","type":"uint8"},{"internalType":"uint16","name":"collateralFactor","type":"uint16"},{"internalType":"uint16","name":"liquidationThreshold","type":"uint16"},{"internalType":"uint16","name":"liquidationBonus","type":"uint16"},{"internalType":"uint16","name":"reserveFactor","type":"uint16"},{"internalType":"bool","name":"isPToken","type":"bool"},{"internalType":"bool","name":"isDelisted","type":"bool"},{"internalType":"address","name":"aTokenAddress","type":"address"},{"internalType":"address","name":"debtTokenAddress","type":"address"},{"internalType":"address","name":"interestRateModelAddress","type":"address"},{"internalType":"uint256","name":"supplyCap","type":"uint256"},{"internalType":"uint256","name":"borrowCap","type":"uint256"},{"internalType":"uint256","name":"initialExchangeRate","type":"uint256"}],"internalType":"struct DataTypes.MarketConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"guardian","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"market","type":"address"}],"name":"hardDelistMarket","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"market","type":"address"},{"internalType":"address","name":"aTokenAddress","type":"address"},{"internalType":"address","name":"debtTokenAddress","type":"address"},{"internalType":"address","name":"interestRateModelAddress","type":"address"},{"internalType":"uint16","name":"reserveFactor","type":"uint16"}],"name":"listMarket","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"market","type":"address"},{"internalType":"address","name":"aTokenAddress","type":"address"},{"internalType":"address","name":"interestRateModelAddress","type":"address"},{"internalType":"uint16","name":"reserveFactor","type":"uint16"}],"name":"listPTokenMarket","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_guardian","type":"address"}],"name":"setGuardian","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"market","type":"address"},{"internalType":"uint256","name":"cap","type":"uint256"}],"internalType":"struct MarketConfigurator.MarketCap[]","name":"marketCaps","type":"tuple[]"}],"name":"setMarketBorrowCaps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"market","type":"address"},{"internalType":"bool","name":"paused","type":"bool"}],"name":"setMarketBorrowPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"market","type":"address"},{"internalType":"uint256","name":"cap","type":"uint256"}],"internalType":"struct MarketConfigurator.MarketCap[]","name":"marketCaps","type":"tuple[]"}],"name":"setMarketSupplyCaps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"market","type":"address"},{"internalType":"bool","name":"paused","type":"bool"}],"name":"setMarketSupplyPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"market","type":"address"},{"internalType":"bool","name":"paused","type":"bool"}],"name":"setMarketTransferPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"market","type":"address"}],"name":"softDelistMarket","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60a06040523480156200001157600080fd5b5060405162002ec638038062002ec68339810160408190526200003491620000cb565b6200003f3362000051565b6001600160a01b0316608052620000fd565b600180546001600160a01b031916905562000078816200007b602090811b62001ea317901c565b50565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600060208284031215620000de57600080fd5b81516001600160a01b0381168114620000f657600080fd5b9392505050565b608051612d286200019e600039600081816102c10152818161047f01528181610622015281816106d90152818161087301528181610a6701528181610d6101528181610fa7015281816112140152818161133a015281816114ed01528181611617015281816116940152818161183501528181611a1b01528181611b0601528181611c2d01528181611ca801528181611e1b01526123ae0152612d286000f3fe608060405234801561001057600080fd5b50600436106101735760003560e01c80637aab4f11116100de578063ae36691711610097578063e30c397811610071578063e30c39781461032f578063ee715e3a14610340578063f2fde38b14610353578063f440b61e1461036657600080fd5b8063ae366917146102f6578063ceceb02314610309578063df310df81461031c57600080fd5b80637aab4f11146102725780638598fae8146102855780638a0dac4a146102985780638da5cb5b146102ab5780639b6899db146102bc578063aaa05594146102e357600080fd5b8063366f1fbb11610130578063366f1fbb146101ec5780633ab2b69a146101ff578063452a9320146102125780635a208d5214610242578063715018a61461026257806379ba50971461026a57600080fd5b80630723cf18146101785780630de9de6b1461018d5780631474e055146101a05780631f650d43146101b35780632c9c6a81146101c657806331d97ce2146101d9575b600080fd5b61018b6101863660046124de565b610379565b005b61018b61019b366004612568565b61053c565b61018b6101ae36600461259c565b610746565b61018b6101c1366004612568565b610764565b61018b6101d436600461260d565b61091e565b61018b6101e7366004612646565b610b0e565b61018b6101fa36600461260d565b610e7c565b61018b61020d36600461260d565b611041565b600254610225906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b610255610250366004612568565b6112ae565b6040516102399190612793565b61018b6113ac565b61018b6113c0565b61018b6102803660046127b0565b61143a565b61018b61029336600461260d565b611575565b61018b6102a6366004612568565b61172e565b6000546001600160a01b0316610225565b6102257f000000000000000000000000000000000000000000000000000000000000000081565b61018b6102f13660046124de565b61178a565b61018b610304366004612568565b6118ec565b61018b6103173660046127b0565b611ab1565b61018b61032a3660046127de565b611bc2565b6001546001600160a01b0316610225565b61018b61034e36600461281f565b611bda565b61018b610361366004612568565b611d55565b61018b6103743660046127b0565b611dc6565b610381611ef3565b8060005b818110156105365760008484838181106103a1576103a161284d565b6103b79260206040909202019081019150612568565b905060008585848181106103cd576103cd61284d565b90506040020160200135905060006103e4836112ae565b805190915061040e5760405162461bcd60e51b815260040161040590612863565b60405180910390fd5b8060c00151156104605760405162461bcd60e51b815260206004820181905260248201527f63616e6e6f742073657420626f72726f772063617020666f722070546f6b656e6044820152606401610405565b6101808101829052604051633a1181d960e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690633a1181d9906104b69086908590600401612887565b600060405180830381600087803b1580156104d057600080fd5b505af11580156104e4573d6000803e3d6000fd5b5050604080516001600160a01b0387168152602081018690527f5c3e947e8b26df9badd8a743328d9689b8d650ca70702d0fe8c4cab56ff9a816935001905060405180910390a1505050600101610385565b50505050565b610544611f50565b600061054f826112ae565b80519091506105705760405162461bcd60e51b815260040161040590612863565b61057981611faa565b6105b157610588816001611fbc565b600080516020612cd38339815191528260016040516105a89291906128a5565b60405180910390a15b6105ba81611fe4565b6105f2576105c9816001611ff6565b600080516020612cd38339815191528260016040516105e99291906128de565b60405180910390a15b60a081015161ffff16612710146106c257604051639198e51560e01b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690639198e51590602401600060405180830381600087803b15801561066657600080fd5b505af115801561067a573d6000803e3d6000fd5b505061271060a084018190526040517f9dd9e80184b8d31052f0964bcf5a4f6cd43183301402f6af6bf582d7220f85f393506106b99250859190612917565b60405180910390a15b604051633a1181d960e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690633a1181d9906107109085908590600401612887565b600060405180830381600087803b15801561072a57600080fd5b505af115801561073e573d6000803e3d6000fd5b505050505050565b61074e611f50565b61075d8585858585600061201e565b5050505050565b61076c611ef3565b806001600160a01b0316639816f4736040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ce9190612944565b5060006107da826112ae565b80519091506107fb5760405162461bcd60e51b815260040161040590612863565b8060c00151156108405760405162461bcd60e51b815260206004820152601060248201526f30b63932b0b23c903090382a37b5b2b760811b6044820152606401610405565b600160c08201819052610854908290611ff6565b6001610180820152604051633a1181d960e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690633a1181d9906108aa9085908590600401612887565b600060405180830381600087803b1580156108c457600080fd5b505af11580156108d8573d6000803e3d6000fd5b50506040516001600160a01b03851681527f224a8ad8cc54dff54c72759b1bf650a71137993a18df9deac6f8e844b8c6e32a925060200190505b60405180910390a15050565b610926611f50565b6000610931836112ae565b80519091506109525760405162461bcd60e51b815260040161040590612863565b61ffff821615610a0e5761271061ffff831611801561097757506130d461ffff831611155b6109bf5760405162461bcd60e51b8152602060048201526019602482015278696e76616c6964206c69717569646174696f6e20626f6e757360381b6044820152606401610405565b61271061ffff166127108361ffff16836060015161ffff166109e19190612977565b6109eb9190612996565b1115610a095760405162461bcd60e51b8152600401610405906129b8565b610a46565b604081015161ffff16158015610a2a5750606081015161ffff16155b610a465760405162461bcd60e51b815260040161040590612a15565b61ffff82166080820152604051633a1181d960e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690633a1181d990610a9e9086908590600401612887565b600060405180830381600087803b158015610ab857600080fd5b505af1158015610acc573d6000803e3d6000fd5b505050507f8b6d1a3855943f585bdcfaff3cfd4b1a0f5eefc48baba05f0294427535693e5e8383604051610b01929190612917565b60405180910390a1505050565b610b16611f50565b6000610b21856112ae565b8051909150610b425760405162461bcd60e51b815260040161040590612863565b604081015161ffff16158015610b5e5750606081015161ffff16155b8015610b705750608081015161ffff16155b610bb15760405162461bcd60e51b8152602060048201526012602482015271185b1c9958591e4818dbdb999a59dd5c995960721b6044820152606401610405565b60008461ffff16118015610bcb575061232861ffff851611155b610c135760405162461bcd60e51b815260206004820152601960248201527834b73b30b634b21031b7b63630ba32b930b6103330b1ba37b960391b6044820152606401610405565b60008361ffff16118015610c2d575061271061ffff841611155b8015610c4157508361ffff168361ffff1610155b610c8d5760405162461bcd60e51b815260206004820152601d60248201527f696e76616c6964206c69717569646174696f6e207468726573686f6c640000006044820152606401610405565b61271061ffff8316118015610ca857506130d461ffff831611155b610cf05760405162461bcd60e51b8152602060048201526019602482015278696e76616c6964206c69717569646174696f6e20626f6e757360381b6044820152606401610405565b61271080610d0561ffff858116908716612977565b610d0f9190612996565b1115610d2d5760405162461bcd60e51b8152600401610405906129b8565b61ffff8085166040808401919091528482166060840152908316608083015251633a1181d960e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690633a1181d990610d989088908590600401612887565b600060405180830381600087803b158015610db257600080fd5b505af1158015610dc6573d6000803e3d6000fd5b505050507f4cf4a1fd341f7cd98a4834e3f2a4cf75af4acee229cfe76ab4b421671679b1418585604051610dfb929190612917565b60405180910390a17f6c42639781cb1a85205c1b87aa8e80fc30f1e62c92c44b68f2a38743718e57f18584604051610e34929190612917565b60405180910390a17f8b6d1a3855943f585bdcfaff3cfd4b1a0f5eefc48baba05f0294427535693e5e8583604051610e6d929190612917565b60405180910390a15050505050565b610e84611f50565b6000610e8f836112ae565b8051909150610eb05760405162461bcd60e51b815260040161040590612863565b61ffff821615610f845761232861ffff83161115610f0c5760405162461bcd60e51b815260206004820152601960248201527834b73b30b634b21031b7b63630ba32b930b6103330b1ba37b960391b6044820152606401610405565b806060015161ffff168261ffff161115610f845760405162461bcd60e51b815260206004820152603360248201527f636f6c6c61746572616c20666163746f72206c6172676572207468616e206c696044820152721c5d5a59185d1a5bdb881d1a1c995cda1bdb19606a1b6064820152608401610405565b61ffff821660408083019190915251633a1181d960e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690633a1181d990610fde9086908590600401612887565b600060405180830381600087803b158015610ff857600080fd5b505af115801561100c573d6000803e3d6000fd5b505050507f4cf4a1fd341f7cd98a4834e3f2a4cf75af4acee229cfe76ab4b421671679b1418383604051610b01929190612917565b611049611f50565b6000611054836112ae565b80519091506110755760405162461bcd60e51b815260040161040590612863565b61ffff82161561119d5761271061ffff831611156110d55760405162461bcd60e51b815260206004820152601d60248201527f696e76616c6964206c69717569646174696f6e207468726573686f6c640000006044820152606401610405565b806040015161ffff168261ffff16101561114e5760405162461bcd60e51b815260206004820152603460248201527f6c69717569646174696f6e207468726573686f6c6420736d616c6c657220746860448201527330b71031b7b63630ba32b930b6103330b1ba37b960611b6064820152608401610405565b61271061ffff16612710826080015161ffff168461ffff166111709190612977565b61117a9190612996565b11156111985760405162461bcd60e51b8152600401610405906129b8565b6111f3565b604081015161ffff16156111f35760405162461bcd60e51b815260206004820152601a60248201527f636f6c6c61746572616c20666163746f72206e6f74207a65726f0000000000006044820152606401610405565b61ffff82166060820152604051633a1181d960e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690633a1181d99061124b9086908590600401612887565b600060405180830381600087803b15801561126557600080fd5b505af1158015611279573d6000803e3d6000fd5b505050507f6c42639781cb1a85205c1b87aa8e80fc30f1e62c92c44b68f2a38743718e57f18383604051610b01929190612917565b604080516101c081018252600080825260208201819052818301819052606082018190526080820181905260a0820181905260c0820181905260e08201819052610100820181905261012082018190526101408201819052610160820181905261018082018190526101a08201529051632d1046a960e11b81526001600160a01b0383811660048301527f00000000000000000000000000000000000000000000000000000000000000001690635a208d52906024016101c060405180830381865afa158015611382573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113a69190612ac7565b92915050565b6113b4611f50565b6113be6000612487565b565b60015433906001600160a01b0316811461142e5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608401610405565b61143781612487565b50565b611442611ef3565b600061144d836112ae565b805190915061146e5760405162461bcd60e51b815260040161040590612863565b8060c00151156114cc5760405162461bcd60e51b815260206004820152602360248201527f63616e6e6f742073657420626f72726f772070617573656420666f722070546f60448201526235b2b760e91b6064820152608401610405565b6114d68183611ff6565b604051633a1181d960e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690633a1181d9906115249086908590600401612887565b600060405180830381600087803b15801561153e57600080fd5b505af1158015611552573d6000803e3d6000fd5b50505050600080516020612cd38339815191528383604051610b019291906128de565b61157d611f50565b6000611588836112ae565b80519091506115a95760405162461bcd60e51b815260040161040590612863565b61271061ffff831611156115f85760405162461bcd60e51b815260206004820152601660248201527534b73b30b634b2103932b9b2b93b32903330b1ba37b960511b6044820152606401610405565b604051639198e51560e01b81526001600160a01b0384811660048301527f00000000000000000000000000000000000000000000000000000000000000001690639198e51590602401600060405180830381600087803b15801561165b57600080fd5b505af115801561166f573d6000803e3d6000fd5b50505061ffff831660a083015250604051633a1181d960e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690633a1181d9906116cb9086908590600401612887565b600060405180830381600087803b1580156116e557600080fd5b505af11580156116f9573d6000803e3d6000fd5b505050507f9dd9e80184b8d31052f0964bcf5a4f6cd43183301402f6af6bf582d7220f85f38383604051610b01929190612917565b611736611f50565b600280546001600160a01b0319166001600160a01b0383169081179091556040519081527fe6c09ffe4572dc9ceaa5ddde4ae41befa655d6fdfe8052077af0970f700e942e9060200160405180910390a150565b611792611ef3565b8060005b818110156105365760008484838181106117b2576117b261284d565b6117c89260206040909202019081019150612568565b905060008585848181106117de576117de61284d565b90506040020160200135905060006117f5836112ae565b80519091506118165760405162461bcd60e51b815260040161040590612863565b6101608101829052604051633a1181d960e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690633a1181d99061186c9086908590600401612887565b600060405180830381600087803b15801561188657600080fd5b505af115801561189a573d6000803e3d6000fd5b5050604080516001600160a01b0387168152602081018690527f1d8cf8a9546211e098d6e8d0e49cad5423bb77a20bdd0f29535d893ac5580acd935001905060405180910390a1505050600101611796565b6118f4611f50565b60006118ff826112ae565b80519091506119205760405162461bcd60e51b815260040161040590612863565b61192981611faa565b8015611939575061193981611fe4565b6119725760405162461bcd60e51b815260206004820152600a6024820152691b9bdd081c185d5cd95960b21b6044820152606401610405565b60a081015161ffff16612710146119c45760405162461bcd60e51b81526020600482015260166024820152750e4cae6cae4ecca40ccc2c6e8dee440dcdee840dac2f60531b6044820152606401610405565b604081015161ffff161580156119e05750606081015161ffff16155b6119fc5760405162461bcd60e51b815260040161040590612a15565b60405163b666d84b60e01b81526001600160a01b0383811660048301527f0000000000000000000000000000000000000000000000000000000000000000169063b666d84b90602401600060405180830381600087803b158015611a5f57600080fd5b505af1158015611a73573d6000803e3d6000fd5b50506040516001600160a01b03851681527f9710c341258431a6380fd1febe8985e6b6221e8398c287ea971f2ba85a6e1a1092506020019050610912565b611ab9611f50565b6000611ac4836112ae565b8051909150611ae55760405162461bcd60e51b815260040161040590612863565b611aef81836124a0565b604051633a1181d960e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690633a1181d990611b3d9086908590600401612887565b600060405180830381600087803b158015611b5757600080fd5b505af1158015611b6b573d6000803e3d6000fd5b5050604080516001600160a01b0387168152606060208201819052600890820152673a3930b739b332b960c11b608082015285151591810191909152600080516020612cd3833981519152925060a0019050610b01565b611bca611f50565b610536848460008585600161201e565b611be2611f50565b6000611bed836112ae565b8051909150611c0e5760405162461bcd60e51b815260040161040590612863565b604051639198e51560e01b81526001600160a01b0384811660048301527f00000000000000000000000000000000000000000000000000000000000000001690639198e51590602401600060405180830381600087803b158015611c7157600080fd5b505af1158015611c85573d6000803e3d6000fd5b5050506001600160a01b03808416610140840152604051633a1181d960e01b81527f00000000000000000000000000000000000000000000000000000000000000009091169150633a1181d990611ce29086908590600401612887565b600060405180830381600087803b158015611cfc57600080fd5b505af1158015611d10573d6000803e3d6000fd5b5050604080516001600160a01b038088168252861660208201527f06b044e42af5173491d5dcc4a14c8b01f4d30526c52da1733ff4de51d3b14dcc9350019050610b01565b611d5d611f50565b600180546001600160a01b0383166001600160a01b03199091168117909155611d8e6000546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b611dce611ef3565b6000611dd9836112ae565b8051909150611dfa5760405162461bcd60e51b815260040161040590612863565b611e048183611fbc565b604051633a1181d960e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690633a1181d990611e529086908590600401612887565b600060405180830381600087803b158015611e6c57600080fd5b505af1158015611e80573d6000803e3d6000fd5b50505050600080516020612cd38339815191528383604051610b019291906128a5565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000546001600160a01b0316331480611f1657506002546001600160a01b031633145b6113be5760405162461bcd60e51b815260206004820152600b60248201526a08585d5d1a1bdc9a5e995960aa1b6044820152606401610405565b6000546001600160a01b031633146113be5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610405565b602081015160009060011615156113a6565b6000611fc7826124c8565b602093909301805160fe1660ff94851690921b9093161790915250565b602081015160009060021615156113a6565b6001612001826124c8565b602093909301805160fd1660ff94851690921b9093161790915250565b6000612029876112ae565b80519091501561206c5760405162461bcd60e51b815260206004820152600e60248201526d185b1c9958591e481b1a5cdd195960921b6044820152606401610405565b8060e00151156120b15760405162461bcd60e51b815260206004820152601060248201526f185b1c9958591e4819195b1a5cdd195960821b6044820152606401610405565b866001600160a01b0316866001600160a01b03166338d52e0f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156120f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061211d9190612944565b6001600160a01b0316146121655760405162461bcd60e51b815260206004820152600f60248201526e1b5a5cdb585d18da081b585c9ad95d608a1b6044820152606401610405565b8161221e57866001600160a01b0316856001600160a01b03166338d52e0f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121d69190612944565b6001600160a01b03161461221e5760405162461bcd60e51b815260206004820152600f60248201526e1b5a5cdb585d18da081b585c9ad95d608a1b6044820152606401610405565b61271061ffff8416111561226d5760405162461bcd60e51b815260206004820152601660248201527534b73b30b634b2103932b9b2b93b32903330b1ba37b960511b6044820152606401610405565b6000876001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156122ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122d19190612bc4565b905060128160ff1611156123275760405162461bcd60e51b815260206004820152601a60248201527f6e6f6e7374616e6461726420746f6b656e20646563696d616c730000000000006044820152606401610405565b600182526001600160a01b03808816610100840152851661014083015261ffff841660a083015261235981600a612cc3565b6101a0830152821561238657600160c08301819052612379908390611ff6565b6001610180830152612397565b6001600160a01b0386166101208301525b60405163616613d360e11b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063c2cc27a6906123e5908b908690600401612887565b600060405180830381600087803b1580156123ff57600080fd5b505af1158015612413573d6000803e3d6000fd5b5050604080516001600160a01b038c811682528b811660208301528a8116828401528916606082015261ffff8816608082015286151560a082015290517f0a422e58b8aef621cb0dda9963617b8de1a129cce22be6cd6c3ccbf98591e1d093509081900360c0019150a15050505050505050565b600180546001600160a01b031916905561143781611ea3565b60026124ab826124c8565b602093909301805160fb1660ff94851690921b9093161790915250565b6000816124d65760006113a6565b600192915050565b600080602083850312156124f157600080fd5b823567ffffffffffffffff8082111561250957600080fd5b818501915085601f83011261251d57600080fd5b81358181111561252c57600080fd5b8660208260061b850101111561254157600080fd5b60209290920196919550909350505050565b6001600160a01b038116811461143757600080fd5b60006020828403121561257a57600080fd5b813561258581612553565b9392505050565b61ffff8116811461143757600080fd5b600080600080600060a086880312156125b457600080fd5b85356125bf81612553565b945060208601356125cf81612553565b935060408601356125df81612553565b925060608601356125ef81612553565b915060808601356125ff8161258c565b809150509295509295909350565b6000806040838503121561262057600080fd5b823561262b81612553565b9150602083013561263b8161258c565b809150509250929050565b6000806000806080858703121561265c57600080fd5b843561266781612553565b935060208501356126778161258c565b925060408501356126878161258c565b915060608501356126978161258c565b939692955090935050565b80511515825260208101516126bc602084018260ff169052565b5060408101516126d2604084018261ffff169052565b5060608101516126e8606084018261ffff169052565b5060808101516126fe608084018261ffff169052565b5060a081015161271460a084018261ffff169052565b5060c081015161272860c084018215159052565b5060e081015161273c60e084018215159052565b50610100818101516001600160a01b0390811691840191909152610120808301518216908401526101408083015190911690830152610160808201519083015261018080820151908301526101a090810151910152565b6101c081016113a682846126a2565b801515811461143757600080fd5b600080604083850312156127c357600080fd5b82356127ce81612553565b9150602083013561263b816127a2565b600080600080608085870312156127f457600080fd5b84356127ff81612553565b9350602085013561280f81612553565b9250604085013561268781612553565b6000806040838503121561283257600080fd5b823561283d81612553565b9150602083013561263b81612553565b634e487b7160e01b600052603260045260246000fd5b6020808252600a90820152691b9bdd081b1a5cdd195960b21b604082015260600190565b6001600160a01b03831681526101e0810161258560208301846126a2565b6001600160a01b0392909216825260606020830181905260069083015265737570706c7960d01b60808301521515604082015260a00190565b6001600160a01b0392909216825260606020830181905260069083015265626f72726f7760d01b60808301521515604082015260a00190565b6001600160a01b0392909216825261ffff16602082015260400190565b805161293f81612553565b919050565b60006020828403121561295657600080fd5b815161258581612553565b634e487b7160e01b600052601160045260246000fd5b600081600019048311821515161561299157612991612961565b500290565b6000826129b357634e487b7160e01b600052601260045260246000fd5b500490565b6020808252603a908201527f6c69717569646174696f6e207468726573686f6c64202a206c6971756964617460408201527f696f6e20626f6e7573206c6172676572207468616e2031303025000000000000606082015260800190565b60208082526033908201527f636f6c6c61746572616c20666163746f72206f72206c69717569646174696f6e604082015272207468726573686f6c64206e6f74207a65726f60681b606082015260800190565b6040516101c0810167ffffffffffffffff81118282101715612a9a57634e487b7160e01b600052604160045260246000fd5b60405290565b805161293f816127a2565b805160ff8116811461293f57600080fd5b805161293f8161258c565b60006101c08284031215612ada57600080fd5b612ae2612a68565b612aeb83612aa0565b8152612af960208401612aab565b6020820152612b0a60408401612abc565b6040820152612b1b60608401612abc565b6060820152612b2c60808401612abc565b6080820152612b3d60a08401612abc565b60a0820152612b4e60c08401612aa0565b60c0820152612b5f60e08401612aa0565b60e0820152610100612b72818501612934565b90820152610120612b84848201612934565b90820152610140612b96848201612934565b90820152610160838101519082015261018080840151908201526101a0928301519281019290925250919050565b600060208284031215612bd657600080fd5b61258582612aab565b600181815b80851115612c1a578160001904821115612c0057612c00612961565b80851615612c0d57918102915b93841c9390800290612be4565b509250929050565b600082612c31575060016113a6565b81612c3e575060006113a6565b8160018114612c545760028114612c5e57612c7a565b60019150506113a6565b60ff841115612c6f57612c6f612961565b50506001821b6113a6565b5060208310610133831016604e8410600b8410161715612c9d575081810a6113a6565b612ca78383612bdf565b8060001904821115612cbb57612cbb612961565b029392505050565b600061258560ff841683612c2256feaab441f1961bb53405fbc15a2bbb0f49e2619c2b124e67699da6380b42d59942a264697066735822122087aeca640af389d3ed5e47843ea00adf8b4938de5991f7e280515d3db53e8adf64736f6c634300080a00330000000000000000000000009cf2c7dd1bb947e398f9e12000f81656e4d65adb

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101735760003560e01c80637aab4f11116100de578063ae36691711610097578063e30c397811610071578063e30c39781461032f578063ee715e3a14610340578063f2fde38b14610353578063f440b61e1461036657600080fd5b8063ae366917146102f6578063ceceb02314610309578063df310df81461031c57600080fd5b80637aab4f11146102725780638598fae8146102855780638a0dac4a146102985780638da5cb5b146102ab5780639b6899db146102bc578063aaa05594146102e357600080fd5b8063366f1fbb11610130578063366f1fbb146101ec5780633ab2b69a146101ff578063452a9320146102125780635a208d5214610242578063715018a61461026257806379ba50971461026a57600080fd5b80630723cf18146101785780630de9de6b1461018d5780631474e055146101a05780631f650d43146101b35780632c9c6a81146101c657806331d97ce2146101d9575b600080fd5b61018b6101863660046124de565b610379565b005b61018b61019b366004612568565b61053c565b61018b6101ae36600461259c565b610746565b61018b6101c1366004612568565b610764565b61018b6101d436600461260d565b61091e565b61018b6101e7366004612646565b610b0e565b61018b6101fa36600461260d565b610e7c565b61018b61020d36600461260d565b611041565b600254610225906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b610255610250366004612568565b6112ae565b6040516102399190612793565b61018b6113ac565b61018b6113c0565b61018b6102803660046127b0565b61143a565b61018b61029336600461260d565b611575565b61018b6102a6366004612568565b61172e565b6000546001600160a01b0316610225565b6102257f0000000000000000000000009cf2c7dd1bb947e398f9e12000f81656e4d65adb81565b61018b6102f13660046124de565b61178a565b61018b610304366004612568565b6118ec565b61018b6103173660046127b0565b611ab1565b61018b61032a3660046127de565b611bc2565b6001546001600160a01b0316610225565b61018b61034e36600461281f565b611bda565b61018b610361366004612568565b611d55565b61018b6103743660046127b0565b611dc6565b610381611ef3565b8060005b818110156105365760008484838181106103a1576103a161284d565b6103b79260206040909202019081019150612568565b905060008585848181106103cd576103cd61284d565b90506040020160200135905060006103e4836112ae565b805190915061040e5760405162461bcd60e51b815260040161040590612863565b60405180910390fd5b8060c00151156104605760405162461bcd60e51b815260206004820181905260248201527f63616e6e6f742073657420626f72726f772063617020666f722070546f6b656e6044820152606401610405565b6101808101829052604051633a1181d960e01b81526001600160a01b037f0000000000000000000000009cf2c7dd1bb947e398f9e12000f81656e4d65adb1690633a1181d9906104b69086908590600401612887565b600060405180830381600087803b1580156104d057600080fd5b505af11580156104e4573d6000803e3d6000fd5b5050604080516001600160a01b0387168152602081018690527f5c3e947e8b26df9badd8a743328d9689b8d650ca70702d0fe8c4cab56ff9a816935001905060405180910390a1505050600101610385565b50505050565b610544611f50565b600061054f826112ae565b80519091506105705760405162461bcd60e51b815260040161040590612863565b61057981611faa565b6105b157610588816001611fbc565b600080516020612cd38339815191528260016040516105a89291906128a5565b60405180910390a15b6105ba81611fe4565b6105f2576105c9816001611ff6565b600080516020612cd38339815191528260016040516105e99291906128de565b60405180910390a15b60a081015161ffff16612710146106c257604051639198e51560e01b81526001600160a01b0383811660048301527f0000000000000000000000009cf2c7dd1bb947e398f9e12000f81656e4d65adb1690639198e51590602401600060405180830381600087803b15801561066657600080fd5b505af115801561067a573d6000803e3d6000fd5b505061271060a084018190526040517f9dd9e80184b8d31052f0964bcf5a4f6cd43183301402f6af6bf582d7220f85f393506106b99250859190612917565b60405180910390a15b604051633a1181d960e01b81526001600160a01b037f0000000000000000000000009cf2c7dd1bb947e398f9e12000f81656e4d65adb1690633a1181d9906107109085908590600401612887565b600060405180830381600087803b15801561072a57600080fd5b505af115801561073e573d6000803e3d6000fd5b505050505050565b61074e611f50565b61075d8585858585600061201e565b5050505050565b61076c611ef3565b806001600160a01b0316639816f4736040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107aa573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ce9190612944565b5060006107da826112ae565b80519091506107fb5760405162461bcd60e51b815260040161040590612863565b8060c00151156108405760405162461bcd60e51b815260206004820152601060248201526f30b63932b0b23c903090382a37b5b2b760811b6044820152606401610405565b600160c08201819052610854908290611ff6565b6001610180820152604051633a1181d960e01b81526001600160a01b037f0000000000000000000000009cf2c7dd1bb947e398f9e12000f81656e4d65adb1690633a1181d9906108aa9085908590600401612887565b600060405180830381600087803b1580156108c457600080fd5b505af11580156108d8573d6000803e3d6000fd5b50506040516001600160a01b03851681527f224a8ad8cc54dff54c72759b1bf650a71137993a18df9deac6f8e844b8c6e32a925060200190505b60405180910390a15050565b610926611f50565b6000610931836112ae565b80519091506109525760405162461bcd60e51b815260040161040590612863565b61ffff821615610a0e5761271061ffff831611801561097757506130d461ffff831611155b6109bf5760405162461bcd60e51b8152602060048201526019602482015278696e76616c6964206c69717569646174696f6e20626f6e757360381b6044820152606401610405565b61271061ffff166127108361ffff16836060015161ffff166109e19190612977565b6109eb9190612996565b1115610a095760405162461bcd60e51b8152600401610405906129b8565b610a46565b604081015161ffff16158015610a2a5750606081015161ffff16155b610a465760405162461bcd60e51b815260040161040590612a15565b61ffff82166080820152604051633a1181d960e01b81526001600160a01b037f0000000000000000000000009cf2c7dd1bb947e398f9e12000f81656e4d65adb1690633a1181d990610a9e9086908590600401612887565b600060405180830381600087803b158015610ab857600080fd5b505af1158015610acc573d6000803e3d6000fd5b505050507f8b6d1a3855943f585bdcfaff3cfd4b1a0f5eefc48baba05f0294427535693e5e8383604051610b01929190612917565b60405180910390a1505050565b610b16611f50565b6000610b21856112ae565b8051909150610b425760405162461bcd60e51b815260040161040590612863565b604081015161ffff16158015610b5e5750606081015161ffff16155b8015610b705750608081015161ffff16155b610bb15760405162461bcd60e51b8152602060048201526012602482015271185b1c9958591e4818dbdb999a59dd5c995960721b6044820152606401610405565b60008461ffff16118015610bcb575061232861ffff851611155b610c135760405162461bcd60e51b815260206004820152601960248201527834b73b30b634b21031b7b63630ba32b930b6103330b1ba37b960391b6044820152606401610405565b60008361ffff16118015610c2d575061271061ffff841611155b8015610c4157508361ffff168361ffff1610155b610c8d5760405162461bcd60e51b815260206004820152601d60248201527f696e76616c6964206c69717569646174696f6e207468726573686f6c640000006044820152606401610405565b61271061ffff8316118015610ca857506130d461ffff831611155b610cf05760405162461bcd60e51b8152602060048201526019602482015278696e76616c6964206c69717569646174696f6e20626f6e757360381b6044820152606401610405565b61271080610d0561ffff858116908716612977565b610d0f9190612996565b1115610d2d5760405162461bcd60e51b8152600401610405906129b8565b61ffff8085166040808401919091528482166060840152908316608083015251633a1181d960e01b81526001600160a01b037f0000000000000000000000009cf2c7dd1bb947e398f9e12000f81656e4d65adb1690633a1181d990610d989088908590600401612887565b600060405180830381600087803b158015610db257600080fd5b505af1158015610dc6573d6000803e3d6000fd5b505050507f4cf4a1fd341f7cd98a4834e3f2a4cf75af4acee229cfe76ab4b421671679b1418585604051610dfb929190612917565b60405180910390a17f6c42639781cb1a85205c1b87aa8e80fc30f1e62c92c44b68f2a38743718e57f18584604051610e34929190612917565b60405180910390a17f8b6d1a3855943f585bdcfaff3cfd4b1a0f5eefc48baba05f0294427535693e5e8583604051610e6d929190612917565b60405180910390a15050505050565b610e84611f50565b6000610e8f836112ae565b8051909150610eb05760405162461bcd60e51b815260040161040590612863565b61ffff821615610f845761232861ffff83161115610f0c5760405162461bcd60e51b815260206004820152601960248201527834b73b30b634b21031b7b63630ba32b930b6103330b1ba37b960391b6044820152606401610405565b806060015161ffff168261ffff161115610f845760405162461bcd60e51b815260206004820152603360248201527f636f6c6c61746572616c20666163746f72206c6172676572207468616e206c696044820152721c5d5a59185d1a5bdb881d1a1c995cda1bdb19606a1b6064820152608401610405565b61ffff821660408083019190915251633a1181d960e01b81526001600160a01b037f0000000000000000000000009cf2c7dd1bb947e398f9e12000f81656e4d65adb1690633a1181d990610fde9086908590600401612887565b600060405180830381600087803b158015610ff857600080fd5b505af115801561100c573d6000803e3d6000fd5b505050507f4cf4a1fd341f7cd98a4834e3f2a4cf75af4acee229cfe76ab4b421671679b1418383604051610b01929190612917565b611049611f50565b6000611054836112ae565b80519091506110755760405162461bcd60e51b815260040161040590612863565b61ffff82161561119d5761271061ffff831611156110d55760405162461bcd60e51b815260206004820152601d60248201527f696e76616c6964206c69717569646174696f6e207468726573686f6c640000006044820152606401610405565b806040015161ffff168261ffff16101561114e5760405162461bcd60e51b815260206004820152603460248201527f6c69717569646174696f6e207468726573686f6c6420736d616c6c657220746860448201527330b71031b7b63630ba32b930b6103330b1ba37b960611b6064820152608401610405565b61271061ffff16612710826080015161ffff168461ffff166111709190612977565b61117a9190612996565b11156111985760405162461bcd60e51b8152600401610405906129b8565b6111f3565b604081015161ffff16156111f35760405162461bcd60e51b815260206004820152601a60248201527f636f6c6c61746572616c20666163746f72206e6f74207a65726f0000000000006044820152606401610405565b61ffff82166060820152604051633a1181d960e01b81526001600160a01b037f0000000000000000000000009cf2c7dd1bb947e398f9e12000f81656e4d65adb1690633a1181d99061124b9086908590600401612887565b600060405180830381600087803b15801561126557600080fd5b505af1158015611279573d6000803e3d6000fd5b505050507f6c42639781cb1a85205c1b87aa8e80fc30f1e62c92c44b68f2a38743718e57f18383604051610b01929190612917565b604080516101c081018252600080825260208201819052818301819052606082018190526080820181905260a0820181905260c0820181905260e08201819052610100820181905261012082018190526101408201819052610160820181905261018082018190526101a08201529051632d1046a960e11b81526001600160a01b0383811660048301527f0000000000000000000000009cf2c7dd1bb947e398f9e12000f81656e4d65adb1690635a208d52906024016101c060405180830381865afa158015611382573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113a69190612ac7565b92915050565b6113b4611f50565b6113be6000612487565b565b60015433906001600160a01b0316811461142e5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608401610405565b61143781612487565b50565b611442611ef3565b600061144d836112ae565b805190915061146e5760405162461bcd60e51b815260040161040590612863565b8060c00151156114cc5760405162461bcd60e51b815260206004820152602360248201527f63616e6e6f742073657420626f72726f772070617573656420666f722070546f60448201526235b2b760e91b6064820152608401610405565b6114d68183611ff6565b604051633a1181d960e01b81526001600160a01b037f0000000000000000000000009cf2c7dd1bb947e398f9e12000f81656e4d65adb1690633a1181d9906115249086908590600401612887565b600060405180830381600087803b15801561153e57600080fd5b505af1158015611552573d6000803e3d6000fd5b50505050600080516020612cd38339815191528383604051610b019291906128de565b61157d611f50565b6000611588836112ae565b80519091506115a95760405162461bcd60e51b815260040161040590612863565b61271061ffff831611156115f85760405162461bcd60e51b815260206004820152601660248201527534b73b30b634b2103932b9b2b93b32903330b1ba37b960511b6044820152606401610405565b604051639198e51560e01b81526001600160a01b0384811660048301527f0000000000000000000000009cf2c7dd1bb947e398f9e12000f81656e4d65adb1690639198e51590602401600060405180830381600087803b15801561165b57600080fd5b505af115801561166f573d6000803e3d6000fd5b50505061ffff831660a083015250604051633a1181d960e01b81526001600160a01b037f0000000000000000000000009cf2c7dd1bb947e398f9e12000f81656e4d65adb1690633a1181d9906116cb9086908590600401612887565b600060405180830381600087803b1580156116e557600080fd5b505af11580156116f9573d6000803e3d6000fd5b505050507f9dd9e80184b8d31052f0964bcf5a4f6cd43183301402f6af6bf582d7220f85f38383604051610b01929190612917565b611736611f50565b600280546001600160a01b0319166001600160a01b0383169081179091556040519081527fe6c09ffe4572dc9ceaa5ddde4ae41befa655d6fdfe8052077af0970f700e942e9060200160405180910390a150565b611792611ef3565b8060005b818110156105365760008484838181106117b2576117b261284d565b6117c89260206040909202019081019150612568565b905060008585848181106117de576117de61284d565b90506040020160200135905060006117f5836112ae565b80519091506118165760405162461bcd60e51b815260040161040590612863565b6101608101829052604051633a1181d960e01b81526001600160a01b037f0000000000000000000000009cf2c7dd1bb947e398f9e12000f81656e4d65adb1690633a1181d99061186c9086908590600401612887565b600060405180830381600087803b15801561188657600080fd5b505af115801561189a573d6000803e3d6000fd5b5050604080516001600160a01b0387168152602081018690527f1d8cf8a9546211e098d6e8d0e49cad5423bb77a20bdd0f29535d893ac5580acd935001905060405180910390a1505050600101611796565b6118f4611f50565b60006118ff826112ae565b80519091506119205760405162461bcd60e51b815260040161040590612863565b61192981611faa565b8015611939575061193981611fe4565b6119725760405162461bcd60e51b815260206004820152600a6024820152691b9bdd081c185d5cd95960b21b6044820152606401610405565b60a081015161ffff16612710146119c45760405162461bcd60e51b81526020600482015260166024820152750e4cae6cae4ecca40ccc2c6e8dee440dcdee840dac2f60531b6044820152606401610405565b604081015161ffff161580156119e05750606081015161ffff16155b6119fc5760405162461bcd60e51b815260040161040590612a15565b60405163b666d84b60e01b81526001600160a01b0383811660048301527f0000000000000000000000009cf2c7dd1bb947e398f9e12000f81656e4d65adb169063b666d84b90602401600060405180830381600087803b158015611a5f57600080fd5b505af1158015611a73573d6000803e3d6000fd5b50506040516001600160a01b03851681527f9710c341258431a6380fd1febe8985e6b6221e8398c287ea971f2ba85a6e1a1092506020019050610912565b611ab9611f50565b6000611ac4836112ae565b8051909150611ae55760405162461bcd60e51b815260040161040590612863565b611aef81836124a0565b604051633a1181d960e01b81526001600160a01b037f0000000000000000000000009cf2c7dd1bb947e398f9e12000f81656e4d65adb1690633a1181d990611b3d9086908590600401612887565b600060405180830381600087803b158015611b5757600080fd5b505af1158015611b6b573d6000803e3d6000fd5b5050604080516001600160a01b0387168152606060208201819052600890820152673a3930b739b332b960c11b608082015285151591810191909152600080516020612cd3833981519152925060a0019050610b01565b611bca611f50565b610536848460008585600161201e565b611be2611f50565b6000611bed836112ae565b8051909150611c0e5760405162461bcd60e51b815260040161040590612863565b604051639198e51560e01b81526001600160a01b0384811660048301527f0000000000000000000000009cf2c7dd1bb947e398f9e12000f81656e4d65adb1690639198e51590602401600060405180830381600087803b158015611c7157600080fd5b505af1158015611c85573d6000803e3d6000fd5b5050506001600160a01b03808416610140840152604051633a1181d960e01b81527f0000000000000000000000009cf2c7dd1bb947e398f9e12000f81656e4d65adb9091169150633a1181d990611ce29086908590600401612887565b600060405180830381600087803b158015611cfc57600080fd5b505af1158015611d10573d6000803e3d6000fd5b5050604080516001600160a01b038088168252861660208201527f06b044e42af5173491d5dcc4a14c8b01f4d30526c52da1733ff4de51d3b14dcc9350019050610b01565b611d5d611f50565b600180546001600160a01b0383166001600160a01b03199091168117909155611d8e6000546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b611dce611ef3565b6000611dd9836112ae565b8051909150611dfa5760405162461bcd60e51b815260040161040590612863565b611e048183611fbc565b604051633a1181d960e01b81526001600160a01b037f0000000000000000000000009cf2c7dd1bb947e398f9e12000f81656e4d65adb1690633a1181d990611e529086908590600401612887565b600060405180830381600087803b158015611e6c57600080fd5b505af1158015611e80573d6000803e3d6000fd5b50505050600080516020612cd38339815191528383604051610b019291906128a5565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000546001600160a01b0316331480611f1657506002546001600160a01b031633145b6113be5760405162461bcd60e51b815260206004820152600b60248201526a08585d5d1a1bdc9a5e995960aa1b6044820152606401610405565b6000546001600160a01b031633146113be5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610405565b602081015160009060011615156113a6565b6000611fc7826124c8565b602093909301805160fe1660ff94851690921b9093161790915250565b602081015160009060021615156113a6565b6001612001826124c8565b602093909301805160fd1660ff94851690921b9093161790915250565b6000612029876112ae565b80519091501561206c5760405162461bcd60e51b815260206004820152600e60248201526d185b1c9958591e481b1a5cdd195960921b6044820152606401610405565b8060e00151156120b15760405162461bcd60e51b815260206004820152601060248201526f185b1c9958591e4819195b1a5cdd195960821b6044820152606401610405565b866001600160a01b0316866001600160a01b03166338d52e0f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156120f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061211d9190612944565b6001600160a01b0316146121655760405162461bcd60e51b815260206004820152600f60248201526e1b5a5cdb585d18da081b585c9ad95d608a1b6044820152606401610405565b8161221e57866001600160a01b0316856001600160a01b03166338d52e0f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121d69190612944565b6001600160a01b03161461221e5760405162461bcd60e51b815260206004820152600f60248201526e1b5a5cdb585d18da081b585c9ad95d608a1b6044820152606401610405565b61271061ffff8416111561226d5760405162461bcd60e51b815260206004820152601660248201527534b73b30b634b2103932b9b2b93b32903330b1ba37b960511b6044820152606401610405565b6000876001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156122ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122d19190612bc4565b905060128160ff1611156123275760405162461bcd60e51b815260206004820152601a60248201527f6e6f6e7374616e6461726420746f6b656e20646563696d616c730000000000006044820152606401610405565b600182526001600160a01b03808816610100840152851661014083015261ffff841660a083015261235981600a612cc3565b6101a0830152821561238657600160c08301819052612379908390611ff6565b6001610180830152612397565b6001600160a01b0386166101208301525b60405163616613d360e11b81526001600160a01b037f0000000000000000000000009cf2c7dd1bb947e398f9e12000f81656e4d65adb169063c2cc27a6906123e5908b908690600401612887565b600060405180830381600087803b1580156123ff57600080fd5b505af1158015612413573d6000803e3d6000fd5b5050604080516001600160a01b038c811682528b811660208301528a8116828401528916606082015261ffff8816608082015286151560a082015290517f0a422e58b8aef621cb0dda9963617b8de1a129cce22be6cd6c3ccbf98591e1d093509081900360c0019150a15050505050505050565b600180546001600160a01b031916905561143781611ea3565b60026124ab826124c8565b602093909301805160fb1660ff94851690921b9093161790915250565b6000816124d65760006113a6565b600192915050565b600080602083850312156124f157600080fd5b823567ffffffffffffffff8082111561250957600080fd5b818501915085601f83011261251d57600080fd5b81358181111561252c57600080fd5b8660208260061b850101111561254157600080fd5b60209290920196919550909350505050565b6001600160a01b038116811461143757600080fd5b60006020828403121561257a57600080fd5b813561258581612553565b9392505050565b61ffff8116811461143757600080fd5b600080600080600060a086880312156125b457600080fd5b85356125bf81612553565b945060208601356125cf81612553565b935060408601356125df81612553565b925060608601356125ef81612553565b915060808601356125ff8161258c565b809150509295509295909350565b6000806040838503121561262057600080fd5b823561262b81612553565b9150602083013561263b8161258c565b809150509250929050565b6000806000806080858703121561265c57600080fd5b843561266781612553565b935060208501356126778161258c565b925060408501356126878161258c565b915060608501356126978161258c565b939692955090935050565b80511515825260208101516126bc602084018260ff169052565b5060408101516126d2604084018261ffff169052565b5060608101516126e8606084018261ffff169052565b5060808101516126fe608084018261ffff169052565b5060a081015161271460a084018261ffff169052565b5060c081015161272860c084018215159052565b5060e081015161273c60e084018215159052565b50610100818101516001600160a01b0390811691840191909152610120808301518216908401526101408083015190911690830152610160808201519083015261018080820151908301526101a090810151910152565b6101c081016113a682846126a2565b801515811461143757600080fd5b600080604083850312156127c357600080fd5b82356127ce81612553565b9150602083013561263b816127a2565b600080600080608085870312156127f457600080fd5b84356127ff81612553565b9350602085013561280f81612553565b9250604085013561268781612553565b6000806040838503121561283257600080fd5b823561283d81612553565b9150602083013561263b81612553565b634e487b7160e01b600052603260045260246000fd5b6020808252600a90820152691b9bdd081b1a5cdd195960b21b604082015260600190565b6001600160a01b03831681526101e0810161258560208301846126a2565b6001600160a01b0392909216825260606020830181905260069083015265737570706c7960d01b60808301521515604082015260a00190565b6001600160a01b0392909216825260606020830181905260069083015265626f72726f7760d01b60808301521515604082015260a00190565b6001600160a01b0392909216825261ffff16602082015260400190565b805161293f81612553565b919050565b60006020828403121561295657600080fd5b815161258581612553565b634e487b7160e01b600052601160045260246000fd5b600081600019048311821515161561299157612991612961565b500290565b6000826129b357634e487b7160e01b600052601260045260246000fd5b500490565b6020808252603a908201527f6c69717569646174696f6e207468726573686f6c64202a206c6971756964617460408201527f696f6e20626f6e7573206c6172676572207468616e2031303025000000000000606082015260800190565b60208082526033908201527f636f6c6c61746572616c20666163746f72206f72206c69717569646174696f6e604082015272207468726573686f6c64206e6f74207a65726f60681b606082015260800190565b6040516101c0810167ffffffffffffffff81118282101715612a9a57634e487b7160e01b600052604160045260246000fd5b60405290565b805161293f816127a2565b805160ff8116811461293f57600080fd5b805161293f8161258c565b60006101c08284031215612ada57600080fd5b612ae2612a68565b612aeb83612aa0565b8152612af960208401612aab565b6020820152612b0a60408401612abc565b6040820152612b1b60608401612abc565b6060820152612b2c60808401612abc565b6080820152612b3d60a08401612abc565b60a0820152612b4e60c08401612aa0565b60c0820152612b5f60e08401612aa0565b60e0820152610100612b72818501612934565b90820152610120612b84848201612934565b90820152610140612b96848201612934565b90820152610160838101519082015261018080840151908201526101a0928301519281019290925250919050565b600060208284031215612bd657600080fd5b61258582612aab565b600181815b80851115612c1a578160001904821115612c0057612c00612961565b80851615612c0d57918102915b93841c9390800290612be4565b509250929050565b600082612c31575060016113a6565b81612c3e575060006113a6565b8160018114612c545760028114612c5e57612c7a565b60019150506113a6565b60ff841115612c6f57612c6f612961565b50506001821b6113a6565b5060208310610133831016604e8410600b8410161715612c9d575081810a6113a6565b612ca78383612bdf565b8060001904821115612cbb57612cbb612961565b029392505050565b600061258560ff841683612c2256feaab441f1961bb53405fbc15a2bbb0f49e2619c2b124e67699da6380b42d59942a264697066735822122087aeca640af389d3ed5e47843ea00adf8b4938de5991f7e280515d3db53e8adf64736f6c634300080a0033

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

0000000000000000000000009cf2c7dd1bb947e398f9e12000f81656e4d65adb

-----Decoded View---------------
Arg [0] : apeFinance_ (address): 0x9Cf2c7dD1bB947e398f9e12000f81656e4d65adB

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000009cf2c7dd1bb947e398f9e12000f81656e4d65adb


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

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

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