false
true
0

Contract Address Details

0xad5C70588101D168b52577004A3A209ab90AB49A

Contract Name
Mine
Creator
0x89969f–8cb3c3 at 0xdc85a7–692ca7
Balance
8.327592 tPLS
Tokens
Fetching tokens...
Transactions
Fetching transactions...
Transfers
Fetching transfers...
Gas Used
Fetching gas used...
Last Balance Update
25686159
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
Contract name:
Mine




Optimization enabled
false
Compiler version
v0.8.24+commit.e11b9ed9




EVM Version




Verified at
2026-09-17T19:05:52.892125Z

Constructor Arguments

000000000000000000000000688d8bf5237a42432ee6b4092e15e73c6bcbb80a000000000000000000000000da5734cd1013359bfea1943ee4b109f87e916a89000000000000000000000000788111ad3cf7f4d850e5811b5d78457b28b3914d000000000000000000000000000000000000000000000000000d1c091338a000

Arg [0] (address) : 0x688d8bf5237a42432ee6b4092e15e73c6bcbb80a
Arg [1] (address) : 0xda5734cd1013359bfea1943ee4b109f87e916a89
Arg [2] (address) : 0x788111ad3cf7f4d850e5811b5d78457b28b3914d
Arg [3] (uint256) : 3690000000000000

              

contracts/Mine.sol

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

import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";

interface IBuyBurn {
    function queued() external view returns (uint256);
    function burned() external view returns (uint256);
    function pair() external view returns (address);
    function router() external view returns (address);
}

interface IEKGMint {
    function mint(address to, uint256 amount) external;
    function distribute() external payable;
    function setExcluded(address account, bool value) external;
    function totalSupply() external view returns (uint256);
    function eligibleSupply() external view returns (uint256);
    function approve(address spender, uint256 amount) external returns (bool);
}

interface IRouterLiquidity {
    function addLiquidityETH(
        address token,
        uint256 amountTokenDesired,
        uint256 amountTokenMin,
        uint256 amountETHMin,
        address to,
        uint256 deadline
    ) external payable returns (uint256 amountToken, uint256 amountETH, uint256 liquidity);
}

/// @title Mine
/// @notice The whole emission schedule. 36 halvings, 369,000,000 tokens, and
///         never one more.
///
///         There is no clock anywhere in here. Halving one holds half of
///         everything at one flat price; when it is mined out the next opens
///         at double, in the same transaction if the same buy pays for it.
///         Bitcoin's arithmetic - 36 doublings, boundaries on clean powers of
///         two - with demand as the only pacing.
///
///         Nothing can be mined before the market exists. openMine() runs
///         once: it mines the pool's EKG side at full halving one price,
///         pairs it with PLS on PulseX, and burns the LP tokens, so the
///         founding liquidity can never be withdrawn by anyone. Only then
///         does mine() open. The buy and burn therefore has a pool to buy
///         from before the first ordinary mine ever queues its seven percent.
///
///         You commit PLS. Ninety percent of it is set aside for you and comes
///         back after 24 hours. The protocol keeps ten, so your real cost is a
///         tenth of the headline rate, and of that ten:
///
///             70 percent into the buy and burn, which takes it to the open
///                market, buys EKG with it and destroys what it buys
///             20 percent paid straight out to everyone holding
///             10 percent to operations
///
///         Measured against the whole commit that is 7, 2 and 1 percent.
///
///         The money set aside for miners is accounted separately and nothing
///         in this contract can spend it. It is theirs from the moment they
///         commit.
contract Mine is ReentrancyGuard {
    uint256 public constant CAP = 369_000_000e18;
    uint256 public constant HALVINGS = 36;
    uint256 public constant RETURN_WINDOW = 24 hours;

    uint256 public constant RETURN_BPS = 9000; // comes back to the miner
    uint256 public constant KEEP_BPS = 1000; // the real cost

    // of the ten percent kept
    uint256 public constant FLOOR_BPS = 7000;
    uint256 public constant DIV_BPS = 2000;
    uint256 public constant OPS_BPS = 1000;


    /// @notice The smallest mine the contract will accept, in whole tokens.
    ///         Without it, a commit small enough to round to zero PLS mints
    ///         free tokens, and a supply of a few wei is the lever that turns
    ///         the dividend accumulator into a weapon.
    uint256 public constant MIN_MINE = 1e18;

    /// @notice Below this eligible supply the holders' share is held rather
    ///         than paid, because the token cannot divide it fairly.
    uint256 public constant MIN_ELIGIBLE_TO_PAY = 1e18;

    IEKGMint public immutable token;
    address payable public immutable buyBurn;
    address public immutable ops;

    /// @notice PLS per whole token in the first halving, fixed forever at deploy.
    uint256 public immutable rate0;

    /// @notice Which halving is live. Only mining moves it. There is no clock
    ///         in this contract and no way to advance it by waiting.
    uint256 public halvingNow;
    /// @notice Tokens taken out of the live halving so far.
    uint256 public halvingMinted;
    uint256 public minted;

    uint256 public opsOwed;
    /// @notice Every PLS in this contract that belongs to a miner, not to us.
    uint256 public reserved;
    /// @notice Holders' PLS that arrived while there were no holders. It is
    ///         paid out in full on the next mine that has somebody to pay.
    uint256 public pendingDiv;
    bool public wired;

    /// @notice True once openMine() has created and funded the pool. Every
    ///         ordinary mine is refused until then, so there is never a moment
    ///         where the buy and burn holds money with nothing to buy.
    bool public opened;

    /// @notice Where the founding LP tokens go. Nothing at this address can
    ///         act, so the founding liquidity is locked in the pool forever.
    address public constant LP_GRAVE = 0x000000000000000000000000000000000000dEaD;

    struct Position {
        uint128 committed; // what they sent in
        uint128 returning; // the ninety percent coming back
        uint128 tokens; // what they mined
        uint64 minedAt;
        uint64 unlockAt;
        bool claimed;
    }

    mapping(address => Position[]) private _positions;

    event Mined(
        address indexed account,
        uint256 indexed index,
        uint256 halving,
        uint256 tokens,
        uint256 committed,
        uint256 returning,
        uint256 unlockAt
    );
    event Returned(address indexed account, uint256 indexed index, uint256 amount);
    event HalvingAdvanced(uint256 indexed halving, uint256 newRate);
    event Claimed(address indexed account, uint256 amount);
    event Opened(address indexed pair, uint256 ekgSide, uint256 plsSide);

    error MiningOver();
    error Underpaid();
    error NothingToClaim();
    error TransferFailed();
    error ZeroAmount();
    error AlreadyWired();
    error NoPairYet();
    error NotYet();
    error TooSmall();
    error BadRange();
    error PriceMoved();
    error NoEligibleSupply();
    error NotOpen();
    error AlreadyOpen();
    error NoLiquidity();

    constructor(address token_, address payable buyBurn_, address ops_, uint256 rate0_) {
        // A zero opening rate would mint the entire cap for nothing, and there
        // is no owner and no second chance.
        if (rate0_ == 0) revert ZeroAmount();
        token = IEKGMint(token_);
        buyBurn = buyBurn_;
        ops = ops_;
        rate0 = rate0_;
    }

    /// @notice Keeps the protocol's own contracts out of the dividend split.
    ///         Takes no argument and runs once, so nobody can point it at a holder.
    function wire() external {
        if (wired) revert AlreadyWired();
        wired = true;
        token.setExcluded(buyBurn, true);
        token.setExcluded(address(this), true);
    }

    /// @notice Take the trading pair out of the dividend split, once it exists.
    ///
    ///         The pool holds a large EKG balance that belongs to liquidity
    ///         providers rather than to any one holder, and nothing can claim
    ///         on its behalf. Left in the split, a growing share of every
    ///         dividend would accrue to an address that can never withdraw it,
    ///         and that share would be lost to everybody.
    ///
    ///         Anyone may call this and the caller chooses nothing: the address
    ///         comes from the factory, not from the arguments, so the only
    ///         address it can ever exclude is the real EKG pair. Exclusion is
    ///         one way in the token, so calling it twice does nothing.
    function excludePair() external returns (address p) {
        p = IBuyBurn(buyBurn).pair();
        if (p == address(0)) revert NoPairYet();
        token.setExcluded(p, true);
    }

    // ------------------------------------------------------------------ views

    /// @notice What halving `k` holds in total.
    ///
    ///         Halving one holds half of everything, two a quarter, and so on,
    ///         exactly as Bitcoin's first epoch mints half of all bitcoin. The
    ///         last one sweeps whatever rounding left behind, so the total is
    ///         the cap to the wei with nothing stranded.
    function halvingAllowance(uint256 k) public pure returns (uint256) {
        if (k >= HALVINGS) return 0;
        if (k == HALVINGS - 1) {
            uint256 taken;
            for (uint256 i = 0; i < HALVINGS - 1; i++) taken += CAP >> (i + 1);
            return CAP - taken;
        }
        return CAP >> (k + 1);
    }

    function halving() public view returns (uint256) {
        return halvingNow;
    }

    /// @notice What is left in the halving that is live right now.
    function available() public view returns (uint256) {
        if (halvingNow >= HALVINGS) return 0;
        uint256 all = halvingAllowance(halvingNow);
        return all > halvingMinted ? all - halvingMinted : 0;
    }

    /// @notice Everything left to mine across every halving still to come.
    function remaining() public view returns (uint256) {
        return CAP > minted ? CAP - minted : 0;
    }

    function finished() public view returns (bool) {
        return halvingNow >= HALVINGS || minted >= CAP;
    }

    /// @notice What a token costs in the halving that is live right now. Flat
    ///         inside a halving, doubled at the boundary. Bitcoin's arithmetic
    ///         and nothing else in the way.
    function scheduleRate() public view returns (uint256) {
        if (halvingNow >= HALVINGS) return rate0 << (HALVINGS - 1);
        return rate0 << halvingNow;
    }

    /// @notice The headline rate right now.
    ///
    ///         There used to be a second rule here, a guard tied to a
    ///         redemption pot. The pot is gone, so there is nothing a mint can
    ///         dilute and nothing for a guard to protect. What is left is the
    ///         schedule, and no function anywhere lowers it.
    function rate() public view returns (uint256) {
        return scheduleRate();
    }

    /// @notice What a token actually costs, after the ninety percent returns.
    function trueCost() public view returns (uint256) {
        return (rate() * KEEP_BPS) / 10_000;
    }

    /// @notice What `amount` tokens cost right now, walking across halvings if
    ///         the amount is bigger than what this one has left.
    ///
    ///         This is the whole point of the design. A buyer is never turned
    ///         away and never told to come back later: they simply pay this
    ///         halving's price for what is left of it, the next halving's price
    ///         for the next slice, and so on. Wanting more supply costs
    ///         exponentially more, which is the only fair way to ration it.
    function costOf(uint256 amount) public view returns (uint256 cost) {
        uint256 k = halvingNow;
        uint256 mintedHere = halvingMinted;
        while (amount > 0 && k < HALVINGS) {
            uint256 all = halvingAllowance(k);
            uint256 left = all > mintedHere ? all - mintedHere : 0;
            uint256 take = amount < left ? amount : left;
            if (take > 0) {
                cost += _cost(take, rate0 << k);
                amount -= take;
            }
            if (amount == 0) break;
            k += 1;
            mintedHere = 0;
        }
    }

    /// @notice How many tokens `pls` buys right now, across as many halvings as
    ///         it reaches.
    function quote(uint256 pls) public view returns (uint256 tokens, uint256 spend) {
        uint256 k = halvingNow;
        uint256 mintedHere = halvingMinted;
        uint256 budget = pls;
        while (budget > 0 && k < HALVINGS) {
            uint256 r = rate0 << k;
            uint256 all = halvingAllowance(k);
            uint256 left = all > mintedHere ? all - mintedHere : 0;
            if (left == 0) { k += 1; mintedHere = 0; continue; }
            uint256 affordable = (budget * 1e18) / r;
            uint256 take = affordable < left ? affordable : left;
            if (take == 0) break;
            uint256 c = _cost(take, r);
            if (c > budget) break;
            tokens += take;
            spend += c;
            budget -= c;
            if (take < left) break;
            k += 1;
            mintedHere = 0;
        }
    }

    function _cost(uint256 amount, uint256 r) internal pure returns (uint256) {
        if (amount == 0) return 0;
        // Rounded up, so the scraps of a halving always cost at least one wei
        // and can always be bought. Rounded down, a remainder small enough to
        // price at zero could never be mined and the curve would stop there.
        return (amount * r + 1e18 - 1) / 1e18;
    }

    // --------------------------------------------------------- your positions

    function positionCount(address account) external view returns (uint256) {
        return _positions[account].length;
    }

    function positionAt(address account, uint256 index) external view returns (Position memory) {
        return _positions[account][index];
    }

    /// @notice Everything the front end needs for one wallet in a single read.
    function positionsOf(address account, uint256 from, uint256 count)
        external
        view
        returns (Position[] memory out)
    {
        Position[] storage all = _positions[account];
        if (from >= all.length) return new Position[](0);
        uint256 room = all.length - from;
        uint256 end = from + (count < room ? count : room);
        out = new Position[](end - from);
        for (uint256 i = from; i < end; i++) out[i - from] = all[i];
    }

    /// @notice Returns that have matured and are waiting to be taken.
    ///         Unbounded: use `claimableReturnsRange` once an account has a lot
    ///         of positions, because this one eventually costs more gas than a
    ///         node will spend on a call.
    function claimableReturns(address account) public view returns (uint256 amount, uint256 count) {
        Position[] storage all = _positions[account];
        for (uint256 i = 0; i < all.length; i++) {
            Position storage q = all[i];
            if (!q.claimed && block.timestamp >= q.unlockAt) {
                amount += q.returning;
                count += 1;
            }
        }
    }

    /// @notice Returns still inside the 24 hour window.
    function pendingReturns(address account) public view returns (uint256 amount, uint256 count) {
        Position[] storage all = _positions[account];
        for (uint256 i = 0; i < all.length; i++) {
            Position storage q = all[i];
            if (!q.claimed && block.timestamp < q.unlockAt) {
                amount += q.returning;
                count += 1;
            }
        }
    }

    /// @notice The same reading over a slice of the positions.
    function claimableReturnsRange(address account, uint256 from, uint256 count)
        external
        view
        returns (uint256 amount, uint256 found)
    {
        Position[] storage all = _positions[account];
        if (from >= all.length) return (0, 0);
        uint256 room = all.length - from;
        uint256 end = from + (count < room ? count : room);
        for (uint256 i = from; i < end; i++) {
            Position storage q = all[i];
            if (!q.claimed && block.timestamp >= q.unlockAt) {
                amount += q.returning;
                found += 1;
            }
        }
    }

    // ------------------------------------------------------------------ mining

    /// @notice Spend whatever you send. Pass `type(uint256).max` as `maxRate`
    ///         to accept any price, or a number to refuse a bad one.
    ///
    ///         There is no cap on how much you may mine in one go and no clock
    ///         telling you to come back tomorrow. A large buy simply walks up
    ///         the halvings, paying each one's price for the slice it takes,
    ///         and stops when the money runs out or the cap does.
    /// @notice The one-time launch. Mines the pool's EKG side at the ordinary
    ///         halving one price, creates the EKG/WPLS pair on PulseX, funds it
    ///         with everything sent beyond the mining cost, and burns the LP
    ///         tokens. Runs once, then ordinary mining opens.
    ///
    ///         Nothing here is a premine: the EKG side is bought through the
    ///         same accounting as any other mine - ninety percent of its cost
    ///         comes back to the caller in 24 hours, and the kept tenth splits
    ///         70/20/10 like every commit after it. And nothing here is a rug:
    ///         the LP tokens go to an address nothing can act from, so the
    ///         founding liquidity can never be pulled back out.
    ///
    ///         Anyone can be the caller. Being first costs full price and
    ///         hands the protocol a permanent pool; there is nothing to win.
    function openMine(uint256 ekgSide) external payable nonReentrant returns (address pairAddr) {
        if (opened) revert AlreadyOpen();
        if (ekgSide < MIN_MINE) revert TooSmall();

        uint256 committed = costOf(ekgSide);
        if (msg.value <= committed) revert NoLiquidity();
        uint256 plsSide = msg.value - committed;

        opened = true;
        _take(ekgSide);

        uint256 returning = (committed * RETURN_BPS) / 10_000;
        reserved += returning;
        _positions[msg.sender].push(
            Position({
                committed: uint128(committed),
                returning: uint128(returning),
                tokens: uint128(ekgSide),
                minedAt: uint64(block.timestamp),
                unlockAt: uint64(block.timestamp + RETURN_WINDOW),
                claimed: false
            })
        );
        _split(committed - returning);

        // The pool's EKG side is minted here and spent into the pair in the
        // same transaction. This contract holds tokens for no other reason and
        // at no other time.
        token.mint(address(this), ekgSide);
        address routerAddr = IBuyBurn(buyBurn).router();
        token.approve(routerAddr, ekgSide);
        IRouterLiquidity(routerAddr).addLiquidityETH{value: plsSide}(
            address(token), ekgSide, ekgSide, plsSide, LP_GRAVE, block.timestamp
        );

        pairAddr = IBuyBurn(buyBurn).pair();
        // The pair holds EKG that belongs to the locked liquidity, not to any
        // holder, so it is taken out of the dividend split before a single
        // dividend exists.
        token.setExcluded(pairAddr, true);

        emit Opened(pairAddr, ekgSide, plsSide);
        emit Mined(
            msg.sender,
            _positions[msg.sender].length - 1,
            halvingNow,
            ekgSide,
            committed,
            returning,
            block.timestamp + RETURN_WINDOW
        );
    }

    function mine(uint256 maxRate) external payable nonReentrant returns (uint256 amount) {
        return _mine(type(uint256).max, maxRate);
    }

    /// @notice Buy an exact number of tokens, at no worse than `maxRate` for
    ///         the first token. Anything the current halving cannot cover is
    ///         filled from the next one at its own, higher price.
    function mineExact(uint256 want, uint256 maxRate)
        external
        payable
        nonReentrant
        returns (uint256 amount)
    {
        return _mine(want, maxRate);
    }

    function _mine(uint256 want, uint256 maxRate) internal returns (uint256 amount) {
        // The pool exists before the first mine, always. See openMine().
        if (!opened) revert NotOpen();
        if (finished()) revert MiningOver();

        uint256 opening = rate();
        if (opening > maxRate) revert PriceMoved();

        uint256 committed;
        if (want == type(uint256).max) {
            (amount, committed) = quote(msg.value);
        } else {
            amount = want;
            uint256 left = remaining();
            if (amount > left) amount = left;
            committed = costOf(amount);
        }
        if (amount == 0) revert ZeroAmount();
        // A mine below one whole token is refused, because a supply of a few
        // wei is the lever behind more than one way to kill this.
        //
        // The exception is taking everything on offer. The late halvings hold
        // less than a whole token each - halving thirty holds about a sixth of
        // one - so without this, those halvings could never be cleared by
        // anybody, the schedule would stop there, and the cap would never be
        // reached. Taking all of what is available cannot be a dust attack:
        // it is the only move that exists.
        if (amount < MIN_MINE && amount < available()) revert TooSmall();
        if (msg.value < committed) revert Underpaid();

        _take(amount);

        uint256 returning = (committed * RETURN_BPS) / 10_000;
        uint256 kept = committed - returning;
        reserved += returning;

        _positions[msg.sender].push(
            Position({
                committed: uint128(committed),
                returning: uint128(returning),
                tokens: uint128(amount),
                minedAt: uint64(block.timestamp),
                unlockAt: uint64(block.timestamp + RETURN_WINDOW),
                claimed: false
            })
        );

        // Paid out before the new tokens exist, so a miner is never handed a
        // slice of their own dividend.
        _split(kept);
        token.mint(msg.sender, amount);

        uint256 refund = msg.value - committed;
        if (refund > 0) {
            (bool ok,) = msg.sender.call{value: refund}("");
            if (!ok) revert TransferFailed();
        }

        emit Mined(
            msg.sender,
            _positions[msg.sender].length - 1,
            halvingNow,
            amount,
            committed,
            returning,
            block.timestamp + RETURN_WINDOW
        );
    }

    /// @notice Walk the halvings, taking `amount` tokens out of the schedule,
    ///         advancing the halving as each one empties. The only thing in
    ///         this contract that moves the schedule.
    function _take(uint256 amount) internal {
        uint256 left = amount;
        while (left > 0 && halvingNow < HALVINGS) {
            uint256 all = halvingAllowance(halvingNow);
            uint256 room = all > halvingMinted ? all - halvingMinted : 0;
            uint256 take = left < room ? left : room;
            halvingMinted += take;
            left -= take;
            if (halvingMinted >= all) {
                halvingNow += 1;
                halvingMinted = 0;
                if (halvingNow < HALVINGS) {
                    emit HalvingAdvanced(halvingNow, rate0 << halvingNow);
                }
            }
        }
        minted += amount;
    }

    function _split(uint256 kept) internal {
        uint256 divShare = (kept * DIV_BPS) / 10_000;
        uint256 opsShare = (kept * OPS_BPS) / 10_000;
        opsOwed += opsShare;

        // Every rounding remainder goes to the buy and burn, computed as the
        // remainder rather than as its own percentage so the three slices add
        // up to the whole kept amount exactly and no wei is ever left behind in
        // this contract. Crumbs that belong to nobody should end up buying the
        // token back rather than sitting in a mine that cannot spend them.
        uint256 burnShare = kept - divShare - opsShare;

        // On the very first mine, and any time every token has been redeemed,
        // there is nobody holding to pay. The holders' share is kept here and
        // handed over whole on the next mine that has somebody to pay, rather
        // than being quietly turned into something else.
        // Held back whenever there is nobody meaningful to pay, not only when
        // there is nobody at all. The token refuses to divide by less than one
        // whole token, so pushing a payment against a dust supply would credit
        // a rounding crumb and destroy the rest.
        if (token.eligibleSupply() < MIN_ELIGIBLE_TO_PAY) {
            pendingDiv += divShare;
        } else {
            uint256 owed = divShare + pendingDiv;
            pendingDiv = 0;
            token.distribute{value: owed}();
        }

        (bool ok,) = buyBurn.call{value: burnShare}("");
        if (!ok) revert TransferFailed();
    }


    // ------------------------------------------------------------------ claims

    /// @notice Take back the ninety percent from one matured position.
    function claimReturn(uint256 index) external nonReentrant {
        if (index >= _positions[msg.sender].length) revert BadRange();
        Position storage p = _positions[msg.sender][index];
        if (p.claimed) revert NothingToClaim();
        if (block.timestamp < p.unlockAt) revert NotYet();
        uint256 amount = p.returning;
        p.claimed = true;
        reserved -= amount;
        (bool ok,) = msg.sender.call{value: amount}("");
        if (!ok) revert TransferFailed();
        emit Returned(msg.sender, index, amount);
    }

    /// @notice Take back everything that has matured between two indexes.
    ///         A wallet with thousands of positions cannot sweep them in one
    ///         transaction at any gas limit, so the sweep is bounded and the
    ///         caller walks it. Nothing is ever locked: `claimReturn` reaches
    ///         any single position directly.
    function claimReturns(uint256 from, uint256 count) external nonReentrant returns (uint256 amount) {
        Position[] storage all = _positions[msg.sender];
        if (from >= all.length) revert BadRange();
        uint256 room = all.length - from;
        uint256 end = from + (count < room ? count : room);
        for (uint256 i = from; i < end; i++) {
            Position storage p = all[i];
            if (!p.claimed && block.timestamp >= p.unlockAt) {
                p.claimed = true;
                amount += p.returning;
                emit Returned(msg.sender, i, p.returning);
            }
        }
        if (amount == 0) revert NothingToClaim();
        reserved -= amount;
        (bool ok,) = msg.sender.call{value: amount}("");
        if (!ok) revert TransferFailed();
    }

    /// @notice Take back everything that has matured, in one transaction.
    ///         Fine for a normal wallet. See `claimReturns` for a large one.
    function claimAllReturns() external nonReentrant returns (uint256 amount) {
        Position[] storage all = _positions[msg.sender];
        for (uint256 i = 0; i < all.length; i++) {
            Position storage p = all[i];
            if (!p.claimed && block.timestamp >= p.unlockAt) {
                p.claimed = true;
                amount += p.returning;
                emit Returned(msg.sender, i, p.returning);
            }
        }
        if (amount == 0) revert NothingToClaim();
        reserved -= amount;
        (bool ok,) = msg.sender.call{value: amount}("");
        if (!ok) revert TransferFailed();
    }

    function claimOps() external nonReentrant {
        uint256 amount = opsOwed;
        if (amount == 0) revert NothingToClaim();
        opsOwed = 0;
        (bool ok,) = ops.call{value: amount}("");
        if (!ok) revert TransferFailed();
        emit Claimed(ops, amount);
    }
}
        

@openzeppelin/contracts/utils/ReentrancyGuard.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.5.0) (utils/ReentrancyGuard.sol)

pragma solidity ^0.8.20;

import {StorageSlot} from "./StorageSlot.sol";

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If EIP-1153 (transient storage) is available on the chain you're deploying at,
 * consider using {ReentrancyGuardTransient} instead.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 *
 * IMPORTANT: Deprecated. This storage-based reentrancy guard will be removed and replaced
 * by the {ReentrancyGuardTransient} variant in v6.0.
 *
 * @custom:stateless
 */
abstract contract ReentrancyGuard {
    using StorageSlot for bytes32;

    // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ReentrancyGuard")) - 1)) & ~bytes32(uint256(0xff))
    bytes32 private constant REENTRANCY_GUARD_STORAGE =
        0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00;

    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

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

    /**
     * @dev Unauthorized reentrant call.
     */
    error ReentrancyGuardReentrantCall();

    constructor() {
        _reentrancyGuardStorageSlot().getUint256Slot().value = NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    /**
     * @dev A `view` only version of {nonReentrant}. Use to block view functions
     * from being called, preventing reading from inconsistent contract state.
     *
     * CAUTION: This is a "view" modifier and does not change the reentrancy
     * status. Use it only on view functions. For payable or non-payable functions,
     * use the standard {nonReentrant} modifier instead.
     */
    modifier nonReentrantView() {
        _nonReentrantBeforeView();
        _;
    }

    function _nonReentrantBeforeView() private view {
        if (_reentrancyGuardEntered()) {
            revert ReentrancyGuardReentrantCall();
        }
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be NOT_ENTERED
        _nonReentrantBeforeView();

        // Any calls to nonReentrant after this point will fail
        _reentrancyGuardStorageSlot().getUint256Slot().value = ENTERED;
    }

    function _nonReentrantAfter() private {
        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _reentrancyGuardStorageSlot().getUint256Slot().value = NOT_ENTERED;
    }

    /**
     * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
     * `nonReentrant` function in the call stack.
     */
    function _reentrancyGuardEntered() internal view returns (bool) {
        return _reentrancyGuardStorageSlot().getUint256Slot().value == ENTERED;
    }

    function _reentrancyGuardStorageSlot() internal pure virtual returns (bytes32) {
        return REENTRANCY_GUARD_STORAGE;
    }
}
          

@openzeppelin/contracts/utils/StorageSlot.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.

pragma solidity ^0.8.20;

/**
 * @dev Library for reading and writing primitive types to specific storage slots.
 *
 * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
 * This library helps with reading and writing to such slots without the need for inline assembly.
 *
 * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
 *
 * Example usage to set ERC-1967 implementation slot:
 * ```solidity
 * contract ERC1967 {
 *     // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.
 *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
 *
 *     function _getImplementation() internal view returns (address) {
 *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
 *     }
 *
 *     function _setImplementation(address newImplementation) internal {
 *         require(newImplementation.code.length > 0);
 *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
 *     }
 * }
 * ```
 *
 * TIP: Consider using this library along with {SlotDerivation}.
 */
library StorageSlot {
    struct AddressSlot {
        address value;
    }

    struct BooleanSlot {
        bool value;
    }

    struct Bytes32Slot {
        bytes32 value;
    }

    struct Uint256Slot {
        uint256 value;
    }

    struct Int256Slot {
        int256 value;
    }

    struct StringSlot {
        string value;
    }

    struct BytesSlot {
        bytes value;
    }

    /**
     * @dev Returns an `AddressSlot` with member `value` located at `slot`.
     */
    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
        assembly ("memory-safe") {
            r.slot := slot
        }
    }

    /**
     * @dev Returns a `BooleanSlot` with member `value` located at `slot`.
     */
    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
        assembly ("memory-safe") {
            r.slot := slot
        }
    }

    /**
     * @dev Returns a `Bytes32Slot` with member `value` located at `slot`.
     */
    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
        assembly ("memory-safe") {
            r.slot := slot
        }
    }

    /**
     * @dev Returns a `Uint256Slot` with member `value` located at `slot`.
     */
    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
        assembly ("memory-safe") {
            r.slot := slot
        }
    }

    /**
     * @dev Returns a `Int256Slot` with member `value` located at `slot`.
     */
    function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {
        assembly ("memory-safe") {
            r.slot := slot
        }
    }

    /**
     * @dev Returns a `StringSlot` with member `value` located at `slot`.
     */
    function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
        assembly ("memory-safe") {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `StringSlot` representation of the string storage pointer `store`.
     */
    function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
        assembly ("memory-safe") {
            r.slot := store.slot
        }
    }

    /**
     * @dev Returns a `BytesSlot` with member `value` located at `slot`.
     */
    function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
        assembly ("memory-safe") {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
     */
    function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
        assembly ("memory-safe") {
            r.slot := store.slot
        }
    }
}
          

Compiler Settings

{"viaIR":false,"outputSelection":{"*":{"*":["abi","evm.bytecode","evm.deployedBytecode","evm.methodIdentifiers","metadata"],"":["ast"]}},"optimizer":{"runs":200,"enabled":true},"libraries":{},"evmVersion":"paris"}
              

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"token_","internalType":"address"},{"type":"address","name":"buyBurn_","internalType":"address payable"},{"type":"address","name":"ops_","internalType":"address"},{"type":"uint256","name":"rate0_","internalType":"uint256"}]},{"type":"error","name":"AlreadyOpen","inputs":[]},{"type":"error","name":"AlreadyWired","inputs":[]},{"type":"error","name":"BadRange","inputs":[]},{"type":"error","name":"MiningOver","inputs":[]},{"type":"error","name":"NoEligibleSupply","inputs":[]},{"type":"error","name":"NoLiquidity","inputs":[]},{"type":"error","name":"NoPairYet","inputs":[]},{"type":"error","name":"NotOpen","inputs":[]},{"type":"error","name":"NotYet","inputs":[]},{"type":"error","name":"NothingToClaim","inputs":[]},{"type":"error","name":"PriceMoved","inputs":[]},{"type":"error","name":"ReentrancyGuardReentrantCall","inputs":[]},{"type":"error","name":"TooSmall","inputs":[]},{"type":"error","name":"TransferFailed","inputs":[]},{"type":"error","name":"Underpaid","inputs":[]},{"type":"error","name":"ZeroAmount","inputs":[]},{"type":"event","name":"Claimed","inputs":[{"type":"address","name":"account","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"HalvingAdvanced","inputs":[{"type":"uint256","name":"halving","internalType":"uint256","indexed":true},{"type":"uint256","name":"newRate","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Mined","inputs":[{"type":"address","name":"account","internalType":"address","indexed":true},{"type":"uint256","name":"index","internalType":"uint256","indexed":true},{"type":"uint256","name":"halving","internalType":"uint256","indexed":false},{"type":"uint256","name":"tokens","internalType":"uint256","indexed":false},{"type":"uint256","name":"committed","internalType":"uint256","indexed":false},{"type":"uint256","name":"returning","internalType":"uint256","indexed":false},{"type":"uint256","name":"unlockAt","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Opened","inputs":[{"type":"address","name":"pair","internalType":"address","indexed":true},{"type":"uint256","name":"ekgSide","internalType":"uint256","indexed":false},{"type":"uint256","name":"plsSide","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Returned","inputs":[{"type":"address","name":"account","internalType":"address","indexed":true},{"type":"uint256","name":"index","internalType":"uint256","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"CAP","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"DIV_BPS","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"FLOOR_BPS","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"HALVINGS","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"KEEP_BPS","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"LP_GRAVE","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"MIN_ELIGIBLE_TO_PAY","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"MIN_MINE","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"OPS_BPS","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"RETURN_BPS","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"RETURN_WINDOW","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"available","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address payable"}],"name":"buyBurn","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"amount","internalType":"uint256"}],"name":"claimAllReturns","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"claimOps","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"claimReturn","inputs":[{"type":"uint256","name":"index","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"amount","internalType":"uint256"}],"name":"claimReturns","inputs":[{"type":"uint256","name":"from","internalType":"uint256"},{"type":"uint256","name":"count","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"uint256","name":"count","internalType":"uint256"}],"name":"claimableReturns","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"uint256","name":"found","internalType":"uint256"}],"name":"claimableReturnsRange","inputs":[{"type":"address","name":"account","internalType":"address"},{"type":"uint256","name":"from","internalType":"uint256"},{"type":"uint256","name":"count","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"cost","internalType":"uint256"}],"name":"costOf","inputs":[{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"address","name":"p","internalType":"address"}],"name":"excludePair","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"finished","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"halving","inputs":[]},{"type":"function","stateMutability":"pure","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"halvingAllowance","inputs":[{"type":"uint256","name":"k","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"halvingMinted","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"halvingNow","inputs":[]},{"type":"function","stateMutability":"payable","outputs":[{"type":"uint256","name":"amount","internalType":"uint256"}],"name":"mine","inputs":[{"type":"uint256","name":"maxRate","internalType":"uint256"}]},{"type":"function","stateMutability":"payable","outputs":[{"type":"uint256","name":"amount","internalType":"uint256"}],"name":"mineExact","inputs":[{"type":"uint256","name":"want","internalType":"uint256"},{"type":"uint256","name":"maxRate","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"minted","inputs":[]},{"type":"function","stateMutability":"payable","outputs":[{"type":"address","name":"pairAddr","internalType":"address"}],"name":"openMine","inputs":[{"type":"uint256","name":"ekgSide","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"opened","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"ops","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"opsOwed","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"pendingDiv","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"uint256","name":"count","internalType":"uint256"}],"name":"pendingReturns","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"","internalType":"struct Mine.Position","components":[{"type":"uint128","name":"committed","internalType":"uint128"},{"type":"uint128","name":"returning","internalType":"uint128"},{"type":"uint128","name":"tokens","internalType":"uint128"},{"type":"uint64","name":"minedAt","internalType":"uint64"},{"type":"uint64","name":"unlockAt","internalType":"uint64"},{"type":"bool","name":"claimed","internalType":"bool"}]}],"name":"positionAt","inputs":[{"type":"address","name":"account","internalType":"address"},{"type":"uint256","name":"index","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"positionCount","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple[]","name":"out","internalType":"struct Mine.Position[]","components":[{"type":"uint128","name":"committed","internalType":"uint128"},{"type":"uint128","name":"returning","internalType":"uint128"},{"type":"uint128","name":"tokens","internalType":"uint128"},{"type":"uint64","name":"minedAt","internalType":"uint64"},{"type":"uint64","name":"unlockAt","internalType":"uint64"},{"type":"bool","name":"claimed","internalType":"bool"}]}],"name":"positionsOf","inputs":[{"type":"address","name":"account","internalType":"address"},{"type":"uint256","name":"from","internalType":"uint256"},{"type":"uint256","name":"count","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"tokens","internalType":"uint256"},{"type":"uint256","name":"spend","internalType":"uint256"}],"name":"quote","inputs":[{"type":"uint256","name":"pls","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"rate","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"rate0","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"remaining","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"reserved","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"scheduleRate","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IEKGMint"}],"name":"token","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"trueCost","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"wire","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"wired","inputs":[]}]
              

Contract Creation Code

0x6101006040523480156200001257600080fd5b5060405162002e2d38038062002e2d8339810160408190526200003591620000b8565b60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005560008190036200007c57604051631f2a200560e01b815260040160405180910390fd5b6001600160a01b0393841660805291831660a05290911660c05260e05262000112565b6001600160a01b0381168114620000b557600080fd5b50565b60008060008060808587031215620000cf57600080fd5b8451620000dc816200009f565b6020860151909450620000ef816200009f565b604086015190935062000102816200009f565b6060959095015193969295505050565b60805160a05160c05160e051612c47620001e66000396000818161056301528181611281015281816112ad01528181611e8001528181612012015261216801526000818161071c015281816113ac01526114300152600081816104ed01528181610aa101528181610c700152818161169b01528181611d2f01526123890152600081816107a501528181610a3901528181610b4a01528181610bd101528181610d19015281816116cb0152818161174301528181611dfe015281816122520152818161231101526127240152612c476000f3fe6080604052600436106102935760003560e01c806393c19e181161015a578063d89f2fa9116100c1578063ed1bd76c1161007a578063ed1bd76c1461075e578063ee67ccd71461077e578063f0cf5af614610525578063fc0c546a14610793578063fd326592146107c7578063fe60d12c146107e757600080fd5b8063d89f2fa91461069b578063d982ae84146106b1578063dc9d54ef146106c8578063e5d4a0d9146106f5578063e70abe921461070a578063ec81b4831461073e57600080fd5b8063bef4876b11610113578063bef4876b146105fc578063c478ea9814610611578063c5e3b2dd14610624578063c8df245a14610651578063cda0b07414610666578063d04c02381461068657600080fd5b806393c19e1814610551578063a868188814610585578063af91cf251461059a578063b49822ce146105b0578063b9f30afd146105c6578063bba553bb146105dc57600080fd5b80634b1e36f3116101fe57806370bbfa26116101b757806370bbfa26146104bb57806370e08e61146104db5780637eea3a101461042b57806380f6baff1461050f57806389f1fb7f146105255780638e07257e1461053b57600080fd5b80634b1e36f31461042b5780634d474898146104475780634f02c4201461045a57806355234ec0146104705780635f88eade14610485578063665b9aa3146104a457600080fd5b80632c4e722e116102505780632c4e722e1461036c578063349f2ecf1461038157806334a9642b146103a157806339d57b02146103b657806342fd3880146103e057806348a0d7541461041657600080fd5b80630937732c14610298578063158e35d9146102c85780631954bf6b146102ec578063209c53a31461030257806323e2b7f71461033757806326b387bb1461034c575b600080fd5b6102ab6102a6366004612966565b6107fd565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156102d457600080fd5b506102de60035481565b6040519081526020016102bf565b3480156102f857600080fd5b506102de61232881565b34801561030e57600080fd5b5061032261031d366004612994565b610e4a565b604080519283526020830191909152016102bf565b34801561034357600080fd5b506102de610f00565b34801561035857600080fd5b50610322610367366004612994565b6110aa565b34801561037857600080fd5b506102de611158565b34801561038d57600080fd5b5061032261039c3660046129b1565b611167565b3480156103ad57600080fd5b506102de611267565b3480156103c257600080fd5b506006546103d09060ff1681565b60405190151581526020016102bf565b3480156103ec57600080fd5b506102de6103fb366004612994565b6001600160a01b031660009081526007602052604090205490565b34801561042257600080fd5b506102de6112d1565b34801561043757600080fd5b506102de670de0b6b3a764000081565b6102de610455366004612966565b611315565b34801561046657600080fd5b506102de60025481565b34801561047c57600080fd5b506102de611335565b34801561049157600080fd5b506006546103d090610100900460ff1681565b3480156104b057600080fd5b506104b961136b565b005b3480156104c757600080fd5b506104b96104d6366004612966565b61149d565b3480156104e757600080fd5b506102ab7f000000000000000000000000000000000000000000000000000000000000000081565b34801561051b57600080fd5b506102de6107d081565b34801561053157600080fd5b506102de6103e881565b34801561054757600080fd5b506102de60005481565b34801561055d57600080fd5b506102de7f000000000000000000000000000000000000000000000000000000000000000081565b34801561059157600080fd5b506104b9611650565b3480156105a657600080fd5b506102ab61dead81565b3480156105bc57600080fd5b506102de60015481565b3480156105d257600080fd5b506102de611b5881565b3480156105e857600080fd5b506102de6105f7366004612966565b6117ab565b34801561060857600080fd5b506103d0611852565b6102de61061f3660046129e6565b611878565b34801561063057600080fd5b5061064461063f366004612a08565b61189c565b6040516102bf9190612a8e565b34801561065d57600080fd5b506000546102de565b34801561067257600080fd5b506102de6106813660046129e6565b611953565b34801561069257600080fd5b506102de611b4b565b3480156106a757600080fd5b506102de60055481565b3480156106bd57600080fd5b506102de6201518081565b3480156106d457600080fd5b506106e86106e33660046129b1565b611b6f565b6040516102bf9190612a9c565b34801561070157600080fd5b506102ab611d2b565b34801561071657600080fd5b506102ab7f000000000000000000000000000000000000000000000000000000000000000081565b34801561074a57600080fd5b506102de6b01313aca151562851100000081565b34801561076a57600080fd5b50610322610779366004612966565b611e5d565b34801561078a57600080fd5b506102de602481565b34801561079f57600080fd5b506102ab7f000000000000000000000000000000000000000000000000000000000000000081565b3480156107d357600080fd5b506102de6107e2366004612966565b611fad565b3480156107f357600080fd5b506102de60045481565b6000610807612081565b600654610100900460ff161561083057604051632597e36560e21b815260040160405180910390fd5b670de0b6b3a764000082101561085957604051636989e9d160e11b815260040160405180910390fd5b600061086483611fad565b905080341161088657604051636180f03f60e11b815260040160405180910390fd5b60006108928234612b00565b6006805461ff00191661010017905590506108ac846120b0565b60006127106108bd61232885612b13565b6108c79190612b2a565b905080600460008282546108db9190612b4c565b9250508190555060076000336001600160a01b03166001600160a01b031681526020019081526020016000206040518060c00160405280856001600160801b03168152602001836001600160801b03168152602001876001600160801b03168152602001426001600160401b03168152602001620151804261095d9190612b4c565b6001600160401b03908116825260006020928301819052845460018082018755958252908390208451938501516001600160801b03948516600160801b91861682021760039093029091019182556040850151958201805460608701516080880151989096166001600160c01b031990911617948416909102939093176001600160c01b0316600160c01b959092169490940217905560a001516002909101805460ff1916911515919091179055610a1d610a188285612b00565b6121dc565b6040516340c10f1960e01b8152306004820152602481018690527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906340c10f1990604401600060405180830381600087803b158015610a8557600080fd5b505af1158015610a99573d6000803e3d6000fd5b5050505060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f887ea406040518163ffffffff1660e01b8152600401602060405180830381865afa158015610afd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b219190612b5f565b60405163095ea7b360e01b81526001600160a01b038083166004830152602482018990529192507f00000000000000000000000000000000000000000000000000000000000000009091169063095ea7b3906044016020604051808303816000875af1158015610b95573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bb99190612b7c565b5060405163f305d71960e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260248201889052604482018890526064820185905261dead60848301524260a483015282169063f305d71990859060c40160606040518083038185885af1158015610c46573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610c6b9190612b9e565b5050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a8aa1b316040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ccc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cf09190612b5f565b604051630a0daf8960e21b81526001600160a01b038083166004830152600160248301529196507f000000000000000000000000000000000000000000000000000000000000000090911690632836be2490604401600060405180830381600087803b158015610d5f57600080fd5b505af1158015610d73573d6000803e3d6000fd5b505060408051898152602081018790526001600160a01b03891693507f0e00eb3434eeed137478dadba5581f87fdda6f16b438d9d1b616b24093bfbb4292500160405180910390a233600090815260076020526040902054610dd790600190612b00565b60005433907fea1c66caca012a8cb6b7540750241bea285f813b121558fd7133846a670b66bd90898887610e0e6201518042612b4c565b604080519586526020860194909452928401919091526060830152608082015260a00160405180910390a350505050610e45612420565b919050565b6001600160a01b03811660009081526007602052604081208190815b8154811015610ef9576000828281548110610e8357610e83612bcc565b60009182526020909120600390910201600281015490915060ff16158015610ebf57506001810154600160c01b90046001600160401b03164210155b15610ef0578054610ee090600160801b90046001600160801b031686612b4c565b9450610eed600185612b4c565b93505b50600101610e66565b5050915091565b6000610f0a612081565b336000908152600760205260408120905b8154811015610ffb576000828281548110610f3857610f38612bcc565b60009182526020909120600390910201600281015490915060ff16158015610f7457506001810154600160c01b90046001600160401b03164210155b15610ff25760028101805460ff191660011790558054610fa5906001600160801b03600160801b9091041685612b4c565b8154604051600160801b9091046001600160801b03168152909450829033907f038e5485c9947dae7ff2f1a9213b7cc1b6d0aee561a8bc6c768af736d007b6cb9060200160405180910390a35b50600101610f1b565b508160000361101d576040516312d37ee560e31b815260040160405180910390fd5b816004600082825461102f9190612b00565b9091555050604051600090339084908381818185875af1925050503d8060008114611076576040519150601f19603f3d011682016040523d82523d6000602084013e61107b565b606091505b505090508061109d576040516312171d8360e31b815260040160405180910390fd5b50506110a7612420565b90565b6001600160a01b03811660009081526007602052604081208190815b8154811015610ef95760008282815481106110e3576110e3612bcc565b60009182526020909120600390910201600281015490915060ff1615801561111e57506001810154600160c01b90046001600160401b031642105b1561114f57805461113f90600160801b90046001600160801b031686612b4c565b945061114c600185612b4c565b93505b506001016110c6565b6000611162611267565b905090565b6001600160a01b03831660009081526007602052604081208054829190851061119757600080925092505061125f565b80546000906111a7908790612b00565b905060008186106111b857816111ba565b855b6111c49088612b4c565b9050865b8181101561125a5760008482815481106111e4576111e4612bcc565b60009182526020909120600390910201600281015490915060ff1615801561122057506001810154600160c01b90046001600160401b03164210155b1561125157805461124190600160801b90046001600160801b031688612b4c565b965061124e600187612b4c565b95505b506001016111c8565b505050505b935093915050565b60006024600054106112a75761127f60016024612b00565b7f0000000000000000000000000000000000000000000000000000000000000000901b905090565b506000547f0000000000000000000000000000000000000000000000000000000000000000901b90565b60006024600054106112e35750600090565b60006112f06000546117ab565b9050600154811161130257600061130f565b60015461130f9082612b00565b91505090565b600061131f612081565b61132b60001983612448565b9050610e45612420565b60006002546b01313aca1515628511000000116113525750600090565b600254611162906b01313aca1515628511000000612b00565b611373612081565b6003546000819003611398576040516312d37ee560e31b815260040160405180910390fd5b600060038190556040516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169083908381818185875af1925050503d8060008114611407576040519150601f19603f3d011682016040523d82523d6000602084013e61140c565b606091505b505090508061142e576040516312171d8360e31b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03167fd8138f8a3f377c5259ca548e70e4c2de94f129f5a11036a15b69513cba2b426a8360405161148991815260200190565b60405180910390a2505061149b612420565b565b6114a5612081565b3360009081526007602052604090205481106114d4576040516309aab2bb60e41b815260040160405180910390fd5b3360009081526007602052604081208054839081106114f5576114f5612bcc565b60009182526020909120600390910201600281015490915060ff161561152e576040516312d37ee560e31b815260040160405180910390fd5b6001810154600160c01b90046001600160401b03164210156115635760405163069fbbbb60e11b815260040160405180910390fd5b8054600282018054600160ff1990911617905560048054600160801b9092046001600160801b03169182919060009061159d908490612b00565b9091555050604051600090339083908381818185875af1925050503d80600081146115e4576040519150601f19603f3d011682016040523d82523d6000602084013e6115e9565b606091505b505090508061160b576040516312171d8360e31b815260040160405180910390fd5b604051828152849033907f038e5485c9947dae7ff2f1a9213b7cc1b6d0aee561a8bc6c768af736d007b6cb9060200160405180910390a350505061164d612420565b50565b60065460ff16156116745760405163da7c0e5560e01b815260040160405180910390fd5b6006805460ff19166001908117909155604051630a0daf8960e21b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260248201929092527f000000000000000000000000000000000000000000000000000000000000000090911690632836be2490604401600060405180830381600087803b15801561171157600080fd5b505af1158015611725573d6000803e3d6000fd5b5050604051630a0daf8960e21b8152306004820152600160248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169250632836be249150604401600060405180830381600087803b15801561179157600080fd5b505af11580156117a5573d6000803e3d6000fd5b50505050565b6000602482106117bd57506000919050565b6117c960016024612b00565b8203611832576000805b6117df60016024612b00565b811015611814576117f1816001612b4c565b61180a906b01313aca1515628511000000901c83612b4c565b91506001016117d3565b5061182b816b01313aca1515628511000000612b00565b9392505050565b61183d826001612b4c565b6b01313aca1515628511000000901c92915050565b6000602460005410158061116257506b01313aca15156285110000006002541015905090565b6000611882612081565b61188c8383612448565b9050611896612420565b92915050565b6118a4612931565b6001600160a01b03831660009081526007602052604090208054839081106118ce576118ce612bcc565b60009182526020918290206040805160c081018252600390930290910180546001600160801b038082168552600160801b918290048116958501959095526001820154948516928401929092526001600160401b0391840482166060840152600160c01b90930416608082015260029091015460ff16151560a0820152905092915050565b600061195d612081565b3360009081526007602052604090208054841061198d576040516309aab2bb60e41b815260040160405180910390fd5b805460009061199d908690612b00565b905060008185106119ae57816119b0565b845b6119ba9087612b4c565b9050855b81811015611a9d5760008482815481106119da576119da612bcc565b60009182526020909120600390910201600281015490915060ff16158015611a1657506001810154600160c01b90046001600160401b03164210155b15611a945760028101805460ff191660011790558054611a47906001600160801b03600160801b9091041687612b4c565b8154604051600160801b9091046001600160801b03168152909650829033907f038e5485c9947dae7ff2f1a9213b7cc1b6d0aee561a8bc6c768af736d007b6cb9060200160405180910390a35b506001016119be565b5083600003611abf576040516312d37ee560e31b815260040160405180910390fd5b8360046000828254611ad19190612b00565b9091555050604051600090339086908381818185875af1925050503d8060008114611b18576040519150601f19603f3d011682016040523d82523d6000602084013e611b1d565b606091505b5050905080611b3f576040516312171d8360e31b815260040160405180910390fd5b50505050611896612420565b60006127106103e8611b5b611158565b611b659190612b13565b6111629190612b2a565b6001600160a01b03831660009081526007602052604090208054606091908410611bcd576040805160008082526020820190925290611bc4565b611bb1612931565b815260200190600190039081611ba95790505b5091505061182b565b8054600090611bdd908690612b00565b90506000818510611bee5781611bf0565b845b611bfa9087612b4c565b9050611c068682612b00565b6001600160401b03811115611c1d57611c1d612be2565b604051908082528060200260200182016040528015611c5657816020015b611c43612931565b815260200190600190039081611c3b5790505b509350855b81811015611d2057838181548110611c7557611c75612bcc565b60009182526020918290206040805160c081018252600390930290910180546001600160801b038082168552600160801b918290048116958501959095526001820154948516928401929092526001600160401b0391840482166060840152600160c01b90930416608082015260029091015460ff16151560a082015285611cfd8984612b00565b81518110611d0d57611d0d612bcc565b6020908102919091010152600101611c5b565b505050509392505050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a8aa1b316040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d8b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611daf9190612b5f565b90506001600160a01b038116611dd8576040516315676c7960e11b815260040160405180910390fd5b604051630a0daf8960e21b81526001600160a01b038281166004830152600160248301527f00000000000000000000000000000000000000000000000000000000000000001690632836be2490604401600060405180830381600087803b158015611e4257600080fd5b505af1158015611e56573d6000803e3d6000fd5b5050505090565b60008054600154829190845b600081118015611e795750602483105b15611fa5577f0000000000000000000000000000000000000000000000000000000000000000831b6000611eac856117ab565b90506000848211611ebe576000611ec8565b611ec88583612b00565b905080600003611eeb57611edd600187612b4c565b955060009450505050611e69565b600083611f0086670de0b6b3a7640000612b13565b611f0a9190612b2a565b90506000828210611f1b5782611f1d565b815b905080600003611f31575050505050611fa5565b6000611f3d8287612892565b905086811115611f5257505050505050611fa5565b611f5c828c612b4c565b9a50611f68818b612b4c565b9950611f748188612b00565b965083821015611f8957505050505050611fa5565b611f9460018a612b4c565b985060009750505050505050611e69565b505050915091565b600080546001545b600084118015611fc55750602482105b1561207a576000611fd5836117ab565b90506000828211611fe7576000611ff1565b611ff18383612b00565b905060008187106120025781612004565b865b9050801561205157612038817f0000000000000000000000000000000000000000000000000000000000000000871b612892565b6120429087612b4c565b955061204e8188612b00565b96505b866000036120615750505061207a565b61206c600186612b4c565b945060009350505050611fb5565b5050919050565b6120896128df565b60027f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005b55565b805b6000811180156120c457506024600054105b156121c15760006120d66000546117ab565b9050600060015482116120ea5760006120f7565b6001546120f79083612b00565b90506000818410612108578161210a565b835b9050806001600082825461211e9190612b4c565b9091555061212e90508185612b00565b935082600154106121b957600160008082825461214b9190612b4c565b90915550506000600181905554602411156121b9576000546040517f0000000000000000000000000000000000000000000000000000000000000000821b81527f436f8a67d13337b231e33ab03052cadae3146cbd4b30eabcec024baa58f9e4239060200160405180910390a25b5050506120b2565b81600260008282546121d39190612b4c565b90915550505050565b60006127106121ed6107d084612b13565b6121f79190612b2a565b9050600061271061220a6103e885612b13565b6122149190612b2a565b905080600360008282546122289190612b4c565b90915550600090508161223b8486612b00565b6122459190612b00565b9050670de0b6b3a76400007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316636ade07b06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156122ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122d29190612bf8565b10156122f55782600560008282546122ea9190612b4c565b909155506123859050565b6000600554846123059190612b4c565b905060006005819055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663e4fc6b6d826040518263ffffffff1660e01b81526004016000604051808303818588803b15801561236a57600080fd5b505af115801561237e573d6000803e3d6000fd5b5050505050505b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168260405160006040518083038185875af1925050503d80600081146123f2576040519150601f19603f3d011682016040523d82523d6000602084013e6123f7565b606091505b5050905080612419576040516312171d8360e31b815260040160405180910390fd5b5050505050565b60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f006120ad565b600654600090610100900460ff1661247357604051631bb5f5b360e31b815260040160405180910390fd5b61247b611852565b156124995760405163243af4d960e11b815260040160405180910390fd5b60006124a3611158565b9050828111156124c6576040516338aa5c1560e01b815260040160405180910390fd5b600060001985036124e4576124da34611e5d565b909350905061250c565b84925060006124f1611335565b9050808411156124ff578093505b61250884611fad565b9150505b8260000361252d57604051631f2a200560e01b815260040160405180910390fd5b670de0b6b3a76400008310801561254a57506125476112d1565b83105b1561256857604051636989e9d160e11b815260040160405180910390fd5b803410156125895760405163949ce24160e01b815260040160405180910390fd5b612592836120b0565b60006127106125a361232884612b13565b6125ad9190612b2a565b905060006125bb8284612b00565b905081600460008282546125cf9190612b4c565b9250508190555060076000336001600160a01b03166001600160a01b031681526020019081526020016000206040518060c00160405280856001600160801b03168152602001846001600160801b03168152602001876001600160801b03168152602001426001600160401b0316815260200162015180426126519190612b4c565b6001600160401b03908116825260006020928301819052845460018082018755958252908390208451938501516001600160801b03948516600160801b91861682021760039093029091019182556040850151958201805460608701516080880151989096166001600160c01b031990911617948416909102939093176001600160c01b0316600160c01b959092169490940217905560a001516002909101805460ff1916911515919091179055612708816121dc565b6040516340c10f1960e01b8152336004820152602481018690527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906340c10f1990604401600060405180830381600087803b15801561277057600080fd5b505af1158015612784573d6000803e3d6000fd5b50505050600083346127969190612b00565b9050801561280957604051600090339083908381818185875af1925050503d80600081146127e0576040519150601f19603f3d011682016040523d82523d6000602084013e6127e5565b606091505b5050905080612807576040516312171d8360e31b815260040160405180910390fd5b505b3360009081526007602052604090205461282590600190612b00565b60005433907fea1c66caca012a8cb6b7540750241bea285f813b121558fd7133846a670b66bd9089888861285c6201518042612b4c565b604080519586526020860194909452928401919091526060830152608082015260a00160405180910390a3505050505092915050565b6000826000036128a457506000611896565b670de0b6b3a764000060016128b98486612b13565b6128cb90670de0b6b3a7640000612b4c565b6128d59190612b00565b61182b9190612b2a565b61290c600060027f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0061292a565b1561149b57604051633ee5aeb560e01b815260040160405180910390fd5b5414919050565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b60006020828403121561297857600080fd5b5035919050565b6001600160a01b038116811461164d57600080fd5b6000602082840312156129a657600080fd5b813561182b8161297f565b6000806000606084860312156129c657600080fd5b83356129d18161297f565b95602085013595506040909401359392505050565b600080604083850312156129f957600080fd5b50508035926020909101359150565b60008060408385031215612a1b57600080fd5b8235612a268161297f565b946020939093013593505050565b6001600160801b038082511683528060208301511660208401528060408301511660408401525060608101516001600160401b038082166060850152806080840151166080850152505060a0810151151560a08301525050565b60c081016118968284612a34565b6020808252825182820181905260009190848201906040850190845b81811015612ade57612acb838551612a34565b9284019260c09290920191600101612ab8565b50909695505050505050565b634e487b7160e01b600052601160045260246000fd5b8181038181111561189657611896612aea565b808202811582820484141761189657611896612aea565b600082612b4757634e487b7160e01b600052601260045260246000fd5b500490565b8082018082111561189657611896612aea565b600060208284031215612b7157600080fd5b815161182b8161297f565b600060208284031215612b8e57600080fd5b8151801515811461182b57600080fd5b600080600060608486031215612bb357600080fd5b8351925060208401519150604084015190509250925092565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600060208284031215612c0a57600080fd5b505191905056fea2646970667358221220b066cce5c1af3cd3d40fa1fa4e297393986a6671cfd49d3058155d49ad9dd0a864736f6c63430008180033000000000000000000000000688d8bf5237a42432ee6b4092e15e73c6bcbb80a000000000000000000000000da5734cd1013359bfea1943ee4b109f87e916a89000000000000000000000000788111ad3cf7f4d850e5811b5d78457b28b3914d000000000000000000000000000000000000000000000000000d1c091338a000

Deployed ByteCode

0x6080604052600436106102935760003560e01c806393c19e181161015a578063d89f2fa9116100c1578063ed1bd76c1161007a578063ed1bd76c1461075e578063ee67ccd71461077e578063f0cf5af614610525578063fc0c546a14610793578063fd326592146107c7578063fe60d12c146107e757600080fd5b8063d89f2fa91461069b578063d982ae84146106b1578063dc9d54ef146106c8578063e5d4a0d9146106f5578063e70abe921461070a578063ec81b4831461073e57600080fd5b8063bef4876b11610113578063bef4876b146105fc578063c478ea9814610611578063c5e3b2dd14610624578063c8df245a14610651578063cda0b07414610666578063d04c02381461068657600080fd5b806393c19e1814610551578063a868188814610585578063af91cf251461059a578063b49822ce146105b0578063b9f30afd146105c6578063bba553bb146105dc57600080fd5b80634b1e36f3116101fe57806370bbfa26116101b757806370bbfa26146104bb57806370e08e61146104db5780637eea3a101461042b57806380f6baff1461050f57806389f1fb7f146105255780638e07257e1461053b57600080fd5b80634b1e36f31461042b5780634d474898146104475780634f02c4201461045a57806355234ec0146104705780635f88eade14610485578063665b9aa3146104a457600080fd5b80632c4e722e116102505780632c4e722e1461036c578063349f2ecf1461038157806334a9642b146103a157806339d57b02146103b657806342fd3880146103e057806348a0d7541461041657600080fd5b80630937732c14610298578063158e35d9146102c85780631954bf6b146102ec578063209c53a31461030257806323e2b7f71461033757806326b387bb1461034c575b600080fd5b6102ab6102a6366004612966565b6107fd565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156102d457600080fd5b506102de60035481565b6040519081526020016102bf565b3480156102f857600080fd5b506102de61232881565b34801561030e57600080fd5b5061032261031d366004612994565b610e4a565b604080519283526020830191909152016102bf565b34801561034357600080fd5b506102de610f00565b34801561035857600080fd5b50610322610367366004612994565b6110aa565b34801561037857600080fd5b506102de611158565b34801561038d57600080fd5b5061032261039c3660046129b1565b611167565b3480156103ad57600080fd5b506102de611267565b3480156103c257600080fd5b506006546103d09060ff1681565b60405190151581526020016102bf565b3480156103ec57600080fd5b506102de6103fb366004612994565b6001600160a01b031660009081526007602052604090205490565b34801561042257600080fd5b506102de6112d1565b34801561043757600080fd5b506102de670de0b6b3a764000081565b6102de610455366004612966565b611315565b34801561046657600080fd5b506102de60025481565b34801561047c57600080fd5b506102de611335565b34801561049157600080fd5b506006546103d090610100900460ff1681565b3480156104b057600080fd5b506104b961136b565b005b3480156104c757600080fd5b506104b96104d6366004612966565b61149d565b3480156104e757600080fd5b506102ab7f000000000000000000000000da5734cd1013359bfea1943ee4b109f87e916a8981565b34801561051b57600080fd5b506102de6107d081565b34801561053157600080fd5b506102de6103e881565b34801561054757600080fd5b506102de60005481565b34801561055d57600080fd5b506102de7f000000000000000000000000000000000000000000000000000d1c091338a00081565b34801561059157600080fd5b506104b9611650565b3480156105a657600080fd5b506102ab61dead81565b3480156105bc57600080fd5b506102de60015481565b3480156105d257600080fd5b506102de611b5881565b3480156105e857600080fd5b506102de6105f7366004612966565b6117ab565b34801561060857600080fd5b506103d0611852565b6102de61061f3660046129e6565b611878565b34801561063057600080fd5b5061064461063f366004612a08565b61189c565b6040516102bf9190612a8e565b34801561065d57600080fd5b506000546102de565b34801561067257600080fd5b506102de6106813660046129e6565b611953565b34801561069257600080fd5b506102de611b4b565b3480156106a757600080fd5b506102de60055481565b3480156106bd57600080fd5b506102de6201518081565b3480156106d457600080fd5b506106e86106e33660046129b1565b611b6f565b6040516102bf9190612a9c565b34801561070157600080fd5b506102ab611d2b565b34801561071657600080fd5b506102ab7f000000000000000000000000788111ad3cf7f4d850e5811b5d78457b28b3914d81565b34801561074a57600080fd5b506102de6b01313aca151562851100000081565b34801561076a57600080fd5b50610322610779366004612966565b611e5d565b34801561078a57600080fd5b506102de602481565b34801561079f57600080fd5b506102ab7f000000000000000000000000688d8bf5237a42432ee6b4092e15e73c6bcbb80a81565b3480156107d357600080fd5b506102de6107e2366004612966565b611fad565b3480156107f357600080fd5b506102de60045481565b6000610807612081565b600654610100900460ff161561083057604051632597e36560e21b815260040160405180910390fd5b670de0b6b3a764000082101561085957604051636989e9d160e11b815260040160405180910390fd5b600061086483611fad565b905080341161088657604051636180f03f60e11b815260040160405180910390fd5b60006108928234612b00565b6006805461ff00191661010017905590506108ac846120b0565b60006127106108bd61232885612b13565b6108c79190612b2a565b905080600460008282546108db9190612b4c565b9250508190555060076000336001600160a01b03166001600160a01b031681526020019081526020016000206040518060c00160405280856001600160801b03168152602001836001600160801b03168152602001876001600160801b03168152602001426001600160401b03168152602001620151804261095d9190612b4c565b6001600160401b03908116825260006020928301819052845460018082018755958252908390208451938501516001600160801b03948516600160801b91861682021760039093029091019182556040850151958201805460608701516080880151989096166001600160c01b031990911617948416909102939093176001600160c01b0316600160c01b959092169490940217905560a001516002909101805460ff1916911515919091179055610a1d610a188285612b00565b6121dc565b6040516340c10f1960e01b8152306004820152602481018690527f000000000000000000000000688d8bf5237a42432ee6b4092e15e73c6bcbb80a6001600160a01b0316906340c10f1990604401600060405180830381600087803b158015610a8557600080fd5b505af1158015610a99573d6000803e3d6000fd5b5050505060007f000000000000000000000000da5734cd1013359bfea1943ee4b109f87e916a896001600160a01b031663f887ea406040518163ffffffff1660e01b8152600401602060405180830381865afa158015610afd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b219190612b5f565b60405163095ea7b360e01b81526001600160a01b038083166004830152602482018990529192507f000000000000000000000000688d8bf5237a42432ee6b4092e15e73c6bcbb80a9091169063095ea7b3906044016020604051808303816000875af1158015610b95573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bb99190612b7c565b5060405163f305d71960e01b81526001600160a01b037f000000000000000000000000688d8bf5237a42432ee6b4092e15e73c6bcbb80a8116600483015260248201889052604482018890526064820185905261dead60848301524260a483015282169063f305d71990859060c40160606040518083038185885af1158015610c46573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190610c6b9190612b9e565b5050507f000000000000000000000000da5734cd1013359bfea1943ee4b109f87e916a896001600160a01b031663a8aa1b316040518163ffffffff1660e01b8152600401602060405180830381865afa158015610ccc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cf09190612b5f565b604051630a0daf8960e21b81526001600160a01b038083166004830152600160248301529196507f000000000000000000000000688d8bf5237a42432ee6b4092e15e73c6bcbb80a90911690632836be2490604401600060405180830381600087803b158015610d5f57600080fd5b505af1158015610d73573d6000803e3d6000fd5b505060408051898152602081018790526001600160a01b03891693507f0e00eb3434eeed137478dadba5581f87fdda6f16b438d9d1b616b24093bfbb4292500160405180910390a233600090815260076020526040902054610dd790600190612b00565b60005433907fea1c66caca012a8cb6b7540750241bea285f813b121558fd7133846a670b66bd90898887610e0e6201518042612b4c565b604080519586526020860194909452928401919091526060830152608082015260a00160405180910390a350505050610e45612420565b919050565b6001600160a01b03811660009081526007602052604081208190815b8154811015610ef9576000828281548110610e8357610e83612bcc565b60009182526020909120600390910201600281015490915060ff16158015610ebf57506001810154600160c01b90046001600160401b03164210155b15610ef0578054610ee090600160801b90046001600160801b031686612b4c565b9450610eed600185612b4c565b93505b50600101610e66565b5050915091565b6000610f0a612081565b336000908152600760205260408120905b8154811015610ffb576000828281548110610f3857610f38612bcc565b60009182526020909120600390910201600281015490915060ff16158015610f7457506001810154600160c01b90046001600160401b03164210155b15610ff25760028101805460ff191660011790558054610fa5906001600160801b03600160801b9091041685612b4c565b8154604051600160801b9091046001600160801b03168152909450829033907f038e5485c9947dae7ff2f1a9213b7cc1b6d0aee561a8bc6c768af736d007b6cb9060200160405180910390a35b50600101610f1b565b508160000361101d576040516312d37ee560e31b815260040160405180910390fd5b816004600082825461102f9190612b00565b9091555050604051600090339084908381818185875af1925050503d8060008114611076576040519150601f19603f3d011682016040523d82523d6000602084013e61107b565b606091505b505090508061109d576040516312171d8360e31b815260040160405180910390fd5b50506110a7612420565b90565b6001600160a01b03811660009081526007602052604081208190815b8154811015610ef95760008282815481106110e3576110e3612bcc565b60009182526020909120600390910201600281015490915060ff1615801561111e57506001810154600160c01b90046001600160401b031642105b1561114f57805461113f90600160801b90046001600160801b031686612b4c565b945061114c600185612b4c565b93505b506001016110c6565b6000611162611267565b905090565b6001600160a01b03831660009081526007602052604081208054829190851061119757600080925092505061125f565b80546000906111a7908790612b00565b905060008186106111b857816111ba565b855b6111c49088612b4c565b9050865b8181101561125a5760008482815481106111e4576111e4612bcc565b60009182526020909120600390910201600281015490915060ff1615801561122057506001810154600160c01b90046001600160401b03164210155b1561125157805461124190600160801b90046001600160801b031688612b4c565b965061124e600187612b4c565b95505b506001016111c8565b505050505b935093915050565b60006024600054106112a75761127f60016024612b00565b7f000000000000000000000000000000000000000000000000000d1c091338a000901b905090565b506000547f000000000000000000000000000000000000000000000000000d1c091338a000901b90565b60006024600054106112e35750600090565b60006112f06000546117ab565b9050600154811161130257600061130f565b60015461130f9082612b00565b91505090565b600061131f612081565b61132b60001983612448565b9050610e45612420565b60006002546b01313aca1515628511000000116113525750600090565b600254611162906b01313aca1515628511000000612b00565b611373612081565b6003546000819003611398576040516312d37ee560e31b815260040160405180910390fd5b600060038190556040516001600160a01b037f000000000000000000000000788111ad3cf7f4d850e5811b5d78457b28b3914d169083908381818185875af1925050503d8060008114611407576040519150601f19603f3d011682016040523d82523d6000602084013e61140c565b606091505b505090508061142e576040516312171d8360e31b815260040160405180910390fd5b7f000000000000000000000000788111ad3cf7f4d850e5811b5d78457b28b3914d6001600160a01b03167fd8138f8a3f377c5259ca548e70e4c2de94f129f5a11036a15b69513cba2b426a8360405161148991815260200190565b60405180910390a2505061149b612420565b565b6114a5612081565b3360009081526007602052604090205481106114d4576040516309aab2bb60e41b815260040160405180910390fd5b3360009081526007602052604081208054839081106114f5576114f5612bcc565b60009182526020909120600390910201600281015490915060ff161561152e576040516312d37ee560e31b815260040160405180910390fd5b6001810154600160c01b90046001600160401b03164210156115635760405163069fbbbb60e11b815260040160405180910390fd5b8054600282018054600160ff1990911617905560048054600160801b9092046001600160801b03169182919060009061159d908490612b00565b9091555050604051600090339083908381818185875af1925050503d80600081146115e4576040519150601f19603f3d011682016040523d82523d6000602084013e6115e9565b606091505b505090508061160b576040516312171d8360e31b815260040160405180910390fd5b604051828152849033907f038e5485c9947dae7ff2f1a9213b7cc1b6d0aee561a8bc6c768af736d007b6cb9060200160405180910390a350505061164d612420565b50565b60065460ff16156116745760405163da7c0e5560e01b815260040160405180910390fd5b6006805460ff19166001908117909155604051630a0daf8960e21b81526001600160a01b037f000000000000000000000000da5734cd1013359bfea1943ee4b109f87e916a898116600483015260248201929092527f000000000000000000000000688d8bf5237a42432ee6b4092e15e73c6bcbb80a90911690632836be2490604401600060405180830381600087803b15801561171157600080fd5b505af1158015611725573d6000803e3d6000fd5b5050604051630a0daf8960e21b8152306004820152600160248201527f000000000000000000000000688d8bf5237a42432ee6b4092e15e73c6bcbb80a6001600160a01b03169250632836be249150604401600060405180830381600087803b15801561179157600080fd5b505af11580156117a5573d6000803e3d6000fd5b50505050565b6000602482106117bd57506000919050565b6117c960016024612b00565b8203611832576000805b6117df60016024612b00565b811015611814576117f1816001612b4c565b61180a906b01313aca1515628511000000901c83612b4c565b91506001016117d3565b5061182b816b01313aca1515628511000000612b00565b9392505050565b61183d826001612b4c565b6b01313aca1515628511000000901c92915050565b6000602460005410158061116257506b01313aca15156285110000006002541015905090565b6000611882612081565b61188c8383612448565b9050611896612420565b92915050565b6118a4612931565b6001600160a01b03831660009081526007602052604090208054839081106118ce576118ce612bcc565b60009182526020918290206040805160c081018252600390930290910180546001600160801b038082168552600160801b918290048116958501959095526001820154948516928401929092526001600160401b0391840482166060840152600160c01b90930416608082015260029091015460ff16151560a0820152905092915050565b600061195d612081565b3360009081526007602052604090208054841061198d576040516309aab2bb60e41b815260040160405180910390fd5b805460009061199d908690612b00565b905060008185106119ae57816119b0565b845b6119ba9087612b4c565b9050855b81811015611a9d5760008482815481106119da576119da612bcc565b60009182526020909120600390910201600281015490915060ff16158015611a1657506001810154600160c01b90046001600160401b03164210155b15611a945760028101805460ff191660011790558054611a47906001600160801b03600160801b9091041687612b4c565b8154604051600160801b9091046001600160801b03168152909650829033907f038e5485c9947dae7ff2f1a9213b7cc1b6d0aee561a8bc6c768af736d007b6cb9060200160405180910390a35b506001016119be565b5083600003611abf576040516312d37ee560e31b815260040160405180910390fd5b8360046000828254611ad19190612b00565b9091555050604051600090339086908381818185875af1925050503d8060008114611b18576040519150601f19603f3d011682016040523d82523d6000602084013e611b1d565b606091505b5050905080611b3f576040516312171d8360e31b815260040160405180910390fd5b50505050611896612420565b60006127106103e8611b5b611158565b611b659190612b13565b6111629190612b2a565b6001600160a01b03831660009081526007602052604090208054606091908410611bcd576040805160008082526020820190925290611bc4565b611bb1612931565b815260200190600190039081611ba95790505b5091505061182b565b8054600090611bdd908690612b00565b90506000818510611bee5781611bf0565b845b611bfa9087612b4c565b9050611c068682612b00565b6001600160401b03811115611c1d57611c1d612be2565b604051908082528060200260200182016040528015611c5657816020015b611c43612931565b815260200190600190039081611c3b5790505b509350855b81811015611d2057838181548110611c7557611c75612bcc565b60009182526020918290206040805160c081018252600390930290910180546001600160801b038082168552600160801b918290048116958501959095526001820154948516928401929092526001600160401b0391840482166060840152600160c01b90930416608082015260029091015460ff16151560a082015285611cfd8984612b00565b81518110611d0d57611d0d612bcc565b6020908102919091010152600101611c5b565b505050509392505050565b60007f000000000000000000000000da5734cd1013359bfea1943ee4b109f87e916a896001600160a01b031663a8aa1b316040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d8b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611daf9190612b5f565b90506001600160a01b038116611dd8576040516315676c7960e11b815260040160405180910390fd5b604051630a0daf8960e21b81526001600160a01b038281166004830152600160248301527f000000000000000000000000688d8bf5237a42432ee6b4092e15e73c6bcbb80a1690632836be2490604401600060405180830381600087803b158015611e4257600080fd5b505af1158015611e56573d6000803e3d6000fd5b5050505090565b60008054600154829190845b600081118015611e795750602483105b15611fa5577f000000000000000000000000000000000000000000000000000d1c091338a000831b6000611eac856117ab565b90506000848211611ebe576000611ec8565b611ec88583612b00565b905080600003611eeb57611edd600187612b4c565b955060009450505050611e69565b600083611f0086670de0b6b3a7640000612b13565b611f0a9190612b2a565b90506000828210611f1b5782611f1d565b815b905080600003611f31575050505050611fa5565b6000611f3d8287612892565b905086811115611f5257505050505050611fa5565b611f5c828c612b4c565b9a50611f68818b612b4c565b9950611f748188612b00565b965083821015611f8957505050505050611fa5565b611f9460018a612b4c565b985060009750505050505050611e69565b505050915091565b600080546001545b600084118015611fc55750602482105b1561207a576000611fd5836117ab565b90506000828211611fe7576000611ff1565b611ff18383612b00565b905060008187106120025781612004565b865b9050801561205157612038817f000000000000000000000000000000000000000000000000000d1c091338a000871b612892565b6120429087612b4c565b955061204e8188612b00565b96505b866000036120615750505061207a565b61206c600186612b4c565b945060009350505050611fb5565b5050919050565b6120896128df565b60027f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005b55565b805b6000811180156120c457506024600054105b156121c15760006120d66000546117ab565b9050600060015482116120ea5760006120f7565b6001546120f79083612b00565b90506000818410612108578161210a565b835b9050806001600082825461211e9190612b4c565b9091555061212e90508185612b00565b935082600154106121b957600160008082825461214b9190612b4c565b90915550506000600181905554602411156121b9576000546040517f000000000000000000000000000000000000000000000000000d1c091338a000821b81527f436f8a67d13337b231e33ab03052cadae3146cbd4b30eabcec024baa58f9e4239060200160405180910390a25b5050506120b2565b81600260008282546121d39190612b4c565b90915550505050565b60006127106121ed6107d084612b13565b6121f79190612b2a565b9050600061271061220a6103e885612b13565b6122149190612b2a565b905080600360008282546122289190612b4c565b90915550600090508161223b8486612b00565b6122459190612b00565b9050670de0b6b3a76400007f000000000000000000000000688d8bf5237a42432ee6b4092e15e73c6bcbb80a6001600160a01b0316636ade07b06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156122ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122d29190612bf8565b10156122f55782600560008282546122ea9190612b4c565b909155506123859050565b6000600554846123059190612b4c565b905060006005819055507f000000000000000000000000688d8bf5237a42432ee6b4092e15e73c6bcbb80a6001600160a01b031663e4fc6b6d826040518263ffffffff1660e01b81526004016000604051808303818588803b15801561236a57600080fd5b505af115801561237e573d6000803e3d6000fd5b5050505050505b60007f000000000000000000000000da5734cd1013359bfea1943ee4b109f87e916a896001600160a01b03168260405160006040518083038185875af1925050503d80600081146123f2576040519150601f19603f3d011682016040523d82523d6000602084013e6123f7565b606091505b5050905080612419576040516312171d8360e31b815260040160405180910390fd5b5050505050565b60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f006120ad565b600654600090610100900460ff1661247357604051631bb5f5b360e31b815260040160405180910390fd5b61247b611852565b156124995760405163243af4d960e11b815260040160405180910390fd5b60006124a3611158565b9050828111156124c6576040516338aa5c1560e01b815260040160405180910390fd5b600060001985036124e4576124da34611e5d565b909350905061250c565b84925060006124f1611335565b9050808411156124ff578093505b61250884611fad565b9150505b8260000361252d57604051631f2a200560e01b815260040160405180910390fd5b670de0b6b3a76400008310801561254a57506125476112d1565b83105b1561256857604051636989e9d160e11b815260040160405180910390fd5b803410156125895760405163949ce24160e01b815260040160405180910390fd5b612592836120b0565b60006127106125a361232884612b13565b6125ad9190612b2a565b905060006125bb8284612b00565b905081600460008282546125cf9190612b4c565b9250508190555060076000336001600160a01b03166001600160a01b031681526020019081526020016000206040518060c00160405280856001600160801b03168152602001846001600160801b03168152602001876001600160801b03168152602001426001600160401b0316815260200162015180426126519190612b4c565b6001600160401b03908116825260006020928301819052845460018082018755958252908390208451938501516001600160801b03948516600160801b91861682021760039093029091019182556040850151958201805460608701516080880151989096166001600160c01b031990911617948416909102939093176001600160c01b0316600160c01b959092169490940217905560a001516002909101805460ff1916911515919091179055612708816121dc565b6040516340c10f1960e01b8152336004820152602481018690527f000000000000000000000000688d8bf5237a42432ee6b4092e15e73c6bcbb80a6001600160a01b0316906340c10f1990604401600060405180830381600087803b15801561277057600080fd5b505af1158015612784573d6000803e3d6000fd5b50505050600083346127969190612b00565b9050801561280957604051600090339083908381818185875af1925050503d80600081146127e0576040519150601f19603f3d011682016040523d82523d6000602084013e6127e5565b606091505b5050905080612807576040516312171d8360e31b815260040160405180910390fd5b505b3360009081526007602052604090205461282590600190612b00565b60005433907fea1c66caca012a8cb6b7540750241bea285f813b121558fd7133846a670b66bd9089888861285c6201518042612b4c565b604080519586526020860194909452928401919091526060830152608082015260a00160405180910390a3505050505092915050565b6000826000036128a457506000611896565b670de0b6b3a764000060016128b98486612b13565b6128cb90670de0b6b3a7640000612b4c565b6128d59190612b00565b61182b9190612b2a565b61290c600060027f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0061292a565b1561149b57604051633ee5aeb560e01b815260040160405180910390fd5b5414919050565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b60006020828403121561297857600080fd5b5035919050565b6001600160a01b038116811461164d57600080fd5b6000602082840312156129a657600080fd5b813561182b8161297f565b6000806000606084860312156129c657600080fd5b83356129d18161297f565b95602085013595506040909401359392505050565b600080604083850312156129f957600080fd5b50508035926020909101359150565b60008060408385031215612a1b57600080fd5b8235612a268161297f565b946020939093013593505050565b6001600160801b038082511683528060208301511660208401528060408301511660408401525060608101516001600160401b038082166060850152806080840151166080850152505060a0810151151560a08301525050565b60c081016118968284612a34565b6020808252825182820181905260009190848201906040850190845b81811015612ade57612acb838551612a34565b9284019260c09290920191600101612ab8565b50909695505050505050565b634e487b7160e01b600052601160045260246000fd5b8181038181111561189657611896612aea565b808202811582820484141761189657611896612aea565b600082612b4757634e487b7160e01b600052601260045260246000fd5b500490565b8082018082111561189657611896612aea565b600060208284031215612b7157600080fd5b815161182b8161297f565b600060208284031215612b8e57600080fd5b8151801515811461182b57600080fd5b600080600060608486031215612bb357600080fd5b8351925060208401519150604084015190509250925092565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b600060208284031215612c0a57600080fd5b505191905056fea2646970667358221220b066cce5c1af3cd3d40fa1fa4e297393986a6671cfd49d3058155d49ad9dd0a864736f6c63430008180033