false
true
0

Contract Address Details

0x8B57647c66110B35584b6190E282A7884b56fF9a

Token
TWAP (TWAP)
Creator
0x696fc8–bf69cb at 0xbdfba5–a4c5b3
Balance
0 PLS ( )
Tokens
Fetching tokens...
Transactions
68 Transactions
Transfers
0 Transfers
Gas Used
4,794,965
Last Balance Update
26173589
Contract is not verified. However, we found a verified contract with the same bytecode in Blockscout DB 0xa86bf8669d4a6152f73f330f3cf7a97542f78c42.
All metadata displayed below is from that contract. In order to verify current contract, click Verify & Publish button
Verify & Publish
Contract name:
TWAPOracle




Optimization enabled
true
Compiler version
v0.8.28+commit.7893614a




Optimization runs
200
Verified at
2026-02-15T10:12:41.375573Z

contracts/dss/twap.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IUniswapV2Pair {
    function price0CumulativeLast() external view returns (uint);
    function price1CumulativeLast() external view returns (uint);
    function getReserves()
        external
        view
        returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
    function token0() external view returns (address);
    function token1() external view returns (address);
}

interface IERC20Decimals {
    function decimals() external view returns (uint8);
}

library FixedPoint {
    struct uq112x112 { uint224 _x; }
    struct uq144x112 { uint _x; }
    uint8 private constant RESOLUTION = 112;

    function encode(uint112 x) internal pure returns (uq112x112 memory) {
        return uq112x112(uint224(x) << RESOLUTION);
    }
    function mul(uq112x112 memory self, uint y) internal pure returns (uq144x112 memory) {
        return uq144x112(self._x * y);
    }
    function fraction(uint112 numerator, uint112 denominator) internal pure returns (uq112x112 memory) {
        if (denominator == 0) revert("FixedPoint: DIV_BY_ZERO");
        return uq112x112((uint224(numerator) << RESOLUTION) / denominator);
    }
    function decode144(uq144x112 memory self) internal pure returns (uint144) {
        return uint144(self._x >> RESOLUTION);
    }

    // Optimized RPower for reward calculation (Logarithmic time complexity)
    // Calculates x^n with 1e18 precision to match contract constants
    function rpow(uint x, uint n) internal pure returns (uint z) {
        z = n % 2 != 0 ? x : 1e18;
        for (n /= 2; n != 0; n /= 2) {
            x = (x * x) / 1e18;
            if (n % 2 != 0) z = (z * x) / 1e18;
        }
    }
}

library UniswapV2OracleLibrary {
    using FixedPoint for *;

    function currentBlockTimestamp() internal view returns (uint) { return block.timestamp; }

    function currentCumulativePrices(address pair) internal view returns (uint price0Cumulative, uint price1Cumulative, uint blockTimestamp) {
        blockTimestamp = currentBlockTimestamp();
        price0Cumulative = IUniswapV2Pair(pair).price0CumulativeLast();
        price1Cumulative = IUniswapV2Pair(pair).price1CumulativeLast();
        (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast) = IUniswapV2Pair(pair).getReserves();
        if (blockTimestampLast != blockTimestamp) {
            uint32 timeElapsed = uint32(blockTimestamp - blockTimestampLast);
            unchecked {
                price0Cumulative += uint(FixedPoint.fraction(reserve1, reserve0)._x) * timeElapsed;
                price1Cumulative += uint(FixedPoint.fraction(reserve0, reserve1)._x) * timeElapsed;
            }
        }
    }

    struct PriceData { uint price0Cumulative; uint price1Cumulative; }

    function batchCumulativePrices(address[] memory pairs) internal view returns (PriceData[] memory prices, uint blockTimestamp) {
        blockTimestamp = currentBlockTimestamp();
        prices = new PriceData[](pairs.length);
        for (uint i; i < pairs.length; ) {
            IUniswapV2Pair pair = IUniswapV2Pair(pairs[i]);
            uint price0Cumulative = pair.price0CumulativeLast();
            uint price1Cumulative = pair.price1CumulativeLast();
            (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast) = pair.getReserves();
            if (blockTimestampLast != blockTimestamp) {
                uint32 timeElapsed = uint32(blockTimestamp - blockTimestampLast);
                unchecked {
                    price0Cumulative += uint(FixedPoint.fraction(reserve1, reserve0)._x) * timeElapsed;
                    price1Cumulative += uint(FixedPoint.fraction(reserve0, reserve1)._x) * timeElapsed;
                }
            }
            prices[i] = PriceData(price0Cumulative, price1Cumulative);
            unchecked { ++i; }
        }
    }
}

contract TWAPOracle {
    using FixedPoint for *;

    struct Observation {
        uint timestamp;
        uint price0Cumulative;
        uint price1Cumulative;
    }

    struct ReferenceStable {
        address stable;
        address pair;
        bool isWplsToken0;
        uint8 stableDecimals;
        bool active;
    }

    struct PairInfo {
        address pair;
        bool isToken0;
    }

    error UnknownPair();
    error PairAlreadyAdded();
    error InvalidPair();
    error InvalidTWAPWindow();
    error Unauthorized();
    error PeriodNotElapsed();
    error RewardsNotEnabled();
    error InsufficientBalanceForReward();
    error AlreadyLaunched();
    error NoValidReferences();
    error StalePrice();

    address public immutable wpls;

    mapping(address => uint) public wards;
    function rely(address usr) external auth { wards[usr] = 1; emit Rely(usr); }
    function deny(address usr) external auth { wards[usr] = 0; emit Deny(usr); }
    modifier auth() {
        if (wards[msg.sender] != 1) revert Unauthorized();
        _;
    }

    bool public rewardsEnabled;

    uint public constant PERIOD_SIZE = 3600;
    uint public constant MIN_WINDOW = 3600;
    uint public constant MAX_WINDOW = 18000;
    uint public constant REWARD_WINDOW = 5400; // Peak at 1.5hr total (0.5hr effective)
    uint public constant UPDATE_THRESHOLD = 7200;

    uint public constant DECAY_RATE = 500000000000000000; // 0.5
    uint public constant DECAY_PERIOD = 900;

    string public constant name = "TWAP";
    string public constant symbol = "TWAP";
    uint8 public constant decimals = 18;
    uint public totalSupply;
    mapping(address => uint) public balanceOf;
    mapping(address => mapping(address => uint)) public allowance;

    uint public constant BASE_REWARD_RATE = 13888888888888888;
    uint public constant INITIAL_SUPPLY = 1_000_000 * 10 ** 18;
    uint public constant MIN_HOLDING_DIVISOR = 555;

    // OPTIMIZED: Circular Buffer Data
    mapping(address => Observation[5]) public observations;     // pair => observations
    mapping(address => uint8) public observationHeads;          // pair => next write index (0-4)
    
    // OPTIMIZED: Unified List for Updates
    address[] public livePairs;
    
    mapping(address => PairInfo) public tokenToPairInfo;
    address[] public pricedTokens;

    // REMOVED: mapping(address => uint) public lastUpdateTimestamp; (Redundant, use observation timestamp)

    ReferenceStable[] public referenceStables;

    event PriceUpdated(address indexed token, address indexed pair, uint price0Cumulative, uint price1Cumulative, uint timestamp);
    event Transfer(address indexed from, address indexed to, uint value);
    event Approval(address indexed owner, address indexed spender, uint value);
    event Reward(address indexed updater, uint amount);
    event RewardsLaunched();
    event Rely(address indexed usr);
    event Deny(address indexed usr);
    event ReferenceAdded(address indexed stable, address indexed pair, bool isWplsToken0, uint8 stableDecimals);
    event ReferenceUpdated(uint indexed index, bool active);
    event DirectPairAdded(address indexed token, address indexed pair, bool isToken0);
    event DirectPairRemoved(address indexed token);
    event SuperUpdate(uint timestamp, uint updatedPairs);

    uint public lastSuperUpdateTimestamp;

    constructor(address _wpls) {
        wpls = _wpls;
        wards[msg.sender] = 1;
        emit Rely(msg.sender);
        totalSupply = INITIAL_SUPPLY;
        balanceOf[msg.sender] = INITIAL_SUPPLY;
        emit Transfer(address(0), msg.sender, INITIAL_SUPPLY);
    }

    function getMinHoldingForReward() public view returns (uint) { return totalSupply / MIN_HOLDING_DIVISOR; }

    function launch() external auth {
        if (rewardsEnabled) revert AlreadyLaunched();
        rewardsEnabled = true;
        emit RewardsLaunched();
    }

    // === REFERENCE STABLES ===
    function addReferenceStable(address stable, address pair, bool isWplsToken0) external auth {
        address token0 = IUniswapV2Pair(pair).token0();
        address token1 = IUniswapV2Pair(pair).token1();
        if ((isWplsToken0 && token0 != wpls) || (!isWplsToken0 && token1 != wpls)) revert InvalidPair();

        uint8 stableDecimals = IERC20Decimals(stable).decimals();
        if (stableDecimals > 18) revert("Stable decimals >18");

        referenceStables.push(ReferenceStable(stable, pair, isWplsToken0, stableDecimals, true));

        // Initialize Observation
        (uint price0Cumulative, uint price1Cumulative, ) = UniswapV2OracleLibrary.currentCumulativePrices(pair);
        observations[pair][0] = Observation(block.timestamp, price0Cumulative, price1Cumulative);
        observationHeads[pair] = 1; // Next write goes to index 1
        
        // OPTIMIZATION: Add to unified list
        livePairs.push(pair);

        emit ReferenceAdded(stable, pair, isWplsToken0, stableDecimals);
    }

    function updateReference(uint index, bool active) external auth {
        if (index >= referenceStables.length) revert("Invalid index");
        referenceStables[index].active = active;
        emit ReferenceUpdated(index, active);
    }

    // === DIRECT PAIRS ===
    function addDirectPair(address token, address pair, bool isToken0) external auth {
        if (tokenToPairInfo[token].pair != address(0)) revert PairAlreadyAdded();

        address token0 = IUniswapV2Pair(pair).token0();
        address token1 = IUniswapV2Pair(pair).token1();
        if ((isToken0 && token0 != token) || (!isToken0 && token1 != token)) revert InvalidPair();

        tokenToPairInfo[token] = PairInfo(pair, isToken0);
        pricedTokens.push(token);

        // Initialize Observation
        (uint price0Cumulative, uint price1Cumulative, ) = UniswapV2OracleLibrary.currentCumulativePrices(pair);
        observations[pair][0] = Observation(block.timestamp, price0Cumulative, price1Cumulative);
        observationHeads[pair] = 1;

        // OPTIMIZATION: Add to unified list
        livePairs.push(pair);

        emit DirectPairAdded(token, pair, isToken0);
    }

    function removeDirectPair(address token) external auth {
        PairInfo memory info = tokenToPairInfo[token];
        if (info.pair == address(0)) revert UnknownPair();

        delete tokenToPairInfo[token];
        
        // OPTIMIZATION: Remove from livePairs
        _removeLivePair(info.pair);

        // Clean up storage for gas refund
        delete observations[info.pair];
        delete observationHeads[info.pair];

        // Remove from pricedTokens
        for (uint i = 0; i < pricedTokens.length; i++) {
            if (pricedTokens[i] == token) {
                pricedTokens[i] = pricedTokens[pricedTokens.length - 1];
                pricedTokens.pop();
                break;
            }
        }
        emit DirectPairRemoved(token);
    }

    // Helper to remove from livePairs array
    function _removeLivePair(address pair) internal {
        for (uint i = 0; i < livePairs.length; i++) {
            if (livePairs[i] == pair) {
                livePairs[i] = livePairs[livePairs.length - 1];
                livePairs.pop();
                break;
            }
        }
    }

    // === OPTIMIZED: superUpdate ===
    function superUpdate() public {
        uint currentTimestamp = block.timestamp;

        if (currentTimestamp - lastSuperUpdateTimestamp < MIN_WINDOW) {
            revert PeriodNotElapsed();
        }

        // OPTIMIZATION: Single Pass Collection
        // We allocate max memory size to avoid resizing costs. 
        // Since we have < 100 pairs, this is acceptable gas wise vs dynamic pushing.
        uint totalPairs = livePairs.length;
        address[] memory pairsToUpdate = new address[](totalPairs);
        uint updateCount = 0;

        for (uint i = 0; i < totalPairs; ) {
            address pair = livePairs[i];
            
            // Get the index of the most recently written observation
            uint8 head = observationHeads[pair];
            uint8 lastIdx = (head == 0) ? 4 : head - 1;
            
            // Check timestamp of the latest observation instead of a separate mapping
            if (currentTimestamp - observations[pair][lastIdx].timestamp >= PERIOD_SIZE) {
                pairsToUpdate[updateCount] = pair;
                unchecked { ++updateCount; }
            }
            unchecked { ++i; }
        }

        if (updateCount > 0) {
            // Create a properly sized array for the batch call
            address[] memory activeBatch = new address[](updateCount);
            for (uint i = 0; i < updateCount; i++) {
                activeBatch[i] = pairsToUpdate[i];
            }

            (UniswapV2OracleLibrary.PriceData[] memory prices, ) = 
                UniswapV2OracleLibrary.batchCumulativePrices(activeBatch);

            for (uint i = 0; i < updateCount; i++) {
                _applyUpdate(activeBatch[i], prices[i], currentTimestamp);
            }

            if (rewardsEnabled && balanceOf[msg.sender] >= getMinHoldingForReward()) {
                uint reward = calculateReward(currentTimestamp);
                if (reward > 0) _mintReward(msg.sender, reward);
            }
        }

        lastSuperUpdateTimestamp = currentTimestamp;
        emit SuperUpdate(currentTimestamp, updateCount);
    }

    // === OPTIMIZED: Circular Buffer Update ===
    function _applyUpdate(address pair, UniswapV2OracleLibrary.PriceData memory price, uint blockTimestamp) private {
        uint8 head = observationHeads[pair];
        
        // Overwrite the oldest observation
        observations[pair][head] = Observation(
            block.timestamp, 
            price.price0Cumulative, 
            price.price1Cumulative
        );

        // Move head forward (0 -> 1 -> 2 -> 3 -> 4 -> 0)
        observationHeads[pair] = (head + 1) % 5;
        
        emit PriceUpdated(address(0), pair, price.price0Cumulative, price.price1Cumulative, blockTimestamp);
    }

    // === OPTIMIZED: Read & Sort ===
    function getMedianPrice(address pair, bool needPrice0, uint currentCumulative, uint currentTimestamp) internal view returns (uint224 medianPrice) {
        // 1. Load all 5 observations into memory
        Observation[5] memory obsArray;
        for(uint i=0; i<5; i++) {
            obsArray[i] = observations[pair][i];
        }

        // 2. Sort by timestamp (Descending: Newest first)
        // Using insertion sort for efficiency on small arrays
        for (uint i = 1; i < 5; ) {
            Observation memory key = obsArray[i];
            uint j = i;
            while (j > 0 && obsArray[j-1].timestamp < key.timestamp) {
                obsArray[j] = obsArray[j-1];
                j--;
            }
            obsArray[j] = key;
            unchecked { ++i; }
        }

        // 3. Calculate Segment TWAPs
        uint224[] memory segmentPrices = new uint224[](5);
        uint count = 0;
        uint prevCum = currentCumulative;
        uint prevTs = currentTimestamp;

        for (uint i = 0; i < 5; i++) {
            if (obsArray[i].timestamp == 0) continue;
            uint timeElapsed = prevTs - obsArray[i].timestamp;
            
            if (timeElapsed < MIN_WINDOW || timeElapsed > MAX_WINDOW) continue;

            uint obsCum = needPrice0 ? obsArray[i].price0Cumulative : obsArray[i].price1Cumulative;
            uint segmentTWAP = (prevCum - obsCum) / timeElapsed;
            segmentPrices[count] = uint224(segmentTWAP);
            count++;

            prevCum = obsCum;
            prevTs = obsArray[i].timestamp;
        }

        if (count == 0) revert InvalidTWAPWindow();

        // Sort Segment Prices
        for (uint i = 1; i < count; ) {
            uint224 key = segmentPrices[i];
            uint j = i;
            while (j > 0 && segmentPrices[j - 1] > key) {
                segmentPrices[j] = segmentPrices[j - 1];
                j--;
            }
            segmentPrices[j] = key;
            unchecked { ++i; }
        }

        if (count % 2 == 1) {
            medianPrice = segmentPrices[count / 2];
        } else {
            medianPrice = (segmentPrices[count / 2 - 1] + segmentPrices[count / 2]) / 2;
        }
    }

    function _getNormalizedPriceFromRef(ReferenceStable memory ref) internal view returns (uint priceNormalized) {
        (uint112 reserve0, uint112 reserve1, ) = IUniswapV2Pair(ref.pair).getReserves();
        uint wplsReserve = ref.isWplsToken0 ? uint(reserve0) : uint(reserve1);
        if (wplsReserve == 0) return 0;

        (uint price0Cumulative, uint price1Cumulative, uint blockTimestamp) = UniswapV2OracleLibrary.currentCumulativePrices(ref.pair);
        bool needPrice0 = ref.isWplsToken0;
        uint224 medianPrice = getMedianPrice(ref.pair, needPrice0, needPrice0 ? price0Cumulative : price1Cumulative, blockTimestamp);

        FixedPoint.uq144x112 memory fullPrice = FixedPoint.uq112x112(medianPrice).mul(1e18);
        uint priceNative = FixedPoint.decode144(fullPrice);

        uint decimalAdjustment = 10 ** (18 - ref.stableDecimals);
        priceNormalized = priceNative * decimalAdjustment;
    }

    function getWplsPriceInUsd() public view returns (uint priceWad) {
        uint validCount = 0;
        uint[] memory prices = new uint[](referenceStables.length);

        for (uint i = 0; i < referenceStables.length; i++) {
            ReferenceStable memory ref = referenceStables[i];
            if (!ref.active) continue;

            uint price = _getNormalizedPriceFromRef(ref);
            if (price == 0) continue;

            prices[validCount] = price;
            validCount++;
        }

        if (validCount == 0) revert NoValidReferences();

        // Sort Prices
        for (uint i = 0; i < validCount; i++) {
            for (uint j = i + 1; j < validCount; j++) {
                if (prices[i] > prices[j]) {
                    uint temp = prices[i];
                    prices[i] = prices[j];
                    prices[j] = temp;
                }
            }
        }

        if (validCount % 2 == 1) {
            priceWad = prices[validCount / 2];
        } else {
            priceWad = (prices[validCount / 2 - 1] + prices[validCount / 2]) / 2;
        }
    }

    function getPriceInUsd(address token, uint amountIn) public view returns (uint amountOutUsd) {
        if (token == wpls) {
            return (amountIn * getWplsPriceInUsd()) / 1e18;
        }

        PairInfo memory info = tokenToPairInfo[token];
        if (info.pair != address(0)) {
            (uint price0Cumulative, uint price1Cumulative, uint blockTimestamp) = UniswapV2OracleLibrary.currentCumulativePrices(info.pair);
            uint224 medianPrice = getMedianPrice(info.pair, info.isToken0, info.isToken0 ? price0Cumulative : price1Cumulative, blockTimestamp);

            FixedPoint.uq144x112 memory temp = FixedPoint.uq112x112(medianPrice).mul(amountIn);
            uint amountInWpls = FixedPoint.decode144(temp);

            amountOutUsd = (amountInWpls * getWplsPriceInUsd()) / 1e18;
        } else {
            revert UnknownPair();
        }
    }

    function _mintReward(address updater, uint reward) private {
        if (!rewardsEnabled) revert RewardsNotEnabled();
        uint holding = balanceOf[updater];
        uint minHolding = getMinHoldingForReward();
        if (holding < minHolding) revert InsufficientBalanceForReward();
        if (reward == 0) return;
        totalSupply += reward;
        balanceOf[updater] += reward;
        emit Reward(updater, reward);
    }

    // === OPTIMIZED REWARD MATH ===
    function calculateReward(uint currentTime) internal view returns (uint) {
        if (!rewardsEnabled) return 0;
        uint timeSinceLast = currentTime - lastSuperUpdateTimestamp;
        if (timeSinceLast < MIN_WINDOW) return 0;

        uint effectiveTime = timeSinceLast - MIN_WINDOW;
        uint peakEffectiveTime = REWARD_WINDOW - MIN_WINDOW;

        uint timeBasedReward;
        if (effectiveTime <= peakEffectiveTime) {
            timeBasedReward = BASE_REWARD_RATE * effectiveTime;
        } else {
            uint cappedExtra = effectiveTime - peakEffectiveTime;
            
            // OPTIMIZATION: Use Logarithmic Power function instead of loop
            uint decayIntervals = cappedExtra / DECAY_PERIOD;
            
            // rpow calculates (DECAY_RATE ^ decayIntervals)
            // DECAY_RATE is 5e17 (0.5), rpow expects 1e18 precision
            uint decayFactor = FixedPoint.rpow(DECAY_RATE, decayIntervals);
            
            uint peakReward = BASE_REWARD_RATE * peakEffectiveTime;
            timeBasedReward = (peakReward * decayFactor) / 1e18;
        }

        uint supplyFactor = 1e18;
        if (totalSupply > INITIAL_SUPPLY) {
            uint a = INITIAL_SUPPLY;
            uint b = totalSupply;
            supplyFactor = (2 * a * 1e18) / (a + b);
        }
        return (timeBasedReward * supplyFactor) / 1e18;
    }

    // === ERC20 IMPLEMENTATION ===
    function transfer(address to, uint256 value) external returns (bool) {
        require(to != address(0), "ERC20: transfer to the zero address");
        require(balanceOf[msg.sender] >= value, "ERC20: transfer amount exceeds balance");

        balanceOf[msg.sender] -= value;
        balanceOf[to] += value;
        emit Transfer(msg.sender, to, value);
        return true;
    }

    function transferFrom(address from, address to, uint256 value) external returns (bool) {
        require(from != address(0), "ERC20: transfer from the zero address");
        require(to != address(0), "ERC20: transfer to the zero address");
        require(balanceOf[from] >= value, "ERC20: transfer amount exceeds balance");
        require(allowance[from][msg.sender] >= value, "ERC20: insufficient allowance");

        balanceOf[from] -= value;
        balanceOf[to] += value;
        allowance[from][msg.sender] -= value;
        emit Transfer(from, to, value);
        return true;
    }

    function approve(address spender, uint256 value) external returns (bool) {
        allowance[msg.sender][spender] = value;
        emit Approval(msg.sender, spender, value);
        return true;
    }

    // === VIEW HELPERS ===
    function getTokens() external view returns (address[] memory) { return pricedTokens; }
    function getReferenceCount() external view returns (uint) { return referenceStables.length; }
    function getPricedTokenCount() external view returns (uint) { return pricedTokens.length; }
    function getCurrentReward() external view returns (uint) { return calculateReward(block.timestamp); }
}
        

Compiler Settings

{"outputSelection":{"*":{"*":["*"],"":["*"]}},"optimizer":{"runs":200,"enabled":true},"libraries":{},"evmVersion":"paris"}
              

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_wpls","internalType":"address"}]},{"type":"error","name":"AlreadyLaunched","inputs":[]},{"type":"error","name":"InsufficientBalanceForReward","inputs":[]},{"type":"error","name":"InvalidPair","inputs":[]},{"type":"error","name":"InvalidTWAPWindow","inputs":[]},{"type":"error","name":"NoValidReferences","inputs":[]},{"type":"error","name":"PairAlreadyAdded","inputs":[]},{"type":"error","name":"PeriodNotElapsed","inputs":[]},{"type":"error","name":"RewardsNotEnabled","inputs":[]},{"type":"error","name":"StalePrice","inputs":[]},{"type":"error","name":"Unauthorized","inputs":[]},{"type":"error","name":"UnknownPair","inputs":[]},{"type":"event","name":"Approval","inputs":[{"type":"address","name":"owner","internalType":"address","indexed":true},{"type":"address","name":"spender","internalType":"address","indexed":true},{"type":"uint256","name":"value","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Deny","inputs":[{"type":"address","name":"usr","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"DirectPairAdded","inputs":[{"type":"address","name":"token","internalType":"address","indexed":true},{"type":"address","name":"pair","internalType":"address","indexed":true},{"type":"bool","name":"isToken0","internalType":"bool","indexed":false}],"anonymous":false},{"type":"event","name":"DirectPairRemoved","inputs":[{"type":"address","name":"token","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"PriceUpdated","inputs":[{"type":"address","name":"token","internalType":"address","indexed":true},{"type":"address","name":"pair","internalType":"address","indexed":true},{"type":"uint256","name":"price0Cumulative","internalType":"uint256","indexed":false},{"type":"uint256","name":"price1Cumulative","internalType":"uint256","indexed":false},{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"ReferenceAdded","inputs":[{"type":"address","name":"stable","internalType":"address","indexed":true},{"type":"address","name":"pair","internalType":"address","indexed":true},{"type":"bool","name":"isWplsToken0","internalType":"bool","indexed":false},{"type":"uint8","name":"stableDecimals","internalType":"uint8","indexed":false}],"anonymous":false},{"type":"event","name":"ReferenceUpdated","inputs":[{"type":"uint256","name":"index","internalType":"uint256","indexed":true},{"type":"bool","name":"active","internalType":"bool","indexed":false}],"anonymous":false},{"type":"event","name":"Rely","inputs":[{"type":"address","name":"usr","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Reward","inputs":[{"type":"address","name":"updater","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"RewardsLaunched","inputs":[],"anonymous":false},{"type":"event","name":"SuperUpdate","inputs":[{"type":"uint256","name":"timestamp","internalType":"uint256","indexed":false},{"type":"uint256","name":"updatedPairs","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Transfer","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"value","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"BASE_REWARD_RATE","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"DECAY_PERIOD","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"DECAY_RATE","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"INITIAL_SUPPLY","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"MAX_WINDOW","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"MIN_HOLDING_DIVISOR","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"MIN_WINDOW","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"PERIOD_SIZE","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"REWARD_WINDOW","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"UPDATE_THRESHOLD","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"addDirectPair","inputs":[{"type":"address","name":"token","internalType":"address"},{"type":"address","name":"pair","internalType":"address"},{"type":"bool","name":"isToken0","internalType":"bool"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"addReferenceStable","inputs":[{"type":"address","name":"stable","internalType":"address"},{"type":"address","name":"pair","internalType":"address"},{"type":"bool","name":"isWplsToken0","internalType":"bool"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"allowance","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"approve","inputs":[{"type":"address","name":"spender","internalType":"address"},{"type":"uint256","name":"value","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"balanceOf","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"decimals","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"deny","inputs":[{"type":"address","name":"usr","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getCurrentReward","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getMinHoldingForReward","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"amountOutUsd","internalType":"uint256"}],"name":"getPriceInUsd","inputs":[{"type":"address","name":"token","internalType":"address"},{"type":"uint256","name":"amountIn","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getPricedTokenCount","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getReferenceCount","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address[]","name":"","internalType":"address[]"}],"name":"getTokens","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"priceWad","internalType":"uint256"}],"name":"getWplsPriceInUsd","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"lastSuperUpdateTimestamp","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"launch","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"livePairs","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"name","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"observationHeads","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"timestamp","internalType":"uint256"},{"type":"uint256","name":"price0Cumulative","internalType":"uint256"},{"type":"uint256","name":"price1Cumulative","internalType":"uint256"}],"name":"observations","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"pricedTokens","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"stable","internalType":"address"},{"type":"address","name":"pair","internalType":"address"},{"type":"bool","name":"isWplsToken0","internalType":"bool"},{"type":"uint8","name":"stableDecimals","internalType":"uint8"},{"type":"bool","name":"active","internalType":"bool"}],"name":"referenceStables","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"rely","inputs":[{"type":"address","name":"usr","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"removeDirectPair","inputs":[{"type":"address","name":"token","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"rewardsEnabled","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"superUpdate","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"symbol","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"pair","internalType":"address"},{"type":"bool","name":"isToken0","internalType":"bool"}],"name":"tokenToPairInfo","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalSupply","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"transfer","inputs":[{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"value","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"transferFrom","inputs":[{"type":"address","name":"from","internalType":"address"},{"type":"address","name":"to","internalType":"address"},{"type":"uint256","name":"value","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateReference","inputs":[{"type":"uint256","name":"index","internalType":"uint256"},{"type":"bool","name":"active","internalType":"bool"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"wards","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"wpls","inputs":[]}]
              

Contract Creation Code

Verify & Publish
0x60a060405234801561001057600080fd5b506040516136a83803806136a883398101604081905261002f916100d3565b6001600160a01b0381166080523360008181526020819052604080822060019055517fdd0e34038ac38b2a1ce960229778ac48a8719bc900b6c4f8d0475c6e8b385a609190a269d3c21bcecceda1000000600281905533600081815260036020908152604080832085905551938452919290917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a350610103565b6000602082840312156100e557600080fd5b81516001600160a01b03811681146100fc57600080fd5b9392505050565b60805161357561013360003960008181610446015281816116f40152818161173a0152611c7701526135756000f3fe608060405234801561001057600080fd5b50600436106102745760003560e01c80638aec854211610151578063b5fcf194116100c3578063d2fd9f6c11610087578063d2fd9f6c14610591578063d525ed09146105a4578063dd62ed3e146105b7578063deb96634146105e2578063e837d9a9146105eb578063fc9654ab146103ce57600080fd5b8063b5fcf194146104ef578063bf353dbb14610502578063bf608cce14610522578063cdd00f6914610576578063d0578a011461057e57600080fd5b80639c52a7f1116101155780639c52a7f1146104915780639e5702be146104a4578063a4ef1357146104ac578063a9059cbb146104b4578063aa6ca808146104c7578063b1d06528146104dc57600080fd5b80638aec854214610439578063927ef7fa146104415780639586a5421461048057806395d89b41146102b657806399f91f4f1461048857600080fd5b806323b872dd116101ea57806352b65c4b116101ae57806352b65c4b146103ce57806362e2c848146103d757806365fae35e146103ea5780636b598bbe146103fd57806370a0823114610410578063802fe35d1461043057600080fd5b806323b872dd146103915780632cefe72c146103a45780632ff2e9dc146103ad578063313ce567146103be5780634ae7ee1d146103c657600080fd5b80630e8e81271161023c5780630e8e81271461032557806318160ddd1461032e5780631c0541bd146103375780631dafe16b1461036c5780631de40e49146103795780631e9d49041461038857600080fd5b806301339c2114610279578063024599661461028357806306fdde03146102b6578063095ea7b3146102e65780630e40fe9f14610309575b600080fd5b61028161063b565b005b610296610291366004612f56565b6106c5565b604080519384526020840192909252908201526060015b60405180910390f35b6102d9604051806040016040528060048152602001630545741560e41b81525081565b6040516102ad9190612f82565b6102f96102f4366004612f56565b6106fb565b60405190151581526020016102ad565b610317663157def08c0e3881565b6040519081526020016102ad565b61031761151881565b61031760025481565b61035a610345366004612fd0565b60066020526000908152604090205460ff1681565b60405160ff90911681526020016102ad565b6001546102f99060ff1681565b6103176706f05b59d3b2000081565b61031761038481565b6102f961039f366004612ff4565b610768565b61031761022b81565b61031769d3c21bcecceda100000081565b61035a601281565b600954610317565b610317610e1081565b6102816103e536600461304a565b61098f565b6102816103f8366004612fd0565b610a7b565b61028161040b366004613076565b610aef565b61031761041e366004612fd0565b60036020526000908152604090205481565b610317600b5481565b610317610e08565b6104687f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020016102ad565b610317610e18565b610317611c2081565b61028161049f366004612fd0565b610e2a565b610281610e9d565b6103176111b0565b6102f96104c2366004612f56565b6114a8565b6104cf61158d565b6040516102ad91906130bd565b6102816104ea366004613076565b6115ef565b6102816104fd366004612fd0565b611a40565b610317610510366004612fd0565b60006020819052908152604090205481565b610557610530366004612fd0565b6008602052600090815260409020546001600160a01b03811690600160a01b900460ff1682565b604080516001600160a01b0390931683529015156020830152016102ad565b600a54610317565b61031761058c366004612f56565b611c73565b61046861059f366004613109565b611df5565b6104686105b2366004613109565b611e1f565b6103176105c5366004613122565b600460209081526000928352604080842090915290825290205481565b61031761465081565b6105fe6105f9366004613109565b611e2f565b604080516001600160a01b0396871681529590941660208601529115159284019290925260ff90911660608301521515608082015260a0016102ad565b3360009081526020819052604090205460011461066a576040516282b42960e81b815260040160405180910390fd5b60015460ff161561068e576040516319f4db0f60e31b815260040160405180910390fd5b6001805460ff1916811790556040517fa4d24b6714a5db779b2a933bdca578dbf6e9380ae4de745e84d4a6dd457204d590600090a1565b600560205281600052604060002081600581106106e157600080fd5b600302018054600182015460029092015490935090915083565b3360008181526004602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906107569086815260200190565b60405180910390a35060015b92915050565b60006001600160a01b0384166107d35760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b60648201526084015b60405180910390fd5b6001600160a01b0383166107f95760405162461bcd60e51b81526004016107ca9061315b565b6001600160a01b0384166000908152600360205260409020548211156108315760405162461bcd60e51b81526004016107ca9061319e565b6001600160a01b03841660009081526004602090815260408083203384529091529020548211156108a45760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016107ca565b6001600160a01b038416600090815260036020526040812080548492906108cc9084906131fa565b90915550506001600160a01b038316600090815260036020526040812080548492906108f990849061320d565b90915550506001600160a01b0384166000908152600460209081526040808320338452909152812080548492906109319084906131fa565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161097d91815260200190565b60405180910390a35060019392505050565b336000908152602081905260409020546001146109be576040516282b42960e81b815260040160405180910390fd5b600a5482106109ff5760405162461bcd60e51b815260206004820152600d60248201526c092dcecc2d8d2c840d2dcc8caf609b1b60448201526064016107ca565b80600a8381548110610a1357610a13613220565b906000526020600020906002020160010160166101000a81548160ff021916908315150217905550817f1023261e84bada852098da9e423248e8fc3184408932bed6e2050195c13cfad982604051610a6f911515815260200190565b60405180910390a25050565b33600090815260208190526040902054600114610aaa576040516282b42960e81b815260040160405180910390fd5b6001600160a01b03811660008181526020819052604080822060019055517fdd0e34038ac38b2a1ce960229778ac48a8719bc900b6c4f8d0475c6e8b385a609190a250565b33600090815260208190526040902054600114610b1e576040516282b42960e81b815260040160405180910390fd5b6001600160a01b038381166000908152600860205260409020541615610b575760405163a5d832e360e01b815260040160405180910390fd5b6000826001600160a01b0316630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b97573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bbb9190613236565b90506000836001600160a01b031663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bfd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c219190613236565b9050828015610c425750846001600160a01b0316826001600160a01b031614155b80610c68575082158015610c685750846001600160a01b0316816001600160a01b031614155b15610c8657604051630793df6360e21b815260040160405180910390fd5b6040805180820182526001600160a01b0380871682528515156020808401918252898316600081815260089092529481209351845492511515600160a01b026001600160a81b031990931693169290921717909155600980546001810182559082527f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af0180546001600160a01b03191690921790915580610d2686611e8a565b506040805160608101825242815260208082018581528284018581526001600160a01b038d8116600081815260058652878120965187559351600180880191909155925160029096019590955560068452858320805460ff1916831790556007805492830181559092527fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6880180546001600160a01b0319168417905592518a1515815294965092945092908a16917f5b99e368449b8061a5e6c9aa2ba8d3557d64befc230df2b329603e412e721abb910160405180910390a350505050505050565b6000610e1342612035565b905090565b600061022b600254610e139190613269565b33600090815260208190526040902054600114610e59576040516282b42960e81b815260040160405180910390fd5b6001600160a01b038116600081815260208190526040808220829055517f184450df2e323acec0ed3b5c7531b81f9b4cdef7914dfd4c0a4317416bb5251b9190a250565b600b544290610e1090610eb090836131fa565b1015610ecf5760405163f0aaee6560e01b815260040160405180910390fd5b60075460008167ffffffffffffffff811115610eed57610eed61327d565b604051908082528060200260200182016040528015610f16578160200160208202803683370190505b5090506000805b8381101561101857600060078281548110610f3a57610f3a613220565b60009182526020808320909101546001600160a01b03168083526006909152604082205490925060ff16908115610f7b57610f76600183613293565b610f7e565b60045b9050610e1060056000856001600160a01b03166001600160a01b031681526020019081526020016000208260ff1660058110610fbc57610fbc613220565b6003020154610fcb908a6131fa565b1061100a5782868681518110610fe357610fe3613220565b60200260200101906001600160a01b031690816001600160a01b0316815250508460010194505b836001019350505050610f1d565b50801561116c5760008167ffffffffffffffff81111561103a5761103a61327d565b604051908082528060200260200182016040528015611063578160200160208202803683370190505b50905060005b828110156110bd5783818151811061108357611083613220565b602002602001015182828151811061109d5761109d613220565b6001600160a01b0390921660209283029190910190910152600101611069565b5060006110c9826121aa565b50905060005b8381101561111c576111148382815181106110ec576110ec613220565b602002602001015183838151811061110657611106613220565b602002602001015189612422565b6001016110cf565b5060015460ff1680156111455750611132610e18565b3360009081526003602052604090205410155b1561116957600061115587612035565b90508015611167576111673382612533565b505b50505b600b84905560408051858152602081018390527f3a00c122e9fd49a4a88111ff00ae627346ec777223f410d9c595b32348ca4958910160405180910390a150505050565b600a546000908190819067ffffffffffffffff8111156111d2576111d261327d565b6040519080825280602002602001820160405280156111fb578160200160208202803683370190505b50905060005b600a548110156112f1576000600a828154811061122057611220613220565b60009182526020918290206040805160a081018252600290930290910180546001600160a01b0390811684526001909101549081169383019390935260ff600160a01b84048116151591830191909152600160a81b830481166060830152600160b01b90920490911615156080820181905290915061129f57506112e9565b60006112aa82612631565b9050806000036112bb5750506112e9565b808486815181106112ce576112ce613220565b6020908102919091010152846112e3816132ac565b95505050505b600101611201565b508160000361131357604051630f5ac0cb60e01b815260040160405180910390fd5b60005b828110156113f857600061132b82600161320d565b90505b838110156113ef5782818151811061134857611348613220565b602002602001015183838151811061136257611362613220565b602002602001015111156113e757600083838151811061138457611384613220565b602002602001015190508382815181106113a0576113a0613220565b60200260200101518484815181106113ba576113ba613220565b602002602001018181525050808483815181106113d9576113d9613220565b602002602001018181525050505b60010161132e565b50600101611316565b506114046002836132c5565b6001036114365780611417600284613269565b8151811061142757611427613220565b60200260200101519250505090565b6002816114438285613269565b8151811061145357611453613220565b602002602001015182600160028661146b9190613269565b61147591906131fa565b8151811061148557611485613220565b6020026020010151611497919061320d565b6114a19190613269565b9250505090565b60006001600160a01b0383166114d05760405162461bcd60e51b81526004016107ca9061315b565b336000908152600360205260409020548211156114ff5760405162461bcd60e51b81526004016107ca9061319e565b336000908152600360205260408120805484929061151e9084906131fa565b90915550506001600160a01b0383166000908152600360205260408120805484929061154b90849061320d565b90915550506040518281526001600160a01b0384169033907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610756565b606060098054806020026020016040519081016040528092919081815260200182805480156115e557602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116115c7575b5050505050905090565b3360009081526020819052604090205460011461161e576040516282b42960e81b815260040160405180910390fd5b6000826001600160a01b0316630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa15801561165e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116829190613236565b90506000836001600160a01b031663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116e89190613236565b905082801561172957507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031614155b8061176f57508215801561176f57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316816001600160a01b031614155b1561178d57604051630793df6360e21b815260040160405180910390fd5b6000856001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156117cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117f191906132d9565b905060128160ff16111561183d5760405162461bcd60e51b81526020600482015260136024820152720a6e8c2c4d8ca40c8cac6d2dac2d8e6407c627606b1b60448201526064016107ca565b6040805160a0810182526001600160a01b0388811682528781166020830190815287151593830193845260ff85811660608501908152600160808601818152600a80549283018155600090815296517fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a8600290930292830180546001600160a01b03191691881691909117905593517fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a99091018054975192519451919095166001600160a81b031990971696909617600160a01b911515919091021761ffff60a81b1916600160a81b929091169190910260ff60b01b191617600160b01b93151593909302929092179091558061195387611e8a565b506040805160608101825242815260208082018581528284018581526001600160a01b038e8116600081815260058652878120965187559351600180880191909155925160029096019590955560068452858320805460ff1916831790556007805492830181559092527fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6880180546001600160a01b0319168417905583518c1515815260ff8a1692810192909252949650929450928b16917f5c235f9dae8874242a4334347008c0a971ff3e006b75b4444854aadda93f5fa5910160405180910390a35050505050505050565b33600090815260208190526040902054600114611a6f576040516282b42960e81b815260040160405180910390fd5b6001600160a01b03818116600090815260086020908152604091829020825180840190935254928316808352600160a01b90930460ff1615159082015290611aca57604051633fb801a560e21b815260040160405180910390fd5b6001600160a01b038216600090815260086020526040902080546001600160a81b03191690558051611afb906127a5565b80516001600160a01b03166000908152600560205260408120611b1d91612ec0565b80516001600160a01b03166000908152600660205260408120805460ff191690555b600954811015611c3a57826001600160a01b031660098281548110611b6657611b66613220565b6000918252602090912001546001600160a01b031603611c325760098054611b90906001906131fa565b81548110611ba057611ba0613220565b600091825260209091200154600980546001600160a01b039092169183908110611bcc57611bcc613220565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506009805480611c0b57611c0b6132fc565b600082815260209020810160001990810180546001600160a01b0319169055019055611c3a565b600101611b3f565b506040516001600160a01b038316907fd4bab7746d82129d0d621d803f51fe4b9961fe75c4ddfb9537ebd8f5fa283be790600090a25050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b031603611cda57670de0b6b3a7640000611cbf6111b0565b611cc99084613312565b611cd39190613269565b9050610762565b6001600160a01b03838116600090815260086020908152604091829020825180840190935254928316808352600160a01b90930460ff161515908201529015611dd5576000806000611d2f8460000151611e8a565b9250925092506000611d5b856000015186602001518760200151611d535785611d55565b865b856128a6565b90506000611d89886040518060200160405280856001600160e01b0316815250612d3990919063ffffffff16565b90506000611d98825160701c90565b6001600160901b03169050670de0b6b3a7640000611db46111b0565b611dbe9083613312565b611dc89190613269565b9750505050505050611dee565b604051633fb801a560e21b815260040160405180910390fd5b5092915050565b60098181548110611e0557600080fd5b6000918252602090912001546001600160a01b0316905081565b60078181548110611e0557600080fd5b600a8181548110611e3f57600080fd5b6000918252602090912060029091020180546001909101546001600160a01b0391821692509081169060ff600160a01b8204811691600160a81b8104821691600160b01b9091041685565b60008080429050836001600160a01b0316635909c0d56040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ecf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ef39190613329565b9250836001600160a01b0316635a3d54936040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f33573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f579190613329565b91506000806000866001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa158015611f9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fc09190613359565b925092509250838163ffffffff161461202b576000611fe563ffffffff8316866131fa565b90508063ffffffff16611ff88486612d75565b516001600160e01b031602969096019563ffffffff81166120198585612d75565b516001600160e01b0316029590950194505b5050509193909250565b60015460009060ff1661204a57506000919050565b6000600b548361205a91906131fa565b9050610e1081101561206f5750600092915050565b600061207d610e10836131fa565b9050600061208f610e106115186131fa565b905060008183116120b2576120ab83663157def08c0e38613312565b905061211f565b60006120be83856131fa565b905060006120ce61038483613269565b905060006120e46706f05b59d3b2000083612e25565b905060006120f986663157def08c0e38613312565b9050670de0b6b3a764000061210e8383613312565b6121189190613269565b9450505050505b600254670de0b6b3a76400009069d3c21bcecceda100000010156121825760025469d3c21bcecceda100000090612156818361320d565b612161836002613312565b61217390670de0b6b3a7640000613312565b61217d9190613269565b925050505b670de0b6b3a76400006121958284613312565b61219f9190613269565b979650505050505050565b8051606090429067ffffffffffffffff8111156121c9576121c961327d565b60405190808252806020026020018201604052801561220e57816020015b60408051808201909152600080825260208201528152602001906001900390816121e75790505b50915060005b835181101561241c57600084828151811061223157612231613220565b602002602001015190506000816001600160a01b0316635909c0d56040518163ffffffff1660e01b8152600401602060405180830381865afa15801561227b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061229f9190613329565b90506000826001600160a01b0316635a3d54936040518163ffffffff1660e01b8152600401602060405180830381865afa1580156122e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123059190613329565b90506000806000856001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561234a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061236e9190613359565b925092509250878163ffffffff16146123d957600061239363ffffffff83168a6131fa565b90508063ffffffff166123a68486612d75565b516001600160e01b031602959095019463ffffffff81166123c78585612d75565b516001600160e01b0316029490940193505b60405180604001604052808681526020018581525089888151811061240057612400613220565b6020026020010181905250866001019650505050505050612214565b50915091565b6001600160a01b03831660008181526006602090815260408083205481516060810183524281528751818501528784015181840152948452600592839052922060ff9092169291908390811061247a5761247a613220565b6003020160008201518160000155602082015181600101556040820151816002015590505060058160016124ae91906133a9565b6124b891906133c2565b6001600160a01b0385166000818152600660209081526040808320805460ff191660ff969096169590951790945586518782015185519182529181019190915292830185905290917f9a3f414f907ddb77231900d221b663199d0a42096ca010e25f0bb7292c409b4e9060600160405180910390a350505050565b60015460ff166125565760405163072e9ae360e31b815260040160405180910390fd5b6001600160a01b03821660009081526003602052604081205490612578610e18565b90508082101561259b5760405163a82c3c3960e01b815260040160405180910390fd5b826000036125a95750505050565b82600260008282546125bb919061320d565b90915550506001600160a01b038416600090815260036020526040812080548592906125e890849061320d565b90915550506040518381526001600160a01b038516907f619caafabdd75649b302ba8419e48cccf64f37f1983ac4727cfb38b57703ffc99060200160405180910390a250505050565b600080600083602001516001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa158015612678573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061269c9190613359565b5091509150600084604001516126bb57816001600160701b03166126c6565b826001600160701b03165b9050806000036126db57506000949350505050565b60008060006126ed8860200151611e8a565b925092509250600088604001519050600061271a8a6020015183846127125786612714565b875b866128a6565b90506000612750670de0b6b3a76400006040518060200160405280856001600160e01b0316815250612d3990919063ffffffff16565b9050600061275f825160701c90565b6001600160901b0316905060008c60600151601261277d9190613293565b61278890600a6134cb565b90506127948183613312565b9d9c50505050505050505050505050565b60005b6007548110156128a257816001600160a01b0316600782815481106127cf576127cf613220565b6000918252602090912001546001600160a01b03160361289a57600780546127f9906001906131fa565b8154811061280957612809613220565b600091825260209091200154600780546001600160a01b03909216918390811061283557612835613220565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506007805480612874576128746132fc565b600082815260209020810160001990810180546001600160a01b03191690550190555050565b6001016127a8565b5050565b60006128b0612ed2565b60005b6005811015612934576001600160a01b038716600090815260056020819052604090912090829081106128e8576128e8613220565b60030201604051806060016040529081600082015481526020016001820154815260200160028201548152505082826005811061292757612927613220565b60200201526001016128b3565b5060015b6005811015612a0057600082826005811061295557612955613220565b60200201519050815b60008111801561298f57508151846129776001846131fa565b6005811061298757612987613220565b602002015151105b156129de57836129a06001836131fa565b600581106129b0576129b0613220565b60200201518482600581106129c7576129c7613220565b6020020152806129d6816134da565b91505061295e565b818482600581106129f1576129f1613220565b60200201525050600101612938565b5060408051600580825260c082019092526000916020820160a08036833701905050905060008585825b6005811015612b5157858160058110612a4557612a45613220565b60200201515115612b49576000868260058110612a6457612a64613220565b602002015151612a7490846131fa565b9050610e10811080612a87575061465081115b15612a925750612b49565b60008b612ab957878360058110612aab57612aab613220565b602002015160400151612ad5565b878360058110612acb57612acb613220565b6020020151602001515b9050600082612ae483886131fa565b612aee9190613269565b905080888881518110612b0357612b03613220565b6001600160e01b039092166020928302919091019091015286612b25816132ac565b975050819550888460058110612b3d57612b3d613220565b60200201515194505050505b600101612a2a565b5082600003612b7357604051633711a2a160e01b815260040160405180910390fd5b60015b83811015612c80576000858281518110612b9257612b92613220565b6020026020010151905060008290505b600081118015612be657506001600160e01b03821687612bc36001846131fa565b81518110612bd357612bd3613220565b60200260200101516001600160e01b0316115b15612c4b5786612bf76001836131fa565b81518110612c0757612c07613220565b6020026020010151878281518110612c2157612c21613220565b6001600160e01b039092166020928302919091019091015280612c43816134da565b915050612ba2565b81878281518110612c5e57612c5e613220565b6001600160e01b03909216602092830291909101909101525050600101612b76565b50612c8c6002846132c5565b600103612cbe5783612c9f600285613269565b81518110612caf57612caf613220565b60200260200101519550612d2c565b600284612ccb8286613269565b81518110612cdb57612cdb613220565b6020026020010151856001600287612cf39190613269565b612cfd91906131fa565b81518110612d0d57612d0d613220565b6020026020010151612d1f91906134f1565b612d299190613510565b95505b5050505050949350505050565b60408051602081019091526000815260405180602001604052808385600001516001600160e01b0316612d6c9190613312565b90529392505050565b604080516020810190915260008152816001600160701b0316600003612ddd5760405162461bcd60e51b815260206004820152601760248201527f4669786564506f696e743a204449565f42595f5a45524f00000000000000000060448201526064016107ca565b604080516020810190915280612e136001600160701b0385166dffffffffffffffffffffffffffff60701b607088901b16613510565b6001600160e01b031690529392505050565b6000612e326002836132c5565b600003612e4757670de0b6b3a7640000612e49565b825b9050612e56600283613269565b91505b811561076257670de0b6b3a7640000612e728480613312565b612e7c9190613269565b9250612e896002836132c5565b15612eae57670de0b6b3a7640000612ea18483613312565b612eab9190613269565b90505b612eb9600283613269565b9150612e59565b50612ecf90600f810190612f1b565b50565b6040518060a001604052806005905b612f0560405180606001604052806000815260200160008152602001600081525090565b815260200190600190039081612ee15790505090565b5b80821115612f3d576000808255600182018190556002820155600301612f1c565b5090565b6001600160a01b0381168114612ecf57600080fd5b60008060408385031215612f6957600080fd5b8235612f7481612f41565b946020939093013593505050565b602081526000825180602084015260005b81811015612fb05760208186018101516040868401015201612f93565b506000604082850101526040601f19601f83011684010191505092915050565b600060208284031215612fe257600080fd5b8135612fed81612f41565b9392505050565b60008060006060848603121561300957600080fd5b833561301481612f41565b9250602084013561302481612f41565b929592945050506040919091013590565b8035801515811461304557600080fd5b919050565b6000806040838503121561305d57600080fd5b8235915061306d60208401613035565b90509250929050565b60008060006060848603121561308b57600080fd5b833561309681612f41565b925060208401356130a681612f41565b91506130b460408501613035565b90509250925092565b602080825282518282018190526000918401906040840190835b818110156130fe5783516001600160a01b03168352602093840193909201916001016130d7565b509095945050505050565b60006020828403121561311b57600080fd5b5035919050565b6000806040838503121561313557600080fd5b823561314081612f41565b9150602083013561315081612f41565b809150509250929050565b60208082526023908201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260408201526265737360e81b606082015260800190565b60208082526026908201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604082015265616c616e636560d01b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b81810381811115610762576107626131e4565b80820180821115610762576107626131e4565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561324857600080fd5b8151612fed81612f41565b634e487b7160e01b600052601260045260246000fd5b60008261327857613278613253565b500490565b634e487b7160e01b600052604160045260246000fd5b60ff8281168282160390811115610762576107626131e4565b6000600182016132be576132be6131e4565b5060010190565b6000826132d4576132d4613253565b500690565b6000602082840312156132eb57600080fd5b815160ff81168114612fed57600080fd5b634e487b7160e01b600052603160045260246000fd5b8082028115828204841417610762576107626131e4565b60006020828403121561333b57600080fd5b5051919050565b80516001600160701b038116811461304557600080fd5b60008060006060848603121561336e57600080fd5b61337784613342565b925061338560208501613342565b9150604084015163ffffffff8116811461339e57600080fd5b809150509250925092565b60ff8181168382160190811115610762576107626131e4565b600060ff8316806133d5576133d5613253565b8060ff84160691505092915050565b6001815b600184111561341f57808504811115613403576134036131e4565b600184161561341157908102905b60019390931c9280026133e8565b935093915050565b60008261343657506001610762565b8161344357506000610762565b816001811461345957600281146134635761347f565b6001915050610762565b60ff841115613474576134746131e4565b50506001821b610762565b5060208310610133831016604e8410600b84101617156134a2575081810a610762565b6134af60001984846133e4565b80600019048211156134c3576134c36131e4565b029392505050565b6000612fed60ff841683613427565b6000816134e9576134e96131e4565b506000190190565b6001600160e01b038181168382160190811115610762576107626131e4565b60006001600160e01b0383168061352957613529613253565b6001600160e01b0392909216919091049291505056fea2646970667358221220973a70be6b8260c2aa755c38e02c9606a239ca7b60762d2d35b51fe64c49ae5564736f6c634300081c0033000000000000000000000000a1077a294dde1b09bb078844df40758a5d0f9a27

Deployed ByteCode

0x608060405234801561001057600080fd5b50600436106102745760003560e01c80638aec854211610151578063b5fcf194116100c3578063d2fd9f6c11610087578063d2fd9f6c14610591578063d525ed09146105a4578063dd62ed3e146105b7578063deb96634146105e2578063e837d9a9146105eb578063fc9654ab146103ce57600080fd5b8063b5fcf194146104ef578063bf353dbb14610502578063bf608cce14610522578063cdd00f6914610576578063d0578a011461057e57600080fd5b80639c52a7f1116101155780639c52a7f1146104915780639e5702be146104a4578063a4ef1357146104ac578063a9059cbb146104b4578063aa6ca808146104c7578063b1d06528146104dc57600080fd5b80638aec854214610439578063927ef7fa146104415780639586a5421461048057806395d89b41146102b657806399f91f4f1461048857600080fd5b806323b872dd116101ea57806352b65c4b116101ae57806352b65c4b146103ce57806362e2c848146103d757806365fae35e146103ea5780636b598bbe146103fd57806370a0823114610410578063802fe35d1461043057600080fd5b806323b872dd146103915780632cefe72c146103a45780632ff2e9dc146103ad578063313ce567146103be5780634ae7ee1d146103c657600080fd5b80630e8e81271161023c5780630e8e81271461032557806318160ddd1461032e5780631c0541bd146103375780631dafe16b1461036c5780631de40e49146103795780631e9d49041461038857600080fd5b806301339c2114610279578063024599661461028357806306fdde03146102b6578063095ea7b3146102e65780630e40fe9f14610309575b600080fd5b61028161063b565b005b610296610291366004612f56565b6106c5565b604080519384526020840192909252908201526060015b60405180910390f35b6102d9604051806040016040528060048152602001630545741560e41b81525081565b6040516102ad9190612f82565b6102f96102f4366004612f56565b6106fb565b60405190151581526020016102ad565b610317663157def08c0e3881565b6040519081526020016102ad565b61031761151881565b61031760025481565b61035a610345366004612fd0565b60066020526000908152604090205460ff1681565b60405160ff90911681526020016102ad565b6001546102f99060ff1681565b6103176706f05b59d3b2000081565b61031761038481565b6102f961039f366004612ff4565b610768565b61031761022b81565b61031769d3c21bcecceda100000081565b61035a601281565b600954610317565b610317610e1081565b6102816103e536600461304a565b61098f565b6102816103f8366004612fd0565b610a7b565b61028161040b366004613076565b610aef565b61031761041e366004612fd0565b60036020526000908152604090205481565b610317600b5481565b610317610e08565b6104687f000000000000000000000000a1077a294dde1b09bb078844df40758a5d0f9a2781565b6040516001600160a01b0390911681526020016102ad565b610317610e18565b610317611c2081565b61028161049f366004612fd0565b610e2a565b610281610e9d565b6103176111b0565b6102f96104c2366004612f56565b6114a8565b6104cf61158d565b6040516102ad91906130bd565b6102816104ea366004613076565b6115ef565b6102816104fd366004612fd0565b611a40565b610317610510366004612fd0565b60006020819052908152604090205481565b610557610530366004612fd0565b6008602052600090815260409020546001600160a01b03811690600160a01b900460ff1682565b604080516001600160a01b0390931683529015156020830152016102ad565b600a54610317565b61031761058c366004612f56565b611c73565b61046861059f366004613109565b611df5565b6104686105b2366004613109565b611e1f565b6103176105c5366004613122565b600460209081526000928352604080842090915290825290205481565b61031761465081565b6105fe6105f9366004613109565b611e2f565b604080516001600160a01b0396871681529590941660208601529115159284019290925260ff90911660608301521515608082015260a0016102ad565b3360009081526020819052604090205460011461066a576040516282b42960e81b815260040160405180910390fd5b60015460ff161561068e576040516319f4db0f60e31b815260040160405180910390fd5b6001805460ff1916811790556040517fa4d24b6714a5db779b2a933bdca578dbf6e9380ae4de745e84d4a6dd457204d590600090a1565b600560205281600052604060002081600581106106e157600080fd5b600302018054600182015460029092015490935090915083565b3360008181526004602090815260408083206001600160a01b038716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906107569086815260200190565b60405180910390a35060015b92915050565b60006001600160a01b0384166107d35760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b60648201526084015b60405180910390fd5b6001600160a01b0383166107f95760405162461bcd60e51b81526004016107ca9061315b565b6001600160a01b0384166000908152600360205260409020548211156108315760405162461bcd60e51b81526004016107ca9061319e565b6001600160a01b03841660009081526004602090815260408083203384529091529020548211156108a45760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016107ca565b6001600160a01b038416600090815260036020526040812080548492906108cc9084906131fa565b90915550506001600160a01b038316600090815260036020526040812080548492906108f990849061320d565b90915550506001600160a01b0384166000908152600460209081526040808320338452909152812080548492906109319084906131fa565b92505081905550826001600160a01b0316846001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161097d91815260200190565b60405180910390a35060019392505050565b336000908152602081905260409020546001146109be576040516282b42960e81b815260040160405180910390fd5b600a5482106109ff5760405162461bcd60e51b815260206004820152600d60248201526c092dcecc2d8d2c840d2dcc8caf609b1b60448201526064016107ca565b80600a8381548110610a1357610a13613220565b906000526020600020906002020160010160166101000a81548160ff021916908315150217905550817f1023261e84bada852098da9e423248e8fc3184408932bed6e2050195c13cfad982604051610a6f911515815260200190565b60405180910390a25050565b33600090815260208190526040902054600114610aaa576040516282b42960e81b815260040160405180910390fd5b6001600160a01b03811660008181526020819052604080822060019055517fdd0e34038ac38b2a1ce960229778ac48a8719bc900b6c4f8d0475c6e8b385a609190a250565b33600090815260208190526040902054600114610b1e576040516282b42960e81b815260040160405180910390fd5b6001600160a01b038381166000908152600860205260409020541615610b575760405163a5d832e360e01b815260040160405180910390fd5b6000826001600160a01b0316630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b97573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bbb9190613236565b90506000836001600160a01b031663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bfd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c219190613236565b9050828015610c425750846001600160a01b0316826001600160a01b031614155b80610c68575082158015610c685750846001600160a01b0316816001600160a01b031614155b15610c8657604051630793df6360e21b815260040160405180910390fd5b6040805180820182526001600160a01b0380871682528515156020808401918252898316600081815260089092529481209351845492511515600160a01b026001600160a81b031990931693169290921717909155600980546001810182559082527f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af0180546001600160a01b03191690921790915580610d2686611e8a565b506040805160608101825242815260208082018581528284018581526001600160a01b038d8116600081815260058652878120965187559351600180880191909155925160029096019590955560068452858320805460ff1916831790556007805492830181559092527fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6880180546001600160a01b0319168417905592518a1515815294965092945092908a16917f5b99e368449b8061a5e6c9aa2ba8d3557d64befc230df2b329603e412e721abb910160405180910390a350505050505050565b6000610e1342612035565b905090565b600061022b600254610e139190613269565b33600090815260208190526040902054600114610e59576040516282b42960e81b815260040160405180910390fd5b6001600160a01b038116600081815260208190526040808220829055517f184450df2e323acec0ed3b5c7531b81f9b4cdef7914dfd4c0a4317416bb5251b9190a250565b600b544290610e1090610eb090836131fa565b1015610ecf5760405163f0aaee6560e01b815260040160405180910390fd5b60075460008167ffffffffffffffff811115610eed57610eed61327d565b604051908082528060200260200182016040528015610f16578160200160208202803683370190505b5090506000805b8381101561101857600060078281548110610f3a57610f3a613220565b60009182526020808320909101546001600160a01b03168083526006909152604082205490925060ff16908115610f7b57610f76600183613293565b610f7e565b60045b9050610e1060056000856001600160a01b03166001600160a01b031681526020019081526020016000208260ff1660058110610fbc57610fbc613220565b6003020154610fcb908a6131fa565b1061100a5782868681518110610fe357610fe3613220565b60200260200101906001600160a01b031690816001600160a01b0316815250508460010194505b836001019350505050610f1d565b50801561116c5760008167ffffffffffffffff81111561103a5761103a61327d565b604051908082528060200260200182016040528015611063578160200160208202803683370190505b50905060005b828110156110bd5783818151811061108357611083613220565b602002602001015182828151811061109d5761109d613220565b6001600160a01b0390921660209283029190910190910152600101611069565b5060006110c9826121aa565b50905060005b8381101561111c576111148382815181106110ec576110ec613220565b602002602001015183838151811061110657611106613220565b602002602001015189612422565b6001016110cf565b5060015460ff1680156111455750611132610e18565b3360009081526003602052604090205410155b1561116957600061115587612035565b90508015611167576111673382612533565b505b50505b600b84905560408051858152602081018390527f3a00c122e9fd49a4a88111ff00ae627346ec777223f410d9c595b32348ca4958910160405180910390a150505050565b600a546000908190819067ffffffffffffffff8111156111d2576111d261327d565b6040519080825280602002602001820160405280156111fb578160200160208202803683370190505b50905060005b600a548110156112f1576000600a828154811061122057611220613220565b60009182526020918290206040805160a081018252600290930290910180546001600160a01b0390811684526001909101549081169383019390935260ff600160a01b84048116151591830191909152600160a81b830481166060830152600160b01b90920490911615156080820181905290915061129f57506112e9565b60006112aa82612631565b9050806000036112bb5750506112e9565b808486815181106112ce576112ce613220565b6020908102919091010152846112e3816132ac565b95505050505b600101611201565b508160000361131357604051630f5ac0cb60e01b815260040160405180910390fd5b60005b828110156113f857600061132b82600161320d565b90505b838110156113ef5782818151811061134857611348613220565b602002602001015183838151811061136257611362613220565b602002602001015111156113e757600083838151811061138457611384613220565b602002602001015190508382815181106113a0576113a0613220565b60200260200101518484815181106113ba576113ba613220565b602002602001018181525050808483815181106113d9576113d9613220565b602002602001018181525050505b60010161132e565b50600101611316565b506114046002836132c5565b6001036114365780611417600284613269565b8151811061142757611427613220565b60200260200101519250505090565b6002816114438285613269565b8151811061145357611453613220565b602002602001015182600160028661146b9190613269565b61147591906131fa565b8151811061148557611485613220565b6020026020010151611497919061320d565b6114a19190613269565b9250505090565b60006001600160a01b0383166114d05760405162461bcd60e51b81526004016107ca9061315b565b336000908152600360205260409020548211156114ff5760405162461bcd60e51b81526004016107ca9061319e565b336000908152600360205260408120805484929061151e9084906131fa565b90915550506001600160a01b0383166000908152600360205260408120805484929061154b90849061320d565b90915550506040518281526001600160a01b0384169033907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610756565b606060098054806020026020016040519081016040528092919081815260200182805480156115e557602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116115c7575b5050505050905090565b3360009081526020819052604090205460011461161e576040516282b42960e81b815260040160405180910390fd5b6000826001600160a01b0316630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa15801561165e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116829190613236565b90506000836001600160a01b031663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116e89190613236565b905082801561172957507f000000000000000000000000a1077a294dde1b09bb078844df40758a5d0f9a276001600160a01b0316826001600160a01b031614155b8061176f57508215801561176f57507f000000000000000000000000a1077a294dde1b09bb078844df40758a5d0f9a276001600160a01b0316816001600160a01b031614155b1561178d57604051630793df6360e21b815260040160405180910390fd5b6000856001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156117cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117f191906132d9565b905060128160ff16111561183d5760405162461bcd60e51b81526020600482015260136024820152720a6e8c2c4d8ca40c8cac6d2dac2d8e6407c627606b1b60448201526064016107ca565b6040805160a0810182526001600160a01b0388811682528781166020830190815287151593830193845260ff85811660608501908152600160808601818152600a80549283018155600090815296517fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a8600290930292830180546001600160a01b03191691881691909117905593517fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a99091018054975192519451919095166001600160a81b031990971696909617600160a01b911515919091021761ffff60a81b1916600160a81b929091169190910260ff60b01b191617600160b01b93151593909302929092179091558061195387611e8a565b506040805160608101825242815260208082018581528284018581526001600160a01b038e8116600081815260058652878120965187559351600180880191909155925160029096019590955560068452858320805460ff1916831790556007805492830181559092527fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c6880180546001600160a01b0319168417905583518c1515815260ff8a1692810192909252949650929450928b16917f5c235f9dae8874242a4334347008c0a971ff3e006b75b4444854aadda93f5fa5910160405180910390a35050505050505050565b33600090815260208190526040902054600114611a6f576040516282b42960e81b815260040160405180910390fd5b6001600160a01b03818116600090815260086020908152604091829020825180840190935254928316808352600160a01b90930460ff1615159082015290611aca57604051633fb801a560e21b815260040160405180910390fd5b6001600160a01b038216600090815260086020526040902080546001600160a81b03191690558051611afb906127a5565b80516001600160a01b03166000908152600560205260408120611b1d91612ec0565b80516001600160a01b03166000908152600660205260408120805460ff191690555b600954811015611c3a57826001600160a01b031660098281548110611b6657611b66613220565b6000918252602090912001546001600160a01b031603611c325760098054611b90906001906131fa565b81548110611ba057611ba0613220565b600091825260209091200154600980546001600160a01b039092169183908110611bcc57611bcc613220565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506009805480611c0b57611c0b6132fc565b600082815260209020810160001990810180546001600160a01b0319169055019055611c3a565b600101611b3f565b506040516001600160a01b038316907fd4bab7746d82129d0d621d803f51fe4b9961fe75c4ddfb9537ebd8f5fa283be790600090a25050565b60007f000000000000000000000000a1077a294dde1b09bb078844df40758a5d0f9a276001600160a01b0316836001600160a01b031603611cda57670de0b6b3a7640000611cbf6111b0565b611cc99084613312565b611cd39190613269565b9050610762565b6001600160a01b03838116600090815260086020908152604091829020825180840190935254928316808352600160a01b90930460ff161515908201529015611dd5576000806000611d2f8460000151611e8a565b9250925092506000611d5b856000015186602001518760200151611d535785611d55565b865b856128a6565b90506000611d89886040518060200160405280856001600160e01b0316815250612d3990919063ffffffff16565b90506000611d98825160701c90565b6001600160901b03169050670de0b6b3a7640000611db46111b0565b611dbe9083613312565b611dc89190613269565b9750505050505050611dee565b604051633fb801a560e21b815260040160405180910390fd5b5092915050565b60098181548110611e0557600080fd5b6000918252602090912001546001600160a01b0316905081565b60078181548110611e0557600080fd5b600a8181548110611e3f57600080fd5b6000918252602090912060029091020180546001909101546001600160a01b0391821692509081169060ff600160a01b8204811691600160a81b8104821691600160b01b9091041685565b60008080429050836001600160a01b0316635909c0d56040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ecf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ef39190613329565b9250836001600160a01b0316635a3d54936040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f33573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f579190613329565b91506000806000866001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa158015611f9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fc09190613359565b925092509250838163ffffffff161461202b576000611fe563ffffffff8316866131fa565b90508063ffffffff16611ff88486612d75565b516001600160e01b031602969096019563ffffffff81166120198585612d75565b516001600160e01b0316029590950194505b5050509193909250565b60015460009060ff1661204a57506000919050565b6000600b548361205a91906131fa565b9050610e1081101561206f5750600092915050565b600061207d610e10836131fa565b9050600061208f610e106115186131fa565b905060008183116120b2576120ab83663157def08c0e38613312565b905061211f565b60006120be83856131fa565b905060006120ce61038483613269565b905060006120e46706f05b59d3b2000083612e25565b905060006120f986663157def08c0e38613312565b9050670de0b6b3a764000061210e8383613312565b6121189190613269565b9450505050505b600254670de0b6b3a76400009069d3c21bcecceda100000010156121825760025469d3c21bcecceda100000090612156818361320d565b612161836002613312565b61217390670de0b6b3a7640000613312565b61217d9190613269565b925050505b670de0b6b3a76400006121958284613312565b61219f9190613269565b979650505050505050565b8051606090429067ffffffffffffffff8111156121c9576121c961327d565b60405190808252806020026020018201604052801561220e57816020015b60408051808201909152600080825260208201528152602001906001900390816121e75790505b50915060005b835181101561241c57600084828151811061223157612231613220565b602002602001015190506000816001600160a01b0316635909c0d56040518163ffffffff1660e01b8152600401602060405180830381865afa15801561227b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061229f9190613329565b90506000826001600160a01b0316635a3d54936040518163ffffffff1660e01b8152600401602060405180830381865afa1580156122e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123059190613329565b90506000806000856001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561234a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061236e9190613359565b925092509250878163ffffffff16146123d957600061239363ffffffff83168a6131fa565b90508063ffffffff166123a68486612d75565b516001600160e01b031602959095019463ffffffff81166123c78585612d75565b516001600160e01b0316029490940193505b60405180604001604052808681526020018581525089888151811061240057612400613220565b6020026020010181905250866001019650505050505050612214565b50915091565b6001600160a01b03831660008181526006602090815260408083205481516060810183524281528751818501528784015181840152948452600592839052922060ff9092169291908390811061247a5761247a613220565b6003020160008201518160000155602082015181600101556040820151816002015590505060058160016124ae91906133a9565b6124b891906133c2565b6001600160a01b0385166000818152600660209081526040808320805460ff191660ff969096169590951790945586518782015185519182529181019190915292830185905290917f9a3f414f907ddb77231900d221b663199d0a42096ca010e25f0bb7292c409b4e9060600160405180910390a350505050565b60015460ff166125565760405163072e9ae360e31b815260040160405180910390fd5b6001600160a01b03821660009081526003602052604081205490612578610e18565b90508082101561259b5760405163a82c3c3960e01b815260040160405180910390fd5b826000036125a95750505050565b82600260008282546125bb919061320d565b90915550506001600160a01b038416600090815260036020526040812080548592906125e890849061320d565b90915550506040518381526001600160a01b038516907f619caafabdd75649b302ba8419e48cccf64f37f1983ac4727cfb38b57703ffc99060200160405180910390a250505050565b600080600083602001516001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa158015612678573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061269c9190613359565b5091509150600084604001516126bb57816001600160701b03166126c6565b826001600160701b03165b9050806000036126db57506000949350505050565b60008060006126ed8860200151611e8a565b925092509250600088604001519050600061271a8a6020015183846127125786612714565b875b866128a6565b90506000612750670de0b6b3a76400006040518060200160405280856001600160e01b0316815250612d3990919063ffffffff16565b9050600061275f825160701c90565b6001600160901b0316905060008c60600151601261277d9190613293565b61278890600a6134cb565b90506127948183613312565b9d9c50505050505050505050505050565b60005b6007548110156128a257816001600160a01b0316600782815481106127cf576127cf613220565b6000918252602090912001546001600160a01b03160361289a57600780546127f9906001906131fa565b8154811061280957612809613220565b600091825260209091200154600780546001600160a01b03909216918390811061283557612835613220565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055506007805480612874576128746132fc565b600082815260209020810160001990810180546001600160a01b03191690550190555050565b6001016127a8565b5050565b60006128b0612ed2565b60005b6005811015612934576001600160a01b038716600090815260056020819052604090912090829081106128e8576128e8613220565b60030201604051806060016040529081600082015481526020016001820154815260200160028201548152505082826005811061292757612927613220565b60200201526001016128b3565b5060015b6005811015612a0057600082826005811061295557612955613220565b60200201519050815b60008111801561298f57508151846129776001846131fa565b6005811061298757612987613220565b602002015151105b156129de57836129a06001836131fa565b600581106129b0576129b0613220565b60200201518482600581106129c7576129c7613220565b6020020152806129d6816134da565b91505061295e565b818482600581106129f1576129f1613220565b60200201525050600101612938565b5060408051600580825260c082019092526000916020820160a08036833701905050905060008585825b6005811015612b5157858160058110612a4557612a45613220565b60200201515115612b49576000868260058110612a6457612a64613220565b602002015151612a7490846131fa565b9050610e10811080612a87575061465081115b15612a925750612b49565b60008b612ab957878360058110612aab57612aab613220565b602002015160400151612ad5565b878360058110612acb57612acb613220565b6020020151602001515b9050600082612ae483886131fa565b612aee9190613269565b905080888881518110612b0357612b03613220565b6001600160e01b039092166020928302919091019091015286612b25816132ac565b975050819550888460058110612b3d57612b3d613220565b60200201515194505050505b600101612a2a565b5082600003612b7357604051633711a2a160e01b815260040160405180910390fd5b60015b83811015612c80576000858281518110612b9257612b92613220565b6020026020010151905060008290505b600081118015612be657506001600160e01b03821687612bc36001846131fa565b81518110612bd357612bd3613220565b60200260200101516001600160e01b0316115b15612c4b5786612bf76001836131fa565b81518110612c0757612c07613220565b6020026020010151878281518110612c2157612c21613220565b6001600160e01b039092166020928302919091019091015280612c43816134da565b915050612ba2565b81878281518110612c5e57612c5e613220565b6001600160e01b03909216602092830291909101909101525050600101612b76565b50612c8c6002846132c5565b600103612cbe5783612c9f600285613269565b81518110612caf57612caf613220565b60200260200101519550612d2c565b600284612ccb8286613269565b81518110612cdb57612cdb613220565b6020026020010151856001600287612cf39190613269565b612cfd91906131fa565b81518110612d0d57612d0d613220565b6020026020010151612d1f91906134f1565b612d299190613510565b95505b5050505050949350505050565b60408051602081019091526000815260405180602001604052808385600001516001600160e01b0316612d6c9190613312565b90529392505050565b604080516020810190915260008152816001600160701b0316600003612ddd5760405162461bcd60e51b815260206004820152601760248201527f4669786564506f696e743a204449565f42595f5a45524f00000000000000000060448201526064016107ca565b604080516020810190915280612e136001600160701b0385166dffffffffffffffffffffffffffff60701b607088901b16613510565b6001600160e01b031690529392505050565b6000612e326002836132c5565b600003612e4757670de0b6b3a7640000612e49565b825b9050612e56600283613269565b91505b811561076257670de0b6b3a7640000612e728480613312565b612e7c9190613269565b9250612e896002836132c5565b15612eae57670de0b6b3a7640000612ea18483613312565b612eab9190613269565b90505b612eb9600283613269565b9150612e59565b50612ecf90600f810190612f1b565b50565b6040518060a001604052806005905b612f0560405180606001604052806000815260200160008152602001600081525090565b815260200190600190039081612ee15790505090565b5b80821115612f3d576000808255600182018190556002820155600301612f1c565b5090565b6001600160a01b0381168114612ecf57600080fd5b60008060408385031215612f6957600080fd5b8235612f7481612f41565b946020939093013593505050565b602081526000825180602084015260005b81811015612fb05760208186018101516040868401015201612f93565b506000604082850101526040601f19601f83011684010191505092915050565b600060208284031215612fe257600080fd5b8135612fed81612f41565b9392505050565b60008060006060848603121561300957600080fd5b833561301481612f41565b9250602084013561302481612f41565b929592945050506040919091013590565b8035801515811461304557600080fd5b919050565b6000806040838503121561305d57600080fd5b8235915061306d60208401613035565b90509250929050565b60008060006060848603121561308b57600080fd5b833561309681612f41565b925060208401356130a681612f41565b91506130b460408501613035565b90509250925092565b602080825282518282018190526000918401906040840190835b818110156130fe5783516001600160a01b03168352602093840193909201916001016130d7565b509095945050505050565b60006020828403121561311b57600080fd5b5035919050565b6000806040838503121561313557600080fd5b823561314081612f41565b9150602083013561315081612f41565b809150509250929050565b60208082526023908201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260408201526265737360e81b606082015260800190565b60208082526026908201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604082015265616c616e636560d01b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b81810381811115610762576107626131e4565b80820180821115610762576107626131e4565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561324857600080fd5b8151612fed81612f41565b634e487b7160e01b600052601260045260246000fd5b60008261327857613278613253565b500490565b634e487b7160e01b600052604160045260246000fd5b60ff8281168282160390811115610762576107626131e4565b6000600182016132be576132be6131e4565b5060010190565b6000826132d4576132d4613253565b500690565b6000602082840312156132eb57600080fd5b815160ff81168114612fed57600080fd5b634e487b7160e01b600052603160045260246000fd5b8082028115828204841417610762576107626131e4565b60006020828403121561333b57600080fd5b5051919050565b80516001600160701b038116811461304557600080fd5b60008060006060848603121561336e57600080fd5b61337784613342565b925061338560208501613342565b9150604084015163ffffffff8116811461339e57600080fd5b809150509250925092565b60ff8181168382160190811115610762576107626131e4565b600060ff8316806133d5576133d5613253565b8060ff84160691505092915050565b6001815b600184111561341f57808504811115613403576134036131e4565b600184161561341157908102905b60019390931c9280026133e8565b935093915050565b60008261343657506001610762565b8161344357506000610762565b816001811461345957600281146134635761347f565b6001915050610762565b60ff841115613474576134746131e4565b50506001821b610762565b5060208310610133831016604e8410600b84101617156134a2575081810a610762565b6134af60001984846133e4565b80600019048211156134c3576134c36131e4565b029392505050565b6000612fed60ff841683613427565b6000816134e9576134e96131e4565b506000190190565b6001600160e01b038181168382160190811115610762576107626131e4565b60006001600160e01b0383168061352957613529613253565b6001600160e01b0392909216919091049291505056fea2646970667358221220973a70be6b8260c2aa755c38e02c9606a239ca7b60762d2d35b51fe64c49ae5564736f6c634300081c0033