Contract 0xd56faef5cf06d76c589036fb1a3562af145fd63a

  Note: Our ETH balance display is temporarily unavailable. Please check back later.

Contract Overview

Balance:
Txn Hash Method
Block
From
To
Value
0x17dc84eec27f6a2d40ca6582f81f04f4f782c3c8daccd31003463f7d0269ab260x60806040133774872023-08-16 10:50:42332 days 8 hrs ago0x9841484a4a6c0b61c4eea71376d76453fd05ec9c IN  Create: GamesOddsObtainer0 ETH0.0000000526270.00001
[ Download CSV Export 
Parent Txn Hash Block From To Value
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
GamesOddsObtainer

Compiler Version
v0.8.4+commit.c7e474f2

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 17 : GamesOddsObtainer.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

// internal
import "../../utils/proxy/solidity-0.8.0/ProxyOwned.sol";
import "../../utils/proxy/solidity-0.8.0/ProxyPausable.sol";

// interface
import "../../interfaces/ISportPositionalMarketManager.sol";
import "../../interfaces/ITherundownConsumerVerifier.sol";
import "../../interfaces/ITherundownConsumer.sol";
import "../../interfaces/IGamesOddsObtainer.sol";

/// @title Contract, which works on odds obtain
/// @author gruja
contract GamesOddsObtainer is Initializable, ProxyOwned, ProxyPausable {
    /* ========== CONSTANTS =========== */
    uint public constant MIN_TAG_NUMBER = 9000;
    uint public constant TAG_NUMBER_SPREAD = 10001;
    uint public constant TAG_NUMBER_TOTAL = 10002;
    uint public constant CANCELLED = 0;
    uint public constant HOME_WIN = 1;
    uint public constant AWAY_WIN = 2;

    /* ========== CONSUMER STATE VARIABLES ========== */

    ITherundownConsumer public consumer;
    ITherundownConsumerVerifier public verifier;
    ISportPositionalMarketManager public sportsManager;

    // game properties
    mapping(bytes32 => IGamesOddsObtainer.GameOdds) public gameOdds;
    mapping(bytes32 => IGamesOddsObtainer.GameOdds) public backupOdds;
    mapping(address => bool) public invalidOdds;
    mapping(bytes32 => uint) public oddsLastPulledForGame;
    mapping(address => bytes32) public gameIdPerChildMarket;
    mapping(uint => bool) public doesSportSupportSpreadAndTotal;

    // market props
    mapping(address => mapping(uint => address)) public mainMarketChildMarketIndex;
    mapping(address => uint) public numberOfChildMarkets;
    mapping(address => mapping(int16 => address)) public mainMarketSpreadChildMarket;
    mapping(address => mapping(uint24 => address)) public mainMarketTotalChildMarket;
    mapping(address => address) public childMarketMainMarket;
    mapping(address => int16) public childMarketSread;
    mapping(address => uint24) public childMarketTotal;
    mapping(address => address) public currentActiveTotalChildMarket;
    mapping(address => address) public currentActiveSpreadChildMarket;
    mapping(address => bool) public isSpreadChildMarket;
    mapping(address => bool) public childMarketCreated;
    mapping(address => bool) public normalizedOddsForMarketFulfilled;
    mapping(address => uint[]) public normalizedOddsForMarket;
    address public oddsReceiver;

    /* ========== CONSTRUCTOR ========== */

    function initialize(
        address _owner,
        address _consumer,
        address _verifier,
        address _sportsManager,
        uint[] memory _supportedSportIds
    ) external initializer {
        setOwner(_owner);
        consumer = ITherundownConsumer(_consumer);
        verifier = ITherundownConsumerVerifier(_verifier);
        sportsManager = ISportPositionalMarketManager(_sportsManager);

        for (uint i; i < _supportedSportIds.length; i++) {
            doesSportSupportSpreadAndTotal[_supportedSportIds[i]] = true;
        }
    }

    /* ========== OBTAINER MAIN FUNCTIONS ========== */

    /// @notice main function for odds obtaining
    /// @param requestId chainlnink request ID
    /// @param _game game odds struct see @ IGamesOddsObtainer.GameOdds
    function obtainOdds(
        bytes32 requestId,
        IGamesOddsObtainer.GameOdds memory _game,
        uint _sportId
    ) external canUpdateOdds {
        if (_areOddsValid(_game)) {
            uint[] memory currentNormalizedOdd = _getNormalizedOdds(_game.gameId);
            IGamesOddsObtainer.GameOdds memory currentOddsBeforeSave = gameOdds[_game.gameId];
            gameOdds[_game.gameId] = _game;
            oddsLastPulledForGame[_game.gameId] = block.timestamp;

            address _main = consumer.marketPerGameId(_game.gameId);
            _setNormalizedOdds(_main, _game.gameId, true);
            if (doesSportSupportSpreadAndTotal[_sportId]) {
                _obtainTotalAndSpreadOdds(_game, _main);
            }

            // if was paused and paused by invalid odds unpause
            if (sportsManager.isMarketPaused(_main)) {
                if (invalidOdds[_main] || consumer.isPausedByCanceledStatus(_main)) {
                    invalidOdds[_main] = false;
                    consumer.setPausedByCanceledStatus(_main, false);
                    if (
                        !verifier.areOddsArrayInThreshold(
                            _sportId,
                            currentNormalizedOdd,
                            normalizedOddsForMarket[_main],
                            consumer.isSportTwoPositionsSport(_sportId)
                        )
                    ) {
                        backupOdds[_game.gameId] = currentOddsBeforeSave;
                        emit OddsCircuitBreaker(_main, _game.gameId);
                    } else {
                        _pauseOrUnpauseMarkets(_game, _main, false, true);
                    }
                }
            } else if (
                //if market is not paused but odd are not in threshold, pause parket
                !sportsManager.isMarketPaused(_main) &&
                !verifier.areOddsArrayInThreshold(
                    _sportId,
                    currentNormalizedOdd,
                    normalizedOddsForMarket[_main],
                    consumer.isSportTwoPositionsSport(_sportId)
                )
            ) {
                _pauseOrUnpauseMarkets(_game, _main, true, true);
                _pauseOrUnpausePlayerProps(_main, true, false, true);
                backupOdds[_game.gameId] = currentOddsBeforeSave;
                emit OddsCircuitBreaker(_main, _game.gameId);
            }
            emit GameOddsAdded(requestId, _game.gameId, _game, normalizedOddsForMarket[_main]);
        } else {
            address _main = consumer.marketPerGameId(_game.gameId);
            if (!sportsManager.isMarketPaused(_main)) {
                invalidOdds[_main] = true;
                _pauseOrUnpauseMarkets(_game, _main, true, true);
                _pauseOrUnpausePlayerProps(_main, true, true, false);
            }

            emit InvalidOddsForMarket(requestId, _main, _game.gameId, _game);
        }
    }

    /// @notice set first odds on creation
    /// @param _gameId game id
    /// @param _homeOdds home odds for a game
    /// @param _awayOdds away odds for a game
    /// @param _drawOdds draw odds for a game
    function setFirstOdds(
        bytes32 _gameId,
        int24 _homeOdds,
        int24 _awayOdds,
        int24 _drawOdds
    ) external onlyConsumer {
        gameOdds[_gameId] = IGamesOddsObtainer.GameOdds(_gameId, _homeOdds, _awayOdds, _drawOdds, 0, 0, 0, 0, 0, 0, 0, 0);
        oddsLastPulledForGame[_gameId] = block.timestamp;
    }

    /// @notice set first odds on creation market
    /// @param _gameId game id
    /// @param _market market
    function setFirstNormalizedOdds(bytes32 _gameId, address _market) external onlyConsumer {
        _setNormalizedOdds(_market, _gameId, true);
    }

    /// @notice set backup odds to be main odds
    /// @param _gameId game id which is using backup odds
    function setBackupOddsAsMainOddsForGame(bytes32 _gameId) external onlyConsumer {
        gameOdds[_gameId] = backupOdds[_gameId];
        address _main = consumer.marketPerGameId(_gameId);
        _setNormalizedOdds(_main, _gameId, true);
        emit GameOddsAdded(
            _gameId, // // no req. from CL (manual cancel) so just put gameID
            _gameId,
            gameOdds[_gameId],
            normalizedOddsForMarket[_main]
        );
    }

    /// @notice pause/unpause all child markets
    /// @param _main parent market for which we are pause/unpause child markets
    /// @param _flag pause -> true, unpause -> false
    function pauseUnpauseChildMarkets(address _main, bool _flag) external onlyConsumer {
        // number of childs more then 0
        for (uint i = 0; i < numberOfChildMarkets[_main]; i++) {
            consumer.pauseOrUnpauseMarket(mainMarketChildMarketIndex[_main][i], _flag);
        }
    }

    /// @notice pause/unpause current active child markets
    /// @param _gameId game id for spread and totals checking
    /// @param _main parent market for which we are pause/unpause child markets
    /// @param _flag pause -> true, unpause -> false
    function pauseUnpauseCurrentActiveChildMarket(
        bytes32 _gameId,
        address _main,
        bool _flag
    ) external onlyConsumer {
        _pauseOrUnpauseMarkets(gameOdds[_gameId], _main, _flag, true);
    }

    function setChildMarketGameId(bytes32 gameId, address market) external onlyManager {
        consumer.setGameIdPerChildMarket(gameId, market);
    }

    /// @notice resolve all child markets
    /// @param _main parent market for which we are resolving
    /// @param _outcome poitions thet is winning (homw, away, cancel)
    /// @param _homeScore points that home team score
    /// @param _awayScore points that away team score
    function resolveChildMarkets(
        address _main,
        uint _outcome,
        uint8 _homeScore,
        uint8 _awayScore
    ) external onlyConsumer {
        for (uint i = 0; i < numberOfChildMarkets[_main]; i++) {
            address child = mainMarketChildMarketIndex[_main][i];
            if (_outcome == CANCELLED) {
                sportsManager.resolveMarket(child, _outcome);
            } else if (isSpreadChildMarket[child]) {
                _resolveMarketSpread(child, uint16(_homeScore), uint16(_awayScore));
            } else {
                _resolveMarketTotal(child, uint24(_homeScore), uint24(_awayScore));
            }
        }
    }

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

    /// @notice view function which returns normalized odds up to 100 (Example: 50-40-10)
    /// @param _gameId game id for which game is looking
    /// @return uint[] odds array normalized
    function getNormalizedOdds(bytes32 _gameId) external view returns (uint[] memory) {
        return _getNormalizedOdds(_gameId);
    }

    /// @notice view function which returns normalized odds up to 100 (Example: 50-50)
    /// @param _market market
    /// @return uint[] odds array normalized
    function getNormalizedOddsForMarket(address _market) external view returns (uint[] memory) {
        return _getNormalizedChildOdds(_market);
    }

    /// @notice function which retrievers all markert addresses for given parent market
    /// @param _parent parent market
    /// @return address[] child addresses
    function getAllChildMarketsFromParent(address _parent) external view returns (address[] memory) {
        address[] memory allMarkets = new address[](numberOfChildMarkets[_parent]);
        for (uint i = 0; i < numberOfChildMarkets[_parent]; i++) {
            allMarkets[i] = mainMarketChildMarketIndex[_parent][i];
        }
        return allMarkets;
    }

    /// @notice function which retrievers all markert addresses for given parent market
    /// @param _parent parent market
    /// @return totalsMarket totals child address
    /// @return spreadsMarket spread child address
    function getActiveChildMarketsFromParent(address _parent)
        external
        view
        returns (address totalsMarket, address spreadsMarket)
    {
        totalsMarket = currentActiveTotalChildMarket[_parent];
        spreadsMarket = currentActiveSpreadChildMarket[_parent];
    }

    /// @notice are odds valid or not
    /// @param _gameId game id for which game is looking
    /// @param _useBackup see if looking at backupOdds
    /// @return bool true/false (valid or not)
    function areOddsValid(bytes32 _gameId, bool _useBackup) external view returns (bool) {
        return _useBackup ? _areOddsValid(backupOdds[_gameId]) : _areOddsValid(gameOdds[_gameId]);
    }

    /// @notice view function which returns odds
    /// @param _gameId game id
    /// @return spreadHome points difference between home and away
    /// @return spreadAway  points difference between home and away
    /// @return totalOver  points total in a game over limit
    /// @return totalUnder  points total in game under limit
    function getLinesForGame(bytes32 _gameId)
        public
        view
        returns (
            int16,
            int16,
            uint24,
            uint24
        )
    {
        return (
            gameOdds[_gameId].spreadHome,
            gameOdds[_gameId].spreadAway,
            gameOdds[_gameId].totalOver,
            gameOdds[_gameId].totalUnder
        );
    }

    /// @notice view function which returns odds
    /// @param _gameId game id
    /// @return homeOdds moneyline odd in a two decimal places
    /// @return awayOdds moneyline odd in a two decimal places
    /// @return drawOdds moneyline odd in a two decimal places
    /// @return spreadHomeOdds moneyline odd in a two decimal places
    /// @return spreadAwayOdds moneyline odd in a two decimal places
    /// @return totalOverOdds moneyline odd in a two decimal places
    /// @return totalUnderOdds moneyline odd in a two decimal places
    function getOddsForGame(bytes32 _gameId)
        public
        view
        returns (
            int24,
            int24,
            int24,
            int24,
            int24,
            int24,
            int24
        )
    {
        return (
            gameOdds[_gameId].homeOdds,
            gameOdds[_gameId].awayOdds,
            gameOdds[_gameId].drawOdds,
            gameOdds[_gameId].spreadHomeOdds,
            gameOdds[_gameId].spreadAwayOdds,
            gameOdds[_gameId].totalOverOdds,
            gameOdds[_gameId].totalUnderOdds
        );
    }

    /* ========== INTERNALS ========== */

    function _getNormalizedOdds(bytes32 _gameId) internal view returns (uint[] memory) {
        address _market = consumer.marketPerGameId(_gameId);
        return
            normalizedOddsForMarketFulfilled[_market]
                ? normalizedOddsForMarket[_market]
                : _getNormalizedOddsFromGameOddsStruct(_gameId);
    }

    function _getNormalizedChildOdds(address _market) internal view returns (uint[] memory) {
        return
            normalizedOddsForMarketFulfilled[_market]
                ? normalizedOddsForMarket[_market]
                : _getNormalizedChildOddsFromGameOddsStruct(_market);
    }

    function _getNormalizedOddsFromGameOddsStruct(bytes32 _gameId) internal view returns (uint[] memory) {
        int[] memory odds = new int[](3);
        odds[0] = gameOdds[_gameId].homeOdds;
        odds[1] = gameOdds[_gameId].awayOdds;
        odds[2] = gameOdds[_gameId].drawOdds;
        return verifier.calculateAndNormalizeOdds(odds);
    }

    function _getNormalizedChildOddsFromGameOddsStruct(address _market) internal view returns (uint[] memory) {
        bytes32 gameId = gameIdPerChildMarket[_market];
        int[] memory odds = new int[](2);
        odds[0] = isSpreadChildMarket[_market] ? gameOdds[gameId].spreadHomeOdds : gameOdds[gameId].totalOverOdds;
        odds[1] = isSpreadChildMarket[_market] ? gameOdds[gameId].spreadAwayOdds : gameOdds[gameId].totalUnderOdds;
        return verifier.calculateAndNormalizeOdds(odds);
    }

    function _areOddsValid(IGamesOddsObtainer.GameOdds memory _game) internal view returns (bool) {
        return
            verifier.areOddsValid(
                consumer.isSportTwoPositionsSport(consumer.sportsIdPerGame(_game.gameId)),
                _game.homeOdds,
                _game.awayOdds,
                _game.drawOdds
            );
    }

    function _obtainTotalAndSpreadOdds(IGamesOddsObtainer.GameOdds memory _game, address _main) internal {
        if (_areTotalOddsValid(_game)) {
            _obtainSpreadTotal(_game, _main, false);
            emit GamedOddsAddedChild(
                _game.gameId,
                currentActiveTotalChildMarket[_main],
                _game,
                _getNormalizedChildOdds(currentActiveTotalChildMarket[_main]),
                TAG_NUMBER_TOTAL
            );
        } else {
            _pauseTotalSpreadMarkets(_game, false);
        }
        if (_areSpreadOddsValid(_game)) {
            _obtainSpreadTotal(_game, _main, true);
            emit GamedOddsAddedChild(
                _game.gameId,
                currentActiveSpreadChildMarket[_main],
                _game,
                _getNormalizedChildOdds(currentActiveSpreadChildMarket[_main]),
                TAG_NUMBER_SPREAD
            );
        } else {
            _pauseTotalSpreadMarkets(_game, true);
        }
    }

    function _areTotalOddsValid(IGamesOddsObtainer.GameOdds memory _game) internal view returns (bool) {
        return verifier.areTotalOddsValid(_game.totalOver, _game.totalOverOdds, _game.totalUnder, _game.totalUnderOdds);
    }

    function _areSpreadOddsValid(IGamesOddsObtainer.GameOdds memory _game) internal view returns (bool) {
        return verifier.areSpreadOddsValid(_game.spreadHome, _game.spreadHomeOdds, _game.spreadAway, _game.spreadAwayOdds);
    }

    function _obtainSpreadTotal(
        IGamesOddsObtainer.GameOdds memory _game,
        address _main,
        bool _isSpread
    ) internal {
        bool isNewMarket = numberOfChildMarkets[_main] == 0;

        address currentActiveChildMarket = _isSpread
            ? currentActiveSpreadChildMarket[_main]
            : currentActiveTotalChildMarket[_main];

        address currentMarket = _isSpread
            ? mainMarketSpreadChildMarket[_main][_game.spreadHome]
            : mainMarketTotalChildMarket[_main][_game.totalOver];

        if (isNewMarket || currentMarket == address(0)) {
            address newMarket = _createMarketSpreadTotalMarket(
                _game.gameId,
                _main,
                _isSpread,
                _game.spreadHome,
                _game.totalOver
            );

            _setCurrentChildMarkets(_main, newMarket, _isSpread);

            if (currentActiveChildMarket != address(0)) {
                consumer.pauseOrUnpauseMarket(currentActiveChildMarket, true);
            }
            _setNormalizedOdds(newMarket, _game.gameId, false);
        } else if (currentMarket != currentActiveChildMarket) {
            consumer.pauseOrUnpauseMarket(currentMarket, false);
            consumer.pauseOrUnpauseMarket(currentActiveChildMarket, true);
            _setCurrentChildMarkets(_main, currentMarket, _isSpread);
            _setNormalizedOdds(currentMarket, _game.gameId, false);
        } else {
            consumer.pauseOrUnpauseMarket(currentActiveChildMarket, false);
            _setNormalizedOdds(currentActiveChildMarket, _game.gameId, false);
        }
    }

    function _pauseOrUnpausePlayerProps(
        address _market,
        bool _pause,
        bool _invalidOdds,
        bool _circuitBreaker
    ) internal {
        consumer.pauseOrUnpauseMarketForPlayerProps(_market, _pause, _invalidOdds, _circuitBreaker);
    }

    function _setNormalizedOdds(
        address _market,
        bytes32 _gameId,
        bool _isParent
    ) internal {
        normalizedOddsForMarket[_market] = _isParent
            ? _getNormalizedOddsFromGameOddsStruct(_gameId)
            : _getNormalizedChildOddsFromGameOddsStruct(_market);
        normalizedOddsForMarketFulfilled[_market] = true;
    }

    function _createMarketSpreadTotalMarket(
        bytes32 _gameId,
        address _mainMarket,
        bool _isSpread,
        int16 _spreadHome,
        uint24 _totalOver
    ) internal returns (address _childMarket) {
        // create
        uint[] memory tags = _calculateTags(consumer.sportsIdPerGame(_gameId), _isSpread);
        sportsManager.createMarket(
            _gameId,
            _append(_gameId, _isSpread, _spreadHome, _totalOver), // gameLabel
            consumer.getGameCreatedById(_gameId).startTime, //maturity
            0, //initialMint
            2, // always two positions for spread/total
            tags, //tags
            true, // is child
            _mainMarket
        );

        _childMarket = sportsManager.getActiveMarketAddress(sportsManager.numActiveMarkets() - 1);

        // adding child markets
        _setChildMarkets(_gameId, _mainMarket, _childMarket, _isSpread, _spreadHome, _totalOver, tags[1]);
    }

    function _calculateTags(uint _sportsId, bool _isSpread) internal pure returns (uint[] memory) {
        uint[] memory result = new uint[](2);
        result[0] = MIN_TAG_NUMBER + _sportsId;
        result[1] = _isSpread ? TAG_NUMBER_SPREAD : TAG_NUMBER_TOTAL;
        return result;
    }

    function _append(
        bytes32 _gameId,
        bool _isSpread,
        int16 _spreadHome,
        uint24 _totalOver
    ) internal view returns (string memory) {
        string memory teamVsTeam = string(
            abi.encodePacked(
                consumer.getGameCreatedById(_gameId).homeTeam,
                " vs ",
                consumer.getGameCreatedById(_gameId).awayTeam
            )
        );
        if (_isSpread) {
            return string(abi.encodePacked(teamVsTeam, "(", _parseSpread(_spreadHome), ")"));
        } else {
            return string(abi.encodePacked(teamVsTeam, " - ", Strings.toString(_totalOver)));
        }
    }

    function _parseSpread(int16 _spreadHome) internal pure returns (string memory) {
        return
            _spreadHome > 0
                ? Strings.toString(uint16(_spreadHome))
                : string(abi.encodePacked("-", Strings.toString(uint16(_spreadHome * (-1)))));
    }

    function _pauseOrUnpauseMarkets(
        IGamesOddsObtainer.GameOdds memory _game,
        address _main,
        bool _flag,
        bool _unpauseMain
    ) internal {
        if (_unpauseMain) {
            consumer.pauseOrUnpauseMarket(_main, _flag);
        }

        if (numberOfChildMarkets[_main] > 0) {
            if (_flag) {
                for (uint i = 0; i < numberOfChildMarkets[_main]; i++) {
                    consumer.pauseOrUnpauseMarket(mainMarketChildMarketIndex[_main][i], _flag);
                }
            } else {
                if (_areTotalOddsValid(_game)) {
                    address totalChildMarket = mainMarketTotalChildMarket[_main][_game.totalOver];
                    if (totalChildMarket == address(0)) {
                        address newMarket = _createMarketSpreadTotalMarket(
                            _game.gameId,
                            _main,
                            false,
                            _game.spreadHome,
                            _game.totalOver
                        );
                        _setCurrentChildMarkets(_main, newMarket, false);
                    } else {
                        consumer.pauseOrUnpauseMarket(totalChildMarket, _flag);
                        _setCurrentChildMarkets(_main, totalChildMarket, false);
                    }
                }
                if (_areSpreadOddsValid(_game)) {
                    address spreadChildMarket = mainMarketSpreadChildMarket[_main][_game.spreadHome];
                    if (spreadChildMarket == address(0)) {
                        address newMarket = _createMarketSpreadTotalMarket(
                            _game.gameId,
                            _main,
                            true,
                            _game.spreadHome,
                            _game.totalOver
                        );
                        _setCurrentChildMarkets(_main, newMarket, true);
                    } else {
                        consumer.pauseOrUnpauseMarket(spreadChildMarket, _flag);
                        _setCurrentChildMarkets(_main, spreadChildMarket, true);
                    }
                }
            }
        }
    }

    function _pauseTotalSpreadMarkets(IGamesOddsObtainer.GameOdds memory _game, bool _isSpread) internal {
        address _main = consumer.marketPerGameId(_game.gameId);
        // in number of childs more then 0
        if (numberOfChildMarkets[_main] > 0) {
            for (uint i = 0; i < numberOfChildMarkets[_main]; i++) {
                address _child = mainMarketChildMarketIndex[_main][i];
                if (isSpreadChildMarket[_child] == _isSpread) {
                    consumer.pauseOrUnpauseMarket(_child, true);
                }
            }
        }
    }

    function _setCurrentChildMarkets(
        address _main,
        address _child,
        bool _isSpread
    ) internal {
        if (_isSpread) {
            currentActiveSpreadChildMarket[_main] = _child;
        } else {
            currentActiveTotalChildMarket[_main] = _child;
        }
    }

    function _setChildMarkets(
        bytes32 _gameId,
        address _main,
        address _child,
        bool _isSpread,
        int16 _spreadHome,
        uint24 _totalOver,
        uint _type
    ) internal {
        consumer.setGameIdPerChildMarket(_gameId, _child);
        gameIdPerChildMarket[_child] = _gameId;
        childMarketCreated[_child] = true;
        // adding child markets
        childMarketMainMarket[_child] = _main;
        mainMarketChildMarketIndex[_main][numberOfChildMarkets[_main]] = _child;
        numberOfChildMarkets[_main] = numberOfChildMarkets[_main] + 1;
        if (_isSpread) {
            mainMarketSpreadChildMarket[_main][_spreadHome] = _child;
            childMarketSread[_child] = _spreadHome;
            currentActiveSpreadChildMarket[_main] = _child;
            isSpreadChildMarket[_child] = true;
            emit CreateChildSpreadSportsMarket(_main, _child, _gameId, _spreadHome, _getNormalizedChildOdds(_child), _type);
        } else {
            mainMarketTotalChildMarket[_main][_totalOver] = _child;
            childMarketTotal[_child] = _totalOver;
            currentActiveTotalChildMarket[_main] = _child;
            emit CreateChildTotalSportsMarket(_main, _child, _gameId, _totalOver, _getNormalizedChildOdds(_child), _type);
        }
    }

    function _resolveMarketTotal(
        address _child,
        uint24 _homeScore,
        uint24 _awayScore
    ) internal {
        uint24 totalLine = childMarketTotal[_child];

        uint outcome = (_homeScore + _awayScore) * 100 > totalLine ? HOME_WIN : (_homeScore + _awayScore) * 100 < totalLine
            ? AWAY_WIN
            : CANCELLED;

        sportsManager.resolveMarket(_child, outcome);
        emit ResolveChildMarket(_child, outcome, childMarketMainMarket[_child], _homeScore, _awayScore);
    }

    function _resolveMarketSpread(
        address _child,
        uint16 _homeScore,
        uint16 _awayScore
    ) internal {
        int16 homeScoreWithSpread = int16(_homeScore) * 100 + childMarketSread[_child];
        int16 newAwayScore = int16(_awayScore) * 100;

        uint outcome = homeScoreWithSpread > newAwayScore ? HOME_WIN : homeScoreWithSpread < newAwayScore
            ? AWAY_WIN
            : CANCELLED;
        sportsManager.resolveMarket(_child, outcome);
        emit ResolveChildMarket(_child, outcome, childMarketMainMarket[_child], uint24(_homeScore), uint24(_awayScore));
    }

    /* ========== CONTRACT MANAGEMENT ========== */

    /// @notice sets consumer, verifier, manager address
    /// @param _consumer consumer address
    /// @param _verifier verifier address
    /// @param _sportsManager sport manager address
    function setContracts(
        address _consumer,
        address _verifier,
        address _sportsManager,
        address _receiver
    ) external onlyOwner {
        consumer = ITherundownConsumer(_consumer);
        verifier = ITherundownConsumerVerifier(_verifier);
        sportsManager = ISportPositionalMarketManager(_sportsManager);
        oddsReceiver = _receiver;

        emit NewContractAddresses(_consumer, _verifier, _sportsManager, _receiver);
    }

    /// @notice sets if sport is suported or not (delete from supported sport)
    /// @param _sportId sport id which needs to be supported or not
    /// @param _isSupported true/false (supported or not)
    function setSupportedSportForTotalAndSpread(uint _sportId, bool _isSupported) external onlyOwner {
        doesSportSupportSpreadAndTotal[_sportId] = _isSupported;
        emit SupportedSportForTotalAndSpreadAdded(_sportId, _isSupported);
    }

    /* ========== MODIFIERS ========== */

    modifier canUpdateOdds() {
        require(msg.sender == address(consumer) || msg.sender == oddsReceiver, "Invalid sender");
        _;
    }

    modifier onlyConsumer() {
        require(msg.sender == address(consumer), "Only consumer");
        _;
    }

    modifier onlyManager() {
        require(msg.sender == address(sportsManager), "Only manager");
        _;
    }

    /* ========== EVENTS ========== */

    event GameOddsAdded(bytes32 _requestId, bytes32 _id, IGamesOddsObtainer.GameOdds _game, uint[] _normalizedOdds);
    event GamedOddsAddedChild(
        bytes32 _id,
        address _market,
        IGamesOddsObtainer.GameOdds _game,
        uint[] _normalizedChildOdds,
        uint _type
    );
    event InvalidOddsForMarket(bytes32 _requestId, address _marketAddress, bytes32 _id, IGamesOddsObtainer.GameOdds _game);
    event OddsCircuitBreaker(address _marketAddress, bytes32 _id);
    event NewContractAddresses(address _consumer, address _verifier, address _sportsManager, address _receiver);
    event CreateChildSpreadSportsMarket(
        address _main,
        address _child,
        bytes32 _id,
        int16 _spread,
        uint[] _normalizedOdds,
        uint _type
    );
    event CreateChildTotalSportsMarket(
        address _main,
        address _child,
        bytes32 _id,
        uint24 _total,
        uint[] _normalizedOdds,
        uint _type
    );
    event SupportedSportForTotalAndSpreadAdded(uint _sportId, bool _isSupported);
    event ResolveChildMarket(address _child, uint _outcome, address _main, uint24 _homeScore, uint24 _awayScore);
}

File 2 of 17 : PausableUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (security/Pausable.sol)

pragma solidity ^0.8.0;

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

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

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

    bool private _paused;

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

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

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

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

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

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

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

File 3 of 17 : Initializable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (proxy/utils/Initializable.sol)

pragma solidity ^0.8.0;

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

/**
 * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
 * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an
 * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
 * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
 *
 * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
 * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
 *
 * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
 * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
 *
 * [CAUTION]
 * ====
 * Avoid leaving a contract uninitialized.
 *
 * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
 * contract, which may impact the proxy. To initialize the implementation contract, you can either invoke the
 * initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed:
 *
 * [.hljs-theme-light.nopadding]
 * ```
 * /// @custom:oz-upgrades-unsafe-allow constructor
 * constructor() initializer {}
 * ```
 * ====
 */
abstract contract Initializable {
    /**
     * @dev Indicates that the contract has been initialized.
     */
    bool private _initialized;

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

    /**
     * @dev Modifier to protect an initializer function from being invoked twice.
     */
    modifier initializer() {
        // If the contract is initializing we ignore whether _initialized is set in order to support multiple
        // inheritance patterns, but we only do this in the context of a constructor, because in other contexts the
        // contract may have been reentered.
        require(_initializing ? _isConstructor() : !_initialized, "Initializable: contract is already initialized");

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

        _;

        if (isTopLevelCall) {
            _initializing = false;
        }
    }

    /**
     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
     * {initializer} modifier, directly or indirectly.
     */
    modifier onlyInitializing() {
        require(_initializing, "Initializable: contract is not initializing");
        _;
    }

    function _isConstructor() private view returns (bool) {
        return !AddressUpgradeable.isContract(address(this));
    }
}

File 4 of 17 : Strings.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol)

pragma solidity ^0.8.0;

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
    uint8 private constant _ADDRESS_LENGTH = 20;

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        // Inspired by OraclizeAPI's implementation - MIT licence
        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol

        if (value == 0) {
            return "0";
        }
        uint256 temp = value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        return string(buffer);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        if (value == 0) {
            return "0x00";
        }
        uint256 temp = value;
        uint256 length = 0;
        while (temp != 0) {
            length++;
            temp >>= 8;
        }
        return toHexString(value, length);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = _HEX_SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }

    /**
     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
     */
    function toHexString(address addr) internal pure returns (string memory) {
        return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
    }
}

File 5 of 17 : ProxyOwned.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

// Clone of syntetix contract without constructor
contract ProxyOwned {
    address public owner;
    address public nominatedOwner;
    bool private _initialized;
    bool private _transferredAtInit;

    function setOwner(address _owner) public {
        require(_owner != address(0), "Owner address cannot be 0");
        require(!_initialized, "Already initialized, use nominateNewOwner");
        _initialized = true;
        owner = _owner;
        emit OwnerChanged(address(0), _owner);
    }

    function nominateNewOwner(address _owner) external onlyOwner {
        nominatedOwner = _owner;
        emit OwnerNominated(_owner);
    }

    function acceptOwnership() external {
        require(msg.sender == nominatedOwner, "You must be nominated before you can accept ownership");
        emit OwnerChanged(owner, nominatedOwner);
        owner = nominatedOwner;
        nominatedOwner = address(0);
    }

    function transferOwnershipAtInit(address proxyAddress) external onlyOwner {
        require(proxyAddress != address(0), "Invalid address");
        require(!_transferredAtInit, "Already transferred");
        owner = proxyAddress;
        _transferredAtInit = true;
        emit OwnerChanged(owner, proxyAddress);
    }

    modifier onlyOwner {
        _onlyOwner();
        _;
    }

    function _onlyOwner() private view {
        require(msg.sender == owner, "Only the contract owner may perform this action");
    }

    event OwnerNominated(address newOwner);
    event OwnerChanged(address oldOwner, address newOwner);
}

File 6 of 17 : ProxyPausable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

// Inheritance
import "./ProxyOwned.sol";

// Clone of syntetix contract without constructor

contract ProxyPausable is ProxyOwned {
    uint public lastPauseTime;
    bool public paused;

    

    /**
     * @notice Change the paused state of the contract
     * @dev Only the contract owner may call this.
     */
    function setPaused(bool _paused) external onlyOwner {
        // Ensure we're actually changing the state before we do anything
        if (_paused == paused) {
            return;
        }

        // Set our paused state.
        paused = _paused;

        // If applicable, set the last pause time.
        if (paused) {
            lastPauseTime = block.timestamp;
        }

        // Let everyone know that our pause state has changed.
        emit PauseChanged(paused);
    }

    event PauseChanged(bool isPaused);

    modifier notPaused {
        require(!paused, "This action cannot be performed while the contract is paused");
        _;
    }
}

File 7 of 17 : ISportPositionalMarketManager.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "../interfaces/ISportPositionalMarket.sol";

interface ISportPositionalMarketManager {
    /* ========== VIEWS / VARIABLES ========== */

    function marketCreationEnabled() external view returns (bool);

    function totalDeposited() external view returns (uint);

    function numActiveMarkets() external view returns (uint);

    function activeMarkets(uint index, uint pageSize) external view returns (address[] memory);

    function numMaturedMarkets() external view returns (uint);

    function maturedMarkets(uint index, uint pageSize) external view returns (address[] memory);

    function isActiveMarket(address candidate) external view returns (bool);

    function isDoubleChanceMarket(address candidate) external view returns (bool);

    function isDoubleChanceSupported() external view returns (bool);

    function isKnownMarket(address candidate) external view returns (bool);

    function getActiveMarketAddress(uint _index) external view returns (address);

    function transformCollateral(uint value) external view returns (uint);

    function reverseTransformCollateral(uint value) external view returns (uint);

    function isMarketPaused(address _market) external view returns (bool);

    function expiryDuration() external view returns (uint);

    function isWhitelistedAddress(address _address) external view returns (bool);

    function getOddsObtainer() external view returns (address obtainer);

    /* ========== MUTATIVE FUNCTIONS ========== */

    function createMarket(
        bytes32 gameId,
        string memory gameLabel,
        uint maturity,
        uint initialMint, // initial sUSD to mint options for,
        uint positionCount,
        uint[] memory tags,
        bool isChild,
        address parentMarket
    ) external returns (ISportPositionalMarket);

    function setMarketPaused(address _market, bool _paused) external;

    function updateDatesForMarket(address _market, uint256 _newStartTime) external;

    function resolveMarket(address market, uint outcome) external;

    function expireMarkets(address[] calldata market) external;

    function transferSusdTo(
        address sender,
        address receiver,
        uint amount
    ) external;
}

File 8 of 17 : ITherundownConsumerVerifier.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

interface ITherundownConsumerVerifier {
    // view functions
    function isInvalidNames(string memory _teamA, string memory _teamB) external view returns (bool);

    function areTeamsEqual(string memory _teamA, string memory _teamB) external view returns (bool);

    function isSupportedMarketType(string memory _market) external view returns (bool);

    function areOddsArrayInThreshold(
        uint _sportId,
        uint[] memory _currentOddsArray,
        uint[] memory _newOddsArray,
        bool _isTwoPositionalSport
    ) external view returns (bool);

    function areOddsValid(
        bool _isTwoPositionalSport,
        int24 _homeOdds,
        int24 _awayOdds,
        int24 _drawOdds
    ) external view returns (bool);

    function areSpreadOddsValid(
        int16 spreadHome,
        int24 spreadHomeOdds,
        int16 spreadAway,
        int24 spreadAwayOdds
    ) external view returns (bool);

    function areTotalOddsValid(
        uint24 totalOver,
        int24 totalOverOdds,
        uint24 totalUnder,
        int24 totalUnderOdds
    ) external view returns (bool);

    function areOddsAndLinesValidForPlayer(
        uint16 _line,
        int24 _overOdds,
        int24 _underOdds
    ) external pure returns (bool);

    function isValidOutcomeForGame(bool _isTwoPositionalSport, uint _outcome) external view returns (bool);

    function isValidOutcomeWithResult(
        uint _outcome,
        uint _homeScore,
        uint _awayScore
    ) external view returns (bool);

    function calculateAndNormalizeOdds(int[] memory _americanOdds) external view returns (uint[] memory);

    function getBookmakerIdsBySportId(uint256 _sportId) external view returns (uint256[] memory);

    function getBookmakerIdsBySportIdForPlayerProps(uint256 _sportId) external view returns (uint256[] memory);

    function getStringIDsFromBytesArrayIDs(bytes32[] memory _ids) external view returns (string[] memory);
}

File 9 of 17 : ITherundownConsumer.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

interface ITherundownConsumer {
    struct GameCreate {
        bytes32 gameId;
        uint256 startTime;
        int24 homeOdds;
        int24 awayOdds;
        int24 drawOdds;
        string homeTeam;
        string awayTeam;
    }

    // view functions
    function supportedSport(uint _sportId) external view returns (bool);

    function gameOnADate(bytes32 _gameId) external view returns (uint);

    function isGameResolvedOrCanceled(bytes32 _gameId) external view returns (bool);

    function getNormalizedOdds(bytes32 _gameId) external view returns (uint[] memory);

    function getNormalizedOddsForMarket(address _market) external view returns (uint[] memory);

    function getNormalizedChildOdds(address _market) external view returns (uint[] memory);

    function getNormalizedOddsForTwoPosition(bytes32 _gameId) external view returns (uint[] memory);

    function getGamesPerDatePerSport(uint _sportId, uint _date) external view returns (bytes32[] memory);

    function getGamePropsForOdds(address _market)
        external
        view
        returns (
            uint,
            uint,
            bytes32
        );

    function gameIdPerMarket(address _market) external view returns (bytes32);

    function getGameCreatedById(bytes32 _gameId) external view returns (GameCreate memory);

    function isChildMarket(address _market) external view returns (bool);

    function gameFulfilledCreated(bytes32 _gameId) external view returns (bool);

    // write functions
    function fulfillGamesCreated(
        bytes32 _requestId,
        bytes[] memory _games,
        uint _sportsId,
        uint _date
    ) external;

    function fulfillGamesResolved(
        bytes32 _requestId,
        bytes[] memory _games,
        uint _sportsId
    ) external;

    function fulfillGamesOdds(bytes32 _requestId, bytes[] memory _games) external;

    function setPausedByCanceledStatus(address _market, bool _flag) external;

    function setGameIdPerChildMarket(bytes32 _gameId, address _child) external;

    function pauseOrUnpauseMarket(address _market, bool _pause) external;

    function pauseOrUnpauseMarketForPlayerProps(
        address _market,
        bool _pause,
        bool _invalidOdds,
        bool _circuitBreakerMain
    ) external;

    function setChildMarkets(
        bytes32 _gameId,
        address _main,
        address _child,
        bool _isSpread,
        int16 _spreadHome,
        uint24 _totalOver
    ) external;

    function resolveMarketManually(
        address _market,
        uint _outcome,
        uint8 _homeScore,
        uint8 _awayScore,
        bool _usebackupOdds
    ) external;

    function getOddsForGame(bytes32 _gameId)
        external
        view
        returns (
            int24,
            int24,
            int24
        );

    function sportsIdPerGame(bytes32 _gameId) external view returns (uint);

    function getGameStartTime(bytes32 _gameId) external view returns (uint256);

    function marketPerGameId(bytes32 _gameId) external view returns (address);

    function marketResolved(address _market) external view returns (bool);

    function marketCanceled(address _market) external view returns (bool);

    function invalidOdds(address _market) external view returns (bool);

    function isPausedByCanceledStatus(address _market) external view returns (bool);

    function isSportOnADate(uint _date, uint _sportId) external view returns (bool);

    function isSportTwoPositionsSport(uint _sportsId) external view returns (bool);
}

File 10 of 17 : IGamesOddsObtainer.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

interface IGamesOddsObtainer {
    struct GameOdds {
        bytes32 gameId;
        int24 homeOdds;
        int24 awayOdds;
        int24 drawOdds;
        int16 spreadHome;
        int24 spreadHomeOdds;
        int16 spreadAway;
        int24 spreadAwayOdds;
        uint24 totalOver;
        int24 totalOverOdds;
        uint24 totalUnder;
        int24 totalUnderOdds;
    }

    // view

    function getActiveChildMarketsFromParent(address _parent) external view returns (address, address);

    function getSpreadTotalsChildMarketsFromParent(address _parent)
        external
        view
        returns (
            uint numOfSpreadMarkets,
            address[] memory spreadMarkets,
            uint numOfTotalsMarkets,
            address[] memory totalMarkets
        );

    function areOddsValid(bytes32 _gameId, bool _useBackup) external view returns (bool);

    function invalidOdds(address _market) external view returns (bool);

    function getNormalizedOdds(bytes32 _gameId) external view returns (uint[] memory);

    function getNormalizedOddsForMarket(address _market) external view returns (uint[] memory);

    function getOddsForGames(bytes32[] memory _gameIds) external view returns (int24[] memory odds);

    function mainMarketChildMarketIndex(address _main, uint _index) external view returns (address);

    function numberOfChildMarkets(address _main) external view returns (uint);

    function mainMarketSpreadChildMarket(address _main, int16 _spread) external view returns (address);

    function mainMarketTotalChildMarket(address _main, uint24 _total) external view returns (address);

    function childMarketMainMarket(address _market) external view returns (address);

    function currentActiveTotalChildMarket(address _main) external view returns (address);

    function currentActiveSpreadChildMarket(address _main) external view returns (address);

    function isSpreadChildMarket(address _child) external view returns (bool);

    function childMarketCreated(address _child) external view returns (bool);

    function getOddsForGame(bytes32 _gameId)
        external
        view
        returns (
            int24,
            int24,
            int24,
            int24,
            int24,
            int24,
            int24
        );

    function getLinesForGame(bytes32 _gameId)
        external
        view
        returns (
            int16,
            int16,
            uint24,
            uint24
        );

    // executable

    function obtainOdds(
        bytes32 requestId,
        GameOdds memory _game,
        uint _sportId
    ) external;

    function setFirstOdds(
        bytes32 _gameId,
        int24 _homeOdds,
        int24 _awayOdds,
        int24 _drawOdds
    ) external;

    function setFirstNormalizedOdds(bytes32 _gameId, address _market) external;

    function setBackupOddsAsMainOddsForGame(bytes32 _gameId) external;

    function pauseUnpauseChildMarkets(address _main, bool _flag) external;

    function pauseUnpauseCurrentActiveChildMarket(
        bytes32 _gameId,
        address _main,
        bool _flag
    ) external;

    function resolveChildMarkets(
        address _market,
        uint _outcome,
        uint8 _homeScore,
        uint8 _awayScore
    ) external;

    function setChildMarketGameId(bytes32 gameId, address market) external;
}

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

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

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

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

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

File 12 of 17 : AddressUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Address.sol)

pragma solidity ^0.8.0;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

File 13 of 17 : ISportPositionalMarket.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.5.16;

import "../interfaces/IPositionalMarketManager.sol";
import "../interfaces/IPosition.sol";
import "../interfaces/IPriceFeed.sol";

interface ISportPositionalMarket {
    /* ========== TYPES ========== */

    enum Phase {
        Trading,
        Maturity,
        Expiry
    }
    enum Side {
        Cancelled,
        Home,
        Away,
        Draw
    }

    /* ========== VIEWS / VARIABLES ========== */

    function getOptions()
        external
        view
        returns (
            IPosition home,
            IPosition away,
            IPosition draw
        );

    function times() external view returns (uint maturity, uint destruction);

    function initialMint() external view returns (uint);

    function getGameDetails() external view returns (bytes32 gameId, string memory gameLabel);

    function getGameId() external view returns (bytes32);

    function deposited() external view returns (uint);

    function optionsCount() external view returns (uint);

    function creator() external view returns (address);

    function resolved() external view returns (bool);

    function cancelled() external view returns (bool);

    function paused() external view returns (bool);

    function phase() external view returns (Phase);

    function canResolve() external view returns (bool);

    function result() external view returns (Side);

    function isChild() external view returns (bool);

    function tags(uint idx) external view returns (uint);

    function getTags() external view returns (uint tag1, uint tag2);

    function getTagsLength() external view returns (uint tagsLength);

    function getParentMarketPositions() external view returns (IPosition position1, IPosition position2);

    function getStampedOdds()
        external
        view
        returns (
            uint,
            uint,
            uint
        );

    function balancesOf(address account)
        external
        view
        returns (
            uint home,
            uint away,
            uint draw
        );

    function totalSupplies()
        external
        view
        returns (
            uint home,
            uint away,
            uint draw
        );

    function isDoubleChance() external view returns (bool);

    function parentMarket() external view returns (ISportPositionalMarket);

    /* ========== MUTATIVE FUNCTIONS ========== */

    function setPaused(bool _paused) external;

    function updateDates(uint256 _maturity, uint256 _expiry) external;

    function mint(uint value) external;

    function exerciseOptions() external;

    function restoreInvalidOdds(
        uint _homeOdds,
        uint _awayOdds,
        uint _drawOdds
    ) external;
}

File 14 of 17 : IPositionalMarketManager.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.5.16;

import "../interfaces/IPositionalMarket.sol";

interface IPositionalMarketManager {
    /* ========== VIEWS / VARIABLES ========== */

    function durations() external view returns (uint expiryDuration, uint maxTimeToMaturity);

    function capitalRequirement() external view returns (uint);

    function marketCreationEnabled() external view returns (bool);

    function onlyAMMMintingAndBurning() external view returns (bool);

    function transformCollateral(uint value) external view returns (uint);

    function reverseTransformCollateral(uint value) external view returns (uint);

    function totalDeposited() external view returns (uint);

    function numActiveMarkets() external view returns (uint);

    function activeMarkets(uint index, uint pageSize) external view returns (address[] memory);

    function numMaturedMarkets() external view returns (uint);

    function maturedMarkets(uint index, uint pageSize) external view returns (address[] memory);

    function isActiveMarket(address candidate) external view returns (bool);

    function isKnownMarket(address candidate) external view returns (bool);

    function getThalesAMM() external view returns (address);

    /* ========== MUTATIVE FUNCTIONS ========== */

    function createMarket(
        bytes32 oracleKey,
        uint strikePrice,
        uint maturity,
        uint initialMint // initial sUSD to mint options for,
    ) external returns (IPositionalMarket);

    function resolveMarket(address market) external;

    function expireMarkets(address[] calldata market) external;

    function transferSusdTo(
        address sender,
        address receiver,
        uint amount
    ) external;
}

File 15 of 17 : IPosition.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.5.16;

import "./IPositionalMarket.sol";

interface IPosition {
    /* ========== VIEWS / VARIABLES ========== */

    function getBalanceOf(address account) external view returns (uint);

    function getTotalSupply() external view returns (uint);

    function exerciseWithAmount(address claimant, uint amount) external;
}

File 16 of 17 : IPriceFeed.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.5.16;

interface IPriceFeed {
    // Structs
    struct RateAndUpdatedTime {
        uint216 rate;
        uint40 time;
    }

    // Mutative functions
    function addAggregator(bytes32 currencyKey, address aggregatorAddress) external;

    function removeAggregator(bytes32 currencyKey) external;

    // Views

    function rateForCurrency(bytes32 currencyKey) external view returns (uint);

    function rateAndUpdatedTime(bytes32 currencyKey) external view returns (uint rate, uint time);

    function getRates() external view returns (uint[] memory);

    function getCurrencies() external view returns (bytes32[] memory);
}

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

pragma solidity >=0.5.16;

import "../interfaces/IPositionalMarketManager.sol";
import "../interfaces/IPosition.sol";
import "../interfaces/IPriceFeed.sol";

interface IPositionalMarket {
    /* ========== TYPES ========== */

    enum Phase {
        Trading,
        Maturity,
        Expiry
    }
    enum Side {
        Up,
        Down
    }

    /* ========== VIEWS / VARIABLES ========== */

    function getOptions() external view returns (IPosition up, IPosition down);

    function times() external view returns (uint maturity, uint destructino);

    function getOracleDetails()
        external
        view
        returns (
            bytes32 key,
            uint strikePrice,
            uint finalPrice
        );

    function fees() external view returns (uint poolFee, uint creatorFee);

    function deposited() external view returns (uint);

    function creator() external view returns (address);

    function resolved() external view returns (bool);

    function phase() external view returns (Phase);

    function oraclePrice() external view returns (uint);

    function oraclePriceAndTimestamp() external view returns (uint price, uint updatedAt);

    function canResolve() external view returns (bool);

    function result() external view returns (Side);

    function balancesOf(address account) external view returns (uint up, uint down);

    function totalSupplies() external view returns (uint up, uint down);

    function getMaximumBurnable(address account) external view returns (uint amount);

    /* ========== MUTATIVE FUNCTIONS ========== */

    function mint(uint value) external;

    function exerciseOptions() external returns (uint);

    function burnOptions(uint amount) external;

    function burnOptionsMaximum() external;
}

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

Contract ABI

[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_main","type":"address"},{"indexed":false,"internalType":"address","name":"_child","type":"address"},{"indexed":false,"internalType":"bytes32","name":"_id","type":"bytes32"},{"indexed":false,"internalType":"int16","name":"_spread","type":"int16"},{"indexed":false,"internalType":"uint256[]","name":"_normalizedOdds","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"_type","type":"uint256"}],"name":"CreateChildSpreadSportsMarket","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_main","type":"address"},{"indexed":false,"internalType":"address","name":"_child","type":"address"},{"indexed":false,"internalType":"bytes32","name":"_id","type":"bytes32"},{"indexed":false,"internalType":"uint24","name":"_total","type":"uint24"},{"indexed":false,"internalType":"uint256[]","name":"_normalizedOdds","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"_type","type":"uint256"}],"name":"CreateChildTotalSportsMarket","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"_requestId","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"_id","type":"bytes32"},{"components":[{"internalType":"bytes32","name":"gameId","type":"bytes32"},{"internalType":"int24","name":"homeOdds","type":"int24"},{"internalType":"int24","name":"awayOdds","type":"int24"},{"internalType":"int24","name":"drawOdds","type":"int24"},{"internalType":"int16","name":"spreadHome","type":"int16"},{"internalType":"int24","name":"spreadHomeOdds","type":"int24"},{"internalType":"int16","name":"spreadAway","type":"int16"},{"internalType":"int24","name":"spreadAwayOdds","type":"int24"},{"internalType":"uint24","name":"totalOver","type":"uint24"},{"internalType":"int24","name":"totalOverOdds","type":"int24"},{"internalType":"uint24","name":"totalUnder","type":"uint24"},{"internalType":"int24","name":"totalUnderOdds","type":"int24"}],"indexed":false,"internalType":"struct IGamesOddsObtainer.GameOdds","name":"_game","type":"tuple"},{"indexed":false,"internalType":"uint256[]","name":"_normalizedOdds","type":"uint256[]"}],"name":"GameOddsAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"_id","type":"bytes32"},{"indexed":false,"internalType":"address","name":"_market","type":"address"},{"components":[{"internalType":"bytes32","name":"gameId","type":"bytes32"},{"internalType":"int24","name":"homeOdds","type":"int24"},{"internalType":"int24","name":"awayOdds","type":"int24"},{"internalType":"int24","name":"drawOdds","type":"int24"},{"internalType":"int16","name":"spreadHome","type":"int16"},{"internalType":"int24","name":"spreadHomeOdds","type":"int24"},{"internalType":"int16","name":"spreadAway","type":"int16"},{"internalType":"int24","name":"spreadAwayOdds","type":"int24"},{"internalType":"uint24","name":"totalOver","type":"uint24"},{"internalType":"int24","name":"totalOverOdds","type":"int24"},{"internalType":"uint24","name":"totalUnder","type":"uint24"},{"internalType":"int24","name":"totalUnderOdds","type":"int24"}],"indexed":false,"internalType":"struct IGamesOddsObtainer.GameOdds","name":"_game","type":"tuple"},{"indexed":false,"internalType":"uint256[]","name":"_normalizedChildOdds","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"_type","type":"uint256"}],"name":"GamedOddsAddedChild","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"_requestId","type":"bytes32"},{"indexed":false,"internalType":"address","name":"_marketAddress","type":"address"},{"indexed":false,"internalType":"bytes32","name":"_id","type":"bytes32"},{"components":[{"internalType":"bytes32","name":"gameId","type":"bytes32"},{"internalType":"int24","name":"homeOdds","type":"int24"},{"internalType":"int24","name":"awayOdds","type":"int24"},{"internalType":"int24","name":"drawOdds","type":"int24"},{"internalType":"int16","name":"spreadHome","type":"int16"},{"internalType":"int24","name":"spreadHomeOdds","type":"int24"},{"internalType":"int16","name":"spreadAway","type":"int16"},{"internalType":"int24","name":"spreadAwayOdds","type":"int24"},{"internalType":"uint24","name":"totalOver","type":"uint24"},{"internalType":"int24","name":"totalOverOdds","type":"int24"},{"internalType":"uint24","name":"totalUnder","type":"uint24"},{"internalType":"int24","name":"totalUnderOdds","type":"int24"}],"indexed":false,"internalType":"struct IGamesOddsObtainer.GameOdds","name":"_game","type":"tuple"}],"name":"InvalidOddsForMarket","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_consumer","type":"address"},{"indexed":false,"internalType":"address","name":"_verifier","type":"address"},{"indexed":false,"internalType":"address","name":"_sportsManager","type":"address"},{"indexed":false,"internalType":"address","name":"_receiver","type":"address"}],"name":"NewContractAddresses","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_marketAddress","type":"address"},{"indexed":false,"internalType":"bytes32","name":"_id","type":"bytes32"}],"name":"OddsCircuitBreaker","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerNominated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"isPaused","type":"bool"}],"name":"PauseChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_child","type":"address"},{"indexed":false,"internalType":"uint256","name":"_outcome","type":"uint256"},{"indexed":false,"internalType":"address","name":"_main","type":"address"},{"indexed":false,"internalType":"uint24","name":"_homeScore","type":"uint24"},{"indexed":false,"internalType":"uint24","name":"_awayScore","type":"uint24"}],"name":"ResolveChildMarket","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_sportId","type":"uint256"},{"indexed":false,"internalType":"bool","name":"_isSupported","type":"bool"}],"name":"SupportedSportForTotalAndSpreadAdded","type":"event"},{"inputs":[],"name":"AWAY_WIN","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"CANCELLED","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"HOME_WIN","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_TAG_NUMBER","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TAG_NUMBER_SPREAD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TAG_NUMBER_TOTAL","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_gameId","type":"bytes32"},{"internalType":"bool","name":"_useBackup","type":"bool"}],"name":"areOddsValid","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"backupOdds","outputs":[{"internalType":"bytes32","name":"gameId","type":"bytes32"},{"internalType":"int24","name":"homeOdds","type":"int24"},{"internalType":"int24","name":"awayOdds","type":"int24"},{"internalType":"int24","name":"drawOdds","type":"int24"},{"internalType":"int16","name":"spreadHome","type":"int16"},{"internalType":"int24","name":"spreadHomeOdds","type":"int24"},{"internalType":"int16","name":"spreadAway","type":"int16"},{"internalType":"int24","name":"spreadAwayOdds","type":"int24"},{"internalType":"uint24","name":"totalOver","type":"uint24"},{"internalType":"int24","name":"totalOverOdds","type":"int24"},{"internalType":"uint24","name":"totalUnder","type":"uint24"},{"internalType":"int24","name":"totalUnderOdds","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"childMarketCreated","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"childMarketMainMarket","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"childMarketSread","outputs":[{"internalType":"int16","name":"","type":"int16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"childMarketTotal","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"consumer","outputs":[{"internalType":"contract ITherundownConsumer","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"currentActiveSpreadChildMarket","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"currentActiveTotalChildMarket","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"doesSportSupportSpreadAndTotal","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"gameIdPerChildMarket","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"gameOdds","outputs":[{"internalType":"bytes32","name":"gameId","type":"bytes32"},{"internalType":"int24","name":"homeOdds","type":"int24"},{"internalType":"int24","name":"awayOdds","type":"int24"},{"internalType":"int24","name":"drawOdds","type":"int24"},{"internalType":"int16","name":"spreadHome","type":"int16"},{"internalType":"int24","name":"spreadHomeOdds","type":"int24"},{"internalType":"int16","name":"spreadAway","type":"int16"},{"internalType":"int24","name":"spreadAwayOdds","type":"int24"},{"internalType":"uint24","name":"totalOver","type":"uint24"},{"internalType":"int24","name":"totalOverOdds","type":"int24"},{"internalType":"uint24","name":"totalUnder","type":"uint24"},{"internalType":"int24","name":"totalUnderOdds","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_parent","type":"address"}],"name":"getActiveChildMarketsFromParent","outputs":[{"internalType":"address","name":"totalsMarket","type":"address"},{"internalType":"address","name":"spreadsMarket","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_parent","type":"address"}],"name":"getAllChildMarketsFromParent","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_gameId","type":"bytes32"}],"name":"getLinesForGame","outputs":[{"internalType":"int16","name":"","type":"int16"},{"internalType":"int16","name":"","type":"int16"},{"internalType":"uint24","name":"","type":"uint24"},{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_gameId","type":"bytes32"}],"name":"getNormalizedOdds","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_market","type":"address"}],"name":"getNormalizedOddsForMarket","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_gameId","type":"bytes32"}],"name":"getOddsForGame","outputs":[{"internalType":"int24","name":"","type":"int24"},{"internalType":"int24","name":"","type":"int24"},{"internalType":"int24","name":"","type":"int24"},{"internalType":"int24","name":"","type":"int24"},{"internalType":"int24","name":"","type":"int24"},{"internalType":"int24","name":"","type":"int24"},{"internalType":"int24","name":"","type":"int24"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_consumer","type":"address"},{"internalType":"address","name":"_verifier","type":"address"},{"internalType":"address","name":"_sportsManager","type":"address"},{"internalType":"uint256[]","name":"_supportedSportIds","type":"uint256[]"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"invalidOdds","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isSpreadChildMarket","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastPauseTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"mainMarketChildMarketIndex","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"int16","name":"","type":"int16"}],"name":"mainMarketSpreadChildMarket","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint24","name":"","type":"uint24"}],"name":"mainMarketTotalChildMarket","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"nominateNewOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"nominatedOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"normalizedOddsForMarket","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"normalizedOddsForMarketFulfilled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"numberOfChildMarkets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"requestId","type":"bytes32"},{"components":[{"internalType":"bytes32","name":"gameId","type":"bytes32"},{"internalType":"int24","name":"homeOdds","type":"int24"},{"internalType":"int24","name":"awayOdds","type":"int24"},{"internalType":"int24","name":"drawOdds","type":"int24"},{"internalType":"int16","name":"spreadHome","type":"int16"},{"internalType":"int24","name":"spreadHomeOdds","type":"int24"},{"internalType":"int16","name":"spreadAway","type":"int16"},{"internalType":"int24","name":"spreadAwayOdds","type":"int24"},{"internalType":"uint24","name":"totalOver","type":"uint24"},{"internalType":"int24","name":"totalOverOdds","type":"int24"},{"internalType":"uint24","name":"totalUnder","type":"uint24"},{"internalType":"int24","name":"totalUnderOdds","type":"int24"}],"internalType":"struct IGamesOddsObtainer.GameOdds","name":"_game","type":"tuple"},{"internalType":"uint256","name":"_sportId","type":"uint256"}],"name":"obtainOdds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"oddsLastPulledForGame","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oddsReceiver","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_main","type":"address"},{"internalType":"bool","name":"_flag","type":"bool"}],"name":"pauseUnpauseChildMarkets","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_gameId","type":"bytes32"},{"internalType":"address","name":"_main","type":"address"},{"internalType":"bool","name":"_flag","type":"bool"}],"name":"pauseUnpauseCurrentActiveChildMarket","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_main","type":"address"},{"internalType":"uint256","name":"_outcome","type":"uint256"},{"internalType":"uint8","name":"_homeScore","type":"uint8"},{"internalType":"uint8","name":"_awayScore","type":"uint8"}],"name":"resolveChildMarkets","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_gameId","type":"bytes32"}],"name":"setBackupOddsAsMainOddsForGame","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"gameId","type":"bytes32"},{"internalType":"address","name":"market","type":"address"}],"name":"setChildMarketGameId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_consumer","type":"address"},{"internalType":"address","name":"_verifier","type":"address"},{"internalType":"address","name":"_sportsManager","type":"address"},{"internalType":"address","name":"_receiver","type":"address"}],"name":"setContracts","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_gameId","type":"bytes32"},{"internalType":"address","name":"_market","type":"address"}],"name":"setFirstNormalizedOdds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_gameId","type":"bytes32"},{"internalType":"int24","name":"_homeOdds","type":"int24"},{"internalType":"int24","name":"_awayOdds","type":"int24"},{"internalType":"int24","name":"_drawOdds","type":"int24"}],"name":"setFirstOdds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_paused","type":"bool"}],"name":"setPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_sportId","type":"uint256"},{"internalType":"bool","name":"_isSupported","type":"bool"}],"name":"setSupportedSportForTotalAndSpread","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sportsManager","outputs":[{"internalType":"contract ISportPositionalMarketManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"proxyAddress","type":"address"}],"name":"transferOwnershipAtInit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"verifier","outputs":[{"internalType":"contract ITherundownConsumerVerifier","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

608060405234801561001057600080fd5b50615e3c80620000216000396000f3fe608060405234801561001057600080fd5b50600436106103785760003560e01c806360b4df85116101d3578063ae71dcdf11610104578063c480977c116100a2578063d28231bd1161007c578063d28231bd14610b7f578063db0d457914610ba2578063e38f273814610bb5578063fa043f4014610bc857600080fd5b8063c480977c14610b39578063cc5cea2714610b4c578063ceda8e9014610b5f57600080fd5b8063b4fd7296116100de578063b4fd729614610ad2578063b613d8ee14610aea578063bf989b6e14610b13578063c3b83f5f14610b2657600080fd5b8063ae71dcdf14610a20578063b09bd9e314610a28578063b103feb014610abf57600080fd5b806393f4452e116101715780639971441b1161014b5780639971441b146109c15780639aceb36e146109d4578063a12695ca146109f4578063a4f096e814610a1757600080fd5b806393f4452e1461086b57806393ff69d714610975578063988a1309146109ae57600080fd5b80638d220d99116101ad5780638d220d99146107b65780638da5cb5b146107ec57806391b4ded914610805578063937a314f1461080e57600080fd5b806360b4df85146106dd5780636c35b7751461078557806379ba5097146107ae57600080fd5b80632fff7020116102ad5780634adf72191161024b578063574ef5d911610225578063574ef5d9146106505780635a2f7731146106735780635c975abb1461069c5780635d134bc2146106a957600080fd5b80634adf7219146105fd5780635034c5881461061d57806353a47bb71461063d57600080fd5b8063366c16a511610287578063366c16a51461057d57806336c0d8551461059d5780633ea921ae146105c0578063447b1d58146105c957600080fd5b80632fff7020146104eb578063300a0298146104f357806332b566a9146104fb57600080fd5b80631afed5cc1161031a57806323b1d818116102f457806323b1d8181461047e578063263737e2146104915780632b7ac3f3146104c55780632da3f9ce146104d857600080fd5b80631afed5cc146104415780631cededce146104585780631e864c3b1461046b57600080fd5b806313af40351161035657806313af4035146103d557806314bdaa89146103e85780631627540c1461041b57806316c38b3c1461042e57600080fd5b806301a5627e1461037d5780630caf0e0c1461039257806310063fdc146103a5575b600080fd5b61039061038b36600461500d565b610bdb565b005b6103906103a0366004615224565b610cd5565b6005546103b8906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6103906103e3366004614e95565b610dfe565b61040b6103f6366004614e95565b60176020526000908152604090205460ff1681565b60405190151581526020016103cc565b610390610429366004614e95565b610f39565b61039061043c3660046151b0565b610f8f565b61044a61232881565b6040519081526020016103cc565b610390610466366004615200565b611005565b6019546103b8906001600160a01b031681565b61040b61048c366004615265565b611044565b6103b861049f366004615079565b600f6020908152600092835260408084209091529082529020546001600160a01b031681565b6004546103b8906001600160a01b031681565b6103906104e6366004614f28565b611241565b61044a600181565b61044a600281565b61054b6105093660046151e8565b6000908152600660205260409020600190810154600160481b8104820b92600160701b820490920b9162ffffff600160981b8304811692600160c81b90041690565b60408051600195860b81529390940b602084015262ffffff9182169383019390935290911660608201526080016103cc565b61059061058b366004614e95565b6113ca565b6040516103cc91906157e9565b61040b6105ab366004614e95565b60086020526000908152604090205460ff1681565b61044a61271181565b6103b86105d73660046150a4565b600c6020908152600092835260408084209091529082529020546001600160a01b031681565b61044a61060b366004614e95565b600a6020526000908152604090205481565b61044a61062b3660046151e8565b60096020526000908152604090205481565b6001546103b8906001600160a01b031681565b61040b61065e3660046151e8565b600b6020526000908152604090205460ff1681565b6103b8610681366004614e95565b6014602052600090815260409020546001600160a01b031681565b60035461040b9060ff1681565b6103b86106b7366004615045565b600e6020908152600092835260408084209091529082529020546001600160a01b031681565b6107426106eb3660046151e8565b600090815260066020526040902060010154600281810b9263010000008304820b92600160301b8104830b92600160581b8204810b92600160801b8304820b92600160b01b8104830b92600160e01b909104900b90565b60408051600298890b815296880b602088015294870b9486019490945291850b6060850152840b6080840152830b60a083015290910b60c082015260e0016103cc565b6103b8610793366004614e95565b6010602052600090815260409020546001600160a01b031681565b6103906114d7565b6107d96107c4366004614e95565b60116020526000908152604090205460010b81565b60405160019190910b81526020016103cc565b6000546103b8906201000090046001600160a01b031681565b61044a60025481565b61084b61081c366004614e95565b6001600160a01b0390811660009081526013602090815260408083205460149092529091205490821692911690565b604080516001600160a01b039384168152929091166020830152016103cc565b6109026108793660046151e8565b600660205260009081526040902080546001918201549091600282810b9263010000008104820b92600160301b8204830b92600160481b8304820b92600160581b8104820b92600160701b8204900b91600160801b8204810b9162ffffff600160981b8204811692600160b01b8304810b92600160c81b810490921691600160e01b9004900b8c565b604080519c8d5260029b8c0b60208e0152998b0b998c019990995296890b60608b0152600195860b60808b015293880b60a08a01529190930b60c088015291850b60e087015262ffffff918216610100870152840b61012086015216610140840152900b610160820152610180016103cc565b61099a610983366004614e95565b60126020526000908152604090205462ffffff1681565b60405162ffffff90911681526020016103cc565b6103906109bc3660046152d0565b6115d4565b6103906109cf3660046151e8565b61256f565b6109e76109e23660046151e8565b612877565b6040516103cc919061586e565b61040b610a02366004614e95565b60156020526000908152604090205460ff1681565b61044a61271281565b61044a600081565b610902610a363660046151e8565b600760205260009081526040902080546001918201549091600282810b9263010000008104820b92600160301b8204830b92600160481b8304820b92600160581b8104820b92600160701b8204900b91600160801b8204810b9162ffffff600160981b8204811692600160b01b8304810b92600160c81b810490921691600160e01b9004900b8c565b61044a610acd3660046150a4565b612888565b6003546103b89061010090046001600160a01b031681565b6103b8610af8366004614e95565b6013602052600090815260409020546001600160a01b031681565b610390610b21366004614ecd565b6128b9565b610390610b34366004614e95565b612962565b610390610b47366004615289565b612a7b565b610390610b5a366004615265565b612d19565b61044a610b6d366004614e95565b600d6020526000908152604090205481565b61040b610b8d366004614e95565b60166020526000908152604090205460ff1681565b6109e7610bb0366004614e95565b612d73565b610390610bc3366004615200565b612d7e565b610390610bd63660046150cf565b612e2e565b60035461010090046001600160a01b03163314610c135760405162461bcd60e51b8152600401610c0a90615acf565b60405180910390fd5b60005b6001600160a01b0383166000908152600d6020526040902054811015610cd0576003546001600160a01b038481166000908152600c602090815260408083208684529091529081902054905163ed5e00eb60e01b815261010090930482169263ed5e00eb92610c8b9216908690600401615796565b600060405180830381600087803b158015610ca557600080fd5b505af1158015610cb9573d6000803e3d6000fd5b505050508080610cc890615d63565b915050610c16565b505050565b60035461010090046001600160a01b03163314610d045760405162461bcd60e51b8152600401610c0a90615acf565b60008381526006602090815260409182902082516101808101845281548152600191820154600281810b810b810b9483019490945263010000008104840b840b840b94820194909452600160301b8404830b830b830b6060820152600160481b8404820b820b820b6080820152600160581b8404830b830b830b60a0820152600160701b8404820b820b820b60c0820152600160801b8404830b830b830b60e082015262ffffff600160981b85048116610100830152600160b01b8504840b840b840b610120830152600160c81b850416610140820152600160e01b909304820b820b90910b610160830152610cd0919084908490612f78565b6001600160a01b038116610e545760405162461bcd60e51b815260206004820152601960248201527f4f776e657220616464726573732063616e6e6f742062652030000000000000006044820152606401610c0a565b600154600160a01b900460ff1615610ec05760405162461bcd60e51b815260206004820152602960248201527f416c726561647920696e697469616c697a65642c20757365206e6f6d696e617460448201526832a732bba7bbb732b960b91b6064820152608401610c0a565b6001805460ff60a01b1916600160a01b179055600080546001600160a01b03831662010000810262010000600160b01b03199092169190911782556040805192835260208301919091527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c91015b60405180910390a150565b610f416132a7565b600180546001600160a01b0319166001600160a01b0383169081179091556040519081527f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce2290602001610f2e565b610f976132a7565b60035460ff1615158115151415610fab5750565b6003805460ff191682151590811790915560ff1615610fc957426002555b60035460405160ff909116151581527f8fb6c181ee25a520cf3dd6565006ef91229fcfe5a989566c2a3b8c115570cec590602001610f2e565b50565b60035461010090046001600160a01b031633146110345760405162461bcd60e51b8152600401610c0a90615acf565b61104081836001613321565b5050565b6000816111455760008381526006602090815260409182902082516101808101845281548152600191820154600281810b810b810b9483019490945263010000008104840b840b840b94820194909452600160301b8404830b830b830b6060820152600160481b8404820b820b820b6080820152600160581b8404830b830b830b60a0820152600160701b8404820b820b90910b60c0820152600160801b8304820b820b820b60e082015262ffffff600160981b84048116610100830152600160b01b8404830b830b830b610120830152600160c81b840416610140820152600160e01b909204810b810b900b61016082015261114090613391565b61123a565b60008381526007602090815260409182902082516101808101845281548152600191820154600281810b810b810b9483019490945263010000008104840b840b840b94820194909452600160301b8404830b830b830b6060820152600160481b8404820b820b820b6080820152600160581b8404830b830b830b60a0820152600160701b8404820b820b90910b60c0820152600160801b8304820b820b820b60e082015262ffffff600160981b84048116610100830152600160b01b8404830b830b830b610120830152600160c81b840416610140820152600160e01b909204810b810b900b61016082015261123a90613391565b9392505050565b600054610100900460ff1661125c5760005460ff1615611260565b303b155b6112c35760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610c0a565b600054610100900460ff161580156112e5576000805461ffff19166101011790555b6112ee86610dfe565b600380546001600160a01b0380881661010002610100600160a81b031990921691909117909155600480548683166001600160a01b031991821617909155600580549286169290911691909117905560005b82518110156113af576001600b600085848151811061136f57634e487b7160e01b600052603260045260246000fd5b6020026020010151815260200190815260200160002060006101000a81548160ff02191690831515021790555080806113a790615d63565b915050611340565b5080156113c2576000805461ff00191690555b505050505050565b6001600160a01b0381166000908152600d60205260408120546060919067ffffffffffffffff81111561140d57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015611436578160200160208202803683370190505b50905060005b6001600160a01b0384166000908152600d60205260409020548110156114d0576001600160a01b038085166000908152600c6020908152604080832085845290915290205483519116908390839081106114a657634e487b7160e01b600052603260045260246000fd5b6001600160a01b0390921660209283029190910190910152806114c881615d63565b91505061143c565b5092915050565b6001546001600160a01b0316331461154f5760405162461bcd60e51b815260206004820152603560248201527f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7560448201527402063616e20616363657074206f776e65727368697605c1b6064820152608401610c0a565b60005460015460408051620100009093046001600160a01b03908116845290911660208301527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a1600180546000805462010000600160b01b0319166001600160a01b03831662010000021790556001600160a01b0319169055565b60035461010090046001600160a01b03163314806115fc57506019546001600160a01b031633145b6116395760405162461bcd60e51b815260206004820152600e60248201526d24b73b30b634b21039b2b73232b960911b6044820152606401610c0a565b61164282613391565b156123e1576000611656836000015161352d565b90506000600660008560000151815260200190815260200160002060405180610180016040529081600082015481526020016001820160009054906101000a900460020b60020b60020b81526020016001820160039054906101000a900460020b60020b60020b81526020016001820160069054906101000a900460020b60020b60020b81526020016001820160099054906101000a900460010b60010b60010b815260200160018201600b9054906101000a900460020b60020b60020b815260200160018201600e9054906101000a900460010b60010b60010b81526020016001820160109054906101000a900460020b60020b60020b81526020016001820160139054906101000a900462ffffff1662ffffff1662ffffff1681526020016001820160169054906101000a900460020b60020b60020b81526020016001820160199054906101000a900462ffffff1662ffffff1662ffffff16815260200160018201601c9054906101000a900460020b60020b60020b8152505090508360066000866000015181526020019081526020016000206000820151816000015560208201518160010160006101000a81548162ffffff021916908360020b62ffffff16021790555060408201518160010160036101000a81548162ffffff021916908360020b62ffffff16021790555060608201518160010160066101000a81548162ffffff021916908360020b62ffffff16021790555060808201518160010160096101000a81548161ffff021916908360010b61ffff16021790555060a082015181600101600b6101000a81548162ffffff021916908360020b62ffffff16021790555060c082015181600101600e6101000a81548161ffff021916908360010b61ffff16021790555060e08201518160010160106101000a81548162ffffff021916908360020b62ffffff1602179055506101008201518160010160136101000a81548162ffffff021916908362ffffff1602179055506101208201518160010160166101000a81548162ffffff021916908360020b62ffffff1602179055506101408201518160010160196101000a81548162ffffff021916908362ffffff16021790555061016082015181600101601c6101000a81548162ffffff021916908360020b62ffffff160217905550905050426009600086600001518152602001908152602001600020819055506000600360019054906101000a90046001600160a01b03166001600160a01b031663f89c6f1886600001516040518263ffffffff1660e01b8152600401611a1091815260200190565b60206040518083038186803b158015611a2857600080fd5b505afa158015611a3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a609190614eb1565b9050611a728186600001516001613321565b6000848152600b602052604090205460ff1615611a9357611a938582613649565b6005546040516333dfec9960e21b81526001600160a01b0383811660048301529091169063cf7fb2649060240160206040518083038186803b158015611ad857600080fd5b505afa158015611aec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b1091906151cc565b15611f9a576001600160a01b03811660009081526008602052604090205460ff1680611bba5750600354604051630a928f9f60e21b81526001600160a01b03838116600483015261010090920490911690632a4a3e7c9060240160206040518083038186803b158015611b8257600080fd5b505afa158015611b96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bba91906151cc565b15611f95576001600160a01b03808216600090815260086020526040808220805460ff191690556003549051630259f5fd60e01b815261010090910490921691630259f5fd91611c0f91859190600401615796565b600060405180830381600087803b158015611c2957600080fd5b505af1158015611c3d573d6000803e3d6000fd5b5050600480546001600160a01b0385811660009081526018602052604090819020600354915163be27f89d60e01b81529485018b905292821695506342fa646a945089938993926101009092049091169063be27f89d9060240160206040518083038186803b158015611caf57600080fd5b505afa158015611cc3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ce791906151cc565b6040518563ffffffff1660e01b8152600401611d069493929190615af6565b60206040518083038186803b158015611d1e57600080fd5b505afa158015611d32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d5691906151cc565b611f87578160076000876000015181526020019081526020016000206000820151816000015560208201518160010160006101000a81548162ffffff021916908360020b62ffffff16021790555060408201518160010160036101000a81548162ffffff021916908360020b62ffffff16021790555060608201518160010160066101000a81548162ffffff021916908360020b62ffffff16021790555060808201518160010160096101000a81548161ffff021916908360010b61ffff16021790555060a082015181600101600b6101000a81548162ffffff021916908360020b62ffffff16021790555060c082015181600101600e6101000a81548161ffff021916908360010b61ffff16021790555060e08201518160010160106101000a81548162ffffff021916908360020b62ffffff1602179055506101008201518160010160136101000a81548162ffffff021916908362ffffff1602179055506101208201518160010160166101000a81548162ffffff021916908360020b62ffffff1602179055506101408201518160010160196101000a81548162ffffff021916908362ffffff16021790555061016082015181600101601c6101000a81548162ffffff021916908360020b62ffffff1602179055509050507fcb6e87c3d70eab47f84a42c3021b86de43cf8d37ebe9cfa494c4f89b75205a8a818660000151604051611f7a9291906001600160a01b03929092168252602082015260400190565b60405180910390a1612383565b611f95858260006001612f78565b612383565b6005546040516333dfec9960e21b81526001600160a01b0383811660048301529091169063cf7fb2649060240160206040518083038186803b158015611fdf57600080fd5b505afa158015611ff3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061201791906151cc565b1580156121395750600480546001600160a01b0383811660009081526018602052604090819020600354915163be27f89d60e01b8152938316946342fa646a948a948a946101009004169163be27f89d916120789187910190815260200190565b60206040518083038186803b15801561209057600080fd5b505afa1580156120a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120c891906151cc565b6040518563ffffffff1660e01b81526004016120e79493929190615af6565b60206040518083038186803b1580156120ff57600080fd5b505afa158015612113573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061213791906151cc565b155b156123835761214b8582600180612f78565b61215a8160016000600161375c565b8160076000876000015181526020019081526020016000206000820151816000015560208201518160010160006101000a81548162ffffff021916908360020b62ffffff16021790555060408201518160010160036101000a81548162ffffff021916908360020b62ffffff16021790555060608201518160010160066101000a81548162ffffff021916908360020b62ffffff16021790555060808201518160010160096101000a81548161ffff021916908360010b61ffff16021790555060a082015181600101600b6101000a81548162ffffff021916908360020b62ffffff16021790555060c082015181600101600e6101000a81548161ffff021916908360010b61ffff16021790555060e08201518160010160106101000a81548162ffffff021916908360020b62ffffff1602179055506101008201518160010160136101000a81548162ffffff021916908362ffffff1602179055506101208201518160010160166101000a81548162ffffff021916908360020b62ffffff1602179055506101408201518160010160196101000a81548162ffffff021916908362ffffff16021790555061016082015181600101601c6101000a81548162ffffff021916908360020b62ffffff1602179055509050507fcb6e87c3d70eab47f84a42c3021b86de43cf8d37ebe9cfa494c4f89b75205a8a81866000015160405161237a9291906001600160a01b03929092168252602082015260400190565b60405180910390a15b84516001600160a01b0382166000908152601860205260409081902090517f5d8fed649db8e5d2dd77ea4f51ee8548f87d2679e2f5407f8db9793f701f8dfe926123d1928a928a9190615900565b60405180910390a1505050505050565b6003548251604051631f138de360e31b8152600481019190915260009161010090046001600160a01b03169063f89c6f189060240160206040518083038186803b15801561242e57600080fd5b505afa158015612442573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124669190614eb1565b6005546040516333dfec9960e21b81526001600160a01b03808416600483015292935091169063cf7fb2649060240160206040518083038186803b1580156124ad57600080fd5b505afa1580156124c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124e591906151cc565b61252b576001600160a01b0381166000908152600860205260409020805460ff1916600190811790915561251d908490839080612f78565b61252b81600180600061375c565b82516040517f420dbf4677c8331a5938fcc5890c5ae453dd3344f80f9a669d6adb2fea7de3d09161256191879185918890615881565b60405180910390a150505050565b60035461010090046001600160a01b0316331461259e5760405162461bcd60e51b8152600401610c0a90615acf565b600081815260076020908152604080832060069092528083208254815560019283018054918401805462ffffff19811662ffffff600295860b860b81169182178455845465ffffffffffff19909316909117630100000092839004860b860b821690920291909117808355835468ffffff000000000000198216600160301b91829004870b870b8416909102908117845584546affffffffff000000000000199092166affff000000000000000000199091161761ffff600160481b92839004890b890b811690920217808455845462ffffff60581b198216600160581b91829004880b880b85169091029081178555855464ffffffffff60581b1990921661ffff60701b1990911617600160701b91829004890b90980b9091160295909517808255825462ffffff60801b198216600160801b91829004860b860b88169091029081178355835465ffffffffffff60801b1990921662ffffff60981b1990911617600160981b91829004871690910217808255825462ffffff60b01b198216600160b01b91829004860b860b88169091029081178355835465ffffffffffff60b01b1990921662ffffff60c81b1990911617600160c81b91829004871690910217808255915462ffffff60e01b19909216600160e01b92839004840b90930b90941602179091556003549051631f138de360e31b8152600481018490526101009091046001600160a01b03169063f89c6f189060240160206040518083038186803b1580156127cd57600080fd5b505afa1580156127e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128059190614eb1565b905061281381836001613321565b60008281526006602090815260408083206001600160a01b038516845260189092529182902091517f5d8fed649db8e5d2dd77ea4f51ee8548f87d2679e2f5407f8db9793f701f8dfe9261286b928692839290615939565b60405180910390a15050565b60606128828261352d565b92915050565b601860205281600052604060002081815481106128a457600080fd5b90600052602060002001600091509150505481565b6128c16132a7565b60038054610100600160a81b0319166101006001600160a01b0387811691820292909217909255600480546001600160a01b0319908116878416908117909255600580548216878516908117909155601980549092169386169384179091556040805194855260208501929092529083015260608201527fa2cad6ae2699ea86ba233a96ca0e57d895983eeed04f6bd0a770187c58b820dd90608001612561565b61296a6132a7565b6001600160a01b0381166129b25760405162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b6044820152606401610c0a565b600154600160a81b900460ff1615612a025760405162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481d1c985b9cd9995c9c9959606a1b6044820152606401610c0a565b600080546001600160a01b038381166201000081810262010000600160b01b031990941693909317938490556001805460ff60a81b1916600160a81b1790556040805193909404909116825260208201527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9101610f2e565b60035461010090046001600160a01b03163314612aaa5760405162461bcd60e51b8152600401610c0a90615acf565b6040518061018001604052808581526020018460020b81526020018360020b81526020018260020b8152602001600060010b8152602001600060020b8152602001600060010b8152602001600060020b8152602001600062ffffff168152602001600060020b8152602001600062ffffff168152602001600060020b815250600660008681526020019081526020016000206000820151816000015560208201518160010160006101000a81548162ffffff021916908360020b62ffffff16021790555060408201518160010160036101000a81548162ffffff021916908360020b62ffffff16021790555060608201518160010160066101000a81548162ffffff021916908360020b62ffffff16021790555060808201518160010160096101000a81548161ffff021916908360010b61ffff16021790555060a082015181600101600b6101000a81548162ffffff021916908360020b62ffffff16021790555060c082015181600101600e6101000a81548161ffff021916908360010b61ffff16021790555060e08201518160010160106101000a81548162ffffff021916908360020b62ffffff1602179055506101008201518160010160136101000a81548162ffffff021916908362ffffff1602179055506101208201518160010160166101000a81548162ffffff021916908360020b62ffffff1602179055506101408201518160010160196101000a81548162ffffff021916908362ffffff16021790555061016082015181600101601c6101000a81548162ffffff021916908360020b62ffffff16021790555090505042600960008681526020019081526020016000208190555050505050565b612d216132a7565b6000828152600b6020908152604091829020805460ff19168415159081179091558251858152918201527f388428bda48903bbd0180b2e70447674064e582855a643dd2df349c85b0683f6910161286b565b6060612882826137df565b6005546001600160a01b03163314612dc75760405162461bcd60e51b815260206004820152600c60248201526b27b7363c9036b0b730b3b2b960a11b6044820152606401610c0a565b600354604051624dc46d60e41b8152600481018490526001600160a01b038381166024830152610100909204909116906304dc46d090604401600060405180830381600087803b158015612e1a57600080fd5b505af11580156113c2573d6000803e3d6000fd5b60035461010090046001600160a01b03163314612e5d5760405162461bcd60e51b8152600401610c0a90615acf565b60005b6001600160a01b0385166000908152600d6020526040902054811015612f71576001600160a01b038086166000908152600c602090815260408083208584529091529020541684612f165760055460405163b91f5e3560e01b81526001600160a01b038381166004830152602482018890529091169063b91f5e3590604401600060405180830381600087803b158015612ef957600080fd5b505af1158015612f0d573d6000803e3d6000fd5b50505050612f5e565b6001600160a01b03811660009081526015602052604090205460ff1615612f4d57612f48818560ff168560ff16613879565b612f5e565b612f5e818560ff168560ff166139ab565b5080612f6981615d63565b915050612e60565b5050505050565b8015612fe75760035460405163ed5e00eb60e01b81526101009091046001600160a01b03169063ed5e00eb90612fb49086908690600401615796565b600060405180830381600087803b158015612fce57600080fd5b505af1158015612fe2573d6000803e3d6000fd5b505050505b6001600160a01b0383166000908152600d6020526040902054156132a15781156130ce5760005b6001600160a01b0384166000908152600d60205260409020548110156130c8576003546001600160a01b038581166000908152600c602090815260408083208684529091529081902054905163ed5e00eb60e01b815261010090930482169263ed5e00eb926130839216908790600401615796565b600060405180830381600087803b15801561309d57600080fd5b505af11580156130b1573d6000803e3d6000fd5b5050505080806130c090615d63565b91505061300e565b506132a1565b6130d784613aeb565b156131b8576001600160a01b038084166000908152600f6020908152604080832061010089015162ffffff168452909152902054168061314257600061312e866000015186600089608001518a6101000151613b56565b905061313c85826000613e4c565b506131b6565b60035460405163ed5e00eb60e01b81526101009091046001600160a01b03169063ed5e00eb906131789084908790600401615796565b600060405180830381600087803b15801561319257600080fd5b505af11580156131a6573d6000803e3d6000fd5b505050506131b684826000613e4c565b505b6131c184613eb0565b156132a1576001600160a01b038084166000908152600e602090815260408083206080890151600190810b900b8452909152902054168061322d576000613219866000015186600189608001518a6101000151613b56565b905061322785826001613e4c565b50612f71565b60035460405163ed5e00eb60e01b81526101009091046001600160a01b03169063ed5e00eb906132639084908790600401615796565b600060405180830381600087803b15801561327d57600080fd5b505af1158015613291573d6000803e3d6000fd5b50505050612f7184826001613e4c565b50505050565b6000546201000090046001600160a01b0316331461331f5760405162461bcd60e51b815260206004820152602f60248201527f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726660448201526e37b936903a3434b99030b1ba34b7b760891b6064820152608401610c0a565b565b806133345761332f83613f15565b61333d565b61333d826140fd565b6001600160a01b0384166000908152601860209081526040909120825161336a9391929190910190614d82565b5050506001600160a01b03166000908152601760205260409020805460ff19166001179055565b600480546003548351604051631c2ab73160e21b8152938401526000926001600160a01b039283169263abc7b988926101009004169063be27f89d9082906370aadcc49060240160206040518083038186803b1580156133f057600080fd5b505afa158015613404573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342891906154b6565b6040518263ffffffff1660e01b815260040161344691815260200190565b60206040518083038186803b15801561345e57600080fd5b505afa158015613472573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061349691906151cc565b6020850151604080870151606088015191516001600160e01b031960e087901b1681529315156004850152600292830b6024850152820b6044840152900b60648201526084015b60206040518083038186803b1580156134f557600080fd5b505afa158015613509573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061288291906151cc565b600354604051631f138de360e31b8152600481018390526060916000916101009091046001600160a01b03169063f89c6f189060240160206040518083038186803b15801561357b57600080fd5b505afa15801561358f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135b39190614eb1565b6001600160a01b03811660009081526017602052604090205490915060ff166135df57611140836140fd565b6001600160a01b0381166000908152601860209081526040918290208054835181840281018401909452808452909183018282801561363d57602002820191906000526020600020905b815481526020019060010190808311613629575b50505050509392505050565b61365282613aeb565b156136ce5761366382826000614292565b81516001600160a01b038083166000908152601360205260409020547fe796f6828b37337b49eb42b13232da29af82340b30005e54115fadb4a569e85c929116846136ad826137df565b6127126040516136c19594939291906158b5565b60405180910390a16136d9565b6136d98260006145b4565b6136e282613eb0565b15613751576136f382826001614292565b81516001600160a01b038083166000908152601460205260409020547fe796f6828b37337b49eb42b13232da29af82340b30005e54115fadb4a569e85c9291168461373d826137df565b61271160405161286b9594939291906158b5565b6110408260016145b4565b6003546040516302830aeb60e41b81526001600160a01b03868116600483015285151560248301528415156044830152831515606483015261010090920490911690632830aeb090608401600060405180830381600087803b1580156137c157600080fd5b505af11580156137d5573d6000803e3d6000fd5b5050505050505050565b6001600160a01b03811660009081526017602052604090205460609060ff166138105761380b82613f15565b612882565b6001600160a01b0382166000908152601860209081526040918290208054835181840281018401909452808452909183018282801561386e57602002820191906000526020600020905b81548152602001906001019080831161385a575b505050505092915050565b6001600160a01b03831660009081526011602052604081205460010b6138a0846064615c6e565b6138aa9190615bd7565b905060006138b9836064615c6e565b905060008160010b8360010b136138e5578160010b8360010b126138de5760006138e8565b60026138e8565b60015b60055460405163b91f5e3560e01b81526001600160a01b0389811660048301526024820184905292935091169063b91f5e3590604401600060405180830381600087803b15801561393857600080fd5b505af115801561394c573d6000803e3d6000fd5b5050506001600160a01b03808816600090815260106020526040908190205490517f83ceafeb39bed691550da26fa66ed80c145831e22e374c627a71f30479ae59b693506123d1928a92869291169061ffff808c1691908b16906157b1565b6001600160a01b03831660009081526012602052604081205462ffffff1690816139d58486615c1b565b6139e0906064615cf5565b62ffffff1611613a1d5762ffffff82166139fa8486615c1b565b613a05906064615cf5565b62ffffff1610613a16576000613a20565b6002613a20565b60015b60055460405163b91f5e3560e01b81526001600160a01b0388811660048301526024820184905292935091169063b91f5e3590604401600060405180830381600087803b158015613a7057600080fd5b505af1158015613a84573d6000803e3d6000fd5b5050506001600160a01b03808716600090815260106020526040908190205490517f83ceafeb39bed691550da26fa66ed80c145831e22e374c627a71f30479ae59b69350613adc9289928692911690899089906157b1565b60405180910390a15050505050565b60048054610100830151610120840151610140850151610160860151604051634e3a53b760e11b815262ffffff94851696810196909652600292830b6024870152921660448501520b60648301526000916001600160a01b0390911690639c74a76e906084016134dd565b600354604051631c2ab73160e21b8152600481018790526000918291613be49161010090046001600160a01b0316906370aadcc49060240160206040518083038186803b158015613ba657600080fd5b505afa158015613bba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613bde91906154b6565b8661473c565b6005549091506001600160a01b0316634cde32ce88613c05818989896147de565b60035460405163c48e62f160e01b8152600481018d90526101009091046001600160a01b03169063c48e62f19060240160006040518083038186803b158015613c4d57600080fd5b505afa158015613c61573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613c8991908101906153e3565b60200151600060028760018e6040518963ffffffff1660e01b8152600401613cb8989796959493929190615a4a565b602060405180830381600087803b158015613cd257600080fd5b505af1158015613ce6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d0a9190614eb1565b5060055460408051622610c560e41b815290516001600160a01b039092169163dd5adfa39160019184916302610c50916004808301926020929190829003018186803b158015613d5957600080fd5b505afa158015613d6d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d9191906154b6565b613d9b9190615d20565b6040518263ffffffff1660e01b8152600401613db991815260200190565b60206040518083038186803b158015613dd157600080fd5b505afa158015613de5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e099190614eb1565b9150613e4287878488888887600181518110613e3557634e487b7160e01b600052603260045260246000fd5b602002602001015161496e565b5095945050505050565b8015613e8157506001600160a01b03918216600090815260146020526040902080546001600160a01b03191691909216179055565b506001600160a01b03918216600090815260136020526040902080546001600160a01b03191691909216179055565b60048054608083015160a084015160c085015160e0860151604051630df2ba2560e41b8152600194850b96810196909652600292830b6024870152920b60448501520b60648301526000916001600160a01b039091169063df2ba250906084016134dd565b6001600160a01b0381166000908152600a602052604080822054815160028082526060828101909452929391928160200160208202803683375050506001600160a01b03851660009081526015602052604090205490915060ff16613f9557600082815260066020526040902060010154600160b01b900460020b613fb2565b600082815260066020526040902060010154600160581b900460020b5b60020b81600081518110613fd657634e487b7160e01b600052603260045260246000fd5b6020908102919091018101919091526001600160a01b03851660009081526015909152604090205460ff1661402657600082815260066020526040902060010154600160e01b900460020b614043565b600082815260066020526040902060010154600160801b900460020b5b60020b8160018151811061406757634e487b7160e01b600052603260045260246000fd5b602090810291909101015260048054604051632c85b65d60e21b81526001600160a01b039091169163b216d974916140a191859101615836565b60006040518083038186803b1580156140b957600080fd5b505afa1580156140cd573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526140f5919081019061511d565b949350505050565b60408051600380825260808201909252606091600091906020820184803683375050506000848152600660205260408120600101548251929350600290810b900b9183919061415c57634e487b7160e01b600052603260045260246000fd5b6020026020010181815250506006600084815260200190815260200160002060010160039054906101000a900460020b60020b816001815181106141b057634e487b7160e01b600052603260045260246000fd5b6020026020010181815250506006600084815260200190815260200160002060010160069054906101000a900460020b60020b8160028151811061420457634e487b7160e01b600052603260045260246000fd5b602090810291909101015260048054604051632c85b65d60e21b81526001600160a01b039091169163b216d9749161423e91859101615836565b60006040518083038186803b15801561425657600080fd5b505afa15801561426a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261123a919081019061511d565b6001600160a01b0382166000908152600d60205260408120541590826142d2576001600160a01b03808516600090815260136020526040902054166142ee565b6001600160a01b03808516600090815260146020526040902054165b905060008361432c576001600160a01b038086166000908152600f602090815260408083206101008b015162ffffff1684529091529020541661435e565b6001600160a01b038086166000908152600e6020908152604080832060808b0151600190810b900b8452909152902054165b9050828061437357506001600160a01b038116155b15614430576000614394876000015187878a608001518b6101000151613b56565b90506143a1868287613e4c565b6001600160a01b0383161561441a5760035460405163ed5e00eb60e01b81526101009091046001600160a01b03169063ed5e00eb906143e7908690600190600401615796565b600060405180830381600087803b15801561440157600080fd5b505af1158015614415573d6000803e3d6000fd5b505050505b61442a8188600001516000613321565b506113c2565b816001600160a01b0316816001600160a01b03161461453b5760035460405163ed5e00eb60e01b81526101009091046001600160a01b03169063ed5e00eb90614480908490600090600401615796565b600060405180830381600087803b15801561449a57600080fd5b505af11580156144ae573d6000803e3d6000fd5b505060035460405163ed5e00eb60e01b81526101009091046001600160a01b0316925063ed5e00eb91506144e9908590600190600401615796565b600060405180830381600087803b15801561450357600080fd5b505af1158015614517573d6000803e3d6000fd5b50505050614526858286613e4c565b6145368187600001516000613321565b6113c2565b60035460405163ed5e00eb60e01b81526101009091046001600160a01b03169063ed5e00eb90614572908590600090600401615796565b600060405180830381600087803b15801561458c57600080fd5b505af11580156145a0573d6000803e3d6000fd5b505050506113c28287600001516000613321565b6003548251604051631f138de360e31b8152600481019190915260009161010090046001600160a01b03169063f89c6f189060240160206040518083038186803b15801561460157600080fd5b505afa158015614615573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146399190614eb1565b6001600160a01b0381166000908152600d602052604090205490915015610cd05760005b6001600160a01b0382166000908152600d60205260409020548110156132a1576001600160a01b038083166000908152600c6020908152604080832085845282528083205490931680835260159091529190205460ff16151584151514156147295760035460405163ed5e00eb60e01b81526101009091046001600160a01b03169063ed5e00eb906146f6908490600190600401615796565b600060405180830381600087803b15801561471057600080fd5b505af1158015614724573d6000803e3d6000fd5b505050505b508061473481615d63565b91505061465d565b6040805160028082526060808301845292600092919060208301908036833701905050905061476d84612328615c42565b8160008151811061478e57634e487b7160e01b600052603260045260246000fd5b602002602001018181525050826147a7576127126147ab565b6127115b816001815181106147cc57634e487b7160e01b600052603260045260246000fd5b60209081029190910101529392505050565b60035460405163c48e62f160e01b8152600481018690526060916000916101009091046001600160a01b03169063c48e62f19060240160006040518083038186803b15801561482c57600080fd5b505afa158015614840573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261486891908101906153e3565b60a0015160035460405163c48e62f160e01b8152600481018990526101009091046001600160a01b03169063c48e62f19060240160006040518083038186803b1580156148b457600080fd5b505afa1580156148c8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526148f091908101906153e3565b60c001516040516020016149059291906156a0565b6040516020818303038152906040529050841561494e578061492685614c16565b604051602001614937929190615618565b6040516020818303038152906040529150506140f5565b8061495d8462ffffff16614c68565b604051602001614937929190615662565b600354604051624dc46d60e41b8152600481018990526001600160a01b038781166024830152610100909204909116906304dc46d090604401600060405180830381600087803b1580156149c157600080fd5b505af11580156149d5573d6000803e3d6000fd5b5050506001600160a01b038087166000818152600a602090815260408083208d905560168252808320805460ff19166001908117909155601083528184208054968e166001600160a01b03199788168117909155808552600c8452828520600d808652848720805488529186529386208054909816909617909655949092525254614a61925090615c42565b6001600160a01b0387166000908152600d60205260409020558315614b58576001600160a01b038681166000818152600e60209081526040808320600189810b80820b865291845282852080546001600160a01b0319908116988e1698891790915587865260118552838620805461ffff191661ffff90941693909317909255948452601483528184208054909116861790559382526015905291909120805460ff191690911790557f41525405a5e10a7f61a75ce8fb247811dadc00a10ad9bd82d09ddab453a686d386868986614b38836137df565b86604051614b4b96959493929190615708565b60405180910390a1614c0d565b6001600160a01b038087166000818152600f6020908152604080832062ffffff88168085529083528184208054968c166001600160a01b0319978816811790915580855260128452828520805462ffffff19169092179091559383526013909152902080549092161790557f2fb9c2a6ac1646a705c03b0657053182a32ea93c368b719a84e352ab42dcb8f886868985614bf1836137df565b86604051614c0496959493929190615758565b60405180910390a15b50505050505050565b606060008260010b13614c5f57614c3b614c3283600019615c6e565b61ffff16614c68565b604051602001614c4b91906156df565b604051602081830303815290604052612882565b6128828261ffff165b606081614c8c5750506040805180820190915260018152600360fc1b602082015290565b8160005b8115614cb65780614ca081615d63565b9150614caf9050600a83615c5a565b9150614c90565b60008167ffffffffffffffff811115614cdf57634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015614d09576020820181803683370190505b5090505b84156140f557614d1e600183615d20565b9150614d2b600a86615d7e565b614d36906030615c42565b60f81b818381518110614d5957634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350614d7b600a86615c5a565b9450614d0d565b828054828255906000526020600020908101928215614dbd579160200282015b82811115614dbd578251825591602001919060010190614da2565b50614dc9929150614dcd565b5090565b5b80821115614dc95760008155600101614dce565b8035600181900b8114614df457600080fd5b919050565b8035614df481615df7565b8051614df481615df7565b600082601f830112614e1f578081fd5b815167ffffffffffffffff811115614e3957614e39615dbe565b614e4c601f8201601f1916602001615b82565b818152846020838601011115614e60578283fd5b6140f5826020830160208701615d37565b803562ffffff81168114614df457600080fd5b803560ff81168114614df457600080fd5b600060208284031215614ea6578081fd5b813561123a81615dd4565b600060208284031215614ec2578081fd5b815161123a81615dd4565b60008060008060808587031215614ee2578283fd5b8435614eed81615dd4565b93506020850135614efd81615dd4565b92506040850135614f0d81615dd4565b91506060850135614f1d81615dd4565b939692955090935050565b600080600080600060a08688031215614f3f578283fd5b8535614f4a81615dd4565b9450602086810135614f5b81615dd4565b94506040870135614f6b81615dd4565b93506060870135614f7b81615dd4565b9250608087013567ffffffffffffffff811115614f96578283fd5b8701601f81018913614fa6578283fd5b8035614fb9614fb482615bb3565b615b82565b8082825284820191508484018c868560051b8701011115614fd8578687fd5b8694505b83851015614ffa578035835260019490940193918501918501614fdc565b5080955050505050509295509295909350565b6000806040838503121561501f578182fd5b823561502a81615dd4565b9150602083013561503a81615de9565b809150509250929050565b60008060408385031215615057578182fd5b823561506281615dd4565b915061507060208401614de2565b90509250929050565b6000806040838503121561508b578182fd5b823561509681615dd4565b915061507060208401614e71565b600080604083850312156150b6578182fd5b82356150c181615dd4565b946020939093013593505050565b600080600080608085870312156150e4578182fd5b84356150ef81615dd4565b93506020850135925061510460408601614e84565b915061511260608601614e84565b905092959194509250565b6000602080838503121561512f578182fd5b825167ffffffffffffffff811115615145578283fd5b8301601f81018513615155578283fd5b8051615163614fb482615bb3565b80828252848201915084840188868560051b8701011115615182578687fd5b8694505b838510156151a4578051835260019490940193918501918501615186565b50979650505050505050565b6000602082840312156151c1578081fd5b813561123a81615de9565b6000602082840312156151dd578081fd5b815161123a81615de9565b6000602082840312156151f9578081fd5b5035919050565b60008060408385031215615212578182fd5b82359150602083013561503a81615dd4565b600080600060608486031215615238578081fd5b83359250602084013561524a81615dd4565b9150604084013561525a81615de9565b809150509250925092565b60008060408385031215615277578182fd5b82359150602083013561503a81615de9565b6000806000806080858703121561529e578182fd5b8435935060208501356152b081615df7565b925060408501356152c081615df7565b91506060850135614f1d81615df7565b60008060008385036101c08112156152e6578182fd5b8435935061018080601f19830112156152fd578283fd5b615305615b35565b91506020860135825261531a60408701614df9565b602083015261532b60608701614df9565b604083015261533c60808701614df9565b606083015261534d60a08701614de2565b608083015261535e60c08701614df9565b60a083015261536f60e08701614de2565b60c0830152610100615382818801614df9565b60e0840152610120615395818901614e71565b8285015261014091506153a9828901614df9565b908401526101606153bb888201614e71565b828501526153ca838901614df9565b908401525093969095506101a094909401359392505050565b6000602082840312156153f4578081fd5b815167ffffffffffffffff8082111561540b578283fd5b9083019060e0828603121561541e578283fd5b615426615b5f565b825181526020830151602082015261544060408401614e04565b604082015261545160608401614e04565b606082015261546260808401614e04565b608082015260a083015182811115615478578485fd5b61548487828601614e0f565b60a08301525060c08301518281111561549b578485fd5b6154a787828601614e0f565b60c08301525095945050505050565b6000602082840312156154c7578081fd5b5051919050565b6000815180845260208085019450808401835b838110156154fd578151875295820195908201906001016154e1565b509495945050505050565b6000815480845260208085019450838352808320835b838110156154fd5781548752958201956001918201910161551e565b805182526020810151615552602084018260020b9052565b506040810151615567604084018260020b9052565b50606081015161557c606084018260020b9052565b506080810151615591608084018260010b9052565b5060a08101516155a660a084018260020b9052565b5060c08101516155bb60c084018260010b9052565b5060e08101516155d060e084018260020b9052565b506101008181015162ffffff169083015261012080820151600281900b8285015250506101408181015162ffffff169083015261016080820151600281900b828501526132a1565b6000835161562a818460208801615d37565b600560fb1b9083019081528351615648816001840160208801615d37565b602960f81b60019290910191820152600201949350505050565b60008351615674818460208801615d37565b6201016960ed1b9083019081528351615694816003840160208801615d37565b01600301949350505050565b600083516156b2818460208801615d37565b630103b39960e51b90830190815283516156d3816004840160208801615d37565b01600401949350505050565b602d60f81b8152600082516156fb816001850160208701615d37565b9190910160010192915050565b6001600160a01b0387811682528616602082015260408101859052600184900b606082015260c060808201819052600090615745908301856154ce565b90508260a0830152979650505050505050565b6001600160a01b038781168252861660208201526040810185905262ffffff8416606082015260c060808201819052600090615745908301856154ce565b6001600160a01b039290921682521515602082015260400190565b6001600160a01b039586168152602081019490945291909316604083015262ffffff9283166060830152909116608082015260a00190565b6020808252825182820181905260009190848201906040850190845b8181101561582a5783516001600160a01b031683529284019291840191600101615805565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561582a57835183529284019291840191600101615852565b60208152600061123a60208301846154ce565b8481526001600160a01b0384166020820152604081018390526101e081016158ac606083018461553a565b95945050505050565b8581526001600160a01b038516602082015260006102006158d9604084018761553a565b806101c08401526158ec818401866154ce565b915050826101e08301529695505050505050565b60006101e086835285602084015261591b604084018661553a565b806101c084015261592e81840185615508565b979650505050505050565b60006101e086835285602084015284546040840152600185015460026159666060860183830b60020b9052565b61597a608086018360181c830b60020b9052565b61598e60a086018360301c830b60020b9052565b6159a360c086018360481c60010b60010b9052565b6159b760e086018360581c830b60020b9052565b6159cd61010086018360701c60010b60010b9052565b6159e261012086018360801c830b60020b9052565b62ffffff609883901c8116610140870152615a0861016087018460b01c840b60020b9052565b615a1f6101808701828560c81c1662ffffff169052565b50615a356101a086018360e01c830b60020b9052565b5050806101c084015261592e81840185615508565b60006101008a8352806020840152895180828501526101209150615a748183860160208e01615d37565b604084018a90526060840189905260808401889052601f01601f19168301838103820160a0850152615aa8828201886154ce565b95151560c08501525050506001600160a01b039190911660e0909101529695505050505050565b6020808252600d908201526c27b7363c9031b7b739bab6b2b960991b604082015260600190565b848152608060208201526000615b0f60808301866154ce565b8281036040840152615b218186615508565b915050821515606083015295945050505050565b604051610180810167ffffffffffffffff81118282101715615b5957615b59615dbe565b60405290565b60405160e0810167ffffffffffffffff81118282101715615b5957615b59615dbe565b604051601f8201601f1916810167ffffffffffffffff81118282101715615bab57615bab615dbe565b604052919050565b600067ffffffffffffffff821115615bcd57615bcd615dbe565b5060051b60200190565b60008160010b8360010b82821282617fff03821381151615615bfb57615bfb615d92565b82617fff19038212811615615c1257615c12615d92565b50019392505050565b600062ffffff808316818516808303821115615c3957615c39615d92565b01949350505050565b60008219821115615c5557615c55615d92565b500190565b600082615c6957615c69615da8565b500490565b60008160010b8360010b617fff83821384841383830485118282161615615c9757615c97615d92565b617fff1986851282811687830587121615615cb457615cb4615d92565b878712925085820587128484161615615ccf57615ccf615d92565b85850587128184161615615ce557615ce5615d92565b5050509290910295945050505050565b600062ffffff80831681851681830481118215151615615d1757615d17615d92565b02949350505050565b600082821015615d3257615d32615d92565b500390565b60005b83811015615d52578181015183820152602001615d3a565b838111156132a15750506000910152565b6000600019821415615d7757615d77615d92565b5060010190565b600082615d8d57615d8d615da8565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461100257600080fd5b801515811461100257600080fd5b8060020b811461100257600080fdfea26469706673582212205761f7e1b6b5b5fb6c9da5a8824e0e8d72a9efc0113ffaf813d0279d3870a07b64736f6c63430008040033

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106103785760003560e01c806360b4df85116101d3578063ae71dcdf11610104578063c480977c116100a2578063d28231bd1161007c578063d28231bd14610b7f578063db0d457914610ba2578063e38f273814610bb5578063fa043f4014610bc857600080fd5b8063c480977c14610b39578063cc5cea2714610b4c578063ceda8e9014610b5f57600080fd5b8063b4fd7296116100de578063b4fd729614610ad2578063b613d8ee14610aea578063bf989b6e14610b13578063c3b83f5f14610b2657600080fd5b8063ae71dcdf14610a20578063b09bd9e314610a28578063b103feb014610abf57600080fd5b806393f4452e116101715780639971441b1161014b5780639971441b146109c15780639aceb36e146109d4578063a12695ca146109f4578063a4f096e814610a1757600080fd5b806393f4452e1461086b57806393ff69d714610975578063988a1309146109ae57600080fd5b80638d220d99116101ad5780638d220d99146107b65780638da5cb5b146107ec57806391b4ded914610805578063937a314f1461080e57600080fd5b806360b4df85146106dd5780636c35b7751461078557806379ba5097146107ae57600080fd5b80632fff7020116102ad5780634adf72191161024b578063574ef5d911610225578063574ef5d9146106505780635a2f7731146106735780635c975abb1461069c5780635d134bc2146106a957600080fd5b80634adf7219146105fd5780635034c5881461061d57806353a47bb71461063d57600080fd5b8063366c16a511610287578063366c16a51461057d57806336c0d8551461059d5780633ea921ae146105c0578063447b1d58146105c957600080fd5b80632fff7020146104eb578063300a0298146104f357806332b566a9146104fb57600080fd5b80631afed5cc1161031a57806323b1d818116102f457806323b1d8181461047e578063263737e2146104915780632b7ac3f3146104c55780632da3f9ce146104d857600080fd5b80631afed5cc146104415780631cededce146104585780631e864c3b1461046b57600080fd5b806313af40351161035657806313af4035146103d557806314bdaa89146103e85780631627540c1461041b57806316c38b3c1461042e57600080fd5b806301a5627e1461037d5780630caf0e0c1461039257806310063fdc146103a5575b600080fd5b61039061038b36600461500d565b610bdb565b005b6103906103a0366004615224565b610cd5565b6005546103b8906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6103906103e3366004614e95565b610dfe565b61040b6103f6366004614e95565b60176020526000908152604090205460ff1681565b60405190151581526020016103cc565b610390610429366004614e95565b610f39565b61039061043c3660046151b0565b610f8f565b61044a61232881565b6040519081526020016103cc565b610390610466366004615200565b611005565b6019546103b8906001600160a01b031681565b61040b61048c366004615265565b611044565b6103b861049f366004615079565b600f6020908152600092835260408084209091529082529020546001600160a01b031681565b6004546103b8906001600160a01b031681565b6103906104e6366004614f28565b611241565b61044a600181565b61044a600281565b61054b6105093660046151e8565b6000908152600660205260409020600190810154600160481b8104820b92600160701b820490920b9162ffffff600160981b8304811692600160c81b90041690565b60408051600195860b81529390940b602084015262ffffff9182169383019390935290911660608201526080016103cc565b61059061058b366004614e95565b6113ca565b6040516103cc91906157e9565b61040b6105ab366004614e95565b60086020526000908152604090205460ff1681565b61044a61271181565b6103b86105d73660046150a4565b600c6020908152600092835260408084209091529082529020546001600160a01b031681565b61044a61060b366004614e95565b600a6020526000908152604090205481565b61044a61062b3660046151e8565b60096020526000908152604090205481565b6001546103b8906001600160a01b031681565b61040b61065e3660046151e8565b600b6020526000908152604090205460ff1681565b6103b8610681366004614e95565b6014602052600090815260409020546001600160a01b031681565b60035461040b9060ff1681565b6103b86106b7366004615045565b600e6020908152600092835260408084209091529082529020546001600160a01b031681565b6107426106eb3660046151e8565b600090815260066020526040902060010154600281810b9263010000008304820b92600160301b8104830b92600160581b8204810b92600160801b8304820b92600160b01b8104830b92600160e01b909104900b90565b60408051600298890b815296880b602088015294870b9486019490945291850b6060850152840b6080840152830b60a083015290910b60c082015260e0016103cc565b6103b8610793366004614e95565b6010602052600090815260409020546001600160a01b031681565b6103906114d7565b6107d96107c4366004614e95565b60116020526000908152604090205460010b81565b60405160019190910b81526020016103cc565b6000546103b8906201000090046001600160a01b031681565b61044a60025481565b61084b61081c366004614e95565b6001600160a01b0390811660009081526013602090815260408083205460149092529091205490821692911690565b604080516001600160a01b039384168152929091166020830152016103cc565b6109026108793660046151e8565b600660205260009081526040902080546001918201549091600282810b9263010000008104820b92600160301b8204830b92600160481b8304820b92600160581b8104820b92600160701b8204900b91600160801b8204810b9162ffffff600160981b8204811692600160b01b8304810b92600160c81b810490921691600160e01b9004900b8c565b604080519c8d5260029b8c0b60208e0152998b0b998c019990995296890b60608b0152600195860b60808b015293880b60a08a01529190930b60c088015291850b60e087015262ffffff918216610100870152840b61012086015216610140840152900b610160820152610180016103cc565b61099a610983366004614e95565b60126020526000908152604090205462ffffff1681565b60405162ffffff90911681526020016103cc565b6103906109bc3660046152d0565b6115d4565b6103906109cf3660046151e8565b61256f565b6109e76109e23660046151e8565b612877565b6040516103cc919061586e565b61040b610a02366004614e95565b60156020526000908152604090205460ff1681565b61044a61271281565b61044a600081565b610902610a363660046151e8565b600760205260009081526040902080546001918201549091600282810b9263010000008104820b92600160301b8204830b92600160481b8304820b92600160581b8104820b92600160701b8204900b91600160801b8204810b9162ffffff600160981b8204811692600160b01b8304810b92600160c81b810490921691600160e01b9004900b8c565b61044a610acd3660046150a4565b612888565b6003546103b89061010090046001600160a01b031681565b6103b8610af8366004614e95565b6013602052600090815260409020546001600160a01b031681565b610390610b21366004614ecd565b6128b9565b610390610b34366004614e95565b612962565b610390610b47366004615289565b612a7b565b610390610b5a366004615265565b612d19565b61044a610b6d366004614e95565b600d6020526000908152604090205481565b61040b610b8d366004614e95565b60166020526000908152604090205460ff1681565b6109e7610bb0366004614e95565b612d73565b610390610bc3366004615200565b612d7e565b610390610bd63660046150cf565b612e2e565b60035461010090046001600160a01b03163314610c135760405162461bcd60e51b8152600401610c0a90615acf565b60405180910390fd5b60005b6001600160a01b0383166000908152600d6020526040902054811015610cd0576003546001600160a01b038481166000908152600c602090815260408083208684529091529081902054905163ed5e00eb60e01b815261010090930482169263ed5e00eb92610c8b9216908690600401615796565b600060405180830381600087803b158015610ca557600080fd5b505af1158015610cb9573d6000803e3d6000fd5b505050508080610cc890615d63565b915050610c16565b505050565b60035461010090046001600160a01b03163314610d045760405162461bcd60e51b8152600401610c0a90615acf565b60008381526006602090815260409182902082516101808101845281548152600191820154600281810b810b810b9483019490945263010000008104840b840b840b94820194909452600160301b8404830b830b830b6060820152600160481b8404820b820b820b6080820152600160581b8404830b830b830b60a0820152600160701b8404820b820b820b60c0820152600160801b8404830b830b830b60e082015262ffffff600160981b85048116610100830152600160b01b8504840b840b840b610120830152600160c81b850416610140820152600160e01b909304820b820b90910b610160830152610cd0919084908490612f78565b6001600160a01b038116610e545760405162461bcd60e51b815260206004820152601960248201527f4f776e657220616464726573732063616e6e6f742062652030000000000000006044820152606401610c0a565b600154600160a01b900460ff1615610ec05760405162461bcd60e51b815260206004820152602960248201527f416c726561647920696e697469616c697a65642c20757365206e6f6d696e617460448201526832a732bba7bbb732b960b91b6064820152608401610c0a565b6001805460ff60a01b1916600160a01b179055600080546001600160a01b03831662010000810262010000600160b01b03199092169190911782556040805192835260208301919091527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c91015b60405180910390a150565b610f416132a7565b600180546001600160a01b0319166001600160a01b0383169081179091556040519081527f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce2290602001610f2e565b610f976132a7565b60035460ff1615158115151415610fab5750565b6003805460ff191682151590811790915560ff1615610fc957426002555b60035460405160ff909116151581527f8fb6c181ee25a520cf3dd6565006ef91229fcfe5a989566c2a3b8c115570cec590602001610f2e565b50565b60035461010090046001600160a01b031633146110345760405162461bcd60e51b8152600401610c0a90615acf565b61104081836001613321565b5050565b6000816111455760008381526006602090815260409182902082516101808101845281548152600191820154600281810b810b810b9483019490945263010000008104840b840b840b94820194909452600160301b8404830b830b830b6060820152600160481b8404820b820b820b6080820152600160581b8404830b830b830b60a0820152600160701b8404820b820b90910b60c0820152600160801b8304820b820b820b60e082015262ffffff600160981b84048116610100830152600160b01b8404830b830b830b610120830152600160c81b840416610140820152600160e01b909204810b810b900b61016082015261114090613391565b61123a565b60008381526007602090815260409182902082516101808101845281548152600191820154600281810b810b810b9483019490945263010000008104840b840b840b94820194909452600160301b8404830b830b830b6060820152600160481b8404820b820b820b6080820152600160581b8404830b830b830b60a0820152600160701b8404820b820b90910b60c0820152600160801b8304820b820b820b60e082015262ffffff600160981b84048116610100830152600160b01b8404830b830b830b610120830152600160c81b840416610140820152600160e01b909204810b810b900b61016082015261123a90613391565b9392505050565b600054610100900460ff1661125c5760005460ff1615611260565b303b155b6112c35760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610c0a565b600054610100900460ff161580156112e5576000805461ffff19166101011790555b6112ee86610dfe565b600380546001600160a01b0380881661010002610100600160a81b031990921691909117909155600480548683166001600160a01b031991821617909155600580549286169290911691909117905560005b82518110156113af576001600b600085848151811061136f57634e487b7160e01b600052603260045260246000fd5b6020026020010151815260200190815260200160002060006101000a81548160ff02191690831515021790555080806113a790615d63565b915050611340565b5080156113c2576000805461ff00191690555b505050505050565b6001600160a01b0381166000908152600d60205260408120546060919067ffffffffffffffff81111561140d57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015611436578160200160208202803683370190505b50905060005b6001600160a01b0384166000908152600d60205260409020548110156114d0576001600160a01b038085166000908152600c6020908152604080832085845290915290205483519116908390839081106114a657634e487b7160e01b600052603260045260246000fd5b6001600160a01b0390921660209283029190910190910152806114c881615d63565b91505061143c565b5092915050565b6001546001600160a01b0316331461154f5760405162461bcd60e51b815260206004820152603560248201527f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7560448201527402063616e20616363657074206f776e65727368697605c1b6064820152608401610c0a565b60005460015460408051620100009093046001600160a01b03908116845290911660208301527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a1600180546000805462010000600160b01b0319166001600160a01b03831662010000021790556001600160a01b0319169055565b60035461010090046001600160a01b03163314806115fc57506019546001600160a01b031633145b6116395760405162461bcd60e51b815260206004820152600e60248201526d24b73b30b634b21039b2b73232b960911b6044820152606401610c0a565b61164282613391565b156123e1576000611656836000015161352d565b90506000600660008560000151815260200190815260200160002060405180610180016040529081600082015481526020016001820160009054906101000a900460020b60020b60020b81526020016001820160039054906101000a900460020b60020b60020b81526020016001820160069054906101000a900460020b60020b60020b81526020016001820160099054906101000a900460010b60010b60010b815260200160018201600b9054906101000a900460020b60020b60020b815260200160018201600e9054906101000a900460010b60010b60010b81526020016001820160109054906101000a900460020b60020b60020b81526020016001820160139054906101000a900462ffffff1662ffffff1662ffffff1681526020016001820160169054906101000a900460020b60020b60020b81526020016001820160199054906101000a900462ffffff1662ffffff1662ffffff16815260200160018201601c9054906101000a900460020b60020b60020b8152505090508360066000866000015181526020019081526020016000206000820151816000015560208201518160010160006101000a81548162ffffff021916908360020b62ffffff16021790555060408201518160010160036101000a81548162ffffff021916908360020b62ffffff16021790555060608201518160010160066101000a81548162ffffff021916908360020b62ffffff16021790555060808201518160010160096101000a81548161ffff021916908360010b61ffff16021790555060a082015181600101600b6101000a81548162ffffff021916908360020b62ffffff16021790555060c082015181600101600e6101000a81548161ffff021916908360010b61ffff16021790555060e08201518160010160106101000a81548162ffffff021916908360020b62ffffff1602179055506101008201518160010160136101000a81548162ffffff021916908362ffffff1602179055506101208201518160010160166101000a81548162ffffff021916908360020b62ffffff1602179055506101408201518160010160196101000a81548162ffffff021916908362ffffff16021790555061016082015181600101601c6101000a81548162ffffff021916908360020b62ffffff160217905550905050426009600086600001518152602001908152602001600020819055506000600360019054906101000a90046001600160a01b03166001600160a01b031663f89c6f1886600001516040518263ffffffff1660e01b8152600401611a1091815260200190565b60206040518083038186803b158015611a2857600080fd5b505afa158015611a3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a609190614eb1565b9050611a728186600001516001613321565b6000848152600b602052604090205460ff1615611a9357611a938582613649565b6005546040516333dfec9960e21b81526001600160a01b0383811660048301529091169063cf7fb2649060240160206040518083038186803b158015611ad857600080fd5b505afa158015611aec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b1091906151cc565b15611f9a576001600160a01b03811660009081526008602052604090205460ff1680611bba5750600354604051630a928f9f60e21b81526001600160a01b03838116600483015261010090920490911690632a4a3e7c9060240160206040518083038186803b158015611b8257600080fd5b505afa158015611b96573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bba91906151cc565b15611f95576001600160a01b03808216600090815260086020526040808220805460ff191690556003549051630259f5fd60e01b815261010090910490921691630259f5fd91611c0f91859190600401615796565b600060405180830381600087803b158015611c2957600080fd5b505af1158015611c3d573d6000803e3d6000fd5b5050600480546001600160a01b0385811660009081526018602052604090819020600354915163be27f89d60e01b81529485018b905292821695506342fa646a945089938993926101009092049091169063be27f89d9060240160206040518083038186803b158015611caf57600080fd5b505afa158015611cc3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ce791906151cc565b6040518563ffffffff1660e01b8152600401611d069493929190615af6565b60206040518083038186803b158015611d1e57600080fd5b505afa158015611d32573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d5691906151cc565b611f87578160076000876000015181526020019081526020016000206000820151816000015560208201518160010160006101000a81548162ffffff021916908360020b62ffffff16021790555060408201518160010160036101000a81548162ffffff021916908360020b62ffffff16021790555060608201518160010160066101000a81548162ffffff021916908360020b62ffffff16021790555060808201518160010160096101000a81548161ffff021916908360010b61ffff16021790555060a082015181600101600b6101000a81548162ffffff021916908360020b62ffffff16021790555060c082015181600101600e6101000a81548161ffff021916908360010b61ffff16021790555060e08201518160010160106101000a81548162ffffff021916908360020b62ffffff1602179055506101008201518160010160136101000a81548162ffffff021916908362ffffff1602179055506101208201518160010160166101000a81548162ffffff021916908360020b62ffffff1602179055506101408201518160010160196101000a81548162ffffff021916908362ffffff16021790555061016082015181600101601c6101000a81548162ffffff021916908360020b62ffffff1602179055509050507fcb6e87c3d70eab47f84a42c3021b86de43cf8d37ebe9cfa494c4f89b75205a8a818660000151604051611f7a9291906001600160a01b03929092168252602082015260400190565b60405180910390a1612383565b611f95858260006001612f78565b612383565b6005546040516333dfec9960e21b81526001600160a01b0383811660048301529091169063cf7fb2649060240160206040518083038186803b158015611fdf57600080fd5b505afa158015611ff3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061201791906151cc565b1580156121395750600480546001600160a01b0383811660009081526018602052604090819020600354915163be27f89d60e01b8152938316946342fa646a948a948a946101009004169163be27f89d916120789187910190815260200190565b60206040518083038186803b15801561209057600080fd5b505afa1580156120a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120c891906151cc565b6040518563ffffffff1660e01b81526004016120e79493929190615af6565b60206040518083038186803b1580156120ff57600080fd5b505afa158015612113573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061213791906151cc565b155b156123835761214b8582600180612f78565b61215a8160016000600161375c565b8160076000876000015181526020019081526020016000206000820151816000015560208201518160010160006101000a81548162ffffff021916908360020b62ffffff16021790555060408201518160010160036101000a81548162ffffff021916908360020b62ffffff16021790555060608201518160010160066101000a81548162ffffff021916908360020b62ffffff16021790555060808201518160010160096101000a81548161ffff021916908360010b61ffff16021790555060a082015181600101600b6101000a81548162ffffff021916908360020b62ffffff16021790555060c082015181600101600e6101000a81548161ffff021916908360010b61ffff16021790555060e08201518160010160106101000a81548162ffffff021916908360020b62ffffff1602179055506101008201518160010160136101000a81548162ffffff021916908362ffffff1602179055506101208201518160010160166101000a81548162ffffff021916908360020b62ffffff1602179055506101408201518160010160196101000a81548162ffffff021916908362ffffff16021790555061016082015181600101601c6101000a81548162ffffff021916908360020b62ffffff1602179055509050507fcb6e87c3d70eab47f84a42c3021b86de43cf8d37ebe9cfa494c4f89b75205a8a81866000015160405161237a9291906001600160a01b03929092168252602082015260400190565b60405180910390a15b84516001600160a01b0382166000908152601860205260409081902090517f5d8fed649db8e5d2dd77ea4f51ee8548f87d2679e2f5407f8db9793f701f8dfe926123d1928a928a9190615900565b60405180910390a1505050505050565b6003548251604051631f138de360e31b8152600481019190915260009161010090046001600160a01b03169063f89c6f189060240160206040518083038186803b15801561242e57600080fd5b505afa158015612442573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124669190614eb1565b6005546040516333dfec9960e21b81526001600160a01b03808416600483015292935091169063cf7fb2649060240160206040518083038186803b1580156124ad57600080fd5b505afa1580156124c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124e591906151cc565b61252b576001600160a01b0381166000908152600860205260409020805460ff1916600190811790915561251d908490839080612f78565b61252b81600180600061375c565b82516040517f420dbf4677c8331a5938fcc5890c5ae453dd3344f80f9a669d6adb2fea7de3d09161256191879185918890615881565b60405180910390a150505050565b60035461010090046001600160a01b0316331461259e5760405162461bcd60e51b8152600401610c0a90615acf565b600081815260076020908152604080832060069092528083208254815560019283018054918401805462ffffff19811662ffffff600295860b860b81169182178455845465ffffffffffff19909316909117630100000092839004860b860b821690920291909117808355835468ffffff000000000000198216600160301b91829004870b870b8416909102908117845584546affffffffff000000000000199092166affff000000000000000000199091161761ffff600160481b92839004890b890b811690920217808455845462ffffff60581b198216600160581b91829004880b880b85169091029081178555855464ffffffffff60581b1990921661ffff60701b1990911617600160701b91829004890b90980b9091160295909517808255825462ffffff60801b198216600160801b91829004860b860b88169091029081178355835465ffffffffffff60801b1990921662ffffff60981b1990911617600160981b91829004871690910217808255825462ffffff60b01b198216600160b01b91829004860b860b88169091029081178355835465ffffffffffff60b01b1990921662ffffff60c81b1990911617600160c81b91829004871690910217808255915462ffffff60e01b19909216600160e01b92839004840b90930b90941602179091556003549051631f138de360e31b8152600481018490526101009091046001600160a01b03169063f89c6f189060240160206040518083038186803b1580156127cd57600080fd5b505afa1580156127e1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128059190614eb1565b905061281381836001613321565b60008281526006602090815260408083206001600160a01b038516845260189092529182902091517f5d8fed649db8e5d2dd77ea4f51ee8548f87d2679e2f5407f8db9793f701f8dfe9261286b928692839290615939565b60405180910390a15050565b60606128828261352d565b92915050565b601860205281600052604060002081815481106128a457600080fd5b90600052602060002001600091509150505481565b6128c16132a7565b60038054610100600160a81b0319166101006001600160a01b0387811691820292909217909255600480546001600160a01b0319908116878416908117909255600580548216878516908117909155601980549092169386169384179091556040805194855260208501929092529083015260608201527fa2cad6ae2699ea86ba233a96ca0e57d895983eeed04f6bd0a770187c58b820dd90608001612561565b61296a6132a7565b6001600160a01b0381166129b25760405162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b6044820152606401610c0a565b600154600160a81b900460ff1615612a025760405162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481d1c985b9cd9995c9c9959606a1b6044820152606401610c0a565b600080546001600160a01b038381166201000081810262010000600160b01b031990941693909317938490556001805460ff60a81b1916600160a81b1790556040805193909404909116825260208201527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9101610f2e565b60035461010090046001600160a01b03163314612aaa5760405162461bcd60e51b8152600401610c0a90615acf565b6040518061018001604052808581526020018460020b81526020018360020b81526020018260020b8152602001600060010b8152602001600060020b8152602001600060010b8152602001600060020b8152602001600062ffffff168152602001600060020b8152602001600062ffffff168152602001600060020b815250600660008681526020019081526020016000206000820151816000015560208201518160010160006101000a81548162ffffff021916908360020b62ffffff16021790555060408201518160010160036101000a81548162ffffff021916908360020b62ffffff16021790555060608201518160010160066101000a81548162ffffff021916908360020b62ffffff16021790555060808201518160010160096101000a81548161ffff021916908360010b61ffff16021790555060a082015181600101600b6101000a81548162ffffff021916908360020b62ffffff16021790555060c082015181600101600e6101000a81548161ffff021916908360010b61ffff16021790555060e08201518160010160106101000a81548162ffffff021916908360020b62ffffff1602179055506101008201518160010160136101000a81548162ffffff021916908362ffffff1602179055506101208201518160010160166101000a81548162ffffff021916908360020b62ffffff1602179055506101408201518160010160196101000a81548162ffffff021916908362ffffff16021790555061016082015181600101601c6101000a81548162ffffff021916908360020b62ffffff16021790555090505042600960008681526020019081526020016000208190555050505050565b612d216132a7565b6000828152600b6020908152604091829020805460ff19168415159081179091558251858152918201527f388428bda48903bbd0180b2e70447674064e582855a643dd2df349c85b0683f6910161286b565b6060612882826137df565b6005546001600160a01b03163314612dc75760405162461bcd60e51b815260206004820152600c60248201526b27b7363c9036b0b730b3b2b960a11b6044820152606401610c0a565b600354604051624dc46d60e41b8152600481018490526001600160a01b038381166024830152610100909204909116906304dc46d090604401600060405180830381600087803b158015612e1a57600080fd5b505af11580156113c2573d6000803e3d6000fd5b60035461010090046001600160a01b03163314612e5d5760405162461bcd60e51b8152600401610c0a90615acf565b60005b6001600160a01b0385166000908152600d6020526040902054811015612f71576001600160a01b038086166000908152600c602090815260408083208584529091529020541684612f165760055460405163b91f5e3560e01b81526001600160a01b038381166004830152602482018890529091169063b91f5e3590604401600060405180830381600087803b158015612ef957600080fd5b505af1158015612f0d573d6000803e3d6000fd5b50505050612f5e565b6001600160a01b03811660009081526015602052604090205460ff1615612f4d57612f48818560ff168560ff16613879565b612f5e565b612f5e818560ff168560ff166139ab565b5080612f6981615d63565b915050612e60565b5050505050565b8015612fe75760035460405163ed5e00eb60e01b81526101009091046001600160a01b03169063ed5e00eb90612fb49086908690600401615796565b600060405180830381600087803b158015612fce57600080fd5b505af1158015612fe2573d6000803e3d6000fd5b505050505b6001600160a01b0383166000908152600d6020526040902054156132a15781156130ce5760005b6001600160a01b0384166000908152600d60205260409020548110156130c8576003546001600160a01b038581166000908152600c602090815260408083208684529091529081902054905163ed5e00eb60e01b815261010090930482169263ed5e00eb926130839216908790600401615796565b600060405180830381600087803b15801561309d57600080fd5b505af11580156130b1573d6000803e3d6000fd5b5050505080806130c090615d63565b91505061300e565b506132a1565b6130d784613aeb565b156131b8576001600160a01b038084166000908152600f6020908152604080832061010089015162ffffff168452909152902054168061314257600061312e866000015186600089608001518a6101000151613b56565b905061313c85826000613e4c565b506131b6565b60035460405163ed5e00eb60e01b81526101009091046001600160a01b03169063ed5e00eb906131789084908790600401615796565b600060405180830381600087803b15801561319257600080fd5b505af11580156131a6573d6000803e3d6000fd5b505050506131b684826000613e4c565b505b6131c184613eb0565b156132a1576001600160a01b038084166000908152600e602090815260408083206080890151600190810b900b8452909152902054168061322d576000613219866000015186600189608001518a6101000151613b56565b905061322785826001613e4c565b50612f71565b60035460405163ed5e00eb60e01b81526101009091046001600160a01b03169063ed5e00eb906132639084908790600401615796565b600060405180830381600087803b15801561327d57600080fd5b505af1158015613291573d6000803e3d6000fd5b50505050612f7184826001613e4c565b50505050565b6000546201000090046001600160a01b0316331461331f5760405162461bcd60e51b815260206004820152602f60248201527f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726660448201526e37b936903a3434b99030b1ba34b7b760891b6064820152608401610c0a565b565b806133345761332f83613f15565b61333d565b61333d826140fd565b6001600160a01b0384166000908152601860209081526040909120825161336a9391929190910190614d82565b5050506001600160a01b03166000908152601760205260409020805460ff19166001179055565b600480546003548351604051631c2ab73160e21b8152938401526000926001600160a01b039283169263abc7b988926101009004169063be27f89d9082906370aadcc49060240160206040518083038186803b1580156133f057600080fd5b505afa158015613404573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061342891906154b6565b6040518263ffffffff1660e01b815260040161344691815260200190565b60206040518083038186803b15801561345e57600080fd5b505afa158015613472573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061349691906151cc565b6020850151604080870151606088015191516001600160e01b031960e087901b1681529315156004850152600292830b6024850152820b6044840152900b60648201526084015b60206040518083038186803b1580156134f557600080fd5b505afa158015613509573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061288291906151cc565b600354604051631f138de360e31b8152600481018390526060916000916101009091046001600160a01b03169063f89c6f189060240160206040518083038186803b15801561357b57600080fd5b505afa15801561358f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135b39190614eb1565b6001600160a01b03811660009081526017602052604090205490915060ff166135df57611140836140fd565b6001600160a01b0381166000908152601860209081526040918290208054835181840281018401909452808452909183018282801561363d57602002820191906000526020600020905b815481526020019060010190808311613629575b50505050509392505050565b61365282613aeb565b156136ce5761366382826000614292565b81516001600160a01b038083166000908152601360205260409020547fe796f6828b37337b49eb42b13232da29af82340b30005e54115fadb4a569e85c929116846136ad826137df565b6127126040516136c19594939291906158b5565b60405180910390a16136d9565b6136d98260006145b4565b6136e282613eb0565b15613751576136f382826001614292565b81516001600160a01b038083166000908152601460205260409020547fe796f6828b37337b49eb42b13232da29af82340b30005e54115fadb4a569e85c9291168461373d826137df565b61271160405161286b9594939291906158b5565b6110408260016145b4565b6003546040516302830aeb60e41b81526001600160a01b03868116600483015285151560248301528415156044830152831515606483015261010090920490911690632830aeb090608401600060405180830381600087803b1580156137c157600080fd5b505af11580156137d5573d6000803e3d6000fd5b5050505050505050565b6001600160a01b03811660009081526017602052604090205460609060ff166138105761380b82613f15565b612882565b6001600160a01b0382166000908152601860209081526040918290208054835181840281018401909452808452909183018282801561386e57602002820191906000526020600020905b81548152602001906001019080831161385a575b505050505092915050565b6001600160a01b03831660009081526011602052604081205460010b6138a0846064615c6e565b6138aa9190615bd7565b905060006138b9836064615c6e565b905060008160010b8360010b136138e5578160010b8360010b126138de5760006138e8565b60026138e8565b60015b60055460405163b91f5e3560e01b81526001600160a01b0389811660048301526024820184905292935091169063b91f5e3590604401600060405180830381600087803b15801561393857600080fd5b505af115801561394c573d6000803e3d6000fd5b5050506001600160a01b03808816600090815260106020526040908190205490517f83ceafeb39bed691550da26fa66ed80c145831e22e374c627a71f30479ae59b693506123d1928a92869291169061ffff808c1691908b16906157b1565b6001600160a01b03831660009081526012602052604081205462ffffff1690816139d58486615c1b565b6139e0906064615cf5565b62ffffff1611613a1d5762ffffff82166139fa8486615c1b565b613a05906064615cf5565b62ffffff1610613a16576000613a20565b6002613a20565b60015b60055460405163b91f5e3560e01b81526001600160a01b0388811660048301526024820184905292935091169063b91f5e3590604401600060405180830381600087803b158015613a7057600080fd5b505af1158015613a84573d6000803e3d6000fd5b5050506001600160a01b03808716600090815260106020526040908190205490517f83ceafeb39bed691550da26fa66ed80c145831e22e374c627a71f30479ae59b69350613adc9289928692911690899089906157b1565b60405180910390a15050505050565b60048054610100830151610120840151610140850151610160860151604051634e3a53b760e11b815262ffffff94851696810196909652600292830b6024870152921660448501520b60648301526000916001600160a01b0390911690639c74a76e906084016134dd565b600354604051631c2ab73160e21b8152600481018790526000918291613be49161010090046001600160a01b0316906370aadcc49060240160206040518083038186803b158015613ba657600080fd5b505afa158015613bba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613bde91906154b6565b8661473c565b6005549091506001600160a01b0316634cde32ce88613c05818989896147de565b60035460405163c48e62f160e01b8152600481018d90526101009091046001600160a01b03169063c48e62f19060240160006040518083038186803b158015613c4d57600080fd5b505afa158015613c61573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613c8991908101906153e3565b60200151600060028760018e6040518963ffffffff1660e01b8152600401613cb8989796959493929190615a4a565b602060405180830381600087803b158015613cd257600080fd5b505af1158015613ce6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d0a9190614eb1565b5060055460408051622610c560e41b815290516001600160a01b039092169163dd5adfa39160019184916302610c50916004808301926020929190829003018186803b158015613d5957600080fd5b505afa158015613d6d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d9191906154b6565b613d9b9190615d20565b6040518263ffffffff1660e01b8152600401613db991815260200190565b60206040518083038186803b158015613dd157600080fd5b505afa158015613de5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e099190614eb1565b9150613e4287878488888887600181518110613e3557634e487b7160e01b600052603260045260246000fd5b602002602001015161496e565b5095945050505050565b8015613e8157506001600160a01b03918216600090815260146020526040902080546001600160a01b03191691909216179055565b506001600160a01b03918216600090815260136020526040902080546001600160a01b03191691909216179055565b60048054608083015160a084015160c085015160e0860151604051630df2ba2560e41b8152600194850b96810196909652600292830b6024870152920b60448501520b60648301526000916001600160a01b039091169063df2ba250906084016134dd565b6001600160a01b0381166000908152600a602052604080822054815160028082526060828101909452929391928160200160208202803683375050506001600160a01b03851660009081526015602052604090205490915060ff16613f9557600082815260066020526040902060010154600160b01b900460020b613fb2565b600082815260066020526040902060010154600160581b900460020b5b60020b81600081518110613fd657634e487b7160e01b600052603260045260246000fd5b6020908102919091018101919091526001600160a01b03851660009081526015909152604090205460ff1661402657600082815260066020526040902060010154600160e01b900460020b614043565b600082815260066020526040902060010154600160801b900460020b5b60020b8160018151811061406757634e487b7160e01b600052603260045260246000fd5b602090810291909101015260048054604051632c85b65d60e21b81526001600160a01b039091169163b216d974916140a191859101615836565b60006040518083038186803b1580156140b957600080fd5b505afa1580156140cd573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526140f5919081019061511d565b949350505050565b60408051600380825260808201909252606091600091906020820184803683375050506000848152600660205260408120600101548251929350600290810b900b9183919061415c57634e487b7160e01b600052603260045260246000fd5b6020026020010181815250506006600084815260200190815260200160002060010160039054906101000a900460020b60020b816001815181106141b057634e487b7160e01b600052603260045260246000fd5b6020026020010181815250506006600084815260200190815260200160002060010160069054906101000a900460020b60020b8160028151811061420457634e487b7160e01b600052603260045260246000fd5b602090810291909101015260048054604051632c85b65d60e21b81526001600160a01b039091169163b216d9749161423e91859101615836565b60006040518083038186803b15801561425657600080fd5b505afa15801561426a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261123a919081019061511d565b6001600160a01b0382166000908152600d60205260408120541590826142d2576001600160a01b03808516600090815260136020526040902054166142ee565b6001600160a01b03808516600090815260146020526040902054165b905060008361432c576001600160a01b038086166000908152600f602090815260408083206101008b015162ffffff1684529091529020541661435e565b6001600160a01b038086166000908152600e6020908152604080832060808b0151600190810b900b8452909152902054165b9050828061437357506001600160a01b038116155b15614430576000614394876000015187878a608001518b6101000151613b56565b90506143a1868287613e4c565b6001600160a01b0383161561441a5760035460405163ed5e00eb60e01b81526101009091046001600160a01b03169063ed5e00eb906143e7908690600190600401615796565b600060405180830381600087803b15801561440157600080fd5b505af1158015614415573d6000803e3d6000fd5b505050505b61442a8188600001516000613321565b506113c2565b816001600160a01b0316816001600160a01b03161461453b5760035460405163ed5e00eb60e01b81526101009091046001600160a01b03169063ed5e00eb90614480908490600090600401615796565b600060405180830381600087803b15801561449a57600080fd5b505af11580156144ae573d6000803e3d6000fd5b505060035460405163ed5e00eb60e01b81526101009091046001600160a01b0316925063ed5e00eb91506144e9908590600190600401615796565b600060405180830381600087803b15801561450357600080fd5b505af1158015614517573d6000803e3d6000fd5b50505050614526858286613e4c565b6145368187600001516000613321565b6113c2565b60035460405163ed5e00eb60e01b81526101009091046001600160a01b03169063ed5e00eb90614572908590600090600401615796565b600060405180830381600087803b15801561458c57600080fd5b505af11580156145a0573d6000803e3d6000fd5b505050506113c28287600001516000613321565b6003548251604051631f138de360e31b8152600481019190915260009161010090046001600160a01b03169063f89c6f189060240160206040518083038186803b15801561460157600080fd5b505afa158015614615573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146399190614eb1565b6001600160a01b0381166000908152600d602052604090205490915015610cd05760005b6001600160a01b0382166000908152600d60205260409020548110156132a1576001600160a01b038083166000908152600c6020908152604080832085845282528083205490931680835260159091529190205460ff16151584151514156147295760035460405163ed5e00eb60e01b81526101009091046001600160a01b03169063ed5e00eb906146f6908490600190600401615796565b600060405180830381600087803b15801561471057600080fd5b505af1158015614724573d6000803e3d6000fd5b505050505b508061473481615d63565b91505061465d565b6040805160028082526060808301845292600092919060208301908036833701905050905061476d84612328615c42565b8160008151811061478e57634e487b7160e01b600052603260045260246000fd5b602002602001018181525050826147a7576127126147ab565b6127115b816001815181106147cc57634e487b7160e01b600052603260045260246000fd5b60209081029190910101529392505050565b60035460405163c48e62f160e01b8152600481018690526060916000916101009091046001600160a01b03169063c48e62f19060240160006040518083038186803b15801561482c57600080fd5b505afa158015614840573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261486891908101906153e3565b60a0015160035460405163c48e62f160e01b8152600481018990526101009091046001600160a01b03169063c48e62f19060240160006040518083038186803b1580156148b457600080fd5b505afa1580156148c8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526148f091908101906153e3565b60c001516040516020016149059291906156a0565b6040516020818303038152906040529050841561494e578061492685614c16565b604051602001614937929190615618565b6040516020818303038152906040529150506140f5565b8061495d8462ffffff16614c68565b604051602001614937929190615662565b600354604051624dc46d60e41b8152600481018990526001600160a01b038781166024830152610100909204909116906304dc46d090604401600060405180830381600087803b1580156149c157600080fd5b505af11580156149d5573d6000803e3d6000fd5b5050506001600160a01b038087166000818152600a602090815260408083208d905560168252808320805460ff19166001908117909155601083528184208054968e166001600160a01b03199788168117909155808552600c8452828520600d808652848720805488529186529386208054909816909617909655949092525254614a61925090615c42565b6001600160a01b0387166000908152600d60205260409020558315614b58576001600160a01b038681166000818152600e60209081526040808320600189810b80820b865291845282852080546001600160a01b0319908116988e1698891790915587865260118552838620805461ffff191661ffff90941693909317909255948452601483528184208054909116861790559382526015905291909120805460ff191690911790557f41525405a5e10a7f61a75ce8fb247811dadc00a10ad9bd82d09ddab453a686d386868986614b38836137df565b86604051614b4b96959493929190615708565b60405180910390a1614c0d565b6001600160a01b038087166000818152600f6020908152604080832062ffffff88168085529083528184208054968c166001600160a01b0319978816811790915580855260128452828520805462ffffff19169092179091559383526013909152902080549092161790557f2fb9c2a6ac1646a705c03b0657053182a32ea93c368b719a84e352ab42dcb8f886868985614bf1836137df565b86604051614c0496959493929190615758565b60405180910390a15b50505050505050565b606060008260010b13614c5f57614c3b614c3283600019615c6e565b61ffff16614c68565b604051602001614c4b91906156df565b604051602081830303815290604052612882565b6128828261ffff165b606081614c8c5750506040805180820190915260018152600360fc1b602082015290565b8160005b8115614cb65780614ca081615d63565b9150614caf9050600a83615c5a565b9150614c90565b60008167ffffffffffffffff811115614cdf57634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015614d09576020820181803683370190505b5090505b84156140f557614d1e600183615d20565b9150614d2b600a86615d7e565b614d36906030615c42565b60f81b818381518110614d5957634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350614d7b600a86615c5a565b9450614d0d565b828054828255906000526020600020908101928215614dbd579160200282015b82811115614dbd578251825591602001919060010190614da2565b50614dc9929150614dcd565b5090565b5b80821115614dc95760008155600101614dce565b8035600181900b8114614df457600080fd5b919050565b8035614df481615df7565b8051614df481615df7565b600082601f830112614e1f578081fd5b815167ffffffffffffffff811115614e3957614e39615dbe565b614e4c601f8201601f1916602001615b82565b818152846020838601011115614e60578283fd5b6140f5826020830160208701615d37565b803562ffffff81168114614df457600080fd5b803560ff81168114614df457600080fd5b600060208284031215614ea6578081fd5b813561123a81615dd4565b600060208284031215614ec2578081fd5b815161123a81615dd4565b60008060008060808587031215614ee2578283fd5b8435614eed81615dd4565b93506020850135614efd81615dd4565b92506040850135614f0d81615dd4565b91506060850135614f1d81615dd4565b939692955090935050565b600080600080600060a08688031215614f3f578283fd5b8535614f4a81615dd4565b9450602086810135614f5b81615dd4565b94506040870135614f6b81615dd4565b93506060870135614f7b81615dd4565b9250608087013567ffffffffffffffff811115614f96578283fd5b8701601f81018913614fa6578283fd5b8035614fb9614fb482615bb3565b615b82565b8082825284820191508484018c868560051b8701011115614fd8578687fd5b8694505b83851015614ffa578035835260019490940193918501918501614fdc565b5080955050505050509295509295909350565b6000806040838503121561501f578182fd5b823561502a81615dd4565b9150602083013561503a81615de9565b809150509250929050565b60008060408385031215615057578182fd5b823561506281615dd4565b915061507060208401614de2565b90509250929050565b6000806040838503121561508b578182fd5b823561509681615dd4565b915061507060208401614e71565b600080604083850312156150b6578182fd5b82356150c181615dd4565b946020939093013593505050565b600080600080608085870312156150e4578182fd5b84356150ef81615dd4565b93506020850135925061510460408601614e84565b915061511260608601614e84565b905092959194509250565b6000602080838503121561512f578182fd5b825167ffffffffffffffff811115615145578283fd5b8301601f81018513615155578283fd5b8051615163614fb482615bb3565b80828252848201915084840188868560051b8701011115615182578687fd5b8694505b838510156151a4578051835260019490940193918501918501615186565b50979650505050505050565b6000602082840312156151c1578081fd5b813561123a81615de9565b6000602082840312156151dd578081fd5b815161123a81615de9565b6000602082840312156151f9578081fd5b5035919050565b60008060408385031215615212578182fd5b82359150602083013561503a81615dd4565b600080600060608486031215615238578081fd5b83359250602084013561524a81615dd4565b9150604084013561525a81615de9565b809150509250925092565b60008060408385031215615277578182fd5b82359150602083013561503a81615de9565b6000806000806080858703121561529e578182fd5b8435935060208501356152b081615df7565b925060408501356152c081615df7565b91506060850135614f1d81615df7565b60008060008385036101c08112156152e6578182fd5b8435935061018080601f19830112156152fd578283fd5b615305615b35565b91506020860135825261531a60408701614df9565b602083015261532b60608701614df9565b604083015261533c60808701614df9565b606083015261534d60a08701614de2565b608083015261535e60c08701614df9565b60a083015261536f60e08701614de2565b60c0830152610100615382818801614df9565b60e0840152610120615395818901614e71565b8285015261014091506153a9828901614df9565b908401526101606153bb888201614e71565b828501526153ca838901614df9565b908401525093969095506101a094909401359392505050565b6000602082840312156153f4578081fd5b815167ffffffffffffffff8082111561540b578283fd5b9083019060e0828603121561541e578283fd5b615426615b5f565b825181526020830151602082015261544060408401614e04565b604082015261545160608401614e04565b606082015261546260808401614e04565b608082015260a083015182811115615478578485fd5b61548487828601614e0f565b60a08301525060c08301518281111561549b578485fd5b6154a787828601614e0f565b60c08301525095945050505050565b6000602082840312156154c7578081fd5b5051919050565b6000815180845260208085019450808401835b838110156154fd578151875295820195908201906001016154e1565b509495945050505050565b6000815480845260208085019450838352808320835b838110156154fd5781548752958201956001918201910161551e565b805182526020810151615552602084018260020b9052565b506040810151615567604084018260020b9052565b50606081015161557c606084018260020b9052565b506080810151615591608084018260010b9052565b5060a08101516155a660a084018260020b9052565b5060c08101516155bb60c084018260010b9052565b5060e08101516155d060e084018260020b9052565b506101008181015162ffffff169083015261012080820151600281900b8285015250506101408181015162ffffff169083015261016080820151600281900b828501526132a1565b6000835161562a818460208801615d37565b600560fb1b9083019081528351615648816001840160208801615d37565b602960f81b60019290910191820152600201949350505050565b60008351615674818460208801615d37565b6201016960ed1b9083019081528351615694816003840160208801615d37565b01600301949350505050565b600083516156b2818460208801615d37565b630103b39960e51b90830190815283516156d3816004840160208801615d37565b01600401949350505050565b602d60f81b8152600082516156fb816001850160208701615d37565b9190910160010192915050565b6001600160a01b0387811682528616602082015260408101859052600184900b606082015260c060808201819052600090615745908301856154ce565b90508260a0830152979650505050505050565b6001600160a01b038781168252861660208201526040810185905262ffffff8416606082015260c060808201819052600090615745908301856154ce565b6001600160a01b039290921682521515602082015260400190565b6001600160a01b039586168152602081019490945291909316604083015262ffffff9283166060830152909116608082015260a00190565b6020808252825182820181905260009190848201906040850190845b8181101561582a5783516001600160a01b031683529284019291840191600101615805565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561582a57835183529284019291840191600101615852565b60208152600061123a60208301846154ce565b8481526001600160a01b0384166020820152604081018390526101e081016158ac606083018461553a565b95945050505050565b8581526001600160a01b038516602082015260006102006158d9604084018761553a565b806101c08401526158ec818401866154ce565b915050826101e08301529695505050505050565b60006101e086835285602084015261591b604084018661553a565b806101c084015261592e81840185615508565b979650505050505050565b60006101e086835285602084015284546040840152600185015460026159666060860183830b60020b9052565b61597a608086018360181c830b60020b9052565b61598e60a086018360301c830b60020b9052565b6159a360c086018360481c60010b60010b9052565b6159b760e086018360581c830b60020b9052565b6159cd61010086018360701c60010b60010b9052565b6159e261012086018360801c830b60020b9052565b62ffffff609883901c8116610140870152615a0861016087018460b01c840b60020b9052565b615a1f6101808701828560c81c1662ffffff169052565b50615a356101a086018360e01c830b60020b9052565b5050806101c084015261592e81840185615508565b60006101008a8352806020840152895180828501526101209150615a748183860160208e01615d37565b604084018a90526060840189905260808401889052601f01601f19168301838103820160a0850152615aa8828201886154ce565b95151560c08501525050506001600160a01b039190911660e0909101529695505050505050565b6020808252600d908201526c27b7363c9031b7b739bab6b2b960991b604082015260600190565b848152608060208201526000615b0f60808301866154ce565b8281036040840152615b218186615508565b915050821515606083015295945050505050565b604051610180810167ffffffffffffffff81118282101715615b5957615b59615dbe565b60405290565b60405160e0810167ffffffffffffffff81118282101715615b5957615b59615dbe565b604051601f8201601f1916810167ffffffffffffffff81118282101715615bab57615bab615dbe565b604052919050565b600067ffffffffffffffff821115615bcd57615bcd615dbe565b5060051b60200190565b60008160010b8360010b82821282617fff03821381151615615bfb57615bfb615d92565b82617fff19038212811615615c1257615c12615d92565b50019392505050565b600062ffffff808316818516808303821115615c3957615c39615d92565b01949350505050565b60008219821115615c5557615c55615d92565b500190565b600082615c6957615c69615da8565b500490565b60008160010b8360010b617fff83821384841383830485118282161615615c9757615c97615d92565b617fff1986851282811687830587121615615cb457615cb4615d92565b878712925085820587128484161615615ccf57615ccf615d92565b85850587128184161615615ce557615ce5615d92565b5050509290910295945050505050565b600062ffffff80831681851681830481118215151615615d1757615d17615d92565b02949350505050565b600082821015615d3257615d32615d92565b500390565b60005b83811015615d52578181015183820152602001615d3a565b838111156132a15750506000910152565b6000600019821415615d7757615d77615d92565b5060010190565b600082615d8d57615d8d615da8565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461100257600080fd5b801515811461100257600080fd5b8060020b811461100257600080fdfea26469706673582212205761f7e1b6b5b5fb6c9da5a8824e0e8d72a9efc0113ffaf813d0279d3870a07b64736f6c63430008040033

Block Transaction Difficulty Gas Used Reward
Block Uncle Number Difficulty Gas Used Reward
Loading