false
true
0

Contract Address Details

0x4E988b163AaB47FaE182EC32bFE3C4D5908f4f30

Token
MeFi (MEFI)
Creator
0x756639–797eec at 0x76c520–810cfb
Balance
125.185404501867618984 PLS ( )
Tokens
Fetching tokens...
Transactions
23 Transactions
Transfers
24 Transfers
Gas Used
1,318,607
Last Balance Update
26326716
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
This contract has been verified via Sourcify. View contract in Sourcify repository
Contract name:
MeFi




Optimization enabled
true
Compiler version
v0.8.19+commit.7dd6d404




Optimization runs
200
EVM Version
paris




Verified at
2026-04-11T20:01:56.713108Z

Constructor Arguments

000000000000000000000000982f3bdb963c0f09047c32b2283b5b87fa7b3d8d

Arg [0] (address) : 0x982f3bdb963c0f09047c32b2283b5b87fa7b3d8d

              

contracts/AER/MEFIV2.sol

// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

/**
 * @title MeFi (MEFI)
 *
 * WHAT IS MEFI?
 * Holding MEFI is a yield position. The eDAI/MEFI backing ratio only rises
 * over time — every MEFI redeemed later returns more eDAI than it cost to earn.
 *
 * THE CORE INVARIANT
 * backingRatio() = totalEdaiReserve / totalSupply()
 * This ratio can ONLY increase. Three mechanisms drive it up:
 *
 *   1. PROTOCOL FEE on depositTax()
 *      All eDAI enters reserve. MEFI minted = eDAI - fee.
 *      Fee eDAI permanently over-backs supply, ticking ratio up on every mint.
 *
 *   2. BUYBACK-AND-BURN via executeBuyback()
 *      PLS accumulated in receive() is swapped for MEFI on PulseX and burned.
 *      Supply drops, reserve unchanged -> ratio jumps permanently.
 *
 *   3. ARBITRAGE ENFORCEMENT via redeemForEDAI()
 *      If market price < backingRatio(), buying cheap MEFI and redeeming is
 *      instantly profitable. Permissionless enforcement keeps floor intact.
 *
 * SWEEP SAFETY
 * sweepSurplus() is capped to protocol fee accrued only.
 * Buyback gains are permanently locked as yield for MEFI holders.
 */

interface IERC20 {
    function transferFrom(address from, address to, uint256 amount) external returns (bool);
    function transfer(address to, uint256 amount) external returns (bool);
    function balanceOf(address account) external view returns (uint256);
    function approve(address spender, uint256 amount) external returns (bool);
}

interface IPulseXRouter {
    function WPLS() external pure returns (address);
    function swapExactTokensForTokens(
        uint256 amountIn,
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external returns (uint[] memory amounts);
    function swapExactETHForTokens(
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external payable returns (uint[] memory amounts);
    function getAmountsOut(uint amountIn, address[] memory path)
        external view returns (uint[] memory amounts);
}

contract MeFi {

    // ================================================================
    //  ERC20 METADATA — public constants so PulseX resolves correctly
    // ================================================================

    string public constant name     = "MeFi";
    string public constant symbol   = "MEFI";
    uint8  public constant decimals = 18;

    uint256 private _totalSupply;
    mapping(address => uint256) private _balances;
    mapping(address => mapping(address => uint256)) private _allowances;

    // ================================================================
    //  CONSTANTS
    // ================================================================

    address public constant EDAI   = 0xefD766cCb38EaF1dfd701853BFCe31359239F305;
    address public constant ROUTER = 0x165C3410fC91EF562C50559f7d2289fEbed552d9;
    address public constant DEAD   = 0x000000000000000000000000000000000000dEaD;

    uint256 public constant MAX_SUPPLY   = 100_000_000 * 1e18;
    uint256 public constant MIN_DEPOSIT  = 1e12;
    uint256 public constant MAX_FEE_BPS  = 1_000; // 10% hard cap on protocol fee
    uint256 public constant BPS_DENOM    = 10_000;

    // ================================================================
    //  ACCESS CONTROL
    // ================================================================

    address public owner;
    address public pendingOwner;
    mapping(address => bool) public authorizedMinters;

    // ================================================================
    //  RESERVE
    // ================================================================

    /// @notice Total eDAI held as reserve. Always >= totalSupply().
    uint256 public totalEdaiReserve;

    // ================================================================
    //  PROTOCOL FEE
    // ================================================================

    /// @notice Bps of eDAI withheld from minting on each depositTax().
    ///         Fee stays in reserve permanently, over-backing supply and
    ///         raising backingRatio() with every mint. Default 0.
    uint256 public protocolFeeBps;

    // ================================================================
    //  BUYBACK CONFIG
    // ================================================================

    /// @notice % of bought-back MEFI burned. Default 100%.
    uint256 public burnShareBps = BPS_DENOM;
    /// @notice Min PLS before executeBuyback() can trigger.
    uint256 public minBuybackThreshold = 1 ether;
    /// @notice If true, failed MEFI swap falls back to PLS -> eDAI -> reserve.
    bool    public fallbackToReserve = true;
    /// @notice Non-burned MEFI from buybacks goes here.
    address public jackpotAddress;

    // ================================================================
    //  ARBITRAGE CONFIG (from original — keep for DEX arbitrage)
    // ================================================================

    uint256 public arbitragePercent    = 0;         // Start disabled
    uint256 public minSpreadBps        = 200;
    uint256 public maxSpreadBps        = 1000;
    uint256 public maxArbitragePerTx   = 100 * 1e18;
    uint256 public minArbitrageAmount  = 5 * 1e18;

    // ================================================================
    //  STATS
    // ================================================================

    uint256 public totalMinted;
    uint256 public totalBurned;
    uint256 public totalRedeemed;
    uint256 public totalProtocolFeeAccrued;
    uint256 public totalSurplusSwept;
    uint256 public totalBuybackPLSSpent;
    uint256 public totalBuybackMefiBurned;
    uint256 public totalBuybackMefiToJackpot;
    uint256 public totalReserveBoostEdai;
    uint256 public totalArbitrageProfits;
    uint256 public totalArbitrageExecuted;
    uint256 public totalArbitrageSkipped;

    uint256 public immutable deployTime;

    // ================================================================
    //  GUARDS
    // ================================================================

    bool private _paused;
    bool private _locked;

    // ================================================================
    //  EVENTS
    // ================================================================

    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);
    event MinterSet(address indexed minter, bool authorized);
    event TaxDeposited(address indexed creator, uint256 edaiAmount, uint256 mefiMinted, uint256 feeEdai, uint256 newBackingRatio);
    event Redeemed(address indexed user, uint256 mefiAmount, uint256 edaiReceived);
    event BuybackExecuted(uint256 plsSpent, uint256 mefiBought, uint256 burned, uint256 toJackpot);
    event ReserveBoosted(uint256 plsSpent, uint256 edaiAdded, uint256 newBackingRatio);
    event BuybackFailed(string reason);
    event ArbitrageExecuted(bool isSell, uint256 edaiAmount, uint256 mefiAmount, uint256 profit, uint256 newBacking);
    event ArbitrageSkipped(string reason, uint256 edaiAmount);
    event SurplusSwept(address indexed treasury, uint256 edaiSwept, uint256 backingRatioAfter);
    event ProtocolFeeBpsSet(uint256 bps);
    event BurnShareBpsSet(uint256 bps);
    event JackpotAddressSet(address jackpot);
    event MinBuybackThresholdSet(uint256 threshold);
    event FallbackToReserveSet(bool enabled);
    event ArbitrageSettingsUpdated(uint256 percent, uint256 minSpread, uint256 maxSpread, uint256 maxSize, uint256 minAmount);
    event Paused(address account);
    event Unpaused(address account);
    event OwnershipTransferInitiated(address indexed previousOwner, address indexed newOwner);
    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
    event PLSReceived(uint256 amount, address indexed from);

    // ================================================================
    //  MODIFIERS
    // ================================================================

    modifier onlyOwner() {
        require(msg.sender == owner, "Not owner");
        _;
    }

    modifier onlyMinter() {
        require(authorizedMinters[msg.sender], "Not authorized minter");
        _;
    }

    modifier whenNotPaused() {
        require(!_paused, "Paused");
        _;
    }

    modifier nonReentrant() {
        require(!_locked, "Reentrant");
        _locked = true;
        _;
        _locked = false;
    }

    // ================================================================
    //  CONSTRUCTOR
    // ================================================================

    constructor(address _jackpotAddress) {
        owner         = msg.sender;
        jackpotAddress = _jackpotAddress;
        deployTime    = block.timestamp;
    }

    // ================================================================
    //  ERC20
    // ================================================================

    function totalSupply() public view returns (uint256) { return _totalSupply; }

    function balanceOf(address account) public view returns (uint256) { return _balances[account]; }

    function transfer(address to, uint256 amount) public whenNotPaused returns (bool) {
        _transfer(msg.sender, to, amount);
        return true;
    }

    function allowance(address tokenOwner, address spender) public view returns (uint256) {
        return _allowances[tokenOwner][spender];
    }

    function approve(address spender, uint256 amount) public returns (bool) {
        _approve(msg.sender, spender, amount);
        return true;
    }

    function transferFrom(address from, address to, uint256 amount) public whenNotPaused returns (bool) {
        _spendAllowance(from, msg.sender, amount);
        _transfer(from, to, amount);
        return true;
    }

    // ================================================================
    //  CORE: depositTax
    // ================================================================

    /**
     * @notice Accepts eDAI from an authorized minter and mints MEFI to creator.
     *         ALL eDAI enters totalEdaiReserve.
     *         MEFI minted = eDAIAmount - protocolFee.
     *         Fee stays in reserve as permanent over-backing.
     *
     *         Returns (mefiMinted, profitCaptured) — two values to maintain
     *         compatibility with ArtistFactory's IMefiContract interface.
     *
     * @param creator    Address to receive MEFI.
     * @param edaiAmount eDAI the caller is depositing (must approve first).
     */
    function depositTax(address creator, uint256 edaiAmount)
        external
        onlyMinter
        whenNotPaused
        nonReentrant
        returns (uint256 mefiMinted, uint256 profitCaptured)
    {
        require(creator    != address(0), "Invalid creator");
        require(edaiAmount >= MIN_DEPOSIT, "Below minimum");

        bool success = IERC20(EDAI).transferFrom(msg.sender, address(this), edaiAmount);
        require(success, "eDAI transfer failed");

        // All eDAI enters reserve
        totalEdaiReserve += edaiAmount;

        // Protocol fee: stays in reserve, not minted -> ratio increases
        uint256 feeEdai = 0;
        if (protocolFeeBps > 0) {
            feeEdai = (edaiAmount * protocolFeeBps) / BPS_DENOM;
            totalProtocolFeeAccrued += feeEdai;
        }

        mefiMinted = edaiAmount - feeEdai;
        require(mefiMinted > 0, "Nothing after fee");

        totalMinted += mefiMinted;
        _mint(creator, mefiMinted);

        emit TaxDeposited(creator, edaiAmount, mefiMinted, feeEdai, backingRatio());

        profitCaptured = 0; // reserved for future arbitrage integration
    }

    // ================================================================
    //  CORE: redeemForEDAI
    // ================================================================

    /**
     * @notice Burns MEFI and returns eDAI at the current backing rate.
     *         If market price < backingRatio() on PulseX, buying cheap MEFI
     *         and calling this is instantly profitable — permissionless arb
     *         enforcement keeps market price at or above the floor.
     */
    function redeemForEDAI(uint256 mefiAmount)
        external
        whenNotPaused
        nonReentrant
        returns (uint256 edaiAmount)
    {
        require(mefiAmount > 0,                    "Invalid amount");
        require(_balances[msg.sender] >= mefiAmount, "Insufficient balance");
        require(_totalSupply > 0,                  "No supply");

        uint256 backing = getBackingPerMeFi();
        edaiAmount = (mefiAmount * backing) / 1e18;
        require(edaiAmount > 0, "Amount too small");

        uint256 treasury = IERC20(EDAI).balanceOf(address(this));
        require(treasury >= edaiAmount, "Insufficient treasury");

        // Reduce reserve proportionally
        uint256 burnRatio = (mefiAmount * 1e18) / _totalSupply;
        uint256 reserveUsed = (totalEdaiReserve * burnRatio) / 1e18;
        totalEdaiReserve -= reserveUsed;

        totalRedeemed += mefiAmount;
        _burn(msg.sender, mefiAmount);

        bool success = IERC20(EDAI).transfer(msg.sender, edaiAmount);
        require(success, "eDAI transfer failed");

        emit Redeemed(msg.sender, mefiAmount, edaiAmount);
    }

    // ================================================================
    //  BUYBACK (permissionless)
    // ================================================================

    /**
     * @notice Swaps accumulated PLS for MEFI on PulseX and burns it.
     *         If no MEFI liquidity yet and fallbackToReserve is true,
     *         swaps PLS -> eDAI -> adds to reserve instead.
     *         Both paths permanently increase backingRatio().
     */
    function executeBuyback() external whenNotPaused nonReentrant {
        uint256 plsBalance = address(this).balance;
        require(plsBalance >= minBuybackThreshold, "Below threshold");

        address wpls = IPulseXRouter(ROUTER).WPLS();

        address[] memory path = new address[](2);
        path[0] = wpls;
        path[1] = address(this);

        uint256 mefiBefore = _balances[address(this)];

        try IPulseXRouter(ROUTER).swapExactETHForTokens{value: plsBalance}(
            0, path, address(this), block.timestamp + 300
        ) {
            uint256 mefiBought = _balances[address(this)] - mefiBefore;
            if (mefiBought == 0) { emit BuybackFailed("Swap returned 0 MEFI"); return; }

            uint256 burnAmt    = (mefiBought * burnShareBps) / BPS_DENOM;
            uint256 jackpotAmt = mefiBought - burnAmt;

            if (burnAmt > 0) {
                _burn(address(this), burnAmt);
                totalBurned            += burnAmt;
                totalBuybackMefiBurned += burnAmt;
            }

            if (jackpotAmt > 0 && jackpotAddress != address(0)) {
                _transfer(address(this), jackpotAddress, jackpotAmt);
                totalBuybackMefiToJackpot += jackpotAmt;
            } else if (jackpotAmt > 0) {
                _burn(address(this), jackpotAmt);
                totalBurned            += jackpotAmt;
                totalBuybackMefiBurned += jackpotAmt;
                jackpotAmt = 0;
            }

            totalBuybackPLSSpent += plsBalance;
            emit BuybackExecuted(plsBalance, mefiBought, burnAmt, jackpotAmt);

        } catch {
            if (fallbackToReserve) {
                _boostReserveWithPLS(plsBalance, wpls);
            } else {
                emit BuybackFailed("PulseX MEFI swap failed -- PLS held for retry");
            }
        }
    }

    function _boostReserveWithPLS(uint256 plsAmount, address wpls) internal {
        address[] memory path = new address[](2);
        path[0] = wpls;
        path[1] = EDAI;

        uint256 edaiBefore = IERC20(EDAI).balanceOf(address(this));

        try IPulseXRouter(ROUTER).swapExactETHForTokens{value: plsAmount}(
            0, path, address(this), block.timestamp + 300
        ) {
            uint256 edaiGained = IERC20(EDAI).balanceOf(address(this)) - edaiBefore;
            if (edaiGained > 0) {
                totalEdaiReserve      += edaiGained;
                totalReserveBoostEdai += edaiGained;
                totalBuybackPLSSpent  += plsAmount;
                emit ReserveBoosted(plsAmount, edaiGained, backingRatio());
            }
        } catch {
            emit BuybackFailed("Both MEFI and eDAI swap failed -- PLS held for retry");
        }
    }

    receive() external payable {
        emit PLSReceived(msg.value, msg.sender);
    }

    // ================================================================
    //  VIEWS
    // ================================================================

    /**
     * @notice eDAI backing per MEFI, 18-decimal fixed point.
     *         1e18 = 1:1 floor. Only moves up. Never down.
     */
    function backingRatio() public view returns (uint256) {
        if (_totalSupply == 0) return 1e18;
        return (totalEdaiReserve * 1e18) / _totalSupply;
    }

    /// @notice Alias for backingRatio() — backwards compatibility.
    function getBackingPerMeFi() public view returns (uint256) {
        return backingRatio();
    }

    /// @notice Annualized ratio growth since deploy, in basis points.
    function projectedAPY() external view returns (uint256 apyBps) {
        uint256 elapsed = block.timestamp - deployTime;
        if (elapsed < 1 days || _totalSupply == 0) return 0;
        uint256 ratio = backingRatio();
        if (ratio <= 1e18) return 0;
        apyBps = ((ratio - 1e18) * 10_000 * 365 days) / (1e18 * elapsed);
    }

    /// @notice Max eDAI owner can sweep — protocol fee surplus only.
    ///         Buyback gains are permanently locked to MEFI holders.
    function sweepableSurplus() public view returns (uint256) {
        uint256 feeRemaining  = totalProtocolFeeAccrued > totalSurplusSwept
            ? totalProtocolFeeAccrued - totalSurplusSwept : 0;
        uint256 actualSurplus = totalEdaiReserve > _totalSupply
            ? totalEdaiReserve - _totalSupply : 0;
        return feeRemaining < actualSurplus ? feeRemaining : actualSurplus;
    }

    function getTotalBacking() public view returns (uint256) { return totalEdaiReserve; }

    function getTreasuryBalance() external view returns (uint256) {
        return IERC20(EDAI).balanceOf(address(this));
    }

    function estimateRedemption(uint256 mefiAmount) external view returns (uint256) {
        if (_totalSupply == 0) return 0;
        return (mefiAmount * getBackingPerMeFi()) / 1e18;
    }

    function pendingBuybackPLS() external view returns (uint256) {
        return address(this).balance;
    }

    function paused() public view returns (bool) { return _paused; }

    function getStats() external view returns (
        uint256 _totalMintedOut,
        uint256 _totalBurnedOut,
        uint256 _totalRedeemedOut,
        uint256 _circulating,
        uint256 _totalEdaiReserveOut,
        uint256 _sweepableSurplusOut,
        uint256 _backingRatioOut,
        uint256 _projectedAPYbps
    ) {
        uint256 elapsed = block.timestamp - deployTime;
        uint256 ratio   = backingRatio();
        uint256 apy     = (elapsed >= 1 days && _totalSupply > 0 && ratio > 1e18)
            ? ((ratio - 1e18) * 10_000 * 365 days) / (1e18 * elapsed)
            : 0;
        return (
            totalMinted, totalBurned, totalRedeemed, _totalSupply,
            totalEdaiReserve, sweepableSurplus(), ratio, apy
        );
    }

    function getBuybackStats() external view returns (
        uint256 _totalProtocolFeeAccruedOut,
        uint256 _totalSurplusSweptOut,
        uint256 _totalBuybackPLSSpentOut,
        uint256 _totalBuybackMefiBurnedOut,
        uint256 _totalBuybackMefiToJackpotOut,
        uint256 _totalReserveBoostEdaiOut,
        uint256 _pendingBuybackPLS
    ) {
        return (
            totalProtocolFeeAccrued, totalSurplusSwept,
            totalBuybackPLSSpent, totalBuybackMefiBurned,
            totalBuybackMefiToJackpot, totalReserveBoostEdai,
            address(this).balance
        );
    }

    function getArbitrageStats() external view returns (
        uint256 totalProfits,
        uint256 totalExecuted,
        uint256 totalSkipped,
        uint256 currentBacking,
        uint256 backingGrowth
    ) {
        uint256 ratio = backingRatio();
        return (
            totalArbitrageProfits, totalArbitrageExecuted, totalArbitrageSkipped,
            ratio,
            ratio > 1e18 ? ((ratio - 1e18) * 10_000) / 1e18 : 0
        );
    }

    // ================================================================
    //  ADMIN
    // ================================================================

    function setMinter(address minter, bool authorized) external onlyOwner {
        require(minter != address(0), "Invalid");
        authorizedMinters[minter] = authorized;
        emit MinterSet(minter, authorized);
    }

    function setProtocolFeeBps(uint256 bps) external onlyOwner {
        require(bps <= MAX_FEE_BPS, "Exceeds 10% cap");
        protocolFeeBps = bps;
        emit ProtocolFeeBpsSet(bps);
    }

    function setJackpotAddress(address _jackpot) external onlyOwner {
        jackpotAddress = _jackpot;
        emit JackpotAddressSet(_jackpot);
    }

    function setBurnShareBps(uint256 bps) external onlyOwner {
        require(bps <= BPS_DENOM, "Invalid");
        burnShareBps = bps;
        emit BurnShareBpsSet(bps);
    }

    function setMinBuybackThreshold(uint256 threshold) external onlyOwner {
        minBuybackThreshold = threshold;
        emit MinBuybackThresholdSet(threshold);
    }

    function setFallbackToReserve(bool enabled) external onlyOwner {
        fallbackToReserve = enabled;
        emit FallbackToReserveSet(enabled);
    }

    function setArbitrageSettings(
        uint256 _arbitragePercent,
        uint256 _minSpreadBps,
        uint256 _maxSpreadBps,
        uint256 _maxArbitragePerTx,
        uint256 _minArbitrageAmount
    ) external onlyOwner {
        require(_arbitragePercent <= 50,              "Max 50%");
        require(_minSpreadBps     >= 50,              "Min 0.5%");
        require(_maxSpreadBps     <= 2000,            "Max 20%");
        require(_maxSpreadBps     >= _minSpreadBps,   "Max < min");
        arbitragePercent   = _arbitragePercent;
        minSpreadBps       = _minSpreadBps;
        maxSpreadBps       = _maxSpreadBps;
        maxArbitragePerTx  = _maxArbitragePerTx;
        minArbitrageAmount = _minArbitrageAmount;
        emit ArbitrageSettingsUpdated(_arbitragePercent, _minSpreadBps, _maxSpreadBps, _maxArbitragePerTx, _minArbitrageAmount);
    }

    function sweepSurplus(address treasury) external onlyOwner nonReentrant {
        require(treasury != address(0), "Invalid treasury");
        uint256 surplus = sweepableSurplus();
        require(surplus > 0, "No fee surplus to sweep");
        totalEdaiReserve  -= surplus;
        totalSurplusSwept += surplus;
        bool success = IERC20(EDAI).transfer(treasury, surplus);
        require(success, "Transfer failed");
        emit SurplusSwept(treasury, surplus, backingRatio());
    }

    function pause() external onlyOwner { _paused = true; emit Paused(msg.sender); }
    function unpause() external onlyOwner { _paused = false; emit Unpaused(msg.sender); }

    function transferOwnership(address newOwner) external onlyOwner {
        require(newOwner != address(0), "Invalid");
        pendingOwner = newOwner;
        emit OwnershipTransferInitiated(owner, newOwner);
    }

    function acceptOwnership() external {
        require(msg.sender == pendingOwner, "Not pending owner");
        address old = owner;
        owner        = pendingOwner;
        pendingOwner = address(0);
        emit OwnershipTransferred(old, owner);
    }

    function emergencyWithdrawEDAI(uint256 amount) external onlyOwner {
        require(_paused, "Must pause first");
        bool success = IERC20(EDAI).transfer(owner, amount);
        require(success, "Failed");
    }

    function rescueToken(address token) external onlyOwner {
        require(token != EDAI,           "Cannot rescue reserve");
        require(token != address(this),  "Cannot rescue MEFI");
        uint256 bal = IERC20(token).balanceOf(address(this));
        require(bal > 0, "Nothing to rescue");
        IERC20(token).transfer(owner, bal);
    }

    // ================================================================
    //  INTERNAL
    // ================================================================

    function _transfer(address from, address to, uint256 amount) internal {
        require(from != address(0) && to != address(0), "Zero address");
        require(_balances[from] >= amount, "Insufficient");
        _balances[from] -= amount;
        _balances[to]   += amount;
        emit Transfer(from, to, amount);
    }

    function _mint(address account, uint256 amount) internal {
        require(account != address(0), "Zero address");
        require(_totalSupply + amount <= MAX_SUPPLY, "Max supply");
        _totalSupply       += amount;
        _balances[account] += amount;
        emit Transfer(address(0), account, amount);
    }

    function _burn(address account, uint256 amount) internal {
        require(account != address(0), "Zero address");
        require(_balances[account] >= amount, "Insufficient");
        _balances[account] -= amount;
        _totalSupply       -= amount;
        emit Transfer(account, address(0), amount);
    }

    function _approve(address tokenOwner, address spender, uint256 amount) internal {
        require(tokenOwner != address(0) && spender != address(0), "Zero address");
        _allowances[tokenOwner][spender] = amount;
        emit Approval(tokenOwner, spender, amount);
    }

    function _spendAllowance(address tokenOwner, address spender, uint256 amount) internal {
        uint256 current = _allowances[tokenOwner][spender];
        if (current != type(uint256).max) {
            require(current >= amount, "Insufficient allowance");
            unchecked { _allowances[tokenOwner][spender] = current - amount; }
        }
    }
}
        

Compiler Settings

{"remappings":[],"optimizer":{"runs":200,"enabled":true},"metadata":{"bytecodeHash":"ipfs"},"libraries":{},"evmVersion":"paris","compilationTarget":{"contracts/AER/MEFIV2.sol":"MeFi"}}
              

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_jackpotAddress","internalType":"address"}]},{"type":"event","name":"Approval","inputs":[{"type":"address","name":"owner","internalType":"address","indexed":true},{"type":"address","name":"spender","internalType":"address","indexed":true},{"type":"uint256","name":"value","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"ArbitrageExecuted","inputs":[{"type":"bool","name":"isSell","internalType":"bool","indexed":false},{"type":"uint256","name":"edaiAmount","internalType":"uint256","indexed":false},{"type":"uint256","name":"mefiAmount","internalType":"uint256","indexed":false},{"type":"uint256","name":"profit","internalType":"uint256","indexed":false},{"type":"uint256","name":"newBacking","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"ArbitrageSettingsUpdated","inputs":[{"type":"uint256","name":"percent","internalType":"uint256","indexed":false},{"type":"uint256","name":"minSpread","internalType":"uint256","indexed":false},{"type":"uint256","name":"maxSpread","internalType":"uint256","indexed":false},{"type":"uint256","name":"maxSize","internalType":"uint256","indexed":false},{"type":"uint256","name":"minAmount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"ArbitrageSkipped","inputs":[{"type":"string","name":"reason","internalType":"string","indexed":false},{"type":"uint256","name":"edaiAmount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"BurnShareBpsSet","inputs":[{"type":"uint256","name":"bps","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"BuybackExecuted","inputs":[{"type":"uint256","name":"plsSpent","internalType":"uint256","indexed":false},{"type":"uint256","name":"mefiBought","internalType":"uint256","indexed":false},{"type":"uint256","name":"burned","internalType":"uint256","indexed":false},{"type":"uint256","name":"toJackpot","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"BuybackFailed","inputs":[{"type":"string","name":"reason","internalType":"string","indexed":false}],"anonymous":false},{"type":"event","name":"FallbackToReserveSet","inputs":[{"type":"bool","name":"enabled","internalType":"bool","indexed":false}],"anonymous":false},{"type":"event","name":"JackpotAddressSet","inputs":[{"type":"address","name":"jackpot","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"MinBuybackThresholdSet","inputs":[{"type":"uint256","name":"threshold","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"MinterSet","inputs":[{"type":"address","name":"minter","internalType":"address","indexed":true},{"type":"bool","name":"authorized","internalType":"bool","indexed":false}],"anonymous":false},{"type":"event","name":"OwnershipTransferInitiated","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"PLSReceived","inputs":[{"type":"uint256","name":"amount","internalType":"uint256","indexed":false},{"type":"address","name":"from","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Paused","inputs":[{"type":"address","name":"account","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"ProtocolFeeBpsSet","inputs":[{"type":"uint256","name":"bps","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Redeemed","inputs":[{"type":"address","name":"user","internalType":"address","indexed":true},{"type":"uint256","name":"mefiAmount","internalType":"uint256","indexed":false},{"type":"uint256","name":"edaiReceived","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"ReserveBoosted","inputs":[{"type":"uint256","name":"plsSpent","internalType":"uint256","indexed":false},{"type":"uint256","name":"edaiAdded","internalType":"uint256","indexed":false},{"type":"uint256","name":"newBackingRatio","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"SurplusSwept","inputs":[{"type":"address","name":"treasury","internalType":"address","indexed":true},{"type":"uint256","name":"edaiSwept","internalType":"uint256","indexed":false},{"type":"uint256","name":"backingRatioAfter","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"TaxDeposited","inputs":[{"type":"address","name":"creator","internalType":"address","indexed":true},{"type":"uint256","name":"edaiAmount","internalType":"uint256","indexed":false},{"type":"uint256","name":"mefiMinted","internalType":"uint256","indexed":false},{"type":"uint256","name":"feeEdai","internalType":"uint256","indexed":false},{"type":"uint256","name":"newBackingRatio","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Transfer","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"value","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Unpaused","inputs":[{"type":"address","name":"account","internalType":"address","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"BPS_DENOM","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"DEAD","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"EDAI","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"MAX_FEE_BPS","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"MAX_SUPPLY","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"MIN_DEPOSIT","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"ROUTER","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"acceptOwnership","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"allowance","inputs":[{"type":"address","name":"tokenOwner","internalType":"address"},{"type":"address","name":"spender","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"approve","inputs":[{"type":"address","name":"spender","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"arbitragePercent","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"authorizedMinters","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"backingRatio","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"balanceOf","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"burnShareBps","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"decimals","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"deployTime","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"mefiMinted","internalType":"uint256"},{"type":"uint256","name":"profitCaptured","internalType":"uint256"}],"name":"depositTax","inputs":[{"type":"address","name":"creator","internalType":"address"},{"type":"uint256","name":"edaiAmount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"emergencyWithdrawEDAI","inputs":[{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"estimateRedemption","inputs":[{"type":"uint256","name":"mefiAmount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"executeBuyback","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"fallbackToReserve","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"totalProfits","internalType":"uint256"},{"type":"uint256","name":"totalExecuted","internalType":"uint256"},{"type":"uint256","name":"totalSkipped","internalType":"uint256"},{"type":"uint256","name":"currentBacking","internalType":"uint256"},{"type":"uint256","name":"backingGrowth","internalType":"uint256"}],"name":"getArbitrageStats","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getBackingPerMeFi","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"_totalProtocolFeeAccruedOut","internalType":"uint256"},{"type":"uint256","name":"_totalSurplusSweptOut","internalType":"uint256"},{"type":"uint256","name":"_totalBuybackPLSSpentOut","internalType":"uint256"},{"type":"uint256","name":"_totalBuybackMefiBurnedOut","internalType":"uint256"},{"type":"uint256","name":"_totalBuybackMefiToJackpotOut","internalType":"uint256"},{"type":"uint256","name":"_totalReserveBoostEdaiOut","internalType":"uint256"},{"type":"uint256","name":"_pendingBuybackPLS","internalType":"uint256"}],"name":"getBuybackStats","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"_totalMintedOut","internalType":"uint256"},{"type":"uint256","name":"_totalBurnedOut","internalType":"uint256"},{"type":"uint256","name":"_totalRedeemedOut","internalType":"uint256"},{"type":"uint256","name":"_circulating","internalType":"uint256"},{"type":"uint256","name":"_totalEdaiReserveOut","internalType":"uint256"},{"type":"uint256","name":"_sweepableSurplusOut","internalType":"uint256"},{"type":"uint256","name":"_backingRatioOut","internalType":"uint256"},{"type":"uint256","name":"_projectedAPYbps","internalType":"uint256"}],"name":"getStats","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getTotalBacking","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getTreasuryBalance","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"jackpotAddress","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"maxArbitragePerTx","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"maxSpreadBps","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"minArbitrageAmount","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"minBuybackThreshold","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"minSpreadBps","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"name","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"pause","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"paused","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"pendingBuybackPLS","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"pendingOwner","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"apyBps","internalType":"uint256"}],"name":"projectedAPY","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"protocolFeeBps","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"edaiAmount","internalType":"uint256"}],"name":"redeemForEDAI","inputs":[{"type":"uint256","name":"mefiAmount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"rescueToken","inputs":[{"type":"address","name":"token","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setArbitrageSettings","inputs":[{"type":"uint256","name":"_arbitragePercent","internalType":"uint256"},{"type":"uint256","name":"_minSpreadBps","internalType":"uint256"},{"type":"uint256","name":"_maxSpreadBps","internalType":"uint256"},{"type":"uint256","name":"_maxArbitragePerTx","internalType":"uint256"},{"type":"uint256","name":"_minArbitrageAmount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setBurnShareBps","inputs":[{"type":"uint256","name":"bps","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setFallbackToReserve","inputs":[{"type":"bool","name":"enabled","internalType":"bool"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setJackpotAddress","inputs":[{"type":"address","name":"_jackpot","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setMinBuybackThreshold","inputs":[{"type":"uint256","name":"threshold","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setMinter","inputs":[{"type":"address","name":"minter","internalType":"address"},{"type":"bool","name":"authorized","internalType":"bool"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setProtocolFeeBps","inputs":[{"type":"uint256","name":"bps","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"sweepSurplus","inputs":[{"type":"address","name":"treasury","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"sweepableSurplus","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"symbol","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalArbitrageExecuted","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalArbitrageProfits","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalArbitrageSkipped","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalBurned","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalBuybackMefiBurned","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalBuybackMefiToJackpot","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalBuybackPLSSpent","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalEdaiReserve","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalMinted","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalProtocolFeeAccrued","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalRedeemed","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalReserveBoostEdai","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalSupply","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalSurplusSwept","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"transfer","inputs":[{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"transferFrom","inputs":[{"type":"address","name":"from","internalType":"address"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"unpause","inputs":[]},{"type":"receive","stateMutability":"payable"}]
              

Contract Creation Code

0x60a0604052612710600855670de0b6b3a7640000600955600a805460ff191660011790556000600b5560c8600c556103e8600d5568056bc75e2d63100000600e55674563918244f40000600f553480156200005957600080fd5b506040516200379f3803806200379f8339810160408190526200007c91620000bf565b600380546001600160a01b03191633179055600a80546001600160a01b039290921661010002610100600160a81b031990921691909117905542608052620000f1565b600060208284031215620000d257600080fd5b81516001600160a01b0381168114620000ea57600080fd5b9392505050565b6080516136846200011b6000396000818161081901528181612376015261270601526136846000f3fe60806040526004361061041f5760003560e01c80638da5cb5b1161021e578063c7c463fc11610123578063e1aec3de116100ab578063e4d89f061161007a578063e4d89f0614610cd9578063e6b980ef14610cef578063ecff017d14610d02578063f2fde38b14610d18578063f35dad4014610d3857600080fd5b8063e1aec3de14610c6b578063e1e158a514610c80578063e2896cac14610c99578063e30c397814610cb957600080fd5b8063d2401fb7116100f2578063d2401fb714610bbf578063d55be8c614610bd9578063d89135cd14610bef578063dd62ed3e14610c05578063dfc80c4814610c4b57600080fd5b8063c7c463fc14610b5e578063c7e00f1314610b73578063cd7ab2cd14610b89578063cf456ae714610b9f57600080fd5b8063a759b2a8116101a6578063b574748411610175578063b574748414610aa2578063c0417e5814610ab8578063c0afe83b14610ad8578063c59d484714610aee578063c6189b5514610b3e57600080fd5b8063a759b2a814610a1c578063a9059cbb14610a3c578063aa2fe91b14610a5c578063b19aedf714610a8c57600080fd5b8063980ac815116101ed578063980ac815146109a55780639b5655dc146109bb578063a2309ff8146109d0578063a4b7f82d146109e6578063a595829b146109fc57600080fd5b80638da5cb5b146108ee5780638e10e77a1461090e5780639082163d1461092357806395d89b411461097557600080fd5b80633f4ba83a11610324578063731cd8b7116102ac57806383642d821161027b57806383642d8214610863578063840c86e8146108835780638456cb59146108a357806384e816bb146108b85780638bba1f08146108ce57600080fd5b8063731cd8b7146107dd57806379ba5097146107f25780637a40624b146108075780637aabea951461083b57600080fd5b80635c975abb116102f35780635c975abb146107175780636637e38c1461072f57806366660731146107455780636bc0b3ba1461078257806370a08231146107a757600080fd5b80633f4ba83a146106aa57806341fcca1c146106c15780634460d3cf146106d757806355c3c578146106f757600080fd5b80631f47b528116103a7578063313ce56711610376578063313ce5671461061057806332cb6b0c1461063757806332fe7b261461065657806335659fb81461067e5780633de2271c1461069457600080fd5b80631f47b528146105af57806323b872dd146105c55780632405d0a0146105e5578063275bfd7d146105fb57600080fd5b806309d91a52116103ee57806309d91a521461052457806318160ddd1461053a57806319f041741461054f5780631e8357ea146105645780631f0242dd1461057a57600080fd5b806303fd2a4514610460578063056ee4701461049357806306fdde03146104b7578063095ea7b3146104f457600080fd5b3661045b5760405134815233907feaf46ef28a58d34602af70862442acc09f09424aa8943a7b7e7d18a3398e76ea9060200160405180910390a2005b600080fd5b34801561046c57600080fd5b5061047661dead81565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561049f57600080fd5b506104a9601a5481565b60405190815260200161048a565b3480156104c357600080fd5b506104e7604051806040016040528060048152602001634d65466960e01b81525081565b60405161048a91906131a8565b34801561050057600080fd5b5061051461050f36600461320e565b610d4e565b604051901515815260200161048a565b34801561053057600080fd5b506104a9600e5481565b34801561054657600080fd5b506000546104a9565b34801561055b57600080fd5b506006546104a9565b34801561057057600080fd5b506104a960175481565b34801561058657600080fd5b5061059a61059536600461320e565b610d65565b6040805192835260208301919091520161048a565b3480156105bb57600080fd5b506104a9601b5481565b3480156105d157600080fd5b506105146105e036600461323a565b6110ae565b3480156105f157600080fd5b506104a9600b5481565b34801561060757600080fd5b506104a96110f4565b34801561061c57600080fd5b50610625601281565b60405160ff909116815260200161048a565b34801561064357600080fd5b506104a96a52b7d2dcc80cd2e400000081565b34801561066257600080fd5b5061047673165c3410fc91ef562c50559f7d2289febed552d981565b34801561068a57600080fd5b506104a960075481565b3480156106a057600080fd5b506104a960085481565b3480156106b657600080fd5b506106bf611156565b005b3480156106cd57600080fd5b506104a960095481565b3480156106e357600080fd5b506106bf6106f236600461327b565b6111c0565b34801561070357600080fd5b506106bf6107123660046132ad565b6113c9565b34801561072357600080fd5b50601c5460ff16610514565b34801561073b57600080fd5b506104a961271081565b34801561075157600080fd5b5061075a61143b565b604080519586526020860194909452928401919091526060830152608082015260a00161048a565b34801561078e57600080fd5b50600a546104769061010090046001600160a01b031681565b3480156107b357600080fd5b506104a96107c236600461327b565b6001600160a01b031660009081526001602052604090205490565b3480156107e957600080fd5b506104a96114a9565b3480156107fe57600080fd5b506106bf6114b8565b34801561081357600080fd5b506104a97f000000000000000000000000000000000000000000000000000000000000000081565b34801561084757600080fd5b5061047673efd766ccb38eaf1dfd701853bfce31359239f30581565b34801561086f57600080fd5b506106bf61087e36600461327b565b611563565b34801561088f57600080fd5b506106bf61089e36600461327b565b6115e3565b3480156108af57600080fd5b506106bf61183e565b3480156108c457600080fd5b506104a9600f5481565b3480156108da57600080fd5b506104a96108e93660046132ca565b6118a5565b3480156108fa57600080fd5b50600354610476906001600160a01b031681565b34801561091a57600080fd5b506106bf6118dd565b34801561092f57600080fd5b50601354601454601554601654601754601854604080519687526020870195909552938501929092526060840152608083015260a08201524760c082015260e00161048a565b34801561098157600080fd5b506104e7604051806040016040528060048152602001634d45464960e01b81525081565b3480156109b157600080fd5b506104a960185481565b3480156109c757600080fd5b506104a9611dca565b3480156109dc57600080fd5b506104a960105481565b3480156109f257600080fd5b506104a960145481565b348015610a0857600080fd5b506104a9610a173660046132ca565b611e40565b348015610a2857600080fd5b506106bf610a373660046132ca565b612234565b348015610a4857600080fd5b50610514610a5736600461320e565b612293565b348015610a6857600080fd5b50610514610a7736600461327b565b60056020526000908152604090205460ff1681565b348015610a9857600080fd5b506104a9600c5481565b348015610aae57600080fd5b506104a960135481565b348015610ac457600080fd5b506106bf610ad33660046132ca565b6122c4565b348015610ae457600080fd5b506104a9600d5481565b348015610afa57600080fd5b50610b03612367565b604080519889526020890197909752958701949094526060860192909252608085015260a084015260c083015260e08201526101000161048a565b348015610b4a57600080fd5b506106bf610b593660046132ca565b61245d565b348015610b6a57600080fd5b506104a9612594565b348015610b7f57600080fd5b506104a960065481565b348015610b9557600080fd5b506104a960155481565b348015610bab57600080fd5b506106bf610bba3660046132e3565b6125ce565b348015610bcb57600080fd5b50600a546105149060ff1681565b348015610be557600080fd5b506104a96103e881565b348015610bfb57600080fd5b506104a960115481565b348015610c1157600080fd5b506104a9610c2036600461331c565b6001600160a01b03918216600090815260026020908152604080832093909416825291909152205490565b348015610c5757600080fd5b506106bf610c663660046132ca565b61267d565b348015610c7757600080fd5b506104a96126fe565b348015610c8c57600080fd5b506104a964e8d4a5100081565b348015610ca557600080fd5b506106bf610cb436600461334a565b6127b7565b348015610cc557600080fd5b50600454610476906001600160a01b031681565b348015610ce557600080fd5b506104a960195481565b348015610cfb57600080fd5b50476104a9565b348015610d0e57600080fd5b506104a960165481565b348015610d2457600080fd5b506106bf610d3336600461327b565b612940565b348015610d4457600080fd5b506104a960125481565b6000610d5b3384846129e2565b5060015b92915050565b33600090815260056020526040812054819060ff16610dc35760405162461bcd60e51b81526020600482015260156024820152742737ba1030baba3437b934bd32b21036b4b73a32b960591b60448201526064015b60405180910390fd5b601c5460ff1615610de65760405162461bcd60e51b8152600401610dba90613385565b601c54610100900460ff1615610e0e5760405162461bcd60e51b8152600401610dba906133a5565b601c805461ff0019166101001790556001600160a01b038416610e655760405162461bcd60e51b815260206004820152600f60248201526e24b73b30b634b21031b932b0ba37b960891b6044820152606401610dba565b64e8d4a51000831015610eaa5760405162461bcd60e51b815260206004820152600d60248201526c42656c6f77206d696e696d756d60981b6044820152606401610dba565b6040516323b872dd60e01b81523360048201523060248201526044810184905260009073efd766ccb38eaf1dfd701853bfce31359239f305906323b872dd906064016020604051808303816000875af1158015610f0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f2f91906133c8565b905080610f755760405162461bcd60e51b815260206004820152601460248201527319511052481d1c985b9cd9995c8819985a5b195960621b6044820152606401610dba565b8360066000828254610f8791906133fb565b909155505060075460009015610fcc5761271060075486610fa8919061340e565b610fb29190613425565b90508060136000828254610fc691906133fb565b90915550505b610fd68186613447565b93506000841161101c5760405162461bcd60e51b81526020600482015260116024820152704e6f7468696e672061667465722066656560781b6044820152606401610dba565b836010600082825461102e91906133fb565b9091555061103e90508685612a80565b856001600160a01b03167fd4fc101872e1cc49bddc9ba767df58f081c045ebb7fb08747a09a2774a23d9a6868684611074612594565b60408051948552602085019390935291830152606082015260800160405180910390a25050601c805461ff00191690555092600092509050565b601c5460009060ff16156110d45760405162461bcd60e51b8152600401610dba90613385565b6110df843384612b84565b6110ea848484612c2d565b5060019392505050565b60008060145460135411611109576000611119565b6014546013546111199190613447565b9050600080546006541161112e57600061113e565b60005460065461113e9190613447565b905080821061114d578061114f565b815b9250505090565b6003546001600160a01b031633146111805760405162461bcd60e51b8152600401610dba9061345a565b601c805460ff191690556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b6003546001600160a01b031633146111ea5760405162461bcd60e51b8152600401610dba9061345a565b73efd766ccb38eaf1dfd701853bfce31359239f304196001600160a01b0382160161124f5760405162461bcd60e51b815260206004820152601560248201527443616e6e6f7420726573637565207265736572766560581b6044820152606401610dba565b306001600160a01b0382160361129c5760405162461bcd60e51b815260206004820152601260248201527143616e6e6f7420726573637565204d45464960701b6044820152606401610dba565b6040516370a0823160e01b81523060048201526000906001600160a01b038316906370a0823190602401602060405180830381865afa1580156112e3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611307919061347d565b90506000811161134d5760405162461bcd60e51b81526020600482015260116024820152704e6f7468696e6720746f2072657363756560781b6044820152606401610dba565b60035460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018390529083169063a9059cbb906044016020604051808303816000875af11580156113a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113c491906133c8565b505050565b6003546001600160a01b031633146113f35760405162461bcd60e51b8152600401610dba9061345a565b600a805460ff19168215159081179091556040519081527f9aed1031ab5fa4ac3e1ba880ef433126dcdcf8dd8e12053362b4c1237390fb87906020015b60405180910390a150565b60008060008060008061144c612594565b9050601954601a54601b5483670de0b6b3a7640000851161146e576000611497565b670de0b6b3a76400006114818187613447565b61148d9061271061340e565b6114979190613425565b95509550955095509550509091929394565b60006114b3612594565b905090565b6004546001600160a01b031633146115065760405162461bcd60e51b81526020600482015260116024820152702737ba103832b73234b7339037bbb732b960791b6044820152606401610dba565b60038054600480546001600160a01b03198084166001600160a01b038381169182179096559116909155604051929091169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a350565b6003546001600160a01b0316331461158d5760405162461bcd60e51b8152600401610dba9061345a565b600a8054610100600160a81b0319166101006001600160a01b038416908102919091179091556040519081527f42fac12420f66d27fcf81d658c376841028836161314249278e8feb66cbd160590602001611430565b6003546001600160a01b0316331461160d5760405162461bcd60e51b8152600401610dba9061345a565b601c54610100900460ff16156116355760405162461bcd60e51b8152600401610dba906133a5565b601c805461ff0019166101001790556001600160a01b03811661168d5760405162461bcd60e51b815260206004820152601060248201526f496e76616c696420747265617375727960801b6044820152606401610dba565b60006116976110f4565b9050600081116116e95760405162461bcd60e51b815260206004820152601760248201527f4e6f2066656520737572706c757320746f2073776565700000000000000000006044820152606401610dba565b80600660008282546116fb9190613447565b92505081905550806014600082825461171491906133fb565b909155505060405163a9059cbb60e01b81526001600160a01b03831660048201526024810182905260009073efd766ccb38eaf1dfd701853bfce31359239f3059063a9059cbb906044016020604051808303816000875af115801561177d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117a191906133c8565b9050806117e25760405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b6044820152606401610dba565b826001600160a01b03167f2248de369b140d2aeac207a168f52c736a096760a87ef8f718b5f13e438a86a783611816612594565b6040805192835260208301919091520160405180910390a25050601c805461ff001916905550565b6003546001600160a01b031633146118685760405162461bcd60e51b8152600401610dba9061345a565b601c805460ff191660011790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258906020016111b6565b600080546000036118b857506000919050565b670de0b6b3a76400006118c96114a9565b6118d3908461340e565b610d5f9190613425565b601c5460ff16156119005760405162461bcd60e51b8152600401610dba90613385565b601c54610100900460ff16156119285760405162461bcd60e51b8152600401610dba906133a5565b601c805461ff001916610100179055600954479081101561197d5760405162461bcd60e51b815260206004820152600f60248201526e10995b1bddc81d1a1c995cda1bdb19608a1b6044820152606401610dba565b600073165c3410fc91ef562c50559f7d2289febed552d96001600160a01b031663ef8ef56f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119f59190613496565b60408051600280825260608201835292935060009290916020830190803683370190505090508181600081518110611a2f57611a2f6134c9565b60200260200101906001600160a01b031690816001600160a01b0316815250503081600181518110611a6357611a636134c9565b6001600160a01b03909216602092830291909101820152306000818152600190925260408220549173165c3410fc91ef562c50559f7d2289febed552d991637ff36ab59187918690611ab74261012c6133fb565b6040518663ffffffff1660e01b8152600401611ad694939291906134df565b60006040518083038185885af193505050508015611b1657506040513d6000823e601f3d908101601f19168201604052611b139190810190613549565b60015b611bb657600a5460ff1615611b3457611b2f8484612d61565b611db8565b7ffbea7cb5df5f1173a5f17be8f7b0078cfb855f23d2a609041c036f0820ed8c46604051611ba9906020808252602d908201527f50756c736558204d4546492073776170206661696c6564202d2d20504c53206860408201526c656c6420666f7220726574727960981b606082015260800190565b60405180910390a1611db8565b5030600090815260016020526040812054611bd2908390613447565b905080600003611c44577ffbea7cb5df5f1173a5f17be8f7b0078cfb855f23d2a609041c036f0820ed8c46604051611c3290602080825260149082015273537761702072657475726e65642030204d45464960601b604082015260600190565b60405180910390a15050505050611dbd565b600061271060085483611c57919061340e565b611c619190613425565b90506000611c6f8284613447565b90508115611cb257611c8130836130a8565b8160116000828254611c9391906133fb565b925050819055508160166000828254611cac91906133fb565b90915550505b600081118015611cd15750600a5461010090046001600160a01b031615155b15611d1057600a54611cf390309061010090046001600160a01b031683612c2d565b8060176000828254611d0591906133fb565b90915550611d559050565b8015611d5557611d2030826130a8565b8060116000828254611d3291906133fb565b925050819055508060166000828254611d4b91906133fb565b9091555060009150505b8660156000828254611d6791906133fb565b90915550506040805188815260208101859052908101839052606081018290527f42659a4aa613c1e350c764f0ff2be36a175ac2a1e4b77b8e1467d1fed32becc89060800160405180910390a15050505b505050505b601c805461ff0019169055565b6040516370a0823160e01b815230600482015260009073efd766ccb38eaf1dfd701853bfce31359239f305906370a0823190602401602060405180830381865afa158015611e1c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114b3919061347d565b601c5460009060ff1615611e665760405162461bcd60e51b8152600401610dba90613385565b601c54610100900460ff1615611e8e5760405162461bcd60e51b8152600401610dba906133a5565b601c805461ff00191661010017905581611edb5760405162461bcd60e51b815260206004820152600e60248201526d125b9d985b1a5908185b5bdd5b9d60921b6044820152606401610dba565b33600090815260016020526040902054821115611f315760405162461bcd60e51b8152602060048201526014602482015273496e73756666696369656e742062616c616e636560601b6044820152606401610dba565b6000805411611f6e5760405162461bcd60e51b81526020600482015260096024820152684e6f20737570706c7960b81b6044820152606401610dba565b6000611f786114a9565b9050670de0b6b3a7640000611f8d828561340e565b611f979190613425565b915060008211611fdc5760405162461bcd60e51b815260206004820152601060248201526f105b5bdd5b9d081d1bdbc81cdb585b1b60821b6044820152606401610dba565b6040516370a0823160e01b815230600482015260009073efd766ccb38eaf1dfd701853bfce31359239f305906370a0823190602401602060405180830381865afa15801561202e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612052919061347d565b90508281101561209c5760405162461bcd60e51b8152602060048201526015602482015274496e73756666696369656e7420747265617375727960581b6044820152606401610dba565b600080546120b286670de0b6b3a764000061340e565b6120bc9190613425565b90506000670de0b6b3a7640000826006546120d7919061340e565b6120e19190613425565b905080600660008282546120f59190613447565b92505081905550856012600082825461210e91906133fb565b9091555061211e905033876130a8565b60405163a9059cbb60e01b81523360048201526024810186905260009073efd766ccb38eaf1dfd701853bfce31359239f3059063a9059cbb906044016020604051808303816000875af1158015612179573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061219d91906133c8565b9050806121e35760405162461bcd60e51b815260206004820152601460248201527319511052481d1c985b9cd9995c8819985a5b195960621b6044820152606401610dba565b604080518881526020810188905233917ff3a670cd3af7d64b488926880889d08a8585a138ff455227af6737339a1ec262910160405180910390a25050601c805461ff001916905550919392505050565b6003546001600160a01b0316331461225e5760405162461bcd60e51b8152600401610dba9061345a565b60098190556040518181527f3ffb342d323819a69b25cc0ba12ccd725cf670f5b3562500aa7be976fc046c6d90602001611430565b601c5460009060ff16156122b95760405162461bcd60e51b8152600401610dba90613385565b610d5b338484612c2d565b6003546001600160a01b031633146122ee5760405162461bcd60e51b8152600401610dba9061345a565b6103e88111156123325760405162461bcd60e51b815260206004820152600f60248201526e045786365656473203130252063617608c1b6044820152606401610dba565b60078190556040518181527f1f7984367beac902572c9bfc73b4727796e98a777f5b13cb2b87d78b64d4d14090602001611430565b6000808080808080808061239b7f000000000000000000000000000000000000000000000000000000000000000042613447565b905060006123a7612594565b905060006201518083101580156123bf575060008054115b80156123d25750670de0b6b3a764000082115b6123dd576000612425565b6123ef83670de0b6b3a764000061340e565b612401670de0b6b3a764000084613447565b61240d9061271061340e565b61241b906301e1338061340e565b6124259190613425565b905060105460115460125460005460065461243e6110f4565b87879a509a509a509a509a509a509a509a505050509091929394959697565b6003546001600160a01b031633146124875760405162461bcd60e51b8152600401610dba9061345a565b601c5460ff166124cc5760405162461bcd60e51b815260206004820152601060248201526f135d5cdd081c185d5cd948199a5c9cdd60821b6044820152606401610dba565b60035460405163a9059cbb60e01b81526001600160a01b0390911660048201526024810182905260009073efd766ccb38eaf1dfd701853bfce31359239f3059063a9059cbb906044016020604051808303816000875af1158015612534573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061255891906133c8565b9050806125905760405162461bcd60e51b815260206004820152600660248201526511985a5b195960d21b6044820152606401610dba565b5050565b600080546000036125ac5750670de0b6b3a764000090565b6000546006546125c490670de0b6b3a764000061340e565b6114b39190613425565b6003546001600160a01b031633146125f85760405162461bcd60e51b8152600401610dba9061345a565b6001600160a01b03821661261e5760405162461bcd60e51b8152600401610dba90613607565b6001600160a01b038216600081815260056020908152604091829020805460ff191685151590811790915591519182527f583b0aa0e528532caf4b907c11d7a8158a122fe2a6fb80cd9b09776ebea8d92d910160405180910390a25050565b6003546001600160a01b031633146126a75760405162461bcd60e51b8152600401610dba9061345a565b6127108111156126c95760405162461bcd60e51b8152600401610dba90613607565b60088190556040518181527f5c207cba5b2e38e16fb44288d83fd7362e45e25c03676ee49b3ed3f0b00c043490602001611430565b60008061272b7f000000000000000000000000000000000000000000000000000000000000000042613447565b90506201518081108061273e5750600054155b1561274b57600091505090565b6000612755612594565b9050670de0b6b3a7640000811161276f5760009250505090565b61278182670de0b6b3a764000061340e565b612793670de0b6b3a764000083613447565b61279f9061271061340e565b6127ad906301e1338061340e565b61114f9190613425565b6003546001600160a01b031633146127e15760405162461bcd60e51b8152600401610dba9061345a565b603285111561281c5760405162461bcd60e51b81526020600482015260076024820152664d61782035302560c81b6044820152606401610dba565b60328410156128585760405162461bcd60e51b81526020600482015260086024820152674d696e20302e352560c01b6044820152606401610dba565b6107d08311156128945760405162461bcd60e51b81526020600482015260076024820152664d61782032302560c81b6044820152606401610dba565b838310156128d05760405162461bcd60e51b815260206004820152600960248201526826b0bc101e1036b4b760b91b6044820152606401610dba565b600b859055600c849055600d839055600e829055600f819055604080518681526020810186905290810184905260608101839052608081018290527fd7eb6830d58fec1f7218ede3317273bc3ddc1292d5444175e5ed3e0f98716be89060a0015b60405180910390a15050505050565b6003546001600160a01b0316331461296a5760405162461bcd60e51b8152600401610dba9061345a565b6001600160a01b0381166129905760405162461bcd60e51b8152600401610dba90613607565b600480546001600160a01b0319166001600160a01b03838116918217909255600354604051919216907fb150023a879fd806e3599b6ca8ee3b60f0e360ab3846d128d67ebce1a391639a90600090a350565b6001600160a01b03831615801590612a0257506001600160a01b03821615155b612a1e5760405162461bcd60e51b8152600401610dba90613628565b6001600160a01b0383811660008181526002602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b6001600160a01b038216612aa65760405162461bcd60e51b8152600401610dba90613628565b6a52b7d2dcc80cd2e400000081600054612ac091906133fb565b1115612afb5760405162461bcd60e51b815260206004820152600a6024820152694d617820737570706c7960b01b6044820152606401610dba565b80600080828254612b0c91906133fb565b90915550506001600160a01b03821660009081526001602052604081208054839290612b399084906133fb565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b6001600160a01b038084166000908152600260209081526040808320938616835292905220546000198114612c275781811015612bfc5760405162461bcd60e51b8152602060048201526016602482015275496e73756666696369656e7420616c6c6f77616e636560501b6044820152606401610dba565b6001600160a01b03808516600090815260026020908152604080832093871683529290522082820390555b50505050565b6001600160a01b03831615801590612c4d57506001600160a01b03821615155b612c695760405162461bcd60e51b8152600401610dba90613628565b6001600160a01b038316600090815260016020526040902054811115612cc05760405162461bcd60e51b815260206004820152600c60248201526b125b9cdd59999a58da595b9d60a21b6044820152606401610dba565b6001600160a01b03831660009081526001602052604081208054839290612ce8908490613447565b90915550506001600160a01b03821660009081526001602052604081208054839290612d159084906133fb565b92505081905550816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612a7391815260200190565b6040805160028082526060820183526000926020830190803683370190505090508181600081518110612d9657612d966134c9565b60200260200101906001600160a01b031690816001600160a01b03168152505073efd766ccb38eaf1dfd701853bfce31359239f30581600181518110612dde57612dde6134c9565b6001600160a01b0392909216602092830291909101909101526040516370a0823160e01b815230600482015260009073efd766ccb38eaf1dfd701853bfce31359239f305906370a0823190602401602060405180830381865afa158015612e49573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e6d919061347d565b905073165c3410fc91ef562c50559f7d2289febed552d9637ff36ab58560008530612e9a4261012c6133fb565b6040518663ffffffff1660e01b8152600401612eb994939291906134df565b60006040518083038185885af193505050508015612ef957506040513d6000823e601f3d908101601f19168201604052612ef69190810190613549565b60015b612f86577ffbea7cb5df5f1173a5f17be8f7b0078cfb855f23d2a609041c036f0820ed8c46604051612f799060208082526034908201527f426f7468204d45464920616e6420654441492073776170206661696c6564202d6040820152732d20504c532068656c6420666f7220726574727960601b606082015260800190565b60405180910390a1612c27565b506040516370a0823160e01b8152306004820152600090829073efd766ccb38eaf1dfd701853bfce31359239f305906370a0823190602401602060405180830381865afa158015612fdb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fff919061347d565b6130099190613447565b905080156130a157806006600082825461302391906133fb565b92505081905550806018600082825461303c91906133fb565b92505081905550846015600082825461305591906133fb565b909155507faf36536e4700ebb12eed19ca1d1ec7a1b3ccd6ec34778563a203b8c88b3271ae90508582613086612594565b60408051938452602084019290925290820152606001612931565b5050505050565b6001600160a01b0382166130ce5760405162461bcd60e51b8152600401610dba90613628565b6001600160a01b0382166000908152600160205260409020548111156131255760405162461bcd60e51b815260206004820152600c60248201526b125b9cdd59999a58da595b9d60a21b6044820152606401610dba565b6001600160a01b0382166000908152600160205260408120805483929061314d908490613447565b92505081905550806000808282546131659190613447565b90915550506040518181526000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001612b78565b600060208083528351808285015260005b818110156131d5578581018301518582016040015282016131b9565b506000604082860101526040601f19601f8301168501019250505092915050565b6001600160a01b038116811461320b57600080fd5b50565b6000806040838503121561322157600080fd5b823561322c816131f6565b946020939093013593505050565b60008060006060848603121561324f57600080fd5b833561325a816131f6565b9250602084013561326a816131f6565b929592945050506040919091013590565b60006020828403121561328d57600080fd5b8135613298816131f6565b9392505050565b801515811461320b57600080fd5b6000602082840312156132bf57600080fd5b81356132988161329f565b6000602082840312156132dc57600080fd5b5035919050565b600080604083850312156132f657600080fd5b8235613301816131f6565b915060208301356133118161329f565b809150509250929050565b6000806040838503121561332f57600080fd5b823561333a816131f6565b91506020830135613311816131f6565b600080600080600060a0868803121561336257600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b60208082526006908201526514185d5cd95960d21b604082015260600190565b6020808252600990820152681499595b9d1c985b9d60ba1b604082015260600190565b6000602082840312156133da57600080fd5b81516132988161329f565b634e487b7160e01b600052601160045260246000fd5b80820180821115610d5f57610d5f6133e5565b8082028115828204841417610d5f57610d5f6133e5565b60008261344257634e487b7160e01b600052601260045260246000fd5b500490565b81810381811115610d5f57610d5f6133e5565b6020808252600990820152682737ba1037bbb732b960b91b604082015260600190565b60006020828403121561348f57600080fd5b5051919050565b6000602082840312156134a857600080fd5b8151613298816131f6565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b600060808201868352602060808185015281875180845260a086019150828901935060005b818110156135295784516001600160a01b031683529383019391830191600101613504565b50506001600160a01b039690961660408501525050506060015292915050565b6000602080838503121561355c57600080fd5b825167ffffffffffffffff8082111561357457600080fd5b818501915085601f83011261358857600080fd5b81518181111561359a5761359a6134b3565b8060051b604051601f19603f830116810181811085821117156135bf576135bf6134b3565b6040529182528482019250838101850191888311156135dd57600080fd5b938501935b828510156135fb578451845293850193928501926135e2565b98975050505050505050565b602080825260079082015266125b9d985b1a5960ca1b604082015260600190565b6020808252600c908201526b5a65726f206164647265737360a01b60408201526060019056fea26469706673582212207de176f9646ce87ccbac73c7200c39c7f8a76459655c76e6bf62edb98c8b14bc64736f6c63430008130033000000000000000000000000982f3bdb963c0f09047c32b2283b5b87fa7b3d8d

Deployed ByteCode

0x60806040526004361061041f5760003560e01c80638da5cb5b1161021e578063c7c463fc11610123578063e1aec3de116100ab578063e4d89f061161007a578063e4d89f0614610cd9578063e6b980ef14610cef578063ecff017d14610d02578063f2fde38b14610d18578063f35dad4014610d3857600080fd5b8063e1aec3de14610c6b578063e1e158a514610c80578063e2896cac14610c99578063e30c397814610cb957600080fd5b8063d2401fb7116100f2578063d2401fb714610bbf578063d55be8c614610bd9578063d89135cd14610bef578063dd62ed3e14610c05578063dfc80c4814610c4b57600080fd5b8063c7c463fc14610b5e578063c7e00f1314610b73578063cd7ab2cd14610b89578063cf456ae714610b9f57600080fd5b8063a759b2a8116101a6578063b574748411610175578063b574748414610aa2578063c0417e5814610ab8578063c0afe83b14610ad8578063c59d484714610aee578063c6189b5514610b3e57600080fd5b8063a759b2a814610a1c578063a9059cbb14610a3c578063aa2fe91b14610a5c578063b19aedf714610a8c57600080fd5b8063980ac815116101ed578063980ac815146109a55780639b5655dc146109bb578063a2309ff8146109d0578063a4b7f82d146109e6578063a595829b146109fc57600080fd5b80638da5cb5b146108ee5780638e10e77a1461090e5780639082163d1461092357806395d89b411461097557600080fd5b80633f4ba83a11610324578063731cd8b7116102ac57806383642d821161027b57806383642d8214610863578063840c86e8146108835780638456cb59146108a357806384e816bb146108b85780638bba1f08146108ce57600080fd5b8063731cd8b7146107dd57806379ba5097146107f25780637a40624b146108075780637aabea951461083b57600080fd5b80635c975abb116102f35780635c975abb146107175780636637e38c1461072f57806366660731146107455780636bc0b3ba1461078257806370a08231146107a757600080fd5b80633f4ba83a146106aa57806341fcca1c146106c15780634460d3cf146106d757806355c3c578146106f757600080fd5b80631f47b528116103a7578063313ce56711610376578063313ce5671461061057806332cb6b0c1461063757806332fe7b261461065657806335659fb81461067e5780633de2271c1461069457600080fd5b80631f47b528146105af57806323b872dd146105c55780632405d0a0146105e5578063275bfd7d146105fb57600080fd5b806309d91a52116103ee57806309d91a521461052457806318160ddd1461053a57806319f041741461054f5780631e8357ea146105645780631f0242dd1461057a57600080fd5b806303fd2a4514610460578063056ee4701461049357806306fdde03146104b7578063095ea7b3146104f457600080fd5b3661045b5760405134815233907feaf46ef28a58d34602af70862442acc09f09424aa8943a7b7e7d18a3398e76ea9060200160405180910390a2005b600080fd5b34801561046c57600080fd5b5061047661dead81565b6040516001600160a01b0390911681526020015b60405180910390f35b34801561049f57600080fd5b506104a9601a5481565b60405190815260200161048a565b3480156104c357600080fd5b506104e7604051806040016040528060048152602001634d65466960e01b81525081565b60405161048a91906131a8565b34801561050057600080fd5b5061051461050f36600461320e565b610d4e565b604051901515815260200161048a565b34801561053057600080fd5b506104a9600e5481565b34801561054657600080fd5b506000546104a9565b34801561055b57600080fd5b506006546104a9565b34801561057057600080fd5b506104a960175481565b34801561058657600080fd5b5061059a61059536600461320e565b610d65565b6040805192835260208301919091520161048a565b3480156105bb57600080fd5b506104a9601b5481565b3480156105d157600080fd5b506105146105e036600461323a565b6110ae565b3480156105f157600080fd5b506104a9600b5481565b34801561060757600080fd5b506104a96110f4565b34801561061c57600080fd5b50610625601281565b60405160ff909116815260200161048a565b34801561064357600080fd5b506104a96a52b7d2dcc80cd2e400000081565b34801561066257600080fd5b5061047673165c3410fc91ef562c50559f7d2289febed552d981565b34801561068a57600080fd5b506104a960075481565b3480156106a057600080fd5b506104a960085481565b3480156106b657600080fd5b506106bf611156565b005b3480156106cd57600080fd5b506104a960095481565b3480156106e357600080fd5b506106bf6106f236600461327b565b6111c0565b34801561070357600080fd5b506106bf6107123660046132ad565b6113c9565b34801561072357600080fd5b50601c5460ff16610514565b34801561073b57600080fd5b506104a961271081565b34801561075157600080fd5b5061075a61143b565b604080519586526020860194909452928401919091526060830152608082015260a00161048a565b34801561078e57600080fd5b50600a546104769061010090046001600160a01b031681565b3480156107b357600080fd5b506104a96107c236600461327b565b6001600160a01b031660009081526001602052604090205490565b3480156107e957600080fd5b506104a96114a9565b3480156107fe57600080fd5b506106bf6114b8565b34801561081357600080fd5b506104a97f0000000000000000000000000000000000000000000000000000000069daa59381565b34801561084757600080fd5b5061047673efd766ccb38eaf1dfd701853bfce31359239f30581565b34801561086f57600080fd5b506106bf61087e36600461327b565b611563565b34801561088f57600080fd5b506106bf61089e36600461327b565b6115e3565b3480156108af57600080fd5b506106bf61183e565b3480156108c457600080fd5b506104a9600f5481565b3480156108da57600080fd5b506104a96108e93660046132ca565b6118a5565b3480156108fa57600080fd5b50600354610476906001600160a01b031681565b34801561091a57600080fd5b506106bf6118dd565b34801561092f57600080fd5b50601354601454601554601654601754601854604080519687526020870195909552938501929092526060840152608083015260a08201524760c082015260e00161048a565b34801561098157600080fd5b506104e7604051806040016040528060048152602001634d45464960e01b81525081565b3480156109b157600080fd5b506104a960185481565b3480156109c757600080fd5b506104a9611dca565b3480156109dc57600080fd5b506104a960105481565b3480156109f257600080fd5b506104a960145481565b348015610a0857600080fd5b506104a9610a173660046132ca565b611e40565b348015610a2857600080fd5b506106bf610a373660046132ca565b612234565b348015610a4857600080fd5b50610514610a5736600461320e565b612293565b348015610a6857600080fd5b50610514610a7736600461327b565b60056020526000908152604090205460ff1681565b348015610a9857600080fd5b506104a9600c5481565b348015610aae57600080fd5b506104a960135481565b348015610ac457600080fd5b506106bf610ad33660046132ca565b6122c4565b348015610ae457600080fd5b506104a9600d5481565b348015610afa57600080fd5b50610b03612367565b604080519889526020890197909752958701949094526060860192909252608085015260a084015260c083015260e08201526101000161048a565b348015610b4a57600080fd5b506106bf610b593660046132ca565b61245d565b348015610b6a57600080fd5b506104a9612594565b348015610b7f57600080fd5b506104a960065481565b348015610b9557600080fd5b506104a960155481565b348015610bab57600080fd5b506106bf610bba3660046132e3565b6125ce565b348015610bcb57600080fd5b50600a546105149060ff1681565b348015610be557600080fd5b506104a96103e881565b348015610bfb57600080fd5b506104a960115481565b348015610c1157600080fd5b506104a9610c2036600461331c565b6001600160a01b03918216600090815260026020908152604080832093909416825291909152205490565b348015610c5757600080fd5b506106bf610c663660046132ca565b61267d565b348015610c7757600080fd5b506104a96126fe565b348015610c8c57600080fd5b506104a964e8d4a5100081565b348015610ca557600080fd5b506106bf610cb436600461334a565b6127b7565b348015610cc557600080fd5b50600454610476906001600160a01b031681565b348015610ce557600080fd5b506104a960195481565b348015610cfb57600080fd5b50476104a9565b348015610d0e57600080fd5b506104a960165481565b348015610d2457600080fd5b506106bf610d3336600461327b565b612940565b348015610d4457600080fd5b506104a960125481565b6000610d5b3384846129e2565b5060015b92915050565b33600090815260056020526040812054819060ff16610dc35760405162461bcd60e51b81526020600482015260156024820152742737ba1030baba3437b934bd32b21036b4b73a32b960591b60448201526064015b60405180910390fd5b601c5460ff1615610de65760405162461bcd60e51b8152600401610dba90613385565b601c54610100900460ff1615610e0e5760405162461bcd60e51b8152600401610dba906133a5565b601c805461ff0019166101001790556001600160a01b038416610e655760405162461bcd60e51b815260206004820152600f60248201526e24b73b30b634b21031b932b0ba37b960891b6044820152606401610dba565b64e8d4a51000831015610eaa5760405162461bcd60e51b815260206004820152600d60248201526c42656c6f77206d696e696d756d60981b6044820152606401610dba565b6040516323b872dd60e01b81523360048201523060248201526044810184905260009073efd766ccb38eaf1dfd701853bfce31359239f305906323b872dd906064016020604051808303816000875af1158015610f0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f2f91906133c8565b905080610f755760405162461bcd60e51b815260206004820152601460248201527319511052481d1c985b9cd9995c8819985a5b195960621b6044820152606401610dba565b8360066000828254610f8791906133fb565b909155505060075460009015610fcc5761271060075486610fa8919061340e565b610fb29190613425565b90508060136000828254610fc691906133fb565b90915550505b610fd68186613447565b93506000841161101c5760405162461bcd60e51b81526020600482015260116024820152704e6f7468696e672061667465722066656560781b6044820152606401610dba565b836010600082825461102e91906133fb565b9091555061103e90508685612a80565b856001600160a01b03167fd4fc101872e1cc49bddc9ba767df58f081c045ebb7fb08747a09a2774a23d9a6868684611074612594565b60408051948552602085019390935291830152606082015260800160405180910390a25050601c805461ff00191690555092600092509050565b601c5460009060ff16156110d45760405162461bcd60e51b8152600401610dba90613385565b6110df843384612b84565b6110ea848484612c2d565b5060019392505050565b60008060145460135411611109576000611119565b6014546013546111199190613447565b9050600080546006541161112e57600061113e565b60005460065461113e9190613447565b905080821061114d578061114f565b815b9250505090565b6003546001600160a01b031633146111805760405162461bcd60e51b8152600401610dba9061345a565b601c805460ff191690556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b6003546001600160a01b031633146111ea5760405162461bcd60e51b8152600401610dba9061345a565b73efd766ccb38eaf1dfd701853bfce31359239f304196001600160a01b0382160161124f5760405162461bcd60e51b815260206004820152601560248201527443616e6e6f7420726573637565207265736572766560581b6044820152606401610dba565b306001600160a01b0382160361129c5760405162461bcd60e51b815260206004820152601260248201527143616e6e6f7420726573637565204d45464960701b6044820152606401610dba565b6040516370a0823160e01b81523060048201526000906001600160a01b038316906370a0823190602401602060405180830381865afa1580156112e3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611307919061347d565b90506000811161134d5760405162461bcd60e51b81526020600482015260116024820152704e6f7468696e6720746f2072657363756560781b6044820152606401610dba565b60035460405163a9059cbb60e01b81526001600160a01b039182166004820152602481018390529083169063a9059cbb906044016020604051808303816000875af11580156113a0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113c491906133c8565b505050565b6003546001600160a01b031633146113f35760405162461bcd60e51b8152600401610dba9061345a565b600a805460ff19168215159081179091556040519081527f9aed1031ab5fa4ac3e1ba880ef433126dcdcf8dd8e12053362b4c1237390fb87906020015b60405180910390a150565b60008060008060008061144c612594565b9050601954601a54601b5483670de0b6b3a7640000851161146e576000611497565b670de0b6b3a76400006114818187613447565b61148d9061271061340e565b6114979190613425565b95509550955095509550509091929394565b60006114b3612594565b905090565b6004546001600160a01b031633146115065760405162461bcd60e51b81526020600482015260116024820152702737ba103832b73234b7339037bbb732b960791b6044820152606401610dba565b60038054600480546001600160a01b03198084166001600160a01b038381169182179096559116909155604051929091169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a350565b6003546001600160a01b0316331461158d5760405162461bcd60e51b8152600401610dba9061345a565b600a8054610100600160a81b0319166101006001600160a01b038416908102919091179091556040519081527f42fac12420f66d27fcf81d658c376841028836161314249278e8feb66cbd160590602001611430565b6003546001600160a01b0316331461160d5760405162461bcd60e51b8152600401610dba9061345a565b601c54610100900460ff16156116355760405162461bcd60e51b8152600401610dba906133a5565b601c805461ff0019166101001790556001600160a01b03811661168d5760405162461bcd60e51b815260206004820152601060248201526f496e76616c696420747265617375727960801b6044820152606401610dba565b60006116976110f4565b9050600081116116e95760405162461bcd60e51b815260206004820152601760248201527f4e6f2066656520737572706c757320746f2073776565700000000000000000006044820152606401610dba565b80600660008282546116fb9190613447565b92505081905550806014600082825461171491906133fb565b909155505060405163a9059cbb60e01b81526001600160a01b03831660048201526024810182905260009073efd766ccb38eaf1dfd701853bfce31359239f3059063a9059cbb906044016020604051808303816000875af115801561177d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117a191906133c8565b9050806117e25760405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b6044820152606401610dba565b826001600160a01b03167f2248de369b140d2aeac207a168f52c736a096760a87ef8f718b5f13e438a86a783611816612594565b6040805192835260208301919091520160405180910390a25050601c805461ff001916905550565b6003546001600160a01b031633146118685760405162461bcd60e51b8152600401610dba9061345a565b601c805460ff191660011790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258906020016111b6565b600080546000036118b857506000919050565b670de0b6b3a76400006118c96114a9565b6118d3908461340e565b610d5f9190613425565b601c5460ff16156119005760405162461bcd60e51b8152600401610dba90613385565b601c54610100900460ff16156119285760405162461bcd60e51b8152600401610dba906133a5565b601c805461ff001916610100179055600954479081101561197d5760405162461bcd60e51b815260206004820152600f60248201526e10995b1bddc81d1a1c995cda1bdb19608a1b6044820152606401610dba565b600073165c3410fc91ef562c50559f7d2289febed552d96001600160a01b031663ef8ef56f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119f59190613496565b60408051600280825260608201835292935060009290916020830190803683370190505090508181600081518110611a2f57611a2f6134c9565b60200260200101906001600160a01b031690816001600160a01b0316815250503081600181518110611a6357611a636134c9565b6001600160a01b03909216602092830291909101820152306000818152600190925260408220549173165c3410fc91ef562c50559f7d2289febed552d991637ff36ab59187918690611ab74261012c6133fb565b6040518663ffffffff1660e01b8152600401611ad694939291906134df565b60006040518083038185885af193505050508015611b1657506040513d6000823e601f3d908101601f19168201604052611b139190810190613549565b60015b611bb657600a5460ff1615611b3457611b2f8484612d61565b611db8565b7ffbea7cb5df5f1173a5f17be8f7b0078cfb855f23d2a609041c036f0820ed8c46604051611ba9906020808252602d908201527f50756c736558204d4546492073776170206661696c6564202d2d20504c53206860408201526c656c6420666f7220726574727960981b606082015260800190565b60405180910390a1611db8565b5030600090815260016020526040812054611bd2908390613447565b905080600003611c44577ffbea7cb5df5f1173a5f17be8f7b0078cfb855f23d2a609041c036f0820ed8c46604051611c3290602080825260149082015273537761702072657475726e65642030204d45464960601b604082015260600190565b60405180910390a15050505050611dbd565b600061271060085483611c57919061340e565b611c619190613425565b90506000611c6f8284613447565b90508115611cb257611c8130836130a8565b8160116000828254611c9391906133fb565b925050819055508160166000828254611cac91906133fb565b90915550505b600081118015611cd15750600a5461010090046001600160a01b031615155b15611d1057600a54611cf390309061010090046001600160a01b031683612c2d565b8060176000828254611d0591906133fb565b90915550611d559050565b8015611d5557611d2030826130a8565b8060116000828254611d3291906133fb565b925050819055508060166000828254611d4b91906133fb565b9091555060009150505b8660156000828254611d6791906133fb565b90915550506040805188815260208101859052908101839052606081018290527f42659a4aa613c1e350c764f0ff2be36a175ac2a1e4b77b8e1467d1fed32becc89060800160405180910390a15050505b505050505b601c805461ff0019169055565b6040516370a0823160e01b815230600482015260009073efd766ccb38eaf1dfd701853bfce31359239f305906370a0823190602401602060405180830381865afa158015611e1c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114b3919061347d565b601c5460009060ff1615611e665760405162461bcd60e51b8152600401610dba90613385565b601c54610100900460ff1615611e8e5760405162461bcd60e51b8152600401610dba906133a5565b601c805461ff00191661010017905581611edb5760405162461bcd60e51b815260206004820152600e60248201526d125b9d985b1a5908185b5bdd5b9d60921b6044820152606401610dba565b33600090815260016020526040902054821115611f315760405162461bcd60e51b8152602060048201526014602482015273496e73756666696369656e742062616c616e636560601b6044820152606401610dba565b6000805411611f6e5760405162461bcd60e51b81526020600482015260096024820152684e6f20737570706c7960b81b6044820152606401610dba565b6000611f786114a9565b9050670de0b6b3a7640000611f8d828561340e565b611f979190613425565b915060008211611fdc5760405162461bcd60e51b815260206004820152601060248201526f105b5bdd5b9d081d1bdbc81cdb585b1b60821b6044820152606401610dba565b6040516370a0823160e01b815230600482015260009073efd766ccb38eaf1dfd701853bfce31359239f305906370a0823190602401602060405180830381865afa15801561202e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612052919061347d565b90508281101561209c5760405162461bcd60e51b8152602060048201526015602482015274496e73756666696369656e7420747265617375727960581b6044820152606401610dba565b600080546120b286670de0b6b3a764000061340e565b6120bc9190613425565b90506000670de0b6b3a7640000826006546120d7919061340e565b6120e19190613425565b905080600660008282546120f59190613447565b92505081905550856012600082825461210e91906133fb565b9091555061211e905033876130a8565b60405163a9059cbb60e01b81523360048201526024810186905260009073efd766ccb38eaf1dfd701853bfce31359239f3059063a9059cbb906044016020604051808303816000875af1158015612179573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061219d91906133c8565b9050806121e35760405162461bcd60e51b815260206004820152601460248201527319511052481d1c985b9cd9995c8819985a5b195960621b6044820152606401610dba565b604080518881526020810188905233917ff3a670cd3af7d64b488926880889d08a8585a138ff455227af6737339a1ec262910160405180910390a25050601c805461ff001916905550919392505050565b6003546001600160a01b0316331461225e5760405162461bcd60e51b8152600401610dba9061345a565b60098190556040518181527f3ffb342d323819a69b25cc0ba12ccd725cf670f5b3562500aa7be976fc046c6d90602001611430565b601c5460009060ff16156122b95760405162461bcd60e51b8152600401610dba90613385565b610d5b338484612c2d565b6003546001600160a01b031633146122ee5760405162461bcd60e51b8152600401610dba9061345a565b6103e88111156123325760405162461bcd60e51b815260206004820152600f60248201526e045786365656473203130252063617608c1b6044820152606401610dba565b60078190556040518181527f1f7984367beac902572c9bfc73b4727796e98a777f5b13cb2b87d78b64d4d14090602001611430565b6000808080808080808061239b7f0000000000000000000000000000000000000000000000000000000069daa59342613447565b905060006123a7612594565b905060006201518083101580156123bf575060008054115b80156123d25750670de0b6b3a764000082115b6123dd576000612425565b6123ef83670de0b6b3a764000061340e565b612401670de0b6b3a764000084613447565b61240d9061271061340e565b61241b906301e1338061340e565b6124259190613425565b905060105460115460125460005460065461243e6110f4565b87879a509a509a509a509a509a509a509a505050509091929394959697565b6003546001600160a01b031633146124875760405162461bcd60e51b8152600401610dba9061345a565b601c5460ff166124cc5760405162461bcd60e51b815260206004820152601060248201526f135d5cdd081c185d5cd948199a5c9cdd60821b6044820152606401610dba565b60035460405163a9059cbb60e01b81526001600160a01b0390911660048201526024810182905260009073efd766ccb38eaf1dfd701853bfce31359239f3059063a9059cbb906044016020604051808303816000875af1158015612534573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061255891906133c8565b9050806125905760405162461bcd60e51b815260206004820152600660248201526511985a5b195960d21b6044820152606401610dba565b5050565b600080546000036125ac5750670de0b6b3a764000090565b6000546006546125c490670de0b6b3a764000061340e565b6114b39190613425565b6003546001600160a01b031633146125f85760405162461bcd60e51b8152600401610dba9061345a565b6001600160a01b03821661261e5760405162461bcd60e51b8152600401610dba90613607565b6001600160a01b038216600081815260056020908152604091829020805460ff191685151590811790915591519182527f583b0aa0e528532caf4b907c11d7a8158a122fe2a6fb80cd9b09776ebea8d92d910160405180910390a25050565b6003546001600160a01b031633146126a75760405162461bcd60e51b8152600401610dba9061345a565b6127108111156126c95760405162461bcd60e51b8152600401610dba90613607565b60088190556040518181527f5c207cba5b2e38e16fb44288d83fd7362e45e25c03676ee49b3ed3f0b00c043490602001611430565b60008061272b7f0000000000000000000000000000000000000000000000000000000069daa59342613447565b90506201518081108061273e5750600054155b1561274b57600091505090565b6000612755612594565b9050670de0b6b3a7640000811161276f5760009250505090565b61278182670de0b6b3a764000061340e565b612793670de0b6b3a764000083613447565b61279f9061271061340e565b6127ad906301e1338061340e565b61114f9190613425565b6003546001600160a01b031633146127e15760405162461bcd60e51b8152600401610dba9061345a565b603285111561281c5760405162461bcd60e51b81526020600482015260076024820152664d61782035302560c81b6044820152606401610dba565b60328410156128585760405162461bcd60e51b81526020600482015260086024820152674d696e20302e352560c01b6044820152606401610dba565b6107d08311156128945760405162461bcd60e51b81526020600482015260076024820152664d61782032302560c81b6044820152606401610dba565b838310156128d05760405162461bcd60e51b815260206004820152600960248201526826b0bc101e1036b4b760b91b6044820152606401610dba565b600b859055600c849055600d839055600e829055600f819055604080518681526020810186905290810184905260608101839052608081018290527fd7eb6830d58fec1f7218ede3317273bc3ddc1292d5444175e5ed3e0f98716be89060a0015b60405180910390a15050505050565b6003546001600160a01b0316331461296a5760405162461bcd60e51b8152600401610dba9061345a565b6001600160a01b0381166129905760405162461bcd60e51b8152600401610dba90613607565b600480546001600160a01b0319166001600160a01b03838116918217909255600354604051919216907fb150023a879fd806e3599b6ca8ee3b60f0e360ab3846d128d67ebce1a391639a90600090a350565b6001600160a01b03831615801590612a0257506001600160a01b03821615155b612a1e5760405162461bcd60e51b8152600401610dba90613628565b6001600160a01b0383811660008181526002602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b6001600160a01b038216612aa65760405162461bcd60e51b8152600401610dba90613628565b6a52b7d2dcc80cd2e400000081600054612ac091906133fb565b1115612afb5760405162461bcd60e51b815260206004820152600a6024820152694d617820737570706c7960b01b6044820152606401610dba565b80600080828254612b0c91906133fb565b90915550506001600160a01b03821660009081526001602052604081208054839290612b399084906133fb565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b6001600160a01b038084166000908152600260209081526040808320938616835292905220546000198114612c275781811015612bfc5760405162461bcd60e51b8152602060048201526016602482015275496e73756666696369656e7420616c6c6f77616e636560501b6044820152606401610dba565b6001600160a01b03808516600090815260026020908152604080832093871683529290522082820390555b50505050565b6001600160a01b03831615801590612c4d57506001600160a01b03821615155b612c695760405162461bcd60e51b8152600401610dba90613628565b6001600160a01b038316600090815260016020526040902054811115612cc05760405162461bcd60e51b815260206004820152600c60248201526b125b9cdd59999a58da595b9d60a21b6044820152606401610dba565b6001600160a01b03831660009081526001602052604081208054839290612ce8908490613447565b90915550506001600160a01b03821660009081526001602052604081208054839290612d159084906133fb565b92505081905550816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef83604051612a7391815260200190565b6040805160028082526060820183526000926020830190803683370190505090508181600081518110612d9657612d966134c9565b60200260200101906001600160a01b031690816001600160a01b03168152505073efd766ccb38eaf1dfd701853bfce31359239f30581600181518110612dde57612dde6134c9565b6001600160a01b0392909216602092830291909101909101526040516370a0823160e01b815230600482015260009073efd766ccb38eaf1dfd701853bfce31359239f305906370a0823190602401602060405180830381865afa158015612e49573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e6d919061347d565b905073165c3410fc91ef562c50559f7d2289febed552d9637ff36ab58560008530612e9a4261012c6133fb565b6040518663ffffffff1660e01b8152600401612eb994939291906134df565b60006040518083038185885af193505050508015612ef957506040513d6000823e601f3d908101601f19168201604052612ef69190810190613549565b60015b612f86577ffbea7cb5df5f1173a5f17be8f7b0078cfb855f23d2a609041c036f0820ed8c46604051612f799060208082526034908201527f426f7468204d45464920616e6420654441492073776170206661696c6564202d6040820152732d20504c532068656c6420666f7220726574727960601b606082015260800190565b60405180910390a1612c27565b506040516370a0823160e01b8152306004820152600090829073efd766ccb38eaf1dfd701853bfce31359239f305906370a0823190602401602060405180830381865afa158015612fdb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612fff919061347d565b6130099190613447565b905080156130a157806006600082825461302391906133fb565b92505081905550806018600082825461303c91906133fb565b92505081905550846015600082825461305591906133fb565b909155507faf36536e4700ebb12eed19ca1d1ec7a1b3ccd6ec34778563a203b8c88b3271ae90508582613086612594565b60408051938452602084019290925290820152606001612931565b5050505050565b6001600160a01b0382166130ce5760405162461bcd60e51b8152600401610dba90613628565b6001600160a01b0382166000908152600160205260409020548111156131255760405162461bcd60e51b815260206004820152600c60248201526b125b9cdd59999a58da595b9d60a21b6044820152606401610dba565b6001600160a01b0382166000908152600160205260408120805483929061314d908490613447565b92505081905550806000808282546131659190613447565b90915550506040518181526000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001612b78565b600060208083528351808285015260005b818110156131d5578581018301518582016040015282016131b9565b506000604082860101526040601f19601f8301168501019250505092915050565b6001600160a01b038116811461320b57600080fd5b50565b6000806040838503121561322157600080fd5b823561322c816131f6565b946020939093013593505050565b60008060006060848603121561324f57600080fd5b833561325a816131f6565b9250602084013561326a816131f6565b929592945050506040919091013590565b60006020828403121561328d57600080fd5b8135613298816131f6565b9392505050565b801515811461320b57600080fd5b6000602082840312156132bf57600080fd5b81356132988161329f565b6000602082840312156132dc57600080fd5b5035919050565b600080604083850312156132f657600080fd5b8235613301816131f6565b915060208301356133118161329f565b809150509250929050565b6000806040838503121561332f57600080fd5b823561333a816131f6565b91506020830135613311816131f6565b600080600080600060a0868803121561336257600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b60208082526006908201526514185d5cd95960d21b604082015260600190565b6020808252600990820152681499595b9d1c985b9d60ba1b604082015260600190565b6000602082840312156133da57600080fd5b81516132988161329f565b634e487b7160e01b600052601160045260246000fd5b80820180821115610d5f57610d5f6133e5565b8082028115828204841417610d5f57610d5f6133e5565b60008261344257634e487b7160e01b600052601260045260246000fd5b500490565b81810381811115610d5f57610d5f6133e5565b6020808252600990820152682737ba1037bbb732b960b91b604082015260600190565b60006020828403121561348f57600080fd5b5051919050565b6000602082840312156134a857600080fd5b8151613298816131f6565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b600060808201868352602060808185015281875180845260a086019150828901935060005b818110156135295784516001600160a01b031683529383019391830191600101613504565b50506001600160a01b039690961660408501525050506060015292915050565b6000602080838503121561355c57600080fd5b825167ffffffffffffffff8082111561357457600080fd5b818501915085601f83011261358857600080fd5b81518181111561359a5761359a6134b3565b8060051b604051601f19603f830116810181811085821117156135bf576135bf6134b3565b6040529182528482019250838101850191888311156135dd57600080fd5b938501935b828510156135fb578451845293850193928501926135e2565b98975050505050505050565b602080825260079082015266125b9d985b1a5960ca1b604082015260600190565b6020808252600c908201526b5a65726f206164647265737360a01b60408201526060019056fea26469706673582212207de176f9646ce87ccbac73c7200c39c7f8a76459655c76e6bf62edb98c8b14bc64736f6c63430008130033