Contract 0xceb5d113c96ec7bc1eb9c450136e726c63aeffe5

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

Contract Overview

Balance:
Txn Hash Method
Block
From
To
Value
0xb4ac30ff2bc2abf82d8f3165887a969168bf9cade112ce46f335fed3638ba6610x6080604099619372023-05-29 9:19:02382 days 15 hrs ago0x9841484a4a6c0b61c4eea71376d76453fd05ec9c IN  Create: GamesOddsObtainer0 ETH0.0000005438760.00001
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0x8ff2203827015e1d75c41036118ce5d82ff07303d851f810a0d5e28f2f989b99125599432023-07-28 12:39:14322 days 12 hrs ago 0x00d23ce013094f7100b681426c046023d1c02858 0xceb5d113c96ec7bc1eb9c450136e726c63aeffe50 ETH
0x8ff2203827015e1d75c41036118ce5d82ff07303d851f810a0d5e28f2f989b99125599432023-07-28 12:39:14322 days 12 hrs ago 0x00d23ce013094f7100b681426c046023d1c02858 0xceb5d113c96ec7bc1eb9c450136e726c63aeffe50 ETH
0x8ff2203827015e1d75c41036118ce5d82ff07303d851f810a0d5e28f2f989b99125599432023-07-28 12:39:14322 days 12 hrs ago 0x00d23ce013094f7100b681426c046023d1c02858 0xceb5d113c96ec7bc1eb9c450136e726c63aeffe50 ETH
0x8ff2203827015e1d75c41036118ce5d82ff07303d851f810a0d5e28f2f989b99125599432023-07-28 12:39:14322 days 12 hrs ago 0x00d23ce013094f7100b681426c046023d1c02858 0xceb5d113c96ec7bc1eb9c450136e726c63aeffe50 ETH
0x8ff2203827015e1d75c41036118ce5d82ff07303d851f810a0d5e28f2f989b99125599432023-07-28 12:39:14322 days 12 hrs ago 0x00d23ce013094f7100b681426c046023d1c02858 0xceb5d113c96ec7bc1eb9c450136e726c63aeffe50 ETH
0x8ff2203827015e1d75c41036118ce5d82ff07303d851f810a0d5e28f2f989b99125599432023-07-28 12:39:14322 days 12 hrs ago 0x00d23ce013094f7100b681426c046023d1c02858 0xceb5d113c96ec7bc1eb9c450136e726c63aeffe50 ETH
0x8ff2203827015e1d75c41036118ce5d82ff07303d851f810a0d5e28f2f989b99125599432023-07-28 12:39:14322 days 12 hrs ago 0x00d23ce013094f7100b681426c046023d1c02858 0xceb5d113c96ec7bc1eb9c450136e726c63aeffe50 ETH
0x8ff2203827015e1d75c41036118ce5d82ff07303d851f810a0d5e28f2f989b99125599432023-07-28 12:39:14322 days 12 hrs ago 0x00d23ce013094f7100b681426c046023d1c02858 0xceb5d113c96ec7bc1eb9c450136e726c63aeffe50 ETH
0x8ff2203827015e1d75c41036118ce5d82ff07303d851f810a0d5e28f2f989b99125599432023-07-28 12:39:14322 days 12 hrs ago 0x00d23ce013094f7100b681426c046023d1c02858 0xceb5d113c96ec7bc1eb9c450136e726c63aeffe50 ETH
0x8ff2203827015e1d75c41036118ce5d82ff07303d851f810a0d5e28f2f989b99125599432023-07-28 12:39:14322 days 12 hrs ago 0x00d23ce013094f7100b681426c046023d1c02858 0xceb5d113c96ec7bc1eb9c450136e726c63aeffe50 ETH
0x8ff2203827015e1d75c41036118ce5d82ff07303d851f810a0d5e28f2f989b99125599432023-07-28 12:39:14322 days 12 hrs ago 0x00d23ce013094f7100b681426c046023d1c02858 0xceb5d113c96ec7bc1eb9c450136e726c63aeffe50 ETH
0x8ff2203827015e1d75c41036118ce5d82ff07303d851f810a0d5e28f2f989b99125599432023-07-28 12:39:14322 days 12 hrs ago 0x00d23ce013094f7100b681426c046023d1c02858 0xceb5d113c96ec7bc1eb9c450136e726c63aeffe50 ETH
0x8ff2203827015e1d75c41036118ce5d82ff07303d851f810a0d5e28f2f989b99125599432023-07-28 12:39:14322 days 12 hrs ago 0x00d23ce013094f7100b681426c046023d1c02858 0xceb5d113c96ec7bc1eb9c450136e726c63aeffe50 ETH
0x8ff2203827015e1d75c41036118ce5d82ff07303d851f810a0d5e28f2f989b99125599432023-07-28 12:39:14322 days 12 hrs ago 0x00d23ce013094f7100b681426c046023d1c02858 0xceb5d113c96ec7bc1eb9c450136e726c63aeffe50 ETH
0x8ff2203827015e1d75c41036118ce5d82ff07303d851f810a0d5e28f2f989b99125599432023-07-28 12:39:14322 days 12 hrs ago 0x00d23ce013094f7100b681426c046023d1c02858 0xceb5d113c96ec7bc1eb9c450136e726c63aeffe50 ETH
0x8ff2203827015e1d75c41036118ce5d82ff07303d851f810a0d5e28f2f989b99125599432023-07-28 12:39:14322 days 12 hrs ago 0x00d23ce013094f7100b681426c046023d1c02858 0xceb5d113c96ec7bc1eb9c450136e726c63aeffe50 ETH
0x8ff2203827015e1d75c41036118ce5d82ff07303d851f810a0d5e28f2f989b99125599432023-07-28 12:39:14322 days 12 hrs ago 0x00d23ce013094f7100b681426c046023d1c02858 0xceb5d113c96ec7bc1eb9c450136e726c63aeffe50 ETH
0x8ff2203827015e1d75c41036118ce5d82ff07303d851f810a0d5e28f2f989b99125599432023-07-28 12:39:14322 days 12 hrs ago 0x00d23ce013094f7100b681426c046023d1c02858 0xceb5d113c96ec7bc1eb9c450136e726c63aeffe50 ETH
0x8ff2203827015e1d75c41036118ce5d82ff07303d851f810a0d5e28f2f989b99125599432023-07-28 12:39:14322 days 12 hrs ago 0x00d23ce013094f7100b681426c046023d1c02858 0xceb5d113c96ec7bc1eb9c450136e726c63aeffe50 ETH
0x8ff2203827015e1d75c41036118ce5d82ff07303d851f810a0d5e28f2f989b99125599432023-07-28 12:39:14322 days 12 hrs ago 0x00d23ce013094f7100b681426c046023d1c02858 0xceb5d113c96ec7bc1eb9c450136e726c63aeffe50 ETH
0x8ff2203827015e1d75c41036118ce5d82ff07303d851f810a0d5e28f2f989b99125599432023-07-28 12:39:14322 days 12 hrs ago 0x00d23ce013094f7100b681426c046023d1c02858 0xceb5d113c96ec7bc1eb9c450136e726c63aeffe50 ETH
0x8ff2203827015e1d75c41036118ce5d82ff07303d851f810a0d5e28f2f989b99125599432023-07-28 12:39:14322 days 12 hrs ago 0x00d23ce013094f7100b681426c046023d1c02858 0xceb5d113c96ec7bc1eb9c450136e726c63aeffe50 ETH
0x84b72774e52e89fb53fe946b576c61b56933abf3a8357687a19575108efeade7125599322023-07-28 12:38:52322 days 12 hrs ago 0x00d23ce013094f7100b681426c046023d1c02858 0xceb5d113c96ec7bc1eb9c450136e726c63aeffe50 ETH
0x84b72774e52e89fb53fe946b576c61b56933abf3a8357687a19575108efeade7125599322023-07-28 12:38:52322 days 12 hrs ago 0x00d23ce013094f7100b681426c046023d1c02858 0xceb5d113c96ec7bc1eb9c450136e726c63aeffe50 ETH
0x84b72774e52e89fb53fe946b576c61b56933abf3a8357687a19575108efeade7125599322023-07-28 12:38:52322 days 12 hrs ago 0x00d23ce013094f7100b681426c046023d1c02858 0xceb5d113c96ec7bc1eb9c450136e726c63aeffe50 ETH
[ Download CSV Export 
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);
                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);
            }

            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) public view returns (uint[] memory) {
        address market = consumer.marketPerGameId(_gameId);
        return
            normalizedOddsForMarketFulfilled[market]
                ? normalizedOddsForMarket[market]
                : getNormalizedOddsFromGameOddsStruct(_gameId);
    }

    /// @notice view function which returns normalized odds (spread or total) up to 100 (Example: 55-45)
    /// @param _market market
    /// @return uint[] odds array normalized
    function getNormalizedChildOdds(address _market) public view returns (uint[] memory) {
        return
            normalizedOddsForMarketFulfilled[_market]
                ? normalizedOddsForMarket[_market]
                : getNormalizedChildOddsFromGameOddsStruct(_market);
    }

    /// @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) public view returns (uint[] memory) {
        return getNormalizedChildOdds(_market);
    }

    /// @param _gameId game id for which game is looking
    /// @return uint[] odds array normalized
    function getNormalizedOddsFromGameOddsStruct(bytes32 _gameId) public 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);
    }

    /// @notice view function which returns normalized odds (spread or total) up to 100 (Example: 55-45)
    /// @param _market market
    /// @return uint[] odds array normalized
    function getNormalizedChildOddsFromGameOddsStruct(address _market) public 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);
    }

    /// @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 _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 _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 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 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 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 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 getNormalizedChildOdds(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 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 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":"address","name":"_market","type":"address"}],"name":"getNormalizedChildOdds","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_market","type":"address"}],"name":"getNormalizedChildOddsFromGameOddsStruct","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"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":"getNormalizedOddsFromGameOddsStruct","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"}]

608060405234801561001057600080fd5b50615de680620000216000396000f3fe608060405234801561001057600080fd5b50600436106103995760003560e01c806360b4df85116101e9578063ae71dcdf1161010f578063c480977c116100ad578063d46391ee1161007c578063d46391ee14610be9578063db0d457914610bfc578063e38f273814610c0f578063fa043f4014610c2257600080fd5b8063c480977c14610b80578063cc5cea2714610b93578063ceda8e9014610ba6578063d28231bd14610bc657600080fd5b8063b4fd7296116100e9578063b4fd729614610b19578063b613d8ee14610b31578063bf989b6e14610b5a578063c3b83f5f14610b6d57600080fd5b8063ae71dcdf14610a67578063b09bd9e314610a6f578063b103feb014610b0657600080fd5b806393f4452e116101875780639971441b116101565780639971441b14610a155780639aceb36e14610a28578063a12695ca14610a3b578063a4f096e814610a5e57600080fd5b806393f4452e146108ac57806393ff69d7146109b657806396583661146109ef578063988a130914610a0257600080fd5b80638d220d99116101c35780638d220d99146107f75780638da5cb5b1461082d57806391b4ded914610846578063937a314f1461084f57600080fd5b806360b4df851461071e5780636c35b775146107c657806379ba5097146107ef57600080fd5b80632fff7020116102ce5780634adf72191161026c57806359bcf1931161023b57806359bcf193146106945780635a2f7731146106b45780635c975abb146106dd5780635d134bc2146106ea57600080fd5b80634adf72191461061e5780635034c5881461063e57806353a47bb71461065e578063574ef5d91461067157600080fd5b8063366c16a5116102a8578063366c16a51461059e57806336c0d855146105be5780633ea921ae146105e1578063447b1d58146105ea57600080fd5b80632fff70201461050c578063300a02981461051457806332b566a91461051c57600080fd5b80631afed5cc1161033b57806323b1d8181161031557806323b1d8181461049f578063263737e2146104b25780632b7ac3f3146104e65780632da3f9ce146104f957600080fd5b80631afed5cc146104625780631cededce146104795780631e864c3b1461048c57600080fd5b806313af40351161037757806313af4035146103f657806314bdaa89146104095780631627540c1461043c57806316c38b3c1461044f57600080fd5b806301a5627e1461039e5780630caf0e0c146103b357806310063fdc146103c6575b600080fd5b6103b16103ac366004614fb7565b610c35565b005b6103b16103c13660046151ce565b610d2f565b6005546103d9906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6103b1610404366004614e3f565b610e58565b61042c610417366004614e3f565b60176020526000908152604090205460ff1681565b60405190151581526020016103ed565b6103b161044a366004614e3f565b610f93565b6103b161045d36600461515a565b610fe9565b61046b61232881565b6040519081526020016103ed565b6103b16104873660046151aa565b61105f565b6019546103d9906001600160a01b031681565b61042c6104ad36600461520f565b61109e565b6103d96104c0366004615023565b600f6020908152600092835260408084209091529082529020546001600160a01b031681565b6004546103d9906001600160a01b031681565b6103b1610507366004614ed2565b61129b565b61046b600181565b61046b600281565b61056c61052a366004615192565b6000908152600660205260409020600190810154600160481b8104820b92600160701b820490920b9162ffffff600160981b8304811692600160c81b90041690565b60408051600195860b81529390940b602084015262ffffff9182169383019390935290911660608201526080016103ed565b6105b16105ac366004614e3f565b611424565b6040516103ed9190615793565b61042c6105cc366004614e3f565b60086020526000908152604090205460ff1681565b61046b61271181565b6103d96105f836600461504e565b600c6020908152600092835260408084209091529082529020546001600160a01b031681565b61046b61062c366004614e3f565b600a6020526000908152604090205481565b61046b61064c366004615192565b60096020526000908152604090205481565b6001546103d9906001600160a01b031681565b61042c61067f366004615192565b600b6020526000908152604090205460ff1681565b6106a76106a2366004615192565b611531565b6040516103ed9190615818565b6103d96106c2366004614e3f565b6014602052600090815260409020546001600160a01b031681565b60035461042c9060ff1681565b6103d96106f8366004614fef565b600e6020908152600092835260408084209091529082529020546001600160a01b031681565b61078361072c366004615192565b600090815260066020526040902060010154600281810b9263010000008304820b92600160301b8104830b92600160581b8204810b92600160801b8304820b92600160b01b8104830b92600160e01b909104900b90565b60408051600298890b815296880b602088015294870b9486019490945291850b6060850152840b6080840152830b60a083015290910b60c082015260e0016103ed565b6103d96107d4366004614e3f565b6010602052600090815260409020546001600160a01b031681565b6103b16116c6565b61081a610805366004614e3f565b60116020526000908152604090205460010b81565b60405160019190910b81526020016103ed565b6000546103d9906201000090046001600160a01b031681565b61046b60025481565b61088c61085d366004614e3f565b6001600160a01b0390811660009081526013602090815260408083205460149092529091205490821692911690565b604080516001600160a01b039384168152929091166020830152016103ed565b6109436108ba366004615192565b600660205260009081526040902080546001918201549091600282810b9263010000008104820b92600160301b8204830b92600160481b8304820b92600160581b8104820b92600160701b8204900b91600160801b8204810b9162ffffff600160981b8204811692600160b01b8304810b92600160c81b810490921691600160e01b9004900b8c565b604080519c8d5260029b8c0b60208e0152998b0b998c019990995296890b60608b0152600195860b60808b015293880b60a08a01529190930b60c088015291850b60e087015262ffffff918216610100870152840b61012086015216610140840152900b610160820152610180016103ed565b6109db6109c4366004614e3f565b60126020526000908152604090205462ffffff1681565b60405162ffffff90911681526020016103ed565b6106a76109fd366004614e3f565b6117c3565b6103b1610a1036600461527a565b61185e565b6103b1610a23366004615192565b6127dc565b6106a7610a36366004615192565b612ae4565b61042c610a49366004614e3f565b60156020526000908152604090205460ff1681565b61046b61271281565b61046b600081565b610943610a7d366004615192565b600760205260009081526040902080546001918201549091600282810b9263010000008104820b92600160301b8204830b92600160481b8304820b92600160581b8104820b92600160701b8204900b91600160801b8204810b9162ffffff600160981b8204811692600160b01b8304810b92600160c81b810490921691600160e01b9004900b8c565b61046b610b1436600461504e565b612c00565b6003546103d99061010090046001600160a01b031681565b6103d9610b3f366004614e3f565b6013602052600090815260409020546001600160a01b031681565b6103b1610b68366004614e77565b612c31565b6103b1610b7b366004614e3f565b612cda565b6103b1610b8e366004615233565b612df3565b6103b1610ba136600461520f565b613091565b61046b610bb4366004614e3f565b600d6020526000908152604090205481565b61042c610bd4366004614e3f565b60166020526000908152604090205460ff1681565b6106a7610bf7366004614e3f565b6130eb565b6106a7610c0a366004614e3f565b6132d3565b6103b1610c1d3660046151aa565b6132de565b6103b1610c30366004615079565b61338e565b60035461010090046001600160a01b03163314610c6d5760405162461bcd60e51b8152600401610c6490615a79565b60405180910390fd5b60005b6001600160a01b0383166000908152600d6020526040902054811015610d2a576003546001600160a01b038481166000908152600c602090815260408083208684529091529081902054905163ed5e00eb60e01b815261010090930482169263ed5e00eb92610ce59216908690600401615740565b600060405180830381600087803b158015610cff57600080fd5b505af1158015610d13573d6000803e3d6000fd5b505050508080610d2290615d0d565b915050610c70565b505050565b60035461010090046001600160a01b03163314610d5e5760405162461bcd60e51b8152600401610c6490615a79565b60008381526006602090815260409182902082516101808101845281548152600191820154600281810b810b810b9483019490945263010000008104840b840b840b94820194909452600160301b8404830b830b830b6060820152600160481b8404820b820b820b6080820152600160581b8404830b830b830b60a0820152600160701b8404820b820b820b60c0820152600160801b8404830b830b830b60e082015262ffffff600160981b85048116610100830152600160b01b8504840b840b840b610120830152600160c81b850416610140820152600160e01b909304820b820b90910b610160830152610d2a9190849084906134d8565b6001600160a01b038116610eae5760405162461bcd60e51b815260206004820152601960248201527f4f776e657220616464726573732063616e6e6f742062652030000000000000006044820152606401610c64565b600154600160a01b900460ff1615610f1a5760405162461bcd60e51b815260206004820152602960248201527f416c726561647920696e697469616c697a65642c20757365206e6f6d696e617460448201526832a732bba7bbb732b960b91b6064820152608401610c64565b6001805460ff60a01b1916600160a01b179055600080546001600160a01b03831662010000810262010000600160b01b03199092169190911782556040805192835260208301919091527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c91015b60405180910390a150565b610f9b613807565b600180546001600160a01b0319166001600160a01b0383169081179091556040519081527f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce2290602001610f88565b610ff1613807565b60035460ff16151581151514156110055750565b6003805460ff191682151590811790915560ff161561102357426002555b60035460405160ff909116151581527f8fb6c181ee25a520cf3dd6565006ef91229fcfe5a989566c2a3b8c115570cec590602001610f88565b50565b60035461010090046001600160a01b0316331461108e5760405162461bcd60e51b8152600401610c6490615a79565b61109a81836001613881565b5050565b60008161119f5760008381526006602090815260409182902082516101808101845281548152600191820154600281810b810b810b9483019490945263010000008104840b840b840b94820194909452600160301b8404830b830b830b6060820152600160481b8404820b820b820b6080820152600160581b8404830b830b830b60a0820152600160701b8404820b820b90910b60c0820152600160801b8304820b820b820b60e082015262ffffff600160981b84048116610100830152600160b01b8404830b830b830b610120830152600160c81b840416610140820152600160e01b909204810b810b900b61016082015261119a906138f1565b611294565b60008381526007602090815260409182902082516101808101845281548152600191820154600281810b810b810b9483019490945263010000008104840b840b840b94820194909452600160301b8404830b830b830b6060820152600160481b8404820b820b820b6080820152600160581b8404830b830b830b60a0820152600160701b8404820b820b90910b60c0820152600160801b8304820b820b820b60e082015262ffffff600160981b84048116610100830152600160b01b8404830b830b830b610120830152600160c81b840416610140820152600160e01b909204810b810b900b610160820152611294906138f1565b9392505050565b600054610100900460ff166112b65760005460ff16156112ba565b303b155b61131d5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610c64565b600054610100900460ff1615801561133f576000805461ffff19166101011790555b61134886610e58565b600380546001600160a01b0380881661010002610100600160a81b031990921691909117909155600480548683166001600160a01b031991821617909155600580549286169290911691909117905560005b8251811015611409576001600b60008584815181106113c957634e487b7160e01b600052603260045260246000fd5b6020026020010151815260200190815260200160002060006101000a81548160ff021916908315150217905550808061140190615d0d565b91505061139a565b50801561141c576000805461ff00191690555b505050505050565b6001600160a01b0381166000908152600d60205260408120546060919067ffffffffffffffff81111561146757634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015611490578160200160208202803683370190505b50905060005b6001600160a01b0384166000908152600d602052604090205481101561152a576001600160a01b038085166000908152600c60209081526040808320858452909152902054835191169083908390811061150057634e487b7160e01b600052603260045260246000fd5b6001600160a01b03909216602092830291909101909101528061152281615d0d565b915050611496565b5092915050565b60408051600380825260808201909252606091600091906020820184803683375050506000848152600660205260408120600101548251929350600290810b900b9183919061159057634e487b7160e01b600052603260045260246000fd5b6020026020010181815250506006600084815260200190815260200160002060010160039054906101000a900460020b60020b816001815181106115e457634e487b7160e01b600052603260045260246000fd5b6020026020010181815250506006600084815260200190815260200160002060010160069054906101000a900460020b60020b8160028151811061163857634e487b7160e01b600052603260045260246000fd5b602090810291909101015260048054604051632c85b65d60e21b81526001600160a01b039091169163b216d97491611672918591016157e0565b60006040518083038186803b15801561168a57600080fd5b505afa15801561169e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261129491908101906150c7565b6001546001600160a01b0316331461173e5760405162461bcd60e51b815260206004820152603560248201527f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7560448201527402063616e20616363657074206f776e65727368697605c1b6064820152608401610c64565b60005460015460408051620100009093046001600160a01b03908116845290911660208301527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a1600180546000805462010000600160b01b0319166001600160a01b03831662010000021790556001600160a01b0319169055565b6001600160a01b03811660009081526017602052604090205460609060ff166117f4576117ef826130eb565b611858565b6001600160a01b0382166000908152601860209081526040918290208054835181840281018401909452808452909183018282801561185257602002820191906000526020600020905b81548152602001906001019080831161183e575b50505050505b92915050565b60035461010090046001600160a01b031633148061188657506019546001600160a01b031633145b6118c35760405162461bcd60e51b815260206004820152600e60248201526d24b73b30b634b21039b2b73232b960911b6044820152606401610c64565b6118cc826138f1565b1561265c5760006118e08360000151612ae4565b90506000600660008560000151815260200190815260200160002060405180610180016040529081600082015481526020016001820160009054906101000a900460020b60020b60020b81526020016001820160039054906101000a900460020b60020b60020b81526020016001820160069054906101000a900460020b60020b60020b81526020016001820160099054906101000a900460010b60010b60010b815260200160018201600b9054906101000a900460020b60020b60020b815260200160018201600e9054906101000a900460010b60010b60010b81526020016001820160109054906101000a900460020b60020b60020b81526020016001820160139054906101000a900462ffffff1662ffffff1662ffffff1681526020016001820160169054906101000a900460020b60020b60020b81526020016001820160199054906101000a900462ffffff1662ffffff1662ffffff16815260200160018201601c9054906101000a900460020b60020b60020b8152505090508360066000866000015181526020019081526020016000206000820151816000015560208201518160010160006101000a81548162ffffff021916908360020b62ffffff16021790555060408201518160010160036101000a81548162ffffff021916908360020b62ffffff16021790555060608201518160010160066101000a81548162ffffff021916908360020b62ffffff16021790555060808201518160010160096101000a81548161ffff021916908360010b61ffff16021790555060a082015181600101600b6101000a81548162ffffff021916908360020b62ffffff16021790555060c082015181600101600e6101000a81548161ffff021916908360010b61ffff16021790555060e08201518160010160106101000a81548162ffffff021916908360020b62ffffff1602179055506101008201518160010160136101000a81548162ffffff021916908362ffffff1602179055506101208201518160010160166101000a81548162ffffff021916908360020b62ffffff1602179055506101408201518160010160196101000a81548162ffffff021916908362ffffff16021790555061016082015181600101601c6101000a81548162ffffff021916908360020b62ffffff160217905550905050426009600086600001518152602001908152602001600020819055506000600360019054906101000a90046001600160a01b03166001600160a01b031663f89c6f1886600001516040518263ffffffff1660e01b8152600401611c9a91815260200190565b60206040518083038186803b158015611cb257600080fd5b505afa158015611cc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cea9190614e5b565b9050611cfc8186600001516001613881565b6000848152600b602052604090205460ff1615611d1d57611d1d8582613a8d565b6005546040516333dfec9960e21b81526001600160a01b0383811660048301529091169063cf7fb2649060240160206040518083038186803b158015611d6257600080fd5b505afa158015611d76573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d9a9190615176565b15612224576001600160a01b03811660009081526008602052604090205460ff1680611e445750600354604051630a928f9f60e21b81526001600160a01b03838116600483015261010090920490911690632a4a3e7c9060240160206040518083038186803b158015611e0c57600080fd5b505afa158015611e20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e449190615176565b1561221f576001600160a01b03808216600090815260086020526040808220805460ff191690556003549051630259f5fd60e01b815261010090910490921691630259f5fd91611e9991859190600401615740565b600060405180830381600087803b158015611eb357600080fd5b505af1158015611ec7573d6000803e3d6000fd5b5050600480546001600160a01b0385811660009081526018602052604090819020600354915163be27f89d60e01b81529485018b905292821695506342fa646a945089938993926101009092049091169063be27f89d9060240160206040518083038186803b158015611f3957600080fd5b505afa158015611f4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f719190615176565b6040518563ffffffff1660e01b8152600401611f909493929190615aa0565b60206040518083038186803b158015611fa857600080fd5b505afa158015611fbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fe09190615176565b612211578160076000876000015181526020019081526020016000206000820151816000015560208201518160010160006101000a81548162ffffff021916908360020b62ffffff16021790555060408201518160010160036101000a81548162ffffff021916908360020b62ffffff16021790555060608201518160010160066101000a81548162ffffff021916908360020b62ffffff16021790555060808201518160010160096101000a81548161ffff021916908360010b61ffff16021790555060a082015181600101600b6101000a81548162ffffff021916908360020b62ffffff16021790555060c082015181600101600e6101000a81548161ffff021916908360010b61ffff16021790555060e08201518160010160106101000a81548162ffffff021916908360020b62ffffff1602179055506101008201518160010160136101000a81548162ffffff021916908362ffffff1602179055506101208201518160010160166101000a81548162ffffff021916908360020b62ffffff1602179055506101408201518160010160196101000a81548162ffffff021916908362ffffff16021790555061016082015181600101601c6101000a81548162ffffff021916908360020b62ffffff1602179055509050507fcb6e87c3d70eab47f84a42c3021b86de43cf8d37ebe9cfa494c4f89b75205a8a8186600001516040516122049291906001600160a01b03929092168252602082015260400190565b60405180910390a16125fe565b61221f8582600060016134d8565b6125fe565b6005546040516333dfec9960e21b81526001600160a01b0383811660048301529091169063cf7fb2649060240160206040518083038186803b15801561226957600080fd5b505afa15801561227d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122a19190615176565b1580156123c35750600480546001600160a01b0383811660009081526018602052604090819020600354915163be27f89d60e01b8152938316946342fa646a948a948a946101009004169163be27f89d916123029187910190815260200190565b60206040518083038186803b15801561231a57600080fd5b505afa15801561232e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123529190615176565b6040518563ffffffff1660e01b81526004016123719493929190615aa0565b60206040518083038186803b15801561238957600080fd5b505afa15801561239d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123c19190615176565b155b156125fe576123d585826001806134d8565b8160076000876000015181526020019081526020016000206000820151816000015560208201518160010160006101000a81548162ffffff021916908360020b62ffffff16021790555060408201518160010160036101000a81548162ffffff021916908360020b62ffffff16021790555060608201518160010160066101000a81548162ffffff021916908360020b62ffffff16021790555060808201518160010160096101000a81548161ffff021916908360010b61ffff16021790555060a082015181600101600b6101000a81548162ffffff021916908360020b62ffffff16021790555060c082015181600101600e6101000a81548161ffff021916908360010b61ffff16021790555060e08201518160010160106101000a81548162ffffff021916908360020b62ffffff1602179055506101008201518160010160136101000a81548162ffffff021916908362ffffff1602179055506101208201518160010160166101000a81548162ffffff021916908360020b62ffffff1602179055506101408201518160010160196101000a81548162ffffff021916908362ffffff16021790555061016082015181600101601c6101000a81548162ffffff021916908360020b62ffffff1602179055509050507fcb6e87c3d70eab47f84a42c3021b86de43cf8d37ebe9cfa494c4f89b75205a8a8186600001516040516125f59291906001600160a01b03929092168252602082015260400190565b60405180910390a15b84516001600160a01b0382166000908152601860205260409081902090517f5d8fed649db8e5d2dd77ea4f51ee8548f87d2679e2f5407f8db9793f701f8dfe9261264c928a928a91906158aa565b60405180910390a1505050505050565b6003548251604051631f138de360e31b8152600481019190915260009161010090046001600160a01b03169063f89c6f189060240160206040518083038186803b1580156126a957600080fd5b505afa1580156126bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126e19190614e5b565b6005546040516333dfec9960e21b81526001600160a01b03808416600483015292935091169063cf7fb2649060240160206040518083038186803b15801561272857600080fd5b505afa15801561273c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127609190615176565b612798576001600160a01b0381166000908152600860205260409020805460ff191660019081179091556127989084908390806134d8565b82516040517f420dbf4677c8331a5938fcc5890c5ae453dd3344f80f9a669d6adb2fea7de3d0916127ce9187918591889061582b565b60405180910390a150505050565b60035461010090046001600160a01b0316331461280b5760405162461bcd60e51b8152600401610c6490615a79565b600081815260076020908152604080832060069092528083208254815560019283018054918401805462ffffff19811662ffffff600295860b860b81169182178455845465ffffffffffff19909316909117630100000092839004860b860b821690920291909117808355835468ffffff000000000000198216600160301b91829004870b870b8416909102908117845584546affffffffff000000000000199092166affff000000000000000000199091161761ffff600160481b92839004890b890b811690920217808455845462ffffff60581b198216600160581b91829004880b880b85169091029081178555855464ffffffffff60581b1990921661ffff60701b1990911617600160701b91829004890b90980b9091160295909517808255825462ffffff60801b198216600160801b91829004860b860b88169091029081178355835465ffffffffffff60801b1990921662ffffff60981b1990911617600160981b91829004871690910217808255825462ffffff60b01b198216600160b01b91829004860b860b88169091029081178355835465ffffffffffff60b01b1990921662ffffff60c81b1990911617600160c81b91829004871690910217808255915462ffffff60e01b19909216600160e01b92839004840b90930b90941602179091556003549051631f138de360e31b8152600481018490526101009091046001600160a01b03169063f89c6f189060240160206040518083038186803b158015612a3a57600080fd5b505afa158015612a4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a729190614e5b565b9050612a8081836001613881565b60008281526006602090815260408083206001600160a01b038516845260189092529182902091517f5d8fed649db8e5d2dd77ea4f51ee8548f87d2679e2f5407f8db9793f701f8dfe92612ad89286928392906158e3565b60405180910390a15050565b600354604051631f138de360e31b8152600481018390526060916000916101009091046001600160a01b03169063f89c6f189060240160206040518083038186803b158015612b3257600080fd5b505afa158015612b46573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b6a9190614e5b565b6001600160a01b03811660009081526017602052604090205490915060ff16612b965761119a83611531565b6001600160a01b03811660009081526018602090815260409182902080548351818402810184019094528084529091830182828015612bf457602002820191906000526020600020905b815481526020019060010190808311612be0575b50505050509392505050565b60186020528160005260406000208181548110612c1c57600080fd5b90600052602060002001600091509150505481565b612c39613807565b60038054610100600160a81b0319166101006001600160a01b0387811691820292909217909255600480546001600160a01b0319908116878416908117909255600580548216878516908117909155601980549092169386169384179091556040805194855260208501929092529083015260608201527fa2cad6ae2699ea86ba233a96ca0e57d895983eeed04f6bd0a770187c58b820dd906080016127ce565b612ce2613807565b6001600160a01b038116612d2a5760405162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b6044820152606401610c64565b600154600160a81b900460ff1615612d7a5760405162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481d1c985b9cd9995c9c9959606a1b6044820152606401610c64565b600080546001600160a01b038381166201000081810262010000600160b01b031990941693909317938490556001805460ff60a81b1916600160a81b1790556040805193909404909116825260208201527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9101610f88565b60035461010090046001600160a01b03163314612e225760405162461bcd60e51b8152600401610c6490615a79565b6040518061018001604052808581526020018460020b81526020018360020b81526020018260020b8152602001600060010b8152602001600060020b8152602001600060010b8152602001600060020b8152602001600062ffffff168152602001600060020b8152602001600062ffffff168152602001600060020b815250600660008681526020019081526020016000206000820151816000015560208201518160010160006101000a81548162ffffff021916908360020b62ffffff16021790555060408201518160010160036101000a81548162ffffff021916908360020b62ffffff16021790555060608201518160010160066101000a81548162ffffff021916908360020b62ffffff16021790555060808201518160010160096101000a81548161ffff021916908360010b61ffff16021790555060a082015181600101600b6101000a81548162ffffff021916908360020b62ffffff16021790555060c082015181600101600e6101000a81548161ffff021916908360010b61ffff16021790555060e08201518160010160106101000a81548162ffffff021916908360020b62ffffff1602179055506101008201518160010160136101000a81548162ffffff021916908362ffffff1602179055506101208201518160010160166101000a81548162ffffff021916908360020b62ffffff1602179055506101408201518160010160196101000a81548162ffffff021916908362ffffff16021790555061016082015181600101601c6101000a81548162ffffff021916908360020b62ffffff16021790555090505042600960008681526020019081526020016000208190555050505050565b613099613807565b6000828152600b6020908152604091829020805460ff19168415159081179091558251858152918201527f388428bda48903bbd0180b2e70447674064e582855a643dd2df349c85b0683f69101612ad8565b6001600160a01b0381166000908152600a602052604080822054815160028082526060828101909452929391928160200160208202803683375050506001600160a01b03851660009081526015602052604090205490915060ff1661316b57600082815260066020526040902060010154600160b01b900460020b613188565b600082815260066020526040902060010154600160581b900460020b5b60020b816000815181106131ac57634e487b7160e01b600052603260045260246000fd5b6020908102919091018101919091526001600160a01b03851660009081526015909152604090205460ff166131fc57600082815260066020526040902060010154600160e01b900460020b613219565b600082815260066020526040902060010154600160801b900460020b5b60020b8160018151811061323d57634e487b7160e01b600052603260045260246000fd5b602090810291909101015260048054604051632c85b65d60e21b81526001600160a01b039091169163b216d97491613277918591016157e0565b60006040518083038186803b15801561328f57600080fd5b505afa1580156132a3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526132cb91908101906150c7565b949350505050565b6060611858826117c3565b6005546001600160a01b031633146133275760405162461bcd60e51b815260206004820152600c60248201526b27b7363c9036b0b730b3b2b960a11b6044820152606401610c64565b600354604051624dc46d60e41b8152600481018490526001600160a01b038381166024830152610100909204909116906304dc46d090604401600060405180830381600087803b15801561337a57600080fd5b505af115801561141c573d6000803e3d6000fd5b60035461010090046001600160a01b031633146133bd5760405162461bcd60e51b8152600401610c6490615a79565b60005b6001600160a01b0385166000908152600d60205260409020548110156134d1576001600160a01b038086166000908152600c6020908152604080832085845290915290205416846134765760055460405163b91f5e3560e01b81526001600160a01b038381166004830152602482018890529091169063b91f5e3590604401600060405180830381600087803b15801561345957600080fd5b505af115801561346d573d6000803e3d6000fd5b505050506134be565b6001600160a01b03811660009081526015602052604090205460ff16156134ad576134a8818560ff168560ff16613ba0565b6134be565b6134be818560ff168560ff16613cd2565b50806134c981615d0d565b9150506133c0565b5050505050565b80156135475760035460405163ed5e00eb60e01b81526101009091046001600160a01b03169063ed5e00eb906135149086908690600401615740565b600060405180830381600087803b15801561352e57600080fd5b505af1158015613542573d6000803e3d6000fd5b505050505b6001600160a01b0383166000908152600d60205260409020541561380157811561362e5760005b6001600160a01b0384166000908152600d6020526040902054811015613628576003546001600160a01b038581166000908152600c602090815260408083208684529091529081902054905163ed5e00eb60e01b815261010090930482169263ed5e00eb926135e39216908790600401615740565b600060405180830381600087803b1580156135fd57600080fd5b505af1158015613611573d6000803e3d6000fd5b50505050808061362090615d0d565b91505061356e565b50613801565b61363784613e12565b15613718576001600160a01b038084166000908152600f6020908152604080832061010089015162ffffff16845290915290205416806136a257600061368e866000015186600089608001518a6101000151613e7d565b905061369c85826000614173565b50613716565b60035460405163ed5e00eb60e01b81526101009091046001600160a01b03169063ed5e00eb906136d89084908790600401615740565b600060405180830381600087803b1580156136f257600080fd5b505af1158015613706573d6000803e3d6000fd5b5050505061371684826000614173565b505b613721846141d7565b15613801576001600160a01b038084166000908152600e602090815260408083206080890151600190810b900b8452909152902054168061378d576000613779866000015186600189608001518a6101000151613e7d565b905061378785826001614173565b506134d1565b60035460405163ed5e00eb60e01b81526101009091046001600160a01b03169063ed5e00eb906137c39084908790600401615740565b600060405180830381600087803b1580156137dd57600080fd5b505af11580156137f1573d6000803e3d6000fd5b505050506134d184826001614173565b50505050565b6000546201000090046001600160a01b0316331461387f5760405162461bcd60e51b815260206004820152602f60248201527f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726660448201526e37b936903a3434b99030b1ba34b7b760891b6064820152608401610c64565b565b806138945761388f836130eb565b61389d565b61389d82611531565b6001600160a01b038416600090815260186020908152604090912082516138ca9391929190910190614d2c565b5050506001600160a01b03166000908152601760205260409020805460ff19166001179055565b600480546003548351604051631c2ab73160e21b8152938401526000926001600160a01b039283169263abc7b988926101009004169063be27f89d9082906370aadcc49060240160206040518083038186803b15801561395057600080fd5b505afa158015613964573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139889190615460565b6040518263ffffffff1660e01b81526004016139a691815260200190565b60206040518083038186803b1580156139be57600080fd5b505afa1580156139d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139f69190615176565b6020850151604080870151606088015191516001600160e01b031960e087901b1681529315156004850152600292830b6024850152820b6044840152900b60648201526084015b60206040518083038186803b158015613a5557600080fd5b505afa158015613a69573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118589190615176565b613a9682613e12565b15613b1257613aa78282600061423c565b81516001600160a01b038083166000908152601360205260409020547fe796f6828b37337b49eb42b13232da29af82340b30005e54115fadb4a569e85c92911684613af1826117c3565b612712604051613b0595949392919061585f565b60405180910390a1613b1d565b613b1d82600061455e565b613b26826141d7565b15613b9557613b378282600161423c565b81516001600160a01b038083166000908152601460205260409020547fe796f6828b37337b49eb42b13232da29af82340b30005e54115fadb4a569e85c92911684613b81826117c3565b612711604051612ad895949392919061585f565b61109a82600161455e565b6001600160a01b03831660009081526011602052604081205460010b613bc7846064615c18565b613bd19190615b81565b90506000613be0836064615c18565b905060008160010b8360010b13613c0c578160010b8360010b12613c05576000613c0f565b6002613c0f565b60015b60055460405163b91f5e3560e01b81526001600160a01b0389811660048301526024820184905292935091169063b91f5e3590604401600060405180830381600087803b158015613c5f57600080fd5b505af1158015613c73573d6000803e3d6000fd5b5050506001600160a01b03808816600090815260106020526040908190205490517f83ceafeb39bed691550da26fa66ed80c145831e22e374c627a71f30479ae59b6935061264c928a92869291169061ffff808c1691908b169061575b565b6001600160a01b03831660009081526012602052604081205462ffffff169081613cfc8486615bc5565b613d07906064615c9f565b62ffffff1611613d445762ffffff8216613d218486615bc5565b613d2c906064615c9f565b62ffffff1610613d3d576000613d47565b6002613d47565b60015b60055460405163b91f5e3560e01b81526001600160a01b0388811660048301526024820184905292935091169063b91f5e3590604401600060405180830381600087803b158015613d9757600080fd5b505af1158015613dab573d6000803e3d6000fd5b5050506001600160a01b03808716600090815260106020526040908190205490517f83ceafeb39bed691550da26fa66ed80c145831e22e374c627a71f30479ae59b69350613e0392899286929116908990899061575b565b60405180910390a15050505050565b60048054610100830151610120840151610140850151610160860151604051634e3a53b760e11b815262ffffff94851696810196909652600292830b6024870152921660448501520b60648301526000916001600160a01b0390911690639c74a76e90608401613a3d565b600354604051631c2ab73160e21b8152600481018790526000918291613f0b9161010090046001600160a01b0316906370aadcc49060240160206040518083038186803b158015613ecd57600080fd5b505afa158015613ee1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f059190615460565b866146e6565b6005549091506001600160a01b0316634cde32ce88613f2c81898989614788565b60035460405163c48e62f160e01b8152600481018d90526101009091046001600160a01b03169063c48e62f19060240160006040518083038186803b158015613f7457600080fd5b505afa158015613f88573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613fb0919081019061538d565b60200151600060028760018e6040518963ffffffff1660e01b8152600401613fdf9897969594939291906159f4565b602060405180830381600087803b158015613ff957600080fd5b505af115801561400d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140319190614e5b565b5060055460408051622610c560e41b815290516001600160a01b039092169163dd5adfa39160019184916302610c50916004808301926020929190829003018186803b15801561408057600080fd5b505afa158015614094573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140b89190615460565b6140c29190615cca565b6040518263ffffffff1660e01b81526004016140e091815260200190565b60206040518083038186803b1580156140f857600080fd5b505afa15801561410c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141309190614e5b565b91506141698787848888888760018151811061415c57634e487b7160e01b600052603260045260246000fd5b6020026020010151614918565b5095945050505050565b80156141a857506001600160a01b03918216600090815260146020526040902080546001600160a01b03191691909216179055565b506001600160a01b03918216600090815260136020526040902080546001600160a01b03191691909216179055565b60048054608083015160a084015160c085015160e0860151604051630df2ba2560e41b8152600194850b96810196909652600292830b6024870152920b60448501520b60648301526000916001600160a01b039091169063df2ba25090608401613a3d565b6001600160a01b0382166000908152600d602052604081205415908261427c576001600160a01b0380851660009081526013602052604090205416614298565b6001600160a01b03808516600090815260146020526040902054165b90506000836142d6576001600160a01b038086166000908152600f602090815260408083206101008b015162ffffff16845290915290205416614308565b6001600160a01b038086166000908152600e6020908152604080832060808b0151600190810b900b8452909152902054165b9050828061431d57506001600160a01b038116155b156143da57600061433e876000015187878a608001518b6101000151613e7d565b905061434b868287614173565b6001600160a01b038316156143c45760035460405163ed5e00eb60e01b81526101009091046001600160a01b03169063ed5e00eb90614391908690600190600401615740565b600060405180830381600087803b1580156143ab57600080fd5b505af11580156143bf573d6000803e3d6000fd5b505050505b6143d48188600001516000613881565b5061141c565b816001600160a01b0316816001600160a01b0316146144e55760035460405163ed5e00eb60e01b81526101009091046001600160a01b03169063ed5e00eb9061442a908490600090600401615740565b600060405180830381600087803b15801561444457600080fd5b505af1158015614458573d6000803e3d6000fd5b505060035460405163ed5e00eb60e01b81526101009091046001600160a01b0316925063ed5e00eb9150614493908590600190600401615740565b600060405180830381600087803b1580156144ad57600080fd5b505af11580156144c1573d6000803e3d6000fd5b505050506144d0858286614173565b6144e08187600001516000613881565b61141c565b60035460405163ed5e00eb60e01b81526101009091046001600160a01b03169063ed5e00eb9061451c908590600090600401615740565b600060405180830381600087803b15801561453657600080fd5b505af115801561454a573d6000803e3d6000fd5b5050505061141c8287600001516000613881565b6003548251604051631f138de360e31b8152600481019190915260009161010090046001600160a01b03169063f89c6f189060240160206040518083038186803b1580156145ab57600080fd5b505afa1580156145bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145e39190614e5b565b6001600160a01b0381166000908152600d602052604090205490915015610d2a5760005b6001600160a01b0382166000908152600d6020526040902054811015613801576001600160a01b038083166000908152600c6020908152604080832085845282528083205490931680835260159091529190205460ff16151584151514156146d35760035460405163ed5e00eb60e01b81526101009091046001600160a01b03169063ed5e00eb906146a0908490600190600401615740565b600060405180830381600087803b1580156146ba57600080fd5b505af11580156146ce573d6000803e3d6000fd5b505050505b50806146de81615d0d565b915050614607565b6040805160028082526060808301845292600092919060208301908036833701905050905061471784612328615bec565b8160008151811061473857634e487b7160e01b600052603260045260246000fd5b6020026020010181815250508261475157612712614755565b6127115b8160018151811061477657634e487b7160e01b600052603260045260246000fd5b60209081029190910101529392505050565b60035460405163c48e62f160e01b8152600481018690526060916000916101009091046001600160a01b03169063c48e62f19060240160006040518083038186803b1580156147d657600080fd5b505afa1580156147ea573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052614812919081019061538d565b60a0015160035460405163c48e62f160e01b8152600481018990526101009091046001600160a01b03169063c48e62f19060240160006040518083038186803b15801561485e57600080fd5b505afa158015614872573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261489a919081019061538d565b60c001516040516020016148af92919061564a565b604051602081830303815290604052905084156148f857806148d085614bc0565b6040516020016148e19291906155c2565b6040516020818303038152906040529150506132cb565b806149078462ffffff16614c12565b6040516020016148e192919061560c565b600354604051624dc46d60e41b8152600481018990526001600160a01b038781166024830152610100909204909116906304dc46d090604401600060405180830381600087803b15801561496b57600080fd5b505af115801561497f573d6000803e3d6000fd5b5050506001600160a01b038087166000818152600a602090815260408083208d905560168252808320805460ff19166001908117909155601083528184208054968e166001600160a01b03199788168117909155808552600c8452828520600d808652848720805488529186529386208054909816909617909655949092525254614a0b925090615bec565b6001600160a01b0387166000908152600d60205260409020558315614b02576001600160a01b038681166000818152600e60209081526040808320600189810b80820b865291845282852080546001600160a01b0319908116988e1698891790915587865260118552838620805461ffff191661ffff90941693909317909255948452601483528184208054909116861790559382526015905291909120805460ff191690911790557f41525405a5e10a7f61a75ce8fb247811dadc00a10ad9bd82d09ddab453a686d386868986614ae2836117c3565b86604051614af5969594939291906156b2565b60405180910390a1614bb7565b6001600160a01b038087166000818152600f6020908152604080832062ffffff88168085529083528184208054968c166001600160a01b0319978816811790915580855260128452828520805462ffffff19169092179091559383526013909152902080549092161790557f2fb9c2a6ac1646a705c03b0657053182a32ea93c368b719a84e352ab42dcb8f886868985614b9b836117c3565b86604051614bae96959493929190615702565b60405180910390a15b50505050505050565b606060008260010b13614c0957614be5614bdc83600019615c18565b61ffff16614c12565b604051602001614bf59190615689565b604051602081830303815290604052611858565b6118588261ffff165b606081614c365750506040805180820190915260018152600360fc1b602082015290565b8160005b8115614c605780614c4a81615d0d565b9150614c599050600a83615c04565b9150614c3a565b60008167ffffffffffffffff811115614c8957634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015614cb3576020820181803683370190505b5090505b84156132cb57614cc8600183615cca565b9150614cd5600a86615d28565b614ce0906030615bec565b60f81b818381518110614d0357634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350614d25600a86615c04565b9450614cb7565b828054828255906000526020600020908101928215614d67579160200282015b82811115614d67578251825591602001919060010190614d4c565b50614d73929150614d77565b5090565b5b80821115614d735760008155600101614d78565b8035600181900b8114614d9e57600080fd5b919050565b8035614d9e81615da1565b8051614d9e81615da1565b600082601f830112614dc9578081fd5b815167ffffffffffffffff811115614de357614de3615d68565b614df6601f8201601f1916602001615b2c565b818152846020838601011115614e0a578283fd5b6132cb826020830160208701615ce1565b803562ffffff81168114614d9e57600080fd5b803560ff81168114614d9e57600080fd5b600060208284031215614e50578081fd5b813561129481615d7e565b600060208284031215614e6c578081fd5b815161129481615d7e565b60008060008060808587031215614e8c578283fd5b8435614e9781615d7e565b93506020850135614ea781615d7e565b92506040850135614eb781615d7e565b91506060850135614ec781615d7e565b939692955090935050565b600080600080600060a08688031215614ee9578283fd5b8535614ef481615d7e565b9450602086810135614f0581615d7e565b94506040870135614f1581615d7e565b93506060870135614f2581615d7e565b9250608087013567ffffffffffffffff811115614f40578283fd5b8701601f81018913614f50578283fd5b8035614f63614f5e82615b5d565b615b2c565b8082825284820191508484018c868560051b8701011115614f82578687fd5b8694505b83851015614fa4578035835260019490940193918501918501614f86565b5080955050505050509295509295909350565b60008060408385031215614fc9578182fd5b8235614fd481615d7e565b91506020830135614fe481615d93565b809150509250929050565b60008060408385031215615001578182fd5b823561500c81615d7e565b915061501a60208401614d8c565b90509250929050565b60008060408385031215615035578182fd5b823561504081615d7e565b915061501a60208401614e1b565b60008060408385031215615060578182fd5b823561506b81615d7e565b946020939093013593505050565b6000806000806080858703121561508e578182fd5b843561509981615d7e565b9350602085013592506150ae60408601614e2e565b91506150bc60608601614e2e565b905092959194509250565b600060208083850312156150d9578182fd5b825167ffffffffffffffff8111156150ef578283fd5b8301601f810185136150ff578283fd5b805161510d614f5e82615b5d565b80828252848201915084840188868560051b870101111561512c578687fd5b8694505b8385101561514e578051835260019490940193918501918501615130565b50979650505050505050565b60006020828403121561516b578081fd5b813561129481615d93565b600060208284031215615187578081fd5b815161129481615d93565b6000602082840312156151a3578081fd5b5035919050565b600080604083850312156151bc578182fd5b823591506020830135614fe481615d7e565b6000806000606084860312156151e2578081fd5b8335925060208401356151f481615d7e565b9150604084013561520481615d93565b809150509250925092565b60008060408385031215615221578182fd5b823591506020830135614fe481615d93565b60008060008060808587031215615248578182fd5b84359350602085013561525a81615da1565b9250604085013561526a81615da1565b91506060850135614ec781615da1565b60008060008385036101c0811215615290578182fd5b8435935061018080601f19830112156152a7578283fd5b6152af615adf565b9150602086013582526152c460408701614da3565b60208301526152d560608701614da3565b60408301526152e660808701614da3565b60608301526152f760a08701614d8c565b608083015261530860c08701614da3565b60a083015261531960e08701614d8c565b60c083015261010061532c818801614da3565b60e084015261012061533f818901614e1b565b828501526101409150615353828901614da3565b90840152610160615365888201614e1b565b82850152615374838901614da3565b908401525093969095506101a094909401359392505050565b60006020828403121561539e578081fd5b815167ffffffffffffffff808211156153b5578283fd5b9083019060e082860312156153c8578283fd5b6153d0615b09565b82518152602083015160208201526153ea60408401614dae565b60408201526153fb60608401614dae565b606082015261540c60808401614dae565b608082015260a083015182811115615422578485fd5b61542e87828601614db9565b60a08301525060c083015182811115615445578485fd5b61545187828601614db9565b60c08301525095945050505050565b600060208284031215615471578081fd5b5051919050565b6000815180845260208085019450808401835b838110156154a75781518752958201959082019060010161548b565b509495945050505050565b6000815480845260208085019450838352808320835b838110156154a7578154875295820195600191820191016154c8565b8051825260208101516154fc602084018260020b9052565b506040810151615511604084018260020b9052565b506060810151615526606084018260020b9052565b50608081015161553b608084018260010b9052565b5060a081015161555060a084018260020b9052565b5060c081015161556560c084018260010b9052565b5060e081015161557a60e084018260020b9052565b506101008181015162ffffff169083015261012080820151600281900b8285015250506101408181015162ffffff169083015261016080820151600281900b82850152613801565b600083516155d4818460208801615ce1565b600560fb1b90830190815283516155f2816001840160208801615ce1565b602960f81b60019290910191820152600201949350505050565b6000835161561e818460208801615ce1565b6201016960ed1b908301908152835161563e816003840160208801615ce1565b01600301949350505050565b6000835161565c818460208801615ce1565b630103b39960e51b908301908152835161567d816004840160208801615ce1565b01600401949350505050565b602d60f81b8152600082516156a5816001850160208701615ce1565b9190910160010192915050565b6001600160a01b0387811682528616602082015260408101859052600184900b606082015260c0608082018190526000906156ef90830185615478565b90508260a0830152979650505050505050565b6001600160a01b038781168252861660208201526040810185905262ffffff8416606082015260c0608082018190526000906156ef90830185615478565b6001600160a01b039290921682521515602082015260400190565b6001600160a01b039586168152602081019490945291909316604083015262ffffff9283166060830152909116608082015260a00190565b6020808252825182820181905260009190848201906040850190845b818110156157d45783516001600160a01b0316835292840192918401916001016157af565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b818110156157d4578351835292840192918401916001016157fc565b6020815260006112946020830184615478565b8481526001600160a01b0384166020820152604081018390526101e0810161585660608301846154e4565b95945050505050565b8581526001600160a01b0385166020820152600061020061588360408401876154e4565b806101c084015261589681840186615478565b915050826101e08301529695505050505050565b60006101e08683528560208401526158c560408401866154e4565b806101c08401526158d8818401856154b2565b979650505050505050565b60006101e086835285602084015284546040840152600185015460026159106060860183830b60020b9052565b615924608086018360181c830b60020b9052565b61593860a086018360301c830b60020b9052565b61594d60c086018360481c60010b60010b9052565b61596160e086018360581c830b60020b9052565b61597761010086018360701c60010b60010b9052565b61598c61012086018360801c830b60020b9052565b62ffffff609883901c81166101408701526159b261016087018460b01c840b60020b9052565b6159c96101808701828560c81c1662ffffff169052565b506159df6101a086018360e01c830b60020b9052565b5050806101c08401526158d8818401856154b2565b60006101008a8352806020840152895180828501526101209150615a1e8183860160208e01615ce1565b604084018a90526060840189905260808401889052601f01601f19168301838103820160a0850152615a5282820188615478565b95151560c08501525050506001600160a01b039190911660e0909101529695505050505050565b6020808252600d908201526c27b7363c9031b7b739bab6b2b960991b604082015260600190565b848152608060208201526000615ab96080830186615478565b8281036040840152615acb81866154b2565b915050821515606083015295945050505050565b604051610180810167ffffffffffffffff81118282101715615b0357615b03615d68565b60405290565b60405160e0810167ffffffffffffffff81118282101715615b0357615b03615d68565b604051601f8201601f1916810167ffffffffffffffff81118282101715615b5557615b55615d68565b604052919050565b600067ffffffffffffffff821115615b7757615b77615d68565b5060051b60200190565b60008160010b8360010b82821282617fff03821381151615615ba557615ba5615d3c565b82617fff19038212811615615bbc57615bbc615d3c565b50019392505050565b600062ffffff808316818516808303821115615be357615be3615d3c565b01949350505050565b60008219821115615bff57615bff615d3c565b500190565b600082615c1357615c13615d52565b500490565b60008160010b8360010b617fff83821384841383830485118282161615615c4157615c41615d3c565b617fff1986851282811687830587121615615c5e57615c5e615d3c565b878712925085820587128484161615615c7957615c79615d3c565b85850587128184161615615c8f57615c8f615d3c565b5050509290910295945050505050565b600062ffffff80831681851681830481118215151615615cc157615cc1615d3c565b02949350505050565b600082821015615cdc57615cdc615d3c565b500390565b60005b83811015615cfc578181015183820152602001615ce4565b838111156138015750506000910152565b6000600019821415615d2157615d21615d3c565b5060010190565b600082615d3757615d37615d52565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461105c57600080fd5b801515811461105c57600080fd5b8060020b811461105c57600080fdfea2646970667358221220b3cc4734dfa6e9a27210cc8cabfff0e4fc4e255ac45bb3b6a6cef5bfffe5c82864736f6c63430008040033

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106103995760003560e01c806360b4df85116101e9578063ae71dcdf1161010f578063c480977c116100ad578063d46391ee1161007c578063d46391ee14610be9578063db0d457914610bfc578063e38f273814610c0f578063fa043f4014610c2257600080fd5b8063c480977c14610b80578063cc5cea2714610b93578063ceda8e9014610ba6578063d28231bd14610bc657600080fd5b8063b4fd7296116100e9578063b4fd729614610b19578063b613d8ee14610b31578063bf989b6e14610b5a578063c3b83f5f14610b6d57600080fd5b8063ae71dcdf14610a67578063b09bd9e314610a6f578063b103feb014610b0657600080fd5b806393f4452e116101875780639971441b116101565780639971441b14610a155780639aceb36e14610a28578063a12695ca14610a3b578063a4f096e814610a5e57600080fd5b806393f4452e146108ac57806393ff69d7146109b657806396583661146109ef578063988a130914610a0257600080fd5b80638d220d99116101c35780638d220d99146107f75780638da5cb5b1461082d57806391b4ded914610846578063937a314f1461084f57600080fd5b806360b4df851461071e5780636c35b775146107c657806379ba5097146107ef57600080fd5b80632fff7020116102ce5780634adf72191161026c57806359bcf1931161023b57806359bcf193146106945780635a2f7731146106b45780635c975abb146106dd5780635d134bc2146106ea57600080fd5b80634adf72191461061e5780635034c5881461063e57806353a47bb71461065e578063574ef5d91461067157600080fd5b8063366c16a5116102a8578063366c16a51461059e57806336c0d855146105be5780633ea921ae146105e1578063447b1d58146105ea57600080fd5b80632fff70201461050c578063300a02981461051457806332b566a91461051c57600080fd5b80631afed5cc1161033b57806323b1d8181161031557806323b1d8181461049f578063263737e2146104b25780632b7ac3f3146104e65780632da3f9ce146104f957600080fd5b80631afed5cc146104625780631cededce146104795780631e864c3b1461048c57600080fd5b806313af40351161037757806313af4035146103f657806314bdaa89146104095780631627540c1461043c57806316c38b3c1461044f57600080fd5b806301a5627e1461039e5780630caf0e0c146103b357806310063fdc146103c6575b600080fd5b6103b16103ac366004614fb7565b610c35565b005b6103b16103c13660046151ce565b610d2f565b6005546103d9906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6103b1610404366004614e3f565b610e58565b61042c610417366004614e3f565b60176020526000908152604090205460ff1681565b60405190151581526020016103ed565b6103b161044a366004614e3f565b610f93565b6103b161045d36600461515a565b610fe9565b61046b61232881565b6040519081526020016103ed565b6103b16104873660046151aa565b61105f565b6019546103d9906001600160a01b031681565b61042c6104ad36600461520f565b61109e565b6103d96104c0366004615023565b600f6020908152600092835260408084209091529082529020546001600160a01b031681565b6004546103d9906001600160a01b031681565b6103b1610507366004614ed2565b61129b565b61046b600181565b61046b600281565b61056c61052a366004615192565b6000908152600660205260409020600190810154600160481b8104820b92600160701b820490920b9162ffffff600160981b8304811692600160c81b90041690565b60408051600195860b81529390940b602084015262ffffff9182169383019390935290911660608201526080016103ed565b6105b16105ac366004614e3f565b611424565b6040516103ed9190615793565b61042c6105cc366004614e3f565b60086020526000908152604090205460ff1681565b61046b61271181565b6103d96105f836600461504e565b600c6020908152600092835260408084209091529082529020546001600160a01b031681565b61046b61062c366004614e3f565b600a6020526000908152604090205481565b61046b61064c366004615192565b60096020526000908152604090205481565b6001546103d9906001600160a01b031681565b61042c61067f366004615192565b600b6020526000908152604090205460ff1681565b6106a76106a2366004615192565b611531565b6040516103ed9190615818565b6103d96106c2366004614e3f565b6014602052600090815260409020546001600160a01b031681565b60035461042c9060ff1681565b6103d96106f8366004614fef565b600e6020908152600092835260408084209091529082529020546001600160a01b031681565b61078361072c366004615192565b600090815260066020526040902060010154600281810b9263010000008304820b92600160301b8104830b92600160581b8204810b92600160801b8304820b92600160b01b8104830b92600160e01b909104900b90565b60408051600298890b815296880b602088015294870b9486019490945291850b6060850152840b6080840152830b60a083015290910b60c082015260e0016103ed565b6103d96107d4366004614e3f565b6010602052600090815260409020546001600160a01b031681565b6103b16116c6565b61081a610805366004614e3f565b60116020526000908152604090205460010b81565b60405160019190910b81526020016103ed565b6000546103d9906201000090046001600160a01b031681565b61046b60025481565b61088c61085d366004614e3f565b6001600160a01b0390811660009081526013602090815260408083205460149092529091205490821692911690565b604080516001600160a01b039384168152929091166020830152016103ed565b6109436108ba366004615192565b600660205260009081526040902080546001918201549091600282810b9263010000008104820b92600160301b8204830b92600160481b8304820b92600160581b8104820b92600160701b8204900b91600160801b8204810b9162ffffff600160981b8204811692600160b01b8304810b92600160c81b810490921691600160e01b9004900b8c565b604080519c8d5260029b8c0b60208e0152998b0b998c019990995296890b60608b0152600195860b60808b015293880b60a08a01529190930b60c088015291850b60e087015262ffffff918216610100870152840b61012086015216610140840152900b610160820152610180016103ed565b6109db6109c4366004614e3f565b60126020526000908152604090205462ffffff1681565b60405162ffffff90911681526020016103ed565b6106a76109fd366004614e3f565b6117c3565b6103b1610a1036600461527a565b61185e565b6103b1610a23366004615192565b6127dc565b6106a7610a36366004615192565b612ae4565b61042c610a49366004614e3f565b60156020526000908152604090205460ff1681565b61046b61271281565b61046b600081565b610943610a7d366004615192565b600760205260009081526040902080546001918201549091600282810b9263010000008104820b92600160301b8204830b92600160481b8304820b92600160581b8104820b92600160701b8204900b91600160801b8204810b9162ffffff600160981b8204811692600160b01b8304810b92600160c81b810490921691600160e01b9004900b8c565b61046b610b1436600461504e565b612c00565b6003546103d99061010090046001600160a01b031681565b6103d9610b3f366004614e3f565b6013602052600090815260409020546001600160a01b031681565b6103b1610b68366004614e77565b612c31565b6103b1610b7b366004614e3f565b612cda565b6103b1610b8e366004615233565b612df3565b6103b1610ba136600461520f565b613091565b61046b610bb4366004614e3f565b600d6020526000908152604090205481565b61042c610bd4366004614e3f565b60166020526000908152604090205460ff1681565b6106a7610bf7366004614e3f565b6130eb565b6106a7610c0a366004614e3f565b6132d3565b6103b1610c1d3660046151aa565b6132de565b6103b1610c30366004615079565b61338e565b60035461010090046001600160a01b03163314610c6d5760405162461bcd60e51b8152600401610c6490615a79565b60405180910390fd5b60005b6001600160a01b0383166000908152600d6020526040902054811015610d2a576003546001600160a01b038481166000908152600c602090815260408083208684529091529081902054905163ed5e00eb60e01b815261010090930482169263ed5e00eb92610ce59216908690600401615740565b600060405180830381600087803b158015610cff57600080fd5b505af1158015610d13573d6000803e3d6000fd5b505050508080610d2290615d0d565b915050610c70565b505050565b60035461010090046001600160a01b03163314610d5e5760405162461bcd60e51b8152600401610c6490615a79565b60008381526006602090815260409182902082516101808101845281548152600191820154600281810b810b810b9483019490945263010000008104840b840b840b94820194909452600160301b8404830b830b830b6060820152600160481b8404820b820b820b6080820152600160581b8404830b830b830b60a0820152600160701b8404820b820b820b60c0820152600160801b8404830b830b830b60e082015262ffffff600160981b85048116610100830152600160b01b8504840b840b840b610120830152600160c81b850416610140820152600160e01b909304820b820b90910b610160830152610d2a9190849084906134d8565b6001600160a01b038116610eae5760405162461bcd60e51b815260206004820152601960248201527f4f776e657220616464726573732063616e6e6f742062652030000000000000006044820152606401610c64565b600154600160a01b900460ff1615610f1a5760405162461bcd60e51b815260206004820152602960248201527f416c726561647920696e697469616c697a65642c20757365206e6f6d696e617460448201526832a732bba7bbb732b960b91b6064820152608401610c64565b6001805460ff60a01b1916600160a01b179055600080546001600160a01b03831662010000810262010000600160b01b03199092169190911782556040805192835260208301919091527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c91015b60405180910390a150565b610f9b613807565b600180546001600160a01b0319166001600160a01b0383169081179091556040519081527f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce2290602001610f88565b610ff1613807565b60035460ff16151581151514156110055750565b6003805460ff191682151590811790915560ff161561102357426002555b60035460405160ff909116151581527f8fb6c181ee25a520cf3dd6565006ef91229fcfe5a989566c2a3b8c115570cec590602001610f88565b50565b60035461010090046001600160a01b0316331461108e5760405162461bcd60e51b8152600401610c6490615a79565b61109a81836001613881565b5050565b60008161119f5760008381526006602090815260409182902082516101808101845281548152600191820154600281810b810b810b9483019490945263010000008104840b840b840b94820194909452600160301b8404830b830b830b6060820152600160481b8404820b820b820b6080820152600160581b8404830b830b830b60a0820152600160701b8404820b820b90910b60c0820152600160801b8304820b820b820b60e082015262ffffff600160981b84048116610100830152600160b01b8404830b830b830b610120830152600160c81b840416610140820152600160e01b909204810b810b900b61016082015261119a906138f1565b611294565b60008381526007602090815260409182902082516101808101845281548152600191820154600281810b810b810b9483019490945263010000008104840b840b840b94820194909452600160301b8404830b830b830b6060820152600160481b8404820b820b820b6080820152600160581b8404830b830b830b60a0820152600160701b8404820b820b90910b60c0820152600160801b8304820b820b820b60e082015262ffffff600160981b84048116610100830152600160b01b8404830b830b830b610120830152600160c81b840416610140820152600160e01b909204810b810b900b610160820152611294906138f1565b9392505050565b600054610100900460ff166112b65760005460ff16156112ba565b303b155b61131d5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610c64565b600054610100900460ff1615801561133f576000805461ffff19166101011790555b61134886610e58565b600380546001600160a01b0380881661010002610100600160a81b031990921691909117909155600480548683166001600160a01b031991821617909155600580549286169290911691909117905560005b8251811015611409576001600b60008584815181106113c957634e487b7160e01b600052603260045260246000fd5b6020026020010151815260200190815260200160002060006101000a81548160ff021916908315150217905550808061140190615d0d565b91505061139a565b50801561141c576000805461ff00191690555b505050505050565b6001600160a01b0381166000908152600d60205260408120546060919067ffffffffffffffff81111561146757634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015611490578160200160208202803683370190505b50905060005b6001600160a01b0384166000908152600d602052604090205481101561152a576001600160a01b038085166000908152600c60209081526040808320858452909152902054835191169083908390811061150057634e487b7160e01b600052603260045260246000fd5b6001600160a01b03909216602092830291909101909101528061152281615d0d565b915050611496565b5092915050565b60408051600380825260808201909252606091600091906020820184803683375050506000848152600660205260408120600101548251929350600290810b900b9183919061159057634e487b7160e01b600052603260045260246000fd5b6020026020010181815250506006600084815260200190815260200160002060010160039054906101000a900460020b60020b816001815181106115e457634e487b7160e01b600052603260045260246000fd5b6020026020010181815250506006600084815260200190815260200160002060010160069054906101000a900460020b60020b8160028151811061163857634e487b7160e01b600052603260045260246000fd5b602090810291909101015260048054604051632c85b65d60e21b81526001600160a01b039091169163b216d97491611672918591016157e0565b60006040518083038186803b15801561168a57600080fd5b505afa15801561169e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261129491908101906150c7565b6001546001600160a01b0316331461173e5760405162461bcd60e51b815260206004820152603560248201527f596f75206d757374206265206e6f6d696e61746564206265666f726520796f7560448201527402063616e20616363657074206f776e65727368697605c1b6064820152608401610c64565b60005460015460408051620100009093046001600160a01b03908116845290911660208301527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c910160405180910390a1600180546000805462010000600160b01b0319166001600160a01b03831662010000021790556001600160a01b0319169055565b6001600160a01b03811660009081526017602052604090205460609060ff166117f4576117ef826130eb565b611858565b6001600160a01b0382166000908152601860209081526040918290208054835181840281018401909452808452909183018282801561185257602002820191906000526020600020905b81548152602001906001019080831161183e575b50505050505b92915050565b60035461010090046001600160a01b031633148061188657506019546001600160a01b031633145b6118c35760405162461bcd60e51b815260206004820152600e60248201526d24b73b30b634b21039b2b73232b960911b6044820152606401610c64565b6118cc826138f1565b1561265c5760006118e08360000151612ae4565b90506000600660008560000151815260200190815260200160002060405180610180016040529081600082015481526020016001820160009054906101000a900460020b60020b60020b81526020016001820160039054906101000a900460020b60020b60020b81526020016001820160069054906101000a900460020b60020b60020b81526020016001820160099054906101000a900460010b60010b60010b815260200160018201600b9054906101000a900460020b60020b60020b815260200160018201600e9054906101000a900460010b60010b60010b81526020016001820160109054906101000a900460020b60020b60020b81526020016001820160139054906101000a900462ffffff1662ffffff1662ffffff1681526020016001820160169054906101000a900460020b60020b60020b81526020016001820160199054906101000a900462ffffff1662ffffff1662ffffff16815260200160018201601c9054906101000a900460020b60020b60020b8152505090508360066000866000015181526020019081526020016000206000820151816000015560208201518160010160006101000a81548162ffffff021916908360020b62ffffff16021790555060408201518160010160036101000a81548162ffffff021916908360020b62ffffff16021790555060608201518160010160066101000a81548162ffffff021916908360020b62ffffff16021790555060808201518160010160096101000a81548161ffff021916908360010b61ffff16021790555060a082015181600101600b6101000a81548162ffffff021916908360020b62ffffff16021790555060c082015181600101600e6101000a81548161ffff021916908360010b61ffff16021790555060e08201518160010160106101000a81548162ffffff021916908360020b62ffffff1602179055506101008201518160010160136101000a81548162ffffff021916908362ffffff1602179055506101208201518160010160166101000a81548162ffffff021916908360020b62ffffff1602179055506101408201518160010160196101000a81548162ffffff021916908362ffffff16021790555061016082015181600101601c6101000a81548162ffffff021916908360020b62ffffff160217905550905050426009600086600001518152602001908152602001600020819055506000600360019054906101000a90046001600160a01b03166001600160a01b031663f89c6f1886600001516040518263ffffffff1660e01b8152600401611c9a91815260200190565b60206040518083038186803b158015611cb257600080fd5b505afa158015611cc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cea9190614e5b565b9050611cfc8186600001516001613881565b6000848152600b602052604090205460ff1615611d1d57611d1d8582613a8d565b6005546040516333dfec9960e21b81526001600160a01b0383811660048301529091169063cf7fb2649060240160206040518083038186803b158015611d6257600080fd5b505afa158015611d76573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d9a9190615176565b15612224576001600160a01b03811660009081526008602052604090205460ff1680611e445750600354604051630a928f9f60e21b81526001600160a01b03838116600483015261010090920490911690632a4a3e7c9060240160206040518083038186803b158015611e0c57600080fd5b505afa158015611e20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e449190615176565b1561221f576001600160a01b03808216600090815260086020526040808220805460ff191690556003549051630259f5fd60e01b815261010090910490921691630259f5fd91611e9991859190600401615740565b600060405180830381600087803b158015611eb357600080fd5b505af1158015611ec7573d6000803e3d6000fd5b5050600480546001600160a01b0385811660009081526018602052604090819020600354915163be27f89d60e01b81529485018b905292821695506342fa646a945089938993926101009092049091169063be27f89d9060240160206040518083038186803b158015611f3957600080fd5b505afa158015611f4d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f719190615176565b6040518563ffffffff1660e01b8152600401611f909493929190615aa0565b60206040518083038186803b158015611fa857600080fd5b505afa158015611fbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fe09190615176565b612211578160076000876000015181526020019081526020016000206000820151816000015560208201518160010160006101000a81548162ffffff021916908360020b62ffffff16021790555060408201518160010160036101000a81548162ffffff021916908360020b62ffffff16021790555060608201518160010160066101000a81548162ffffff021916908360020b62ffffff16021790555060808201518160010160096101000a81548161ffff021916908360010b61ffff16021790555060a082015181600101600b6101000a81548162ffffff021916908360020b62ffffff16021790555060c082015181600101600e6101000a81548161ffff021916908360010b61ffff16021790555060e08201518160010160106101000a81548162ffffff021916908360020b62ffffff1602179055506101008201518160010160136101000a81548162ffffff021916908362ffffff1602179055506101208201518160010160166101000a81548162ffffff021916908360020b62ffffff1602179055506101408201518160010160196101000a81548162ffffff021916908362ffffff16021790555061016082015181600101601c6101000a81548162ffffff021916908360020b62ffffff1602179055509050507fcb6e87c3d70eab47f84a42c3021b86de43cf8d37ebe9cfa494c4f89b75205a8a8186600001516040516122049291906001600160a01b03929092168252602082015260400190565b60405180910390a16125fe565b61221f8582600060016134d8565b6125fe565b6005546040516333dfec9960e21b81526001600160a01b0383811660048301529091169063cf7fb2649060240160206040518083038186803b15801561226957600080fd5b505afa15801561227d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122a19190615176565b1580156123c35750600480546001600160a01b0383811660009081526018602052604090819020600354915163be27f89d60e01b8152938316946342fa646a948a948a946101009004169163be27f89d916123029187910190815260200190565b60206040518083038186803b15801561231a57600080fd5b505afa15801561232e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123529190615176565b6040518563ffffffff1660e01b81526004016123719493929190615aa0565b60206040518083038186803b15801561238957600080fd5b505afa15801561239d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123c19190615176565b155b156125fe576123d585826001806134d8565b8160076000876000015181526020019081526020016000206000820151816000015560208201518160010160006101000a81548162ffffff021916908360020b62ffffff16021790555060408201518160010160036101000a81548162ffffff021916908360020b62ffffff16021790555060608201518160010160066101000a81548162ffffff021916908360020b62ffffff16021790555060808201518160010160096101000a81548161ffff021916908360010b61ffff16021790555060a082015181600101600b6101000a81548162ffffff021916908360020b62ffffff16021790555060c082015181600101600e6101000a81548161ffff021916908360010b61ffff16021790555060e08201518160010160106101000a81548162ffffff021916908360020b62ffffff1602179055506101008201518160010160136101000a81548162ffffff021916908362ffffff1602179055506101208201518160010160166101000a81548162ffffff021916908360020b62ffffff1602179055506101408201518160010160196101000a81548162ffffff021916908362ffffff16021790555061016082015181600101601c6101000a81548162ffffff021916908360020b62ffffff1602179055509050507fcb6e87c3d70eab47f84a42c3021b86de43cf8d37ebe9cfa494c4f89b75205a8a8186600001516040516125f59291906001600160a01b03929092168252602082015260400190565b60405180910390a15b84516001600160a01b0382166000908152601860205260409081902090517f5d8fed649db8e5d2dd77ea4f51ee8548f87d2679e2f5407f8db9793f701f8dfe9261264c928a928a91906158aa565b60405180910390a1505050505050565b6003548251604051631f138de360e31b8152600481019190915260009161010090046001600160a01b03169063f89c6f189060240160206040518083038186803b1580156126a957600080fd5b505afa1580156126bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126e19190614e5b565b6005546040516333dfec9960e21b81526001600160a01b03808416600483015292935091169063cf7fb2649060240160206040518083038186803b15801561272857600080fd5b505afa15801561273c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127609190615176565b612798576001600160a01b0381166000908152600860205260409020805460ff191660019081179091556127989084908390806134d8565b82516040517f420dbf4677c8331a5938fcc5890c5ae453dd3344f80f9a669d6adb2fea7de3d0916127ce9187918591889061582b565b60405180910390a150505050565b60035461010090046001600160a01b0316331461280b5760405162461bcd60e51b8152600401610c6490615a79565b600081815260076020908152604080832060069092528083208254815560019283018054918401805462ffffff19811662ffffff600295860b860b81169182178455845465ffffffffffff19909316909117630100000092839004860b860b821690920291909117808355835468ffffff000000000000198216600160301b91829004870b870b8416909102908117845584546affffffffff000000000000199092166affff000000000000000000199091161761ffff600160481b92839004890b890b811690920217808455845462ffffff60581b198216600160581b91829004880b880b85169091029081178555855464ffffffffff60581b1990921661ffff60701b1990911617600160701b91829004890b90980b9091160295909517808255825462ffffff60801b198216600160801b91829004860b860b88169091029081178355835465ffffffffffff60801b1990921662ffffff60981b1990911617600160981b91829004871690910217808255825462ffffff60b01b198216600160b01b91829004860b860b88169091029081178355835465ffffffffffff60b01b1990921662ffffff60c81b1990911617600160c81b91829004871690910217808255915462ffffff60e01b19909216600160e01b92839004840b90930b90941602179091556003549051631f138de360e31b8152600481018490526101009091046001600160a01b03169063f89c6f189060240160206040518083038186803b158015612a3a57600080fd5b505afa158015612a4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a729190614e5b565b9050612a8081836001613881565b60008281526006602090815260408083206001600160a01b038516845260189092529182902091517f5d8fed649db8e5d2dd77ea4f51ee8548f87d2679e2f5407f8db9793f701f8dfe92612ad89286928392906158e3565b60405180910390a15050565b600354604051631f138de360e31b8152600481018390526060916000916101009091046001600160a01b03169063f89c6f189060240160206040518083038186803b158015612b3257600080fd5b505afa158015612b46573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b6a9190614e5b565b6001600160a01b03811660009081526017602052604090205490915060ff16612b965761119a83611531565b6001600160a01b03811660009081526018602090815260409182902080548351818402810184019094528084529091830182828015612bf457602002820191906000526020600020905b815481526020019060010190808311612be0575b50505050509392505050565b60186020528160005260406000208181548110612c1c57600080fd5b90600052602060002001600091509150505481565b612c39613807565b60038054610100600160a81b0319166101006001600160a01b0387811691820292909217909255600480546001600160a01b0319908116878416908117909255600580548216878516908117909155601980549092169386169384179091556040805194855260208501929092529083015260608201527fa2cad6ae2699ea86ba233a96ca0e57d895983eeed04f6bd0a770187c58b820dd906080016127ce565b612ce2613807565b6001600160a01b038116612d2a5760405162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b6044820152606401610c64565b600154600160a81b900460ff1615612d7a5760405162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481d1c985b9cd9995c9c9959606a1b6044820152606401610c64565b600080546001600160a01b038381166201000081810262010000600160b01b031990941693909317938490556001805460ff60a81b1916600160a81b1790556040805193909404909116825260208201527fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9101610f88565b60035461010090046001600160a01b03163314612e225760405162461bcd60e51b8152600401610c6490615a79565b6040518061018001604052808581526020018460020b81526020018360020b81526020018260020b8152602001600060010b8152602001600060020b8152602001600060010b8152602001600060020b8152602001600062ffffff168152602001600060020b8152602001600062ffffff168152602001600060020b815250600660008681526020019081526020016000206000820151816000015560208201518160010160006101000a81548162ffffff021916908360020b62ffffff16021790555060408201518160010160036101000a81548162ffffff021916908360020b62ffffff16021790555060608201518160010160066101000a81548162ffffff021916908360020b62ffffff16021790555060808201518160010160096101000a81548161ffff021916908360010b61ffff16021790555060a082015181600101600b6101000a81548162ffffff021916908360020b62ffffff16021790555060c082015181600101600e6101000a81548161ffff021916908360010b61ffff16021790555060e08201518160010160106101000a81548162ffffff021916908360020b62ffffff1602179055506101008201518160010160136101000a81548162ffffff021916908362ffffff1602179055506101208201518160010160166101000a81548162ffffff021916908360020b62ffffff1602179055506101408201518160010160196101000a81548162ffffff021916908362ffffff16021790555061016082015181600101601c6101000a81548162ffffff021916908360020b62ffffff16021790555090505042600960008681526020019081526020016000208190555050505050565b613099613807565b6000828152600b6020908152604091829020805460ff19168415159081179091558251858152918201527f388428bda48903bbd0180b2e70447674064e582855a643dd2df349c85b0683f69101612ad8565b6001600160a01b0381166000908152600a602052604080822054815160028082526060828101909452929391928160200160208202803683375050506001600160a01b03851660009081526015602052604090205490915060ff1661316b57600082815260066020526040902060010154600160b01b900460020b613188565b600082815260066020526040902060010154600160581b900460020b5b60020b816000815181106131ac57634e487b7160e01b600052603260045260246000fd5b6020908102919091018101919091526001600160a01b03851660009081526015909152604090205460ff166131fc57600082815260066020526040902060010154600160e01b900460020b613219565b600082815260066020526040902060010154600160801b900460020b5b60020b8160018151811061323d57634e487b7160e01b600052603260045260246000fd5b602090810291909101015260048054604051632c85b65d60e21b81526001600160a01b039091169163b216d97491613277918591016157e0565b60006040518083038186803b15801561328f57600080fd5b505afa1580156132a3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526132cb91908101906150c7565b949350505050565b6060611858826117c3565b6005546001600160a01b031633146133275760405162461bcd60e51b815260206004820152600c60248201526b27b7363c9036b0b730b3b2b960a11b6044820152606401610c64565b600354604051624dc46d60e41b8152600481018490526001600160a01b038381166024830152610100909204909116906304dc46d090604401600060405180830381600087803b15801561337a57600080fd5b505af115801561141c573d6000803e3d6000fd5b60035461010090046001600160a01b031633146133bd5760405162461bcd60e51b8152600401610c6490615a79565b60005b6001600160a01b0385166000908152600d60205260409020548110156134d1576001600160a01b038086166000908152600c6020908152604080832085845290915290205416846134765760055460405163b91f5e3560e01b81526001600160a01b038381166004830152602482018890529091169063b91f5e3590604401600060405180830381600087803b15801561345957600080fd5b505af115801561346d573d6000803e3d6000fd5b505050506134be565b6001600160a01b03811660009081526015602052604090205460ff16156134ad576134a8818560ff168560ff16613ba0565b6134be565b6134be818560ff168560ff16613cd2565b50806134c981615d0d565b9150506133c0565b5050505050565b80156135475760035460405163ed5e00eb60e01b81526101009091046001600160a01b03169063ed5e00eb906135149086908690600401615740565b600060405180830381600087803b15801561352e57600080fd5b505af1158015613542573d6000803e3d6000fd5b505050505b6001600160a01b0383166000908152600d60205260409020541561380157811561362e5760005b6001600160a01b0384166000908152600d6020526040902054811015613628576003546001600160a01b038581166000908152600c602090815260408083208684529091529081902054905163ed5e00eb60e01b815261010090930482169263ed5e00eb926135e39216908790600401615740565b600060405180830381600087803b1580156135fd57600080fd5b505af1158015613611573d6000803e3d6000fd5b50505050808061362090615d0d565b91505061356e565b50613801565b61363784613e12565b15613718576001600160a01b038084166000908152600f6020908152604080832061010089015162ffffff16845290915290205416806136a257600061368e866000015186600089608001518a6101000151613e7d565b905061369c85826000614173565b50613716565b60035460405163ed5e00eb60e01b81526101009091046001600160a01b03169063ed5e00eb906136d89084908790600401615740565b600060405180830381600087803b1580156136f257600080fd5b505af1158015613706573d6000803e3d6000fd5b5050505061371684826000614173565b505b613721846141d7565b15613801576001600160a01b038084166000908152600e602090815260408083206080890151600190810b900b8452909152902054168061378d576000613779866000015186600189608001518a6101000151613e7d565b905061378785826001614173565b506134d1565b60035460405163ed5e00eb60e01b81526101009091046001600160a01b03169063ed5e00eb906137c39084908790600401615740565b600060405180830381600087803b1580156137dd57600080fd5b505af11580156137f1573d6000803e3d6000fd5b505050506134d184826001614173565b50505050565b6000546201000090046001600160a01b0316331461387f5760405162461bcd60e51b815260206004820152602f60248201527f4f6e6c792074686520636f6e7472616374206f776e6572206d6179207065726660448201526e37b936903a3434b99030b1ba34b7b760891b6064820152608401610c64565b565b806138945761388f836130eb565b61389d565b61389d82611531565b6001600160a01b038416600090815260186020908152604090912082516138ca9391929190910190614d2c565b5050506001600160a01b03166000908152601760205260409020805460ff19166001179055565b600480546003548351604051631c2ab73160e21b8152938401526000926001600160a01b039283169263abc7b988926101009004169063be27f89d9082906370aadcc49060240160206040518083038186803b15801561395057600080fd5b505afa158015613964573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139889190615460565b6040518263ffffffff1660e01b81526004016139a691815260200190565b60206040518083038186803b1580156139be57600080fd5b505afa1580156139d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139f69190615176565b6020850151604080870151606088015191516001600160e01b031960e087901b1681529315156004850152600292830b6024850152820b6044840152900b60648201526084015b60206040518083038186803b158015613a5557600080fd5b505afa158015613a69573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118589190615176565b613a9682613e12565b15613b1257613aa78282600061423c565b81516001600160a01b038083166000908152601360205260409020547fe796f6828b37337b49eb42b13232da29af82340b30005e54115fadb4a569e85c92911684613af1826117c3565b612712604051613b0595949392919061585f565b60405180910390a1613b1d565b613b1d82600061455e565b613b26826141d7565b15613b9557613b378282600161423c565b81516001600160a01b038083166000908152601460205260409020547fe796f6828b37337b49eb42b13232da29af82340b30005e54115fadb4a569e85c92911684613b81826117c3565b612711604051612ad895949392919061585f565b61109a82600161455e565b6001600160a01b03831660009081526011602052604081205460010b613bc7846064615c18565b613bd19190615b81565b90506000613be0836064615c18565b905060008160010b8360010b13613c0c578160010b8360010b12613c05576000613c0f565b6002613c0f565b60015b60055460405163b91f5e3560e01b81526001600160a01b0389811660048301526024820184905292935091169063b91f5e3590604401600060405180830381600087803b158015613c5f57600080fd5b505af1158015613c73573d6000803e3d6000fd5b5050506001600160a01b03808816600090815260106020526040908190205490517f83ceafeb39bed691550da26fa66ed80c145831e22e374c627a71f30479ae59b6935061264c928a92869291169061ffff808c1691908b169061575b565b6001600160a01b03831660009081526012602052604081205462ffffff169081613cfc8486615bc5565b613d07906064615c9f565b62ffffff1611613d445762ffffff8216613d218486615bc5565b613d2c906064615c9f565b62ffffff1610613d3d576000613d47565b6002613d47565b60015b60055460405163b91f5e3560e01b81526001600160a01b0388811660048301526024820184905292935091169063b91f5e3590604401600060405180830381600087803b158015613d9757600080fd5b505af1158015613dab573d6000803e3d6000fd5b5050506001600160a01b03808716600090815260106020526040908190205490517f83ceafeb39bed691550da26fa66ed80c145831e22e374c627a71f30479ae59b69350613e0392899286929116908990899061575b565b60405180910390a15050505050565b60048054610100830151610120840151610140850151610160860151604051634e3a53b760e11b815262ffffff94851696810196909652600292830b6024870152921660448501520b60648301526000916001600160a01b0390911690639c74a76e90608401613a3d565b600354604051631c2ab73160e21b8152600481018790526000918291613f0b9161010090046001600160a01b0316906370aadcc49060240160206040518083038186803b158015613ecd57600080fd5b505afa158015613ee1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f059190615460565b866146e6565b6005549091506001600160a01b0316634cde32ce88613f2c81898989614788565b60035460405163c48e62f160e01b8152600481018d90526101009091046001600160a01b03169063c48e62f19060240160006040518083038186803b158015613f7457600080fd5b505afa158015613f88573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613fb0919081019061538d565b60200151600060028760018e6040518963ffffffff1660e01b8152600401613fdf9897969594939291906159f4565b602060405180830381600087803b158015613ff957600080fd5b505af115801561400d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140319190614e5b565b5060055460408051622610c560e41b815290516001600160a01b039092169163dd5adfa39160019184916302610c50916004808301926020929190829003018186803b15801561408057600080fd5b505afa158015614094573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140b89190615460565b6140c29190615cca565b6040518263ffffffff1660e01b81526004016140e091815260200190565b60206040518083038186803b1580156140f857600080fd5b505afa15801561410c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141309190614e5b565b91506141698787848888888760018151811061415c57634e487b7160e01b600052603260045260246000fd5b6020026020010151614918565b5095945050505050565b80156141a857506001600160a01b03918216600090815260146020526040902080546001600160a01b03191691909216179055565b506001600160a01b03918216600090815260136020526040902080546001600160a01b03191691909216179055565b60048054608083015160a084015160c085015160e0860151604051630df2ba2560e41b8152600194850b96810196909652600292830b6024870152920b60448501520b60648301526000916001600160a01b039091169063df2ba25090608401613a3d565b6001600160a01b0382166000908152600d602052604081205415908261427c576001600160a01b0380851660009081526013602052604090205416614298565b6001600160a01b03808516600090815260146020526040902054165b90506000836142d6576001600160a01b038086166000908152600f602090815260408083206101008b015162ffffff16845290915290205416614308565b6001600160a01b038086166000908152600e6020908152604080832060808b0151600190810b900b8452909152902054165b9050828061431d57506001600160a01b038116155b156143da57600061433e876000015187878a608001518b6101000151613e7d565b905061434b868287614173565b6001600160a01b038316156143c45760035460405163ed5e00eb60e01b81526101009091046001600160a01b03169063ed5e00eb90614391908690600190600401615740565b600060405180830381600087803b1580156143ab57600080fd5b505af11580156143bf573d6000803e3d6000fd5b505050505b6143d48188600001516000613881565b5061141c565b816001600160a01b0316816001600160a01b0316146144e55760035460405163ed5e00eb60e01b81526101009091046001600160a01b03169063ed5e00eb9061442a908490600090600401615740565b600060405180830381600087803b15801561444457600080fd5b505af1158015614458573d6000803e3d6000fd5b505060035460405163ed5e00eb60e01b81526101009091046001600160a01b0316925063ed5e00eb9150614493908590600190600401615740565b600060405180830381600087803b1580156144ad57600080fd5b505af11580156144c1573d6000803e3d6000fd5b505050506144d0858286614173565b6144e08187600001516000613881565b61141c565b60035460405163ed5e00eb60e01b81526101009091046001600160a01b03169063ed5e00eb9061451c908590600090600401615740565b600060405180830381600087803b15801561453657600080fd5b505af115801561454a573d6000803e3d6000fd5b5050505061141c8287600001516000613881565b6003548251604051631f138de360e31b8152600481019190915260009161010090046001600160a01b03169063f89c6f189060240160206040518083038186803b1580156145ab57600080fd5b505afa1580156145bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145e39190614e5b565b6001600160a01b0381166000908152600d602052604090205490915015610d2a5760005b6001600160a01b0382166000908152600d6020526040902054811015613801576001600160a01b038083166000908152600c6020908152604080832085845282528083205490931680835260159091529190205460ff16151584151514156146d35760035460405163ed5e00eb60e01b81526101009091046001600160a01b03169063ed5e00eb906146a0908490600190600401615740565b600060405180830381600087803b1580156146ba57600080fd5b505af11580156146ce573d6000803e3d6000fd5b505050505b50806146de81615d0d565b915050614607565b6040805160028082526060808301845292600092919060208301908036833701905050905061471784612328615bec565b8160008151811061473857634e487b7160e01b600052603260045260246000fd5b6020026020010181815250508261475157612712614755565b6127115b8160018151811061477657634e487b7160e01b600052603260045260246000fd5b60209081029190910101529392505050565b60035460405163c48e62f160e01b8152600481018690526060916000916101009091046001600160a01b03169063c48e62f19060240160006040518083038186803b1580156147d657600080fd5b505afa1580156147ea573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052614812919081019061538d565b60a0015160035460405163c48e62f160e01b8152600481018990526101009091046001600160a01b03169063c48e62f19060240160006040518083038186803b15801561485e57600080fd5b505afa158015614872573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261489a919081019061538d565b60c001516040516020016148af92919061564a565b604051602081830303815290604052905084156148f857806148d085614bc0565b6040516020016148e19291906155c2565b6040516020818303038152906040529150506132cb565b806149078462ffffff16614c12565b6040516020016148e192919061560c565b600354604051624dc46d60e41b8152600481018990526001600160a01b038781166024830152610100909204909116906304dc46d090604401600060405180830381600087803b15801561496b57600080fd5b505af115801561497f573d6000803e3d6000fd5b5050506001600160a01b038087166000818152600a602090815260408083208d905560168252808320805460ff19166001908117909155601083528184208054968e166001600160a01b03199788168117909155808552600c8452828520600d808652848720805488529186529386208054909816909617909655949092525254614a0b925090615bec565b6001600160a01b0387166000908152600d60205260409020558315614b02576001600160a01b038681166000818152600e60209081526040808320600189810b80820b865291845282852080546001600160a01b0319908116988e1698891790915587865260118552838620805461ffff191661ffff90941693909317909255948452601483528184208054909116861790559382526015905291909120805460ff191690911790557f41525405a5e10a7f61a75ce8fb247811dadc00a10ad9bd82d09ddab453a686d386868986614ae2836117c3565b86604051614af5969594939291906156b2565b60405180910390a1614bb7565b6001600160a01b038087166000818152600f6020908152604080832062ffffff88168085529083528184208054968c166001600160a01b0319978816811790915580855260128452828520805462ffffff19169092179091559383526013909152902080549092161790557f2fb9c2a6ac1646a705c03b0657053182a32ea93c368b719a84e352ab42dcb8f886868985614b9b836117c3565b86604051614bae96959493929190615702565b60405180910390a15b50505050505050565b606060008260010b13614c0957614be5614bdc83600019615c18565b61ffff16614c12565b604051602001614bf59190615689565b604051602081830303815290604052611858565b6118588261ffff165b606081614c365750506040805180820190915260018152600360fc1b602082015290565b8160005b8115614c605780614c4a81615d0d565b9150614c599050600a83615c04565b9150614c3a565b60008167ffffffffffffffff811115614c8957634e487b7160e01b600052604160045260246000fd5b6040519080825280601f01601f191660200182016040528015614cb3576020820181803683370190505b5090505b84156132cb57614cc8600183615cca565b9150614cd5600a86615d28565b614ce0906030615bec565b60f81b818381518110614d0357634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a905350614d25600a86615c04565b9450614cb7565b828054828255906000526020600020908101928215614d67579160200282015b82811115614d67578251825591602001919060010190614d4c565b50614d73929150614d77565b5090565b5b80821115614d735760008155600101614d78565b8035600181900b8114614d9e57600080fd5b919050565b8035614d9e81615da1565b8051614d9e81615da1565b600082601f830112614dc9578081fd5b815167ffffffffffffffff811115614de357614de3615d68565b614df6601f8201601f1916602001615b2c565b818152846020838601011115614e0a578283fd5b6132cb826020830160208701615ce1565b803562ffffff81168114614d9e57600080fd5b803560ff81168114614d9e57600080fd5b600060208284031215614e50578081fd5b813561129481615d7e565b600060208284031215614e6c578081fd5b815161129481615d7e565b60008060008060808587031215614e8c578283fd5b8435614e9781615d7e565b93506020850135614ea781615d7e565b92506040850135614eb781615d7e565b91506060850135614ec781615d7e565b939692955090935050565b600080600080600060a08688031215614ee9578283fd5b8535614ef481615d7e565b9450602086810135614f0581615d7e565b94506040870135614f1581615d7e565b93506060870135614f2581615d7e565b9250608087013567ffffffffffffffff811115614f40578283fd5b8701601f81018913614f50578283fd5b8035614f63614f5e82615b5d565b615b2c565b8082825284820191508484018c868560051b8701011115614f82578687fd5b8694505b83851015614fa4578035835260019490940193918501918501614f86565b5080955050505050509295509295909350565b60008060408385031215614fc9578182fd5b8235614fd481615d7e565b91506020830135614fe481615d93565b809150509250929050565b60008060408385031215615001578182fd5b823561500c81615d7e565b915061501a60208401614d8c565b90509250929050565b60008060408385031215615035578182fd5b823561504081615d7e565b915061501a60208401614e1b565b60008060408385031215615060578182fd5b823561506b81615d7e565b946020939093013593505050565b6000806000806080858703121561508e578182fd5b843561509981615d7e565b9350602085013592506150ae60408601614e2e565b91506150bc60608601614e2e565b905092959194509250565b600060208083850312156150d9578182fd5b825167ffffffffffffffff8111156150ef578283fd5b8301601f810185136150ff578283fd5b805161510d614f5e82615b5d565b80828252848201915084840188868560051b870101111561512c578687fd5b8694505b8385101561514e578051835260019490940193918501918501615130565b50979650505050505050565b60006020828403121561516b578081fd5b813561129481615d93565b600060208284031215615187578081fd5b815161129481615d93565b6000602082840312156151a3578081fd5b5035919050565b600080604083850312156151bc578182fd5b823591506020830135614fe481615d7e565b6000806000606084860312156151e2578081fd5b8335925060208401356151f481615d7e565b9150604084013561520481615d93565b809150509250925092565b60008060408385031215615221578182fd5b823591506020830135614fe481615d93565b60008060008060808587031215615248578182fd5b84359350602085013561525a81615da1565b9250604085013561526a81615da1565b91506060850135614ec781615da1565b60008060008385036101c0811215615290578182fd5b8435935061018080601f19830112156152a7578283fd5b6152af615adf565b9150602086013582526152c460408701614da3565b60208301526152d560608701614da3565b60408301526152e660808701614da3565b60608301526152f760a08701614d8c565b608083015261530860c08701614da3565b60a083015261531960e08701614d8c565b60c083015261010061532c818801614da3565b60e084015261012061533f818901614e1b565b828501526101409150615353828901614da3565b90840152610160615365888201614e1b565b82850152615374838901614da3565b908401525093969095506101a094909401359392505050565b60006020828403121561539e578081fd5b815167ffffffffffffffff808211156153b5578283fd5b9083019060e082860312156153c8578283fd5b6153d0615b09565b82518152602083015160208201526153ea60408401614dae565b60408201526153fb60608401614dae565b606082015261540c60808401614dae565b608082015260a083015182811115615422578485fd5b61542e87828601614db9565b60a08301525060c083015182811115615445578485fd5b61545187828601614db9565b60c08301525095945050505050565b600060208284031215615471578081fd5b5051919050565b6000815180845260208085019450808401835b838110156154a75781518752958201959082019060010161548b565b509495945050505050565b6000815480845260208085019450838352808320835b838110156154a7578154875295820195600191820191016154c8565b8051825260208101516154fc602084018260020b9052565b506040810151615511604084018260020b9052565b506060810151615526606084018260020b9052565b50608081015161553b608084018260010b9052565b5060a081015161555060a084018260020b9052565b5060c081015161556560c084018260010b9052565b5060e081015161557a60e084018260020b9052565b506101008181015162ffffff169083015261012080820151600281900b8285015250506101408181015162ffffff169083015261016080820151600281900b82850152613801565b600083516155d4818460208801615ce1565b600560fb1b90830190815283516155f2816001840160208801615ce1565b602960f81b60019290910191820152600201949350505050565b6000835161561e818460208801615ce1565b6201016960ed1b908301908152835161563e816003840160208801615ce1565b01600301949350505050565b6000835161565c818460208801615ce1565b630103b39960e51b908301908152835161567d816004840160208801615ce1565b01600401949350505050565b602d60f81b8152600082516156a5816001850160208701615ce1565b9190910160010192915050565b6001600160a01b0387811682528616602082015260408101859052600184900b606082015260c0608082018190526000906156ef90830185615478565b90508260a0830152979650505050505050565b6001600160a01b038781168252861660208201526040810185905262ffffff8416606082015260c0608082018190526000906156ef90830185615478565b6001600160a01b039290921682521515602082015260400190565b6001600160a01b039586168152602081019490945291909316604083015262ffffff9283166060830152909116608082015260a00190565b6020808252825182820181905260009190848201906040850190845b818110156157d45783516001600160a01b0316835292840192918401916001016157af565b50909695505050505050565b6020808252825182820181905260009190848201906040850190845b818110156157d4578351835292840192918401916001016157fc565b6020815260006112946020830184615478565b8481526001600160a01b0384166020820152604081018390526101e0810161585660608301846154e4565b95945050505050565b8581526001600160a01b0385166020820152600061020061588360408401876154e4565b806101c084015261589681840186615478565b915050826101e08301529695505050505050565b60006101e08683528560208401526158c560408401866154e4565b806101c08401526158d8818401856154b2565b979650505050505050565b60006101e086835285602084015284546040840152600185015460026159106060860183830b60020b9052565b615924608086018360181c830b60020b9052565b61593860a086018360301c830b60020b9052565b61594d60c086018360481c60010b60010b9052565b61596160e086018360581c830b60020b9052565b61597761010086018360701c60010b60010b9052565b61598c61012086018360801c830b60020b9052565b62ffffff609883901c81166101408701526159b261016087018460b01c840b60020b9052565b6159c96101808701828560c81c1662ffffff169052565b506159df6101a086018360e01c830b60020b9052565b5050806101c08401526158d8818401856154b2565b60006101008a8352806020840152895180828501526101209150615a1e8183860160208e01615ce1565b604084018a90526060840189905260808401889052601f01601f19168301838103820160a0850152615a5282820188615478565b95151560c08501525050506001600160a01b039190911660e0909101529695505050505050565b6020808252600d908201526c27b7363c9031b7b739bab6b2b960991b604082015260600190565b848152608060208201526000615ab96080830186615478565b8281036040840152615acb81866154b2565b915050821515606083015295945050505050565b604051610180810167ffffffffffffffff81118282101715615b0357615b03615d68565b60405290565b60405160e0810167ffffffffffffffff81118282101715615b0357615b03615d68565b604051601f8201601f1916810167ffffffffffffffff81118282101715615b5557615b55615d68565b604052919050565b600067ffffffffffffffff821115615b7757615b77615d68565b5060051b60200190565b60008160010b8360010b82821282617fff03821381151615615ba557615ba5615d3c565b82617fff19038212811615615bbc57615bbc615d3c565b50019392505050565b600062ffffff808316818516808303821115615be357615be3615d3c565b01949350505050565b60008219821115615bff57615bff615d3c565b500190565b600082615c1357615c13615d52565b500490565b60008160010b8360010b617fff83821384841383830485118282161615615c4157615c41615d3c565b617fff1986851282811687830587121615615c5e57615c5e615d3c565b878712925085820587128484161615615c7957615c79615d3c565b85850587128184161615615c8f57615c8f615d3c565b5050509290910295945050505050565b600062ffffff80831681851681830481118215151615615cc157615cc1615d3c565b02949350505050565b600082821015615cdc57615cdc615d3c565b500390565b60005b83811015615cfc578181015183820152602001615ce4565b838111156138015750506000910152565b6000600019821415615d2157615d21615d3c565b5060010190565b600082615d3757615d37615d52565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461105c57600080fd5b801515811461105c57600080fd5b8060020b811461105c57600080fdfea2646970667358221220b3cc4734dfa6e9a27210cc8cabfff0e4fc4e255ac45bb3b6a6cef5bfffe5c82864736f6c63430008040033

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