Contract 0xE78B5Cdbf2dE2233909B8eB00b38C30148dC9144 2

 
 
Txn Hash
Method
Block
From
To
Value
0xff31448acc7be7f0899aa9f044ad41cfe7b5a51a5a4add894407e81954d09650Set Approval For...149454602022-06-11 17:18:24230 days 10 hrs ago0x6b254f8a91e255a4fb916501f896e15522799d82 IN  0xe78b5cdbf2de2233909b8eb00b38c30148dc91440 Ether0.00173046 69.26563119
0x47f944e423a91fc31ccd11e281b083404441fd53477533611032da57e39ac15eSet Approval For...94658842020-02-12 3:54:111081 days 16 mins ago0xfe36046f6193d691f99e2c90153003f8938cfc41 IN  0xe78b5cdbf2de2233909b8eb00b38c30148dc91440 Ether0.000227975
0x4f50a99dbd2db9efc746f5b8a5f0ef2c00f2e796ee02606c60acb3f547b617d4Admin Withdraw B...68655512018-12-11 7:11:161508 days 20 hrs ago0xa21993ea77164da77007e83c4a4b89244a7ab2db IN  0xe78b5cdbf2de2233909b8eb00b38c30148dc91440 Ether0.0002104210
0x94a62364f079fdda6ae03e62642bf92fb5d5b459fb7266827822c431e4d8cbefWithdraw Prize68256222018-12-04 16:46:261515 days 11 hrs ago0x6b254f8a91e255a4fb916501f896e15522799d82 IN  0xe78b5cdbf2de2233909b8eb00b38c30148dc91440 Ether0.000214910
0xc88790cb08fb5d136ccb100bdd632d9dea4e2089a38ca9ab46a8dee9cff820f0Withdraw Prize68248702018-12-04 13:47:411515 days 14 hrs ago0x368c2487f5ca79b2ed928f8258a1714aef1112df IN  0xe78b5cdbf2de2233909b8eb00b38c30148dc91440 Ether0.000285528
0x3a1b4856dd1fa2a2d156a097827e6cc11ccf5dfa064e58e276c54829da7209a1Withdraw Prize68214762018-12-04 0:17:511516 days 3 hrs ago0x41d3deae4e9cab7de5755992e957f6e775d773ea IN  0xe78b5cdbf2de2233909b8eb00b38c30148dc91440 Ether0.000107455
0xa97418b8068eace6bf2988cdfae49995143bfeed24d1b15833585587ee61400eWithdraw Prize68206172018-12-03 20:57:191516 days 7 hrs ago0x2ea007b62fb0b4a909d57fc8e76d112912e34171 IN  0xe78b5cdbf2de2233909b8eb00b38c30148dc91440 Ether0.0002115310
0x4e610a14885094820092e84773c36b03e6c870e5b7c06f026e52f13c1026fba6Withdraw Prize68201612018-12-03 19:20:571516 days 8 hrs agoENS Name rcorbitt.eth IN  0xe78b5cdbf2de2233909b8eb00b38c30148dc91440 Ether0.000214910
0x2020c543838a8e5a696f8502e5f19ebd33b37a5714842e90ca123054aed0156fWithdraw Prize67982892018-11-30 4:29:241519 days 23 hrs ago0xb112dc077f19dd3d603ba7b008c5c0508779737f IN  0xe78b5cdbf2de2233909b8eb00b38c30148dc91440 Ether0.0002259610
0xd4776ca6c3f4552f08ca10e7cb3e87d92df3f52f984a32506e4d039f8a1e5c85Set End67732382018-11-26 0:54:121524 days 3 hrs ago0xa21993ea77164da77007e83c4a4b89244a7ab2db IN  0xe78b5cdbf2de2233909b8eb00b38c30148dc91440 Ether0.0009415610
0xa546aeeb25c30f0c3204b3911d5e069002800b308b198ba170f1ce292a05756aSet Winner Prize...67732282018-11-26 0:50:081524 days 3 hrs ago0xa21993ea77164da77007e83c4a4b89244a7ab2db IN  0xe78b5cdbf2de2233909b8eb00b38c30148dc91440 Ether0.0004096610
0xd3f6869fc95fad9f0aba87dda3818e92a838361fc69375a884f23963fd99eaefSet Winner Prize...67732112018-11-26 0:46:531524 days 3 hrs ago0xa21993ea77164da77007e83c4a4b89244a7ab2db IN  0xe78b5cdbf2de2233909b8eb00b38c30148dc91440 Ether0.0002336210
0x48c1b1d613131aa9669e96a95c6c20ffa787295badb17081d1b12dfda19cf9d1Set Top Winner P...67732002018-11-26 0:44:561524 days 3 hrs ago0xa21993ea77164da77007e83c4a4b89244a7ab2db IN  0xe78b5cdbf2de2233909b8eb00b38c30148dc91440 Ether0.0032676910
0xe4ec7e48c723a92b9596173adc7db217d5192ce444ed95f4882138173d3c25b4Check Order67731922018-11-26 0:43:171524 days 3 hrs ago0xa21993ea77164da77007e83c4a4b89244a7ab2db IN  0xe78b5cdbf2de2233909b8eb00b38c30148dc91440 Ether0.0030896410
0x86cbdc6b12b798f24195e4df3264151d15236f50a7c6a84034b077373c1d63f0Calculate Winner...67731642018-11-26 0:36:531524 days 3 hrs ago0xa21993ea77164da77007e83c4a4b89244a7ab2db IN  0xe78b5cdbf2de2233909b8eb00b38c30148dc91440 Ether0.0005491510
0xb2af7c556a390952b3c0fa8cabeb0109c209351f5ccaf77da679aecbeb6c39f6Calculate Winner...67731422018-11-26 0:31:561524 days 3 hrs ago0xa21993ea77164da77007e83c4a4b89244a7ab2db IN  0xe78b5cdbf2de2233909b8eb00b38c30148dc91440 Ether0.0005793910
0x562ab30968cdbc2aed09bef428aebbdc5bcfb764243052ef8d10480d30446c56Calculate Winner...67731312018-11-26 0:30:111524 days 3 hrs ago0xa21993ea77164da77007e83c4a4b89244a7ab2db IN  0xe78b5cdbf2de2233909b8eb00b38c30148dc91440 Ether0.0006839710
0x7f12d4aa22d55e0c149dfcf1c3c2ddf04259d296c5e5a3070e5c1baf5eeef9dfSet Limit67731002018-11-26 0:23:351524 days 3 hrs ago0xa21993ea77164da77007e83c4a4b89244a7ab2db IN  0xe78b5cdbf2de2233909b8eb00b38c30148dc91440 Ether0.0020043710
0x43a4cc046bf91de4658b4be649e15e296c10c91283e9f8ef168edb8ab462abf8Calculate Points...67730782018-11-26 0:16:211524 days 3 hrs ago0xa21993ea77164da77007e83c4a4b89244a7ab2db IN  0xe78b5cdbf2de2233909b8eb00b38c30148dc91440 Ether0.028485210
0x52af92342b4c0dbe394c4e1edbca4e32746750d8c42f06aed8ce151dd35383caCalculate Points...67730732018-11-26 0:15:341524 days 3 hrs ago0xa21993ea77164da77007e83c4a4b89244a7ab2db IN  0xe78b5cdbf2de2233909b8eb00b38c30148dc91440 Ether0.0387525610
0x929933fb91ef877fe4c5c367a952fbe48eb2ca9dfc64be85c6c799714d46165cCalculate Points...67730662018-11-26 0:14:141524 days 3 hrs ago0xa21993ea77164da77007e83c4a4b89244a7ab2db IN  0xe78b5cdbf2de2233909b8eb00b38c30148dc91440 Ether0.0388910810
0xc16799116a774786570328695ffaae453e4951748c716c09fdd38b21b2e0beb1Calculate Points...67730462018-11-26 0:09:371524 days 4 hrs ago0xa21993ea77164da77007e83c4a4b89244a7ab2db IN  0xe78b5cdbf2de2233909b8eb00b38c30148dc91440 Ether0.0699936110
0x20b8de0f3337d4631c4149c1ce35c8210edf93835ee457cafb3ec6dfd0c96d27Calculate Points...67730392018-11-26 0:07:581524 days 4 hrs ago0xa21993ea77164da77007e83c4a4b89244a7ab2db IN  0xe78b5cdbf2de2233909b8eb00b38c30148dc91440 Ether0.0699936110
0xa077bb4a1996eaa1e0fb29622dfd741b4b41d80ddaf3142e2b41f9f07de8fa45Data Source Get ...67730192018-11-26 0:04:051524 days 4 hrs ago0xa21993ea77164da77007e83c4a4b89244a7ab2db IN  0xe78b5cdbf2de2233909b8eb00b38c30148dc91440 Ether0.0004815510
0x8230105934b16a026a4544e6765eb5a1261e0972c4b5c3de15142cfcd3b191efData Source Get ...67730132018-11-26 0:02:451524 days 4 hrs ago0xa21993ea77164da77007e83c4a4b89244a7ab2db IN  0xe78b5cdbf2de2233909b8eb00b38c30148dc91440 Ether0.0011601110
[ Download CSV Export 
Latest 12 internal transactions
Parent Txn Hash Block From To Value
0x4f50a99dbd2db9efc746f5b8a5f0ef2c00f2e796ee02606c60acb3f547b617d468655512018-12-11 7:11:161508 days 20 hrs ago 0xe78b5cdbf2de2233909b8eb00b38c30148dc91440xa21993ea77164da77007e83c4a4b89244a7ab2db0.376 Ether
0x94a62364f079fdda6ae03e62642bf92fb5d5b459fb7266827822c431e4d8cbef68256222018-12-04 16:46:261515 days 11 hrs ago 0xe78b5cdbf2de2233909b8eb00b38c30148dc91440x6b254f8a91e255a4fb916501f896e15522799d820.13536 Ether
0xc88790cb08fb5d136ccb100bdd632d9dea4e2089a38ca9ab46a8dee9cff820f068248702018-12-04 13:47:411515 days 14 hrs ago 0xe78b5cdbf2de2233909b8eb00b38c30148dc91440x368c2487f5ca79b2ed928f8258a1714aef1112df1.32822 Ether
0x3a1b4856dd1fa2a2d156a097827e6cc11ccf5dfa064e58e276c54829da7209a168214762018-12-04 0:17:511516 days 3 hrs ago 0xe78b5cdbf2de2233909b8eb00b38c30148dc91440x41d3deae4e9cab7de5755992e957f6e775d773ea0.1204704 Ether
0xa97418b8068eace6bf2988cdfae49995143bfeed24d1b15833585587ee61400e68206172018-12-03 20:57:191516 days 7 hrs ago 0xe78b5cdbf2de2233909b8eb00b38c30148dc91440x2ea007b62fb0b4a909d57fc8e76d112912e341710.8196048 Ether
0x4e610a14885094820092e84773c36b03e6c870e5b7c06f026e52f13c1026fba668201612018-12-03 19:20:571516 days 8 hrs ago 0xe78b5cdbf2de2233909b8eb00b38c30148dc9144ENS Name rcorbitt.eth0.9803448 Ether
0x92d2b4706b2eabc0c32bedbaed31fc57b72f09a95fcca83eab16ea46873afe3667607702018-11-24 0:12:031526 days 3 hrs ago 0x894398c584c9ac855d9aa94b5d1a501ccfd3bc33 0xe78b5cdbf2de2233909b8eb00b38c30148dc91440.0075 Ether
0x21c592e00cb3733cdd4ef7d875321d02e907aafafdbdec0b5a0ab3a2104fcd1267305072018-11-19 0:37:431531 days 3 hrs ago 0x894398c584c9ac855d9aa94b5d1a501ccfd3bc33 0xe78b5cdbf2de2233909b8eb00b38c30148dc91440.005 Ether
0xf2475931b9d2e2f54c94309aa9c95b67ea938d6334184f32c89419323e93a0b267303042018-11-18 23:41:171531 days 4 hrs ago 0x894398c584c9ac855d9aa94b5d1a501ccfd3bc33 0xe78b5cdbf2de2233909b8eb00b38c30148dc91440.005 Ether
0x78b3cc721331bd5ee864ecf5041f92807d3bf01210fd075587ad3432907f5e2b67302852018-11-18 23:35:521531 days 4 hrs ago 0x894398c584c9ac855d9aa94b5d1a501ccfd3bc33 0xe78b5cdbf2de2233909b8eb00b38c30148dc91440.005 Ether
0xbc625558c2f6487ec5b0fdbe70c41fba3fd37cae9ba4ef17da6ab1be502a09a467302682018-11-18 23:30:421531 days 4 hrs ago 0x894398c584c9ac855d9aa94b5d1a501ccfd3bc33 0xe78b5cdbf2de2233909b8eb00b38c30148dc91440.005 Ether
0xdfae85413c52e73227720a6d4d01fe10457c1f991a9ae07fe040cf3a0694cd1567302182018-11-18 23:21:031531 days 4 hrs ago 0x894398c584c9ac855d9aa94b5d1a501ccfd3bc33 0xe78b5cdbf2de2233909b8eb00b38c30148dc91440.005 Ether
[ Download CSV Export 
Loading
This contract contains unverified libraries: PayoutDistribution, PointsCalculator
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.

Contract Source Code Verified (Exact Match)

Contract Name:
CryptocupNFL

Compiler Version
v0.4.24+commit.e67f0147

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2018-10-17
*/

pragma solidity ^0.4.24;

// File: contracts/libs/PointsCalculator.sol

library PointsCalculator {

    uint8 constant MATCHES_NUMBER = 20;
    uint8 constant BONUS_MATCHES = 5;
    
    uint16 constant EXTRA_STATS_MASK = 65535;
    uint8 constant MATCH_UNDEROVER_MASK = 1;
    uint8 constant MATCH_RESULT_MASK = 3;
    uint8 constant MATCH_TOUCHDOWNS_MASK = 31;
    uint8 constant BONUS_STAT_MASK = 63;

    struct MatchResult{
        uint8 result; /*  0-> draw, 1-> won 1, 2-> won 2 */
        uint8 under49;
        uint8 touchdowns;
    }

    struct Extras {
        uint16 interceptions;
        uint16 missedFieldGoals;
        uint16 overtimes;
        uint16 sacks;
        uint16 fieldGoals;
        uint16 fumbles;
    }

    struct BonusMatch {
        uint16 bonus;
    }    
    
    /**
    * @notice get points from a single match 
    * @param matchIndex index of the match
    * @param matches token predictions
    * @return 
    */
    function getMatchPoints (uint256 matchIndex, uint160 matches, MatchResult[] matchResults, bool[] starMatches) private pure returns(uint16 matchPoints) {

        uint8 tResult = uint8(matches & MATCH_RESULT_MASK);
        uint8 tUnder49 = uint8((matches >> 2) & MATCH_UNDEROVER_MASK);
        uint8 tTouchdowns = uint8((matches >> 3) & MATCH_TOUCHDOWNS_MASK);

        uint8 rResult = matchResults[matchIndex].result;
        uint8 rUnder49 = matchResults[matchIndex].under49;
        uint8 rTouchdowns = matchResults[matchIndex].touchdowns;
        
        if (rResult == tResult) {
            matchPoints += 5;
            if(rResult == 0) {
                matchPoints += 5;
            }
            if(starMatches[matchIndex]) {
                matchPoints += 2;
            }
        }
        if(tUnder49 == rUnder49) {
            matchPoints += 1;
        }
        if(tTouchdowns == rTouchdowns) {
            matchPoints += 4;
        }
    }

    /**
    * @notice calculates points won by yellow and red cards predictions
    * @param extras token predictions
    * @return amount of points
    */
    function getExtraPoints(uint96 extras, Extras extraStats) private pure returns(uint16 extraPoints){

        uint16 interceptions = uint16(extras & EXTRA_STATS_MASK);
        extras = extras >> 16;
        uint16 missedFieldGoals = uint16(extras & EXTRA_STATS_MASK);
        extras = extras >> 16;
        uint16 overtimes = uint16(extras & EXTRA_STATS_MASK);
        extras = extras >> 16;
        uint16 sacks = uint16(extras & EXTRA_STATS_MASK);
        extras = extras >> 16;
        uint16 fieldGoals = uint16(extras & EXTRA_STATS_MASK);
        extras = extras >> 16;
        uint16 fumbles = uint16(extras & EXTRA_STATS_MASK);

        if (interceptions == extraStats.interceptions){
            extraPoints += 6;
        }
        
        if (missedFieldGoals == extraStats.missedFieldGoals){
            extraPoints += 6;
        }

        if (overtimes == extraStats.overtimes){
            extraPoints += 6;
        }

        if (sacks == extraStats.sacks){
            extraPoints += 6;
        }

        if (fieldGoals == extraStats.fieldGoals){
            extraPoints += 6;
        }

        if (fumbles == extraStats.fumbles){
            extraPoints += 6;
        }

    }

    /**
    *
    *
    *
    */
    function getBonusPoints (uint256 bonusId, uint32 bonuses, BonusMatch[] bonusMatches) private pure returns(uint16 bonusPoints) {
        uint8 bonus = uint8(bonuses & BONUS_STAT_MASK);

        if(bonusMatches[bonusId].bonus == bonus) {
            bonusPoints += 2;
        }
    }


    function calculateTokenPoints (uint160 tMatchResults, uint32 tBonusMatches, uint96 tExtraStats, MatchResult[] storage matchResults, Extras storage extraStats, BonusMatch[] storage bonusMatches, bool[] starMatches) 
    external pure returns(uint16 points){
        
        //Matches
        uint160 m = tMatchResults;
        for (uint256 i = 0; i < MATCHES_NUMBER; i++){
            points += getMatchPoints(MATCHES_NUMBER - i - 1, m, matchResults, starMatches);
            m = m >> 8;
        }

        //BonusMatches
        uint32 b = tBonusMatches;
        for(uint256 j = 0; j < BONUS_MATCHES; j++) {
            points += getBonusPoints(BONUS_MATCHES - j - 1, b, bonusMatches);
            b = b >> 6;
        }

        //Extras
        points += getExtraPoints(tExtraStats, extraStats);

    }
}

// File: contracts/dataSource/DataSourceInterface.sol

contract DataSourceInterface {

    function isDataSource() public pure returns (bool);

    function getMatchResults() external;
    function getExtraStats() external;
    function getBonusResults() external;

}

// File: contracts/game/GameStorage.sol

// Matches
    // 0  Baltimore,Cleveland   Bonus
    // 1  Denver,New York       Bonus
    // 2  Atlanta,Pittsburgh
    // 3  New York,Carolina
    // 4 Minnesota,Philadelphia Bonus
    // 5 Arizona,San Francisco
    // 6 Los Angeles,Seattle
    // 7 Dallas,Houston         Star





contract GameStorage{

    event LogTokenBuilt(address creatorAddress, uint256 tokenId, string message, uint160 m, uint96 e, uint32 b);
    event LogTokenGift(address creatorAddress, address giftedAddress, uint256 tokenId, string message, uint160 m, uint96 e, uint32 b);
    event LogPrepaidTokenBuilt(address creatorAddress, bytes32 secret);
    event LogPrepaidRedeemed(address redeemer, uint256 tokenId, string message, uint160 m, uint96 e, uint32 b);

    uint256 constant STARTING_PRICE = 50 finney;
    uint256 constant FIRST_PHASE  = 1540393200;
    uint256 constant EVENT_START = 1541084400;

    uint8 constant MATCHES_NUMBER = 20;
    uint8 constant BONUS_MATCHES = 5;

    //6, 12, 18    
    bool[] internal starMatches = [false, false, false, false, false, false, true, false, false, false, false, false, true, false, false, false, false, false, true, false];
    
    uint16 constant EXTRA_STATS_MASK = 65535;
    uint8 constant MATCH_UNDEROVER_MASK = 1;
    uint8 constant MATCH_RESULT_MASK = 3;
    uint8 constant MATCH_TOUCHDOWNS_MASK = 31;
    uint8 constant BONUS_STAT_MASK = 63;

    uint256 public prizePool = 0;
    uint256 public adminPool = 0;

    mapping (uint256 => uint16) public tokenToPointsMap;    
    mapping (uint256 => uint256) public tokenToPayoutMap;
    mapping (bytes32 => uint8) public secretsMap;


    address public dataSourceAddress;
    DataSourceInterface internal dataSource;


    enum pointsValidationState { Unstarted, LimitSet, LimitCalculated, OrderChecked, TopWinnersAssigned, WinnersAssigned, Finished }
    pointsValidationState public pValidationState = pointsValidationState.Unstarted;

    uint256 internal pointsLimit = 0;
    uint32 internal lastCalculatedToken = 0;
    uint32 internal lastCheckedToken = 0;
    uint32 internal winnerCounter = 0;
    uint32 internal lastAssigned = 0;
    uint32 internal payoutRange = 0;
    uint32 internal lastPrizeGiven = 0;

    uint16 internal superiorQuota;
    
    uint16[] internal payDistributionAmount = [1,1,1,1,1,1,1,1,1,1,5,5,10,20,50,100,100,200,500,1500,2500];
    uint24[21] internal payoutDistribution;

    uint256[] internal sortedWinners;

    PointsCalculator.MatchResult[] public matchResults;
    PointsCalculator.BonusMatch[] public bonusMatches;
    PointsCalculator.Extras public extraStats;


}

// File: contracts/CryptocupStorage.sol

contract CryptocupStorage is GameStorage {

}

// File: contracts/ticket/TicketInterface.sol

/**
 * @title ERC721 Non-Fungible Token Standard basic interface
 * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
 */
interface TicketInterface {

    event Transfer(
        address indexed from,
        address indexed to,
        uint256 indexed tokenId
    );
    event Approval(
        address indexed owner,
        address indexed approved,
        uint256 indexed tokenId
    );
    event ApprovalForAll(
        address indexed owner,
        address indexed operator,
        bool approved
    );


    function balanceOf(address owner) public view returns (uint256 balance);
    function ownerOf(uint256 tokenId) public view returns (address owner);
    function getOwnedTokens(address _from) public view returns(uint256[]);


    function approve(address to, uint256 tokenId) public;
    function getApproved(uint256 tokenId) public view returns (address operator);

    function setApprovalForAll(address operator, bool _approved) public;
    function isApprovedForAll(address owner, address operator) public view returns (bool);

    function transferFrom(address from, address to, uint256 tokenId) public;
    function safeTransferFrom(address from, address to, uint256 tokenId) public;

    function safeTransferFrom(address from, address to, uint256 tokenId, bytes data) public;

}

// File: contracts/ticket/TicketStorage.sol

contract TicketStorage is TicketInterface{

    // Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
    // which can be also obtained as `ERC721Receiver(0).onERC721Received.selector`
    bytes4 private constant ERC721_RECEIVED = 0x150b7a02;

    struct Token {
        uint160 matches;
        uint32 bonusMatches;
        uint96 extraStats;
        uint64 timeStamp;
        string message;  
    }
    
    // List of all tokens
    Token[] tokens;

    mapping (uint256 => address) public tokenOwner;
    mapping (uint256 => address) public tokenApprovals;
    mapping (address => uint256[]) internal ownedTokens;
    mapping (address => mapping (address => bool)) public operatorApprovals;

}

// File: contracts/libs/SafeMath.sol

/**
 * @title SafeMath
 * @dev Math operations with safety checks that throw on error
 */
library SafeMath {

  /**
  * @dev Multiplies two numbers, throws on overflow.
  */
  function mul(uint256 _a, uint256 _b) internal pure returns (uint256 c) {
    // Gas optimization: this is cheaper than asserting 'a' not being zero, but the
    // benefit is lost if 'b' is also tested.
    // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
    if (_a == 0) {
      return 0;
    }

    c = _a * _b;
    assert(c / _a == _b);
    return c;
  }

  /**
  * @dev Integer division of two numbers, truncating the quotient.
  */
  function div(uint256 _a, uint256 _b) internal pure returns (uint256) {
    // assert(_b > 0); // Solidity automatically throws when dividing by 0
    // uint256 c = _a / _b;
    // assert(_a == _b * c + _a % _b); // There is no case in which this doesn't hold
    return _a / _b;
  }

  /**
  * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
  */
  function sub(uint256 _a, uint256 _b) internal pure returns (uint256) {
    assert(_b <= _a);
    return _a - _b;
  }

  /**
  * @dev Adds two numbers, throws on overflow.
  */
  function add(uint256 _a, uint256 _b) internal pure returns (uint256 c) {
    c = _a + _b;
    assert(c >= _a);
    return c;
  }
}

// File: contracts/helpers/AddressUtils.sol

/**
 * Utility library of inline functions on addresses
 */
library AddressUtils {

  /**
   * Returns whether the target address is a contract
   * @dev This function will return false if invoked during the constructor of a contract,
   * as the code is not actually created until after the constructor finishes.
   * @param _addr address to check
   * @return whether the target address is a contract
   */
  function isContract(address _addr) internal view returns (bool) {
    uint256 size;
    // XXX Currently there is no better way to check if there is a contract in an address
    // than to check the size of the code at that address.
    // See https://ethereum.stackexchange.com/a/14016/36603
    // for more details about how this works.
    // TODO Check this again before the Serenity release, because all addresses will be
    // contracts then.
    // solium-disable-next-line security/no-inline-assembly
    assembly { size := extcodesize(_addr) }
    return size > 0;
  }

}

// File: contracts/access/AccessStorage.sol

contract AccessStorage{

	bool public paused = false;
    bool public finalized = false;
    
    address public adminAddress;
    address public dataSourceAddress;
    address public marketplaceAddress;

    uint256 internal deploymentTime = 0;
    uint256 public gameFinishedTime = 0; 
    uint256 public finalizedTime = 0;

}

// File: contracts/access/AccessRegistry.sol

/**
* @title AccessControlLayer
* @author CryptoCup Team (https://cryptocup.io/about)
* @dev Containes basic admin modifiers to restrict access to some functions. Allows
* for pauseing, and setting emergency stops.
*/
contract AccessRegistry is AccessStorage {


   /**
   * @dev Main modifier to limit access to delicate functions.
   */
    modifier onlyAdmin() {
        require(msg.sender == adminAddress, "Only admin.");
        _;
    }

    /**
   * @dev Main modifier to limit access to delicate functions.
   */
    modifier onlyDataSource() {
        require(msg.sender == dataSourceAddress, "Only dataSource.");
        _;
    }

    /**
   * @dev Main modifier to limit access to delicate functions.
   */
    modifier onlyMarketPlace() {
        require(msg.sender == marketplaceAddress, "Only marketplace.");
        _;
    }


    /**
    * @dev Modifier that checks that the contract is not paused
    */
    modifier isNotPaused() {
        require(!paused, "Only if not paused.");
        _;
    }

    /**
    * @dev Modifier that checks that the contract is paused
    */
    modifier isPaused() {
        require(paused, "Only if paused.");
        _;
    }

    /**
    * @dev Modifier that checks that the contract has finished successfully
    */
    modifier hasFinished() {
        require((gameFinishedTime != 0) && now >= (gameFinishedTime + (15 days)), "Only if game has finished.");
        _;
    }

    /**
    * @dev Modifier that checks that the contract has finalized
    */
    modifier hasFinalized() {
        require(finalized, "Only if game has finalized.");
        _;
    }

    function setPause () internal {
        paused = true;
    }

    function unSetPause() internal {
        paused = false;
    }

    /**
    * @dev Transfer contract's ownership
    * @param _newAdmin Address to be set
    */
    function setAdmin(address _newAdmin) external onlyAdmin {

        require(_newAdmin != address(0));
        adminAddress = _newAdmin;
    }

     /**
    * @dev Adds contract's mkt
    * @param _newMkt Address to be set
    */
    function setMarketplaceAddress(address _newMkt) external onlyAdmin {

        require(_newMkt != address(0));
        marketplaceAddress = _newMkt;
    }

    /**
    * @dev Sets the contract pause state
    * @param state True to pause
    */
    function setPauseState(bool state) external onlyAdmin {
        paused = state;
    }

    /**
    * @dev Sets the contract to finalized
    * @param state True to finalize
    */
    function setFinalized(bool state) external onlyAdmin {
        paused = state;
        finalized = state;
        if(finalized == true)
            finalizedTime = now;
    }
}

// File: contracts/ticket/TicketRegistry.sol

/**
 * @title ERC721 Non-Fungible Token Standard basic implementation
 * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md
 */
contract TicketRegistry is TicketInterface, TicketStorage, AccessRegistry{

    using SafeMath for uint256;
    using AddressUtils for address;
    
    /**
     * @dev Gets the balance of the specified address
     * @param _owner address to query the balance of
     * @return uint256 representing the amount owned by the passed address
     */
    function balanceOf(address _owner) public view returns (uint256) {
        require(_owner != address(0));
        return ownedTokens[_owner].length;
    }

    /**
     * @dev Gets the owner of the specified token ID
     * @param _tokenId uint256 ID of the token to query the owner of
     * @return owner address currently marked as the owner of the given token ID
     */
    function ownerOf(uint256 _tokenId) public view returns (address) {
        address owner = tokenOwner[_tokenId];
        require(owner != address(0));
        return owner;
    }

    /**
     * @dev Gets tokens of owner
     * @param _from address of the owner
     * @return array with token ids
     */
    function getOwnedTokens(address _from) public view returns(uint256[]) {
        return ownedTokens[_from];   
    }

    /**
     * @dev Returns whether the specified token exists
     * @param _tokenId uint256 ID of the token to query the existence of
     * @return whether the token exists
     */
    function exists(uint256 _tokenId) public view returns (bool) {
        address owner = tokenOwner[_tokenId];
        return owner != address(0);
    }

    /**
     * @dev Approves another address to transfer the given token ID
     * The zero address indicates there is no approved address.
     * There can only be one approved address per token at a given time.
     * Can only be called by the token owner or an approved operator.
     * @param _to address to be approved for the given token ID
     * @param _tokenId uint256 ID of the token to be approved
     */
    function approve(address _to, uint256 _tokenId) public {
        address owner = ownerOf(_tokenId);
        require(_to != owner);
        require(msg.sender == owner || isApprovedForAll(owner, msg.sender));

        tokenApprovals[_tokenId] = _to;
        emit Approval(owner, _to, _tokenId);
    }

    /**
     * @dev Gets the approved address for a token ID, or zero if no address set
     * @param _tokenId uint256 ID of the token to query the approval of
     * @return address currently approved for the given token ID
     */
    function getApproved(uint256 _tokenId) public view returns (address) {
        return tokenApprovals[_tokenId];
    }

    /**
     * @dev Sets or unsets the approval of a given operator
     * An operator is allowed to transfer all tokens of the sender on their behalf
     * @param _to operator address to set the approval
     * @param _approved representing the status of the approval to be set
     */
    function setApprovalForAll(address _to, bool _approved) public {
        require(_to != msg.sender);
        operatorApprovals[msg.sender][_to] = _approved;
        emit ApprovalForAll(msg.sender, _to, _approved);
    }

    /**
     * @dev Tells whether an operator is approved by a given owner
     * @param _owner owner address which you want to query the approval of
     * @param _operator operator address which you want to query the approval of
     * @return bool whether the given operator is approved by the given owner
     */
    function isApprovedForAll(address _owner, address _operator) public view returns (bool)  {
        return operatorApprovals[_owner][_operator];
    }

    /**
     * @dev Transfers the ownership of a given token ID to another address
     * Usage of this method is discouraged, use `safeTransferFrom` whenever possible
     * Requires the msg sender to be the owner, approved, or operator
     * @param _from current owner of the token
     * @param _to address to receive the ownership of the given token ID
     * @param _tokenId uint256 ID of the token to be transferred
    */
    function transferFrom(address _from, address _to, uint256 _tokenId) public isNotPaused{
        
        require(isApprovedOrOwner(msg.sender, _tokenId));
        require(_from != address(0));
        require(_to != address(0));
        require (_from != _to);
        
        clearApproval(_from, _tokenId);
        removeTokenFrom(_from, _tokenId);
        addTokenTo(_to, _tokenId);

        emit Transfer(_from, _to, _tokenId);
    }

    /**
     * @dev Safely transfers the ownership of a given token ID to another address
     * If the target address is a contract, it must implement `onERC721Received`,
     * which is called upon a safe transfer, and return the magic value
     * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
     * the transfer is reverted.
     *
     * Requires the msg sender to be the owner, approved, or operator
     * @param _from current owner of the token
     * @param _to address to receive the ownership of the given token ID
     * @param _tokenId uint256 ID of the token to be transferred
    */
    function safeTransferFrom(address _from, address _to, uint256 _tokenId) public {
        // solium-disable-next-line arg-overflow
        safeTransferFrom(_from, _to, _tokenId, "");
    }

    /**
     * @dev Safely transfers the ownership of a given token ID to another address
     * If the target address is a contract, it must implement `onERC721Received`,
     * which is called upon a safe transfer, and return the magic value
     * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise,
     * the transfer is reverted.
     * Requires the msg sender to be the owner, approved, or operator
     * @param _from current owner of the token
     * @param _to address to receive the ownership of the given token ID
     * @param _tokenId uint256 ID of the token to be transferred
     * @param _data bytes data to send along with a safe transfer check
     */
    function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes _data) public {
        transferFrom(_from, _to, _tokenId);
        // solium-disable-next-line arg-overflow
        // require(checkAndCallSafeTransfer(_from, _to, _tokenId, _data));
    }


    /**
     * @dev Returns whether the given spender can transfer a given token ID
     * @param _spender address of the spender to query
     * @param _tokenId uint256 ID of the token to be transferred
     * @return bool whether the msg.sender is approved for the given token ID,
     *  is an operator of the owner, or is the owner of the token
     */
    function isApprovedOrOwner(address _spender, uint256 _tokenId) internal view returns (bool){
        address owner = ownerOf(_tokenId);
        // Disable solium check because of
        // https://github.com/duaraghav8/Solium/issues/175
        // solium-disable-next-line operator-whitespace
        return (
            _spender == owner ||
            getApproved(_tokenId) == _spender ||
            isApprovedForAll(owner, _spender)
        );
    }

    /**
     * @dev Internal function to mint a new token
     * Reverts if the given token ID already exists
     * @param _to The address that will own the minted token
     * @param _tokenId uint256 ID of the token to be minted by the msg.sender
     */
    function _mint(address _to, uint256 _tokenId) internal {
        require(_to != address(0));
        addTokenTo(_to, _tokenId);
        //emit Transfer(address(0), _to, _tokenId);
    }

    /**
     * @dev Internal function to clear current approval of a given token ID
     * Reverts if the given address is not indeed the owner of the token
     * @param _owner owner of the token
     * @param _tokenId uint256 ID of the token to be transferred
     */
    function clearApproval(address _owner, uint256 _tokenId) internal {
        require(ownerOf(_tokenId) == _owner);
        if (tokenApprovals[_tokenId] != address(0)) {
            tokenApprovals[_tokenId] = address(0);
        }
    }

    /**
     * @dev Internal function to add a token ID to the list of a given address
     * @param _to address representing the new owner of the given token ID
     * @param _tokenId uint256 ID of the token to be added to the tokens list of the given address
     */
    function addTokenTo(address _to, uint256 _tokenId) internal {
        require(tokenOwner[_tokenId] == address(0));
        tokenOwner[_tokenId] = _to;
        ownedTokens[_to].push(_tokenId);
    }

    /**
     * @dev Internal function to remove a token ID from the list of a given address
     * @param _from address representing the previous owner of the given token ID
     * @param _tokenId uint256 ID of the token to be removed from the tokens list of the given address
     */
    function removeTokenFrom(address _from, uint256 _tokenId) internal {

        require(ownerOf(_tokenId) == _from);
        require(ownedTokens[_from].length < 100);

        tokenOwner[_tokenId] = address(0);

        uint256[] storage tokenArray = ownedTokens[_from];
        for (uint256 i = 0; i < tokenArray.length; i++){
            if(tokenArray[i] == _tokenId){
                tokenArray[i] = tokenArray[tokenArray.length-1];
            }
        }
        
        delete tokenArray[tokenArray.length-1];
        tokenArray.length--;

    }



}

// File: contracts/libs/PayoutDistribution.sol

library PayoutDistribution {

	function getDistribution(uint256 tokenCount) external pure returns (uint24[21] payoutDistribution) {

		if(tokenCount < 101){
            payoutDistribution = [289700, 189700, 120000, 92500, 75000, 62500, 52500, 42500, 40000, 35600, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
        }else if(tokenCount < 201){
            payoutDistribution = [265500, 165500, 105500, 75500, 63000, 48000, 35500, 20500, 20000, 19500, 18500, 17800, 0, 0, 0, 0, 0, 0, 0, 0, 0];
        }else if(tokenCount < 301){
            payoutDistribution = [260700, 155700, 100700, 70900, 60700, 45700, 35500, 20500, 17900, 12500, 11500, 11000, 10670, 0, 0, 0, 0, 0, 0, 0, 0];
        }else if(tokenCount < 501){
            payoutDistribution = [238600, 138600, 88800, 63800, 53800, 43800, 33800, 18800, 17500, 12500, 9500, 7500, 7100, 6700, 0, 0, 0, 0, 0, 0, 0];
        }else if(tokenCount < 1001){
            payoutDistribution = [218300, 122300, 72300, 52400, 43900, 33900, 23900, 16000, 13000, 10000, 9000, 7000, 5000, 4000, 3600, 0, 0, 0, 0, 0, 0];
        }else if(tokenCount < 2001){
            payoutDistribution = [204500, 114000, 64000, 44100, 35700, 26700, 22000, 15000, 11000, 9500, 8500, 6500, 4600, 2500, 2000, 1800, 0, 0, 0, 0, 0];
        }else if(tokenCount < 3001){
            payoutDistribution = [189200, 104800, 53900, 34900, 29300, 19300, 15300, 14000, 10500, 8300, 8000, 6000, 3800, 2500, 2000, 1500, 1100, 0, 0, 0, 0];
        }else if(tokenCount < 5001){
            payoutDistribution = [178000, 100500, 47400, 30400, 24700, 15500, 15000, 12000, 10200, 7800, 7400, 5500, 3300, 2000, 1500, 1200, 900, 670, 0, 0, 0];
        }else if(tokenCount < 10001){
            payoutDistribution = [157600, 86500, 39000, 23100, 18900, 15000, 14000, 11000, 9300, 6100, 6000, 5000, 3800, 1500, 1100, 900, 700, 500, 360, 0, 0];
        }else if(tokenCount < 25001){
            payoutDistribution = [132500, 70200, 31300, 18500, 17500, 14000, 13500, 10500, 7500, 5500, 5000, 4000, 3000, 1000, 900, 700, 600, 400, 200, 152, 0];
        } else {
            payoutDistribution = [120000, 63000,  27000, 18800, 17300, 13700, 13000, 10000, 6300, 5000, 4500, 3900, 2500, 900, 800, 600, 500, 350, 150, 100, 70];
        }
	}

	function getSuperiorQuota(uint256 tokenCount) external pure returns (uint16 superiorQuota){

		if(tokenCount < 101){
            superiorQuota = 10;
        }else if(tokenCount < 201){
            superiorQuota = 20;
        }else if(tokenCount < 301){
            superiorQuota = 30;
        }else if(tokenCount < 501){
            superiorQuota = 50;
        }else if(tokenCount < 1001){
            superiorQuota = 100;
        }else if(tokenCount < 2001){
            superiorQuota = 200;
        }else if(tokenCount < 3001){
            superiorQuota = 300;
        }else if(tokenCount < 5001){
            superiorQuota = 500;
        }else if(tokenCount < 10001){
            superiorQuota = 1000;
        }else if(tokenCount < 25001){
            superiorQuota = 2500;
        } else {
            superiorQuota = 5000;
        }
	}

}

// File: contracts/game/GameRegistry.sol

contract GameRegistry is CryptocupStorage, TicketRegistry{
	
    using PointsCalculator for PointsCalculator.MatchResult;
    using PointsCalculator for PointsCalculator.BonusMatch;
    using PointsCalculator for PointsCalculator.Extras;

     /**
    * @dev Checks if pValidationState is in the provided stats
    * @param state State required to run
    */
    modifier checkState(pointsValidationState state){
        require(pValidationState == state, "Points validation stage invalid.");
        _;
    }
    
    /**
    * @notice Gets current token price 
    */
    function _getTokenPrice() internal view returns(uint256 tokenPrice){

        if (now >= FIRST_PHASE) {
            tokenPrice = (80 finney);
        } else {
            tokenPrice = STARTING_PRICE;
        }

        require(tokenPrice >= STARTING_PRICE && tokenPrice <= (80 finney));

    }

    function _prepareMatchResultsArray() internal {
        matchResults.length = MATCHES_NUMBER;
    }

    function _prepareBonusResultsArray() internal {
        bonusMatches.length = BONUS_MATCHES;
    }

    /** 
    * @notice Builds ERC721 token with the predictions provided by the user.
    * @param matches  - Matches results (who wins, amount of points)
    * @param bonusMatches -  Stats from bonus matches
    * @param extraStats - Total number of extra stats like touchdonws, etc.
    * @dev An automatic timestamp is added for internal use.
    */
    function _createToken(uint160 matches, uint32 bonusMatches, uint96 extraStats, string userMessage) internal returns (uint256){

        Token memory token = Token({
            matches: matches,
            bonusMatches: bonusMatches,
            extraStats: extraStats,
            timeStamp: uint64(now),
            message: userMessage
        });

        uint256 tokenId = tokens.push(token) - 1;
        require(tokenId == uint256(uint32(tokenId)), "Failed to convert tokenId to uint256.");
        
        return tokenId;
    }

    /**
    * @dev Sets the data source contract address 
    * @param _address Address to be set
    */
    function setDataSourceAddress(address _address) external onlyAdmin {
        
        DataSourceInterface c = DataSourceInterface(_address);

        require(c.isDataSource());

        dataSource = c;
        dataSourceAddress = _address;
    }


    /**
    * @notice Called by the development team once the World Cup has ended (adminPool is set) 
    * @dev Allows dev team to retrieve adminPool
    */
    function adminWithdrawBalance() external onlyAdmin {

        uint256 adminPrize = adminPool;

        adminPool = 0;
        adminAddress.transfer(adminPrize);

    }


     /**
    * @notice Let the admin cash-out the entire contract balance 10 days after game has finished.
    */
    function finishedGameWithdraw() external onlyAdmin hasFinished{

        uint256 balance = address(this).balance;
        adminAddress.transfer(balance);

    }
    
    /**
    * @notice Let the admin cash-out the entire contract balance 10 days after game has finished.
    */
    function emergencyWithdrawAdmin() external hasFinalized onlyAdmin{

        require(finalizedTime != 0 &&  now >= finalizedTime + 10 days );
        msg.sender.transfer(address(this).balance);

    }


    function isDataSourceCallback() external pure returns (bool){
        return true;
    }

    function dataSourceGetMatchesResults() external onlyAdmin {
        dataSource.getMatchResults();
    }

    function dataSourceGetBonusResults() external onlyAdmin{
        dataSource.getBonusResults();
    }

    function dataSourceGetExtraStats() external onlyAdmin{
        dataSource.getExtraStats();
    }

    function dataSourceCallbackMatch(uint160 matches) external onlyDataSource{
        uint160 m = matches;
        for(uint256 i = 0; i < MATCHES_NUMBER; i++) {
            matchResults[MATCHES_NUMBER - i - 1].result = uint8(m & MATCH_RESULT_MASK);
            matchResults[MATCHES_NUMBER - i - 1].under49 = uint8((m >> 2) & MATCH_UNDEROVER_MASK);
            matchResults[MATCHES_NUMBER - i - 1].touchdowns = uint8((m >> 3) & MATCH_TOUCHDOWNS_MASK);
            m = m >> 8;
        }
    }

    function dataSourceCallbackBonus(uint32 bonusResults) external onlyDataSource{
        uint32 b = bonusResults;
        for(uint256 i = 0; i < BONUS_MATCHES; i++) {
            bonusMatches[BONUS_MATCHES - i - 1].bonus = uint8(b & BONUS_STAT_MASK);
            b = b >> 6;
        }
    }

    function dataSourceCallbackExtras(uint96 es) external onlyDataSource{
        uint96 e = es;
        extraStats.interceptions = uint16(e & EXTRA_STATS_MASK);
        e = e >> 16;
        extraStats.missedFieldGoals = uint16(e & EXTRA_STATS_MASK);
        e = e >> 16;
        extraStats.overtimes = uint16(e & EXTRA_STATS_MASK);
        e = e >> 16;
        extraStats.sacks = uint16(e & EXTRA_STATS_MASK);
        e = e >> 16;
        extraStats.fieldGoals = uint16(e & EXTRA_STATS_MASK);
        e = e >> 16;
        extraStats.fumbles = uint16(e & EXTRA_STATS_MASK);
    }

    /**
    * @notice Sets the points of all the tokens between the last chunk set and the amount given.
    * @dev This function uses all the data collected earlier by oraclize to calculate points.
    * @param amount The amount of tokens that should be analyzed.
    */
    function calculatePointsBlock(uint32 amount) external{

        require (gameFinishedTime == 0);
        require(amount + lastCheckedToken <= tokens.length);

        for (uint256 i = lastCalculatedToken; i < (lastCalculatedToken + amount); i++) {
            uint16 points = PointsCalculator.calculateTokenPoints(tokens[i].matches, tokens[i].bonusMatches,
                tokens[i].extraStats, matchResults, extraStats, bonusMatches, starMatches);
            tokenToPointsMap[i] = points;
        }

        lastCalculatedToken += amount;
    }

    /**
    * @notice Sets the structures for payout distribution, last position and superior quota. Payout distribution is the
    * percentage of the pot each position gets, last position is the percentage of the pot the last position gets,
    * and superior quota is the total amount OF winners that are given a prize.
    * @dev Each of this structures is dynamic and is assigned depending on the total amount of tokens in the game  
    */
    function setPayoutDistributionId () internal {

        uint24[21] memory auxArr = PayoutDistribution.getDistribution(tokens.length);

        for(uint256 i = 0; i < auxArr.length; i++){
            payoutDistribution[i] = auxArr[i];
        }
        
        superiorQuota = PayoutDistribution.getSuperiorQuota(tokens.length);
    }

    /**
    * @notice Sets the id of the last token that will be given a prize.
    * @dev This is done to offload some of the calculations needed for sorting, and to cap the number of sorts
    * needed to just the winners and not the whole array of tokens.
    * @param tokenId last token id
    */
    function setLimit(uint256 tokenId) external onlyAdmin{
        require(tokenId < tokens.length);
        require(pValidationState == pointsValidationState.Unstarted || pValidationState == pointsValidationState.LimitSet);
        pointsLimit = tokenId;
        pValidationState = pointsValidationState.LimitSet;
        lastCheckedToken = 0;
        lastCalculatedToken = 0;
        winnerCounter = 0;
        
        setPause();
        setPayoutDistributionId();
    }


    /**
    * @notice Sets the 10th percentile of the sorted array of points
    * @param amount tokens in a chunk
    */
    function calculateWinners(uint32 amount) external onlyAdmin checkState(pointsValidationState.LimitSet){
        require(amount + lastCheckedToken <= tokens.length);
        uint256 points = tokenToPointsMap[pointsLimit];

        for(uint256 i = lastCheckedToken; i < lastCheckedToken + amount; i++){
            if(tokenToPointsMap[i] > points ||
                (tokenToPointsMap[i] == points && i <= pointsLimit)){
                winnerCounter++;
            }
        }
        lastCheckedToken += amount;

        if(lastCheckedToken == tokens.length){
            require(superiorQuota == winnerCounter);
            pValidationState = pointsValidationState.LimitCalculated;
        }
    }

    /**
    * @notice Checks if the order given offchain coincides with the order of the actual previously calculated points
    * in the smart contract.
    * @dev the token sorting is done offchain so as to save on the huge amount of gas and complications that 
    * could occur from doing all the sorting onchain.
    * @param sortedChunk chunk sorted by points
    */
    function checkOrder(uint32[] sortedChunk) external onlyAdmin checkState(pointsValidationState.LimitCalculated){
        require(sortedChunk.length + sortedWinners.length <= winnerCounter);

        for(uint256 i = 0; i < sortedChunk.length - 1; i++){
            uint256 id = sortedChunk[i];
            uint256 sigId = sortedChunk[i+1];
            require(tokenToPointsMap[id] > tokenToPointsMap[sigId] || (tokenToPointsMap[id] == tokenToPointsMap[sigId] &&
                id < sigId));
        }

        if(sortedWinners.length != 0){
            uint256 id2 = sortedWinners[sortedWinners.length-1];
            uint256 sigId2 = sortedChunk[0];
            require(tokenToPointsMap[id2] > tokenToPointsMap[sigId2] ||
                (tokenToPointsMap[id2] == tokenToPointsMap[sigId2] && id2 < sigId2));
        }

        for(uint256 j = 0; j < sortedChunk.length; j++){
            sortedWinners.push(sortedChunk[j]);
        }

        if(sortedWinners.length == winnerCounter){
            require(sortedWinners[sortedWinners.length-1] == pointsLimit);
            pValidationState = pointsValidationState.OrderChecked;
        }

    }

    /**
    * @notice If anything during the point calculation and sorting part should fail, this function can reset 
    * data structures to their initial position, so as to  
    */
    function resetWinners(uint256 newLength) external onlyAdmin checkState(pointsValidationState.LimitCalculated){
        
        sortedWinners.length = newLength;
    
    }

    /**
    * @notice Assigns prize percentage for the lucky top 30 winners. Each token will be assigned a uint256 inside
    * tokenToPayoutMap structure that represents the size of the pot that belongs to that token. If any tokens
    * tie inside of the first 30 tokens, the prize will be summed and divided equally. 
    */
    function setTopWinnerPrizes() external onlyAdmin checkState(pointsValidationState.OrderChecked){

        uint256 percent = 0;
        uint[] memory tokensEquals = new uint[](30);
        uint16 tokenEqualsCounter = 0;
        uint256 currentTokenId;
        uint256 currentTokenPoints;
        uint256 lastTokenPoints;
        uint32 counter = 0;
        uint256 maxRange = 13;
        if(tokens.length < 201){
            maxRange = 10;
        }
        

        while(payoutRange < maxRange){
            uint256 inRangecounter = payDistributionAmount[payoutRange];
            while(inRangecounter > 0){
                currentTokenId = sortedWinners[counter];
                currentTokenPoints = tokenToPointsMap[currentTokenId];

                inRangecounter--;

                //Special case for the last one
                if(inRangecounter == 0 && payoutRange == maxRange - 1){
                    if(currentTokenPoints == lastTokenPoints){
                        percent += payoutDistribution[payoutRange];
                        tokensEquals[tokenEqualsCounter] = currentTokenId;
                        tokenEqualsCounter++;
                    } else {
                        tokenToPayoutMap[currentTokenId] = payoutDistribution[payoutRange];
                    }
                }

                //Fix second condition
                if(counter != 0 && (currentTokenPoints != lastTokenPoints || (inRangecounter == 0 && payoutRange == maxRange - 1))){ 
                    for(uint256 i = 0; i < tokenEqualsCounter; i++){
                        tokenToPayoutMap[tokensEquals[i]] = percent.div(tokenEqualsCounter);
                    }
                    percent = 0;
                    tokensEquals = new uint[](30);
                    tokenEqualsCounter = 0;
                }

                percent += payoutDistribution[payoutRange];
                tokensEquals[tokenEqualsCounter] = currentTokenId;
                
                tokenEqualsCounter++;
                counter++;

                lastTokenPoints = currentTokenPoints;
            }
            payoutRange++;
        }

        pValidationState = pointsValidationState.TopWinnersAssigned;
        lastPrizeGiven = counter;
    }

    /**
    * @notice Sets prize percentage to every address that wins from the position 30th onwards
    * @dev If there are less than 300 tokens playing, then this function will set nothing.
    * @param amount tokens in a chunk
    */
    function setWinnerPrizes(uint32 amount) external onlyAdmin checkState(pointsValidationState.TopWinnersAssigned){
        require(lastPrizeGiven + amount <= winnerCounter);
        
        uint16 inRangeCounter = payDistributionAmount[payoutRange];
        for(uint256 i = 0; i < amount; i++){
            if (inRangeCounter == 0){
                payoutRange++;
                inRangeCounter = payDistributionAmount[payoutRange];
            }

            uint256 tokenId = sortedWinners[i + lastPrizeGiven];

            tokenToPayoutMap[tokenId] = payoutDistribution[payoutRange];

            inRangeCounter--;
        }
        //i + amount prize was not given yet, so amount -1
        lastPrizeGiven += amount;
        payDistributionAmount[payoutRange] = inRangeCounter;

        if(lastPrizeGiven == winnerCounter){
            pValidationState = pointsValidationState.WinnersAssigned;
            return;
        }
    }


     /**
    * @notice Sets prizes for last tokens and sets prize pool amount
    */
    function setEnd() external onlyAdmin checkState(pointsValidationState.WinnersAssigned){
            
        uint256 balance = address(this).balance;
        adminPool = balance.mul(10).div(100);
        prizePool = balance.mul(90).div(100);

        pValidationState = pointsValidationState.Finished;
        gameFinishedTime = now;
        unSetPause();
    }

}

// File: contracts/CryptocupNFL.sol

contract CryptocupNFL is GameRegistry {

	constructor() public {
        adminAddress = msg.sender;
        deploymentTime = now;

        _prepareMatchResultsArray();
        _prepareBonusResultsArray();
    }

     /** 
    * @dev Only accept eth from the admin
    */
    function() external payable {
        require(msg.sender == adminAddress || msg.sender == marketplaceAddress);

    }

    function buildToken(uint160 matches, uint32 bonusMatches, uint96 extraStats, string message) external payable isNotPaused returns(uint256){

        require(msg.value >= _getTokenPrice(), "Eth sent is not enough.");
        require(msg.sender != address(0), "Sender cannot be 0 address.");
        require(ownedTokens[msg.sender].length < 100, "Sender cannot have more than 100 tokens.");
        require(now < EVENT_START, "Event already started."); //Event Start
        require (bytes(message).length <= 100);
        

        uint256 tokenId = _createToken(matches, bonusMatches, extraStats, message);
        
        _mint(msg.sender, tokenId);
        
        emit LogTokenBuilt(msg.sender, tokenId, message, matches, extraStats, bonusMatches);

        return tokenId;
    }

    function giftToken(address giftedAddress, uint160 matches, uint32 bonusMatches, uint96 extraStats, string message) external payable isNotPaused returns(uint256){

        require(msg.value >= _getTokenPrice(), "Eth sent is not enough.");
        require(msg.sender != address(0), "Sender cannot be 0 address.");
        require(ownedTokens[giftedAddress].length < 100, "Sender cannot have more than 100 tokens.");
        require(now < EVENT_START, "Event already started."); //Event Start
        require (bytes(message).length <= 100);

        uint256 tokenId = _createToken(matches, bonusMatches, extraStats, message);

        _mint(giftedAddress, tokenId);
        
        emit LogTokenGift(msg.sender, giftedAddress, tokenId, message, matches, extraStats, bonusMatches);

        return tokenId;
    }

    function buildPrepaidToken(bytes32 secret) external payable onlyAdmin isNotPaused {

        require(msg.value >= _getTokenPrice(), "Eth sent is not enough.");
        require(msg.sender != address(0), "Sender cannot be 0 address.");
        require(now < EVENT_START, "Event already started."); //Event Start

        secretsMap[secret] = 1;
        
        emit LogPrepaidTokenBuilt(msg.sender, secret);
    }

    function redeemPrepaidToken(bytes32 preSecret, uint160 matches, uint32 bonusMatches, uint96 extraStats, string message) external isNotPaused returns(uint256){

        require(msg.sender != address(0), "Sender cannot be 0 address.");
        require(ownedTokens[msg.sender].length < 100, "Sender cannot have more than 100 tokens.");
        require(now < EVENT_START, "Event already started."); //Event Start
        require (bytes(message).length <= 100);

        bytes32 secret = keccak256(preSecret);

        require (secretsMap[secret] == 1, "Invalid secret.");
        
        secretsMap[secret] = 0;

        uint256 tokenId = _createToken(matches, bonusMatches, extraStats, message);
        _mint(msg.sender, tokenId);
        
        emit LogPrepaidRedeemed(msg.sender, tokenId, message, matches, extraStats, bonusMatches);

        return tokenId;
    }


    /** 
    * @param tokenId - ID of token to get.
    * @return Returns all the valuable information about a specific token.
    */
    function getToken(uint256 tokenId) external view returns (uint160 matches, uint32 bonusMatches, uint96 extraStats, uint64 timeStamp, string message) {

        Token storage token = tokens[tokenId];

        matches = token.matches;
        bonusMatches = token.bonusMatches;
        extraStats = token.extraStats;
        timeStamp = token.timeStamp;
        message = token.message;

    }

    /**
    * @notice Allows any user to retrieve their asigned prize. This would be the sum of the price of all the tokens
    * owned by the caller of this function.
    * @dev If the caller has no prize, the function will revert costing no gas to the caller.
    */
    function withdrawPrize() external checkState(pointsValidationState.Finished){
        
        uint256 prize = 0;
        uint256[] memory tokenList = ownedTokens[msg.sender];
        
        for(uint256 i = 0;i < tokenList.length; i++){
            prize += tokenToPayoutMap[tokenList[i]];
            tokenToPayoutMap[tokenList[i]] = 0;
        }
        
        require(prize > 0);
        msg.sender.transfer((prizePool.mul(prize)).div(1000000));   
    }


    //EMERGENCY CALLS
    //If something goes wrong or fails, these functions will allow retribution for token holders 

    /**
    * @notice if there is an unresolvable problem, users can call to this function to get a refund.
    */
    function emergencyWithdraw() external hasFinalized{

        uint256 balance = STARTING_PRICE * ownedTokens[msg.sender].length;

        delete ownedTokens[msg.sender];
        msg.sender.transfer(balance);

    }

}

Contract Security Audit

Contract ABI

[{"constant":true,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_tokenId","type":"uint256"}],"name":"approve","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"operatorApprovals","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"dataSourceGetBonusResults","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"tokenOwner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"dataSourceGetExtraStats","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"state","type":"bool"}],"name":"setFinalized","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"secretsMap","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"tokenId","type":"uint256"}],"name":"setLimit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"amount","type":"uint32"}],"name":"calculateWinners","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"tokenToPayoutMap","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_address","type":"address"}],"name":"setDataSourceAddress","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"tokenToPointsMap","outputs":[{"name":"","type":"uint16"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"withdrawPrize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"exists","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"matches","type":"uint160"}],"name":"dataSourceCallbackMatch","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"isDataSourceCallback","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[],"name":"setTopWinnerPrizes","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"preSecret","type":"bytes32"},{"name":"matches","type":"uint160"},{"name":"bonusMatches","type":"uint32"},{"name":"extraStats","type":"uint96"},{"name":"message","type":"string"}],"name":"redeemPrepaidToken","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"paused","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newLength","type":"uint256"}],"name":"resetWinners","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"sortedChunk","type":"uint32[]"}],"name":"checkOrder","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_newAdmin","type":"address"}],"name":"setAdmin","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"matches","type":"uint160"},{"name":"bonusMatches","type":"uint32"},{"name":"extraStats","type":"uint96"},{"name":"message","type":"string"}],"name":"buildToken","outputs":[{"name":"","type":"uint256"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"prizePool","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"setEnd","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"pValidationState","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"es","type":"uint96"}],"name":"dataSourceCallbackExtras","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"amount","type":"uint32"}],"name":"setWinnerPrizes","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"emergencyWithdrawAdmin","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"bonusResults","type":"uint32"}],"name":"dataSourceCallbackBonus","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"tokenApprovals","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"finalized","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"finishedGameWithdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"amount","type":"uint32"}],"name":"calculatePointsBlock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_newMkt","type":"address"}],"name":"setMarketplaceAddress","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"adminPool","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_tokenId","type":"uint256"},{"name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"giftedAddress","type":"address"},{"name":"matches","type":"uint160"},{"name":"bonusMatches","type":"uint32"},{"name":"extraStats","type":"uint96"},{"name":"message","type":"string"}],"name":"giftToken","outputs":[{"name":"","type":"uint256"}],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"state","type":"bool"}],"name":"setPauseState","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"dataSourceAddress","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"dataSourceGetMatchesResults","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"secret","type":"bytes32"}],"name":"buildPrepaidToken","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"_from","type":"address"}],"name":"getOwnedTokens","outputs":[{"name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"marketplaceAddress","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"emergencyWithdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"tokenId","type":"uint256"}],"name":"getToken","outputs":[{"name":"matches","type":"uint160"},{"name":"bonusMatches","type":"uint32"},{"name":"extraStats","type":"uint96"},{"name":"timeStamp","type":"uint64"},{"name":"message","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"bonusMatches","outputs":[{"name":"bonus","type":"uint16"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"matchResults","outputs":[{"name":"result","type":"uint8"},{"name":"under49","type":"uint8"},{"name":"touchdowns","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"adminAddress","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"extraStats","outputs":[{"name":"interceptions","type":"uint16"},{"name":"missedFieldGoals","type":"uint16"},{"name":"overtimes","type":"uint16"},{"name":"sacks","type":"uint16"},{"name":"fieldGoals","type":"uint16"},{"name":"fumbles","type":"uint16"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"adminWithdrawBalance","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"finalizedTime","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"gameFinishedTime","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":true,"name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"approved","type":"address"},{"indexed":true,"name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"operator","type":"address"},{"indexed":false,"name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"creatorAddress","type":"address"},{"indexed":false,"name":"tokenId","type":"uint256"},{"indexed":false,"name":"message","type":"string"},{"indexed":false,"name":"m","type":"uint160"},{"indexed":false,"name":"e","type":"uint96"},{"indexed":false,"name":"b","type":"uint32"}],"name":"LogTokenBuilt","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"creatorAddress","type":"address"},{"indexed":false,"name":"giftedAddress","type":"address"},{"indexed":false,"name":"tokenId","type":"uint256"},{"indexed":false,"name":"message","type":"string"},{"indexed":false,"name":"m","type":"uint160"},{"indexed":false,"name":"e","type":"uint96"},{"indexed":false,"name":"b","type":"uint32"}],"name":"LogTokenGift","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"creatorAddress","type":"address"},{"indexed":false,"name":"secret","type":"bytes32"}],"name":"LogPrepaidTokenBuilt","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"redeemer","type":"address"},{"indexed":false,"name":"tokenId","type":"uint256"},{"indexed":false,"name":"message","type":"string"},{"indexed":false,"name":"m","type":"uint160"},{"indexed":false,"name":"e","type":"uint96"},{"indexed":false,"name":"b","type":"uint32"}],"name":"LogPrepaidRedeemed","type":"event"}]

6103006040526000608081815260a082905260c082905260e082905261010082905261012082905260016101408190526101608390526101808390526101a08390526101c08390526101e08390526102008190526102208390526102408390526102608390526102808390526102a08390526102c0526102e0829052620000899190601462000208565b506000600181815560028290556007805460a060020a60ff021916905560089190915560098054600160c060020a0319169055604080516102a08101825282815260208101839052908101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081019190915260056101408201819052610160820152600a610180820181905260146101a083015260326101c083015260646101e0830181905261020083015260c86102208301526101f46102408301526105dc6102608301526109c461028083015262000175916015620002b4565b506017805461ffff191690556000601a819055601b819055601c553480156200019d57600080fd5b50601780546201000060b060020a03191633620100000217905542601a55620001ce640100000000620001e7810204565b620001e1640100000000620001f9810204565b6200041c565b6014620001f6600f8262000360565b50565b6005620001f66010826200038c565b82805482825590600052602060002090601f01602090048101928215620002a25791602002820160005b838211156200027157835183826101000a81548160ff021916908315150217905550926020019260010160208160000104928301926001030262000232565b8015620002a05782816101000a81549060ff021916905560010160208160000104928301926001030262000271565b505b50620002b0929150620003b3565b5090565b82805482825590600052602060002090600f01601090048101928215620003525791602002820160005b838211156200032057835183826101000a81548161ffff021916908361ffff1602179055509260200192600201602081600101049283019260010302620002de565b8015620003505782816101000a81549061ffff021916905560020160208160010104928301926001030262000320565b505b50620002b0929150620003d7565b815481835581811115620003875760008381526020902062000387918101908301620003f9565b505050565b815481835581811115620003875760008381526020902062000387918101908301620003d7565b620003d491905b80821115620002b057805460ff19168155600101620003ba565b90565b620003d491905b80821115620002b057805461ffff19168155600101620003de565b620003d491905b80821115620002b057805462ffffff1916815560010162000400565b614606806200042c6000396000f3006080604052600436106102b05763ffffffff60e060020a600035041663081812fc81146102e6578063095ea7b31461031a5780630d95e0541461033e5780630fe081ea146103795780631caaa4871461038e5780632065b966146103a657806320b27291146103bb578063237bcb2d146103d557806323b872dd1461040357806327ea6f2b1461042d578063299e7abb146104455780632cdc078d146104635780633a1fc7621461048d57806342842e0e146104ae57806345b95aa7146104d857806348d37a58146105075780634f558e791461051c5780634feb22d014610534578063582b6add146105555780635a2a30391461056a5780635bd34b601461057f5780635c975abb146105cc5780635dedd9cc146105e15780636352211e146105f957806363e561b614610611578063704b6c021461063157806370a0823114610652578063716dba9e14610673578063719ce73e146106af578063746a3aa8146106c4578063810a217f146106d95780638857179a1461071257806388fdf3d4146107385780638f75362d14610756578063a22cb4651461076b578063a72841ee14610791578063acdeb5b9146107af578063b3f05b97146107c7578063b3f50029146107dc578063b427c148146107f1578063b47cc5561461080f578063b86a1fb214610830578063b88d4fde14610845578063bf60c386146108b4578063cdb88ad1146108f8578063d5a3b73414610912578063d5b92d0814610927578063d9ac31fe1461093c578063d9d6165514610947578063daa17f49146109b8578063db2e21bc146109cd578063e4b50cb8146109e2578063e985e9c514610adc578063eb941fec14610b03578063f17b342814610b1b578063fc6f946814610b58578063fcef338614610b6d578063fdf061f014610bc0578063fe67a18914610bd5578063fefaa62614610bea575b601754620100009004600160a060020a03163314806102d95750601954600160a060020a031633145b15156102e457600080fd5b005b3480156102f257600080fd5b506102fe600435610bff565b60408051600160a060020a039092168252519081900360200190f35b34801561032657600080fd5b506102e4600160a060020a0360043516602435610c1a565b34801561034a57600080fd5b50610365600160a060020a0360043581169060243516610cc3565b604080519115158252519081900360200190f35b34801561038557600080fd5b506102e4610ce3565b34801561039a57600080fd5b506102fe600435610da6565b3480156103b257600080fd5b506102e4610dc1565b3480156103c757600080fd5b506102e46004351515610e6a565b3480156103e157600080fd5b506103ed600435610ef5565b6040805160ff9092168252519081900360200190f35b34801561040f57600080fd5b506102e4600160a060020a0360043581169060243516604435610f0a565b34801561043957600080fd5b506102e460043561100f565b34801561045157600080fd5b506102e463ffffffff600435166110fb565b34801561046f57600080fd5b5061047b600435611352565b60408051918252519081900360200190f35b34801561049957600080fd5b506102e4600160a060020a0360043516611364565b3480156104ba57600080fd5b506102e4600160a060020a0360043581169060243516604435611466565b3480156104e457600080fd5b506104f0600435611487565b6040805161ffff9092168252519081900360200190f35b34801561051357600080fd5b506102e461149d565b34801561052857600080fd5b50610365600435611647565b34801561054057600080fd5b506102e4600160a060020a0360043516611664565b34801561056157600080fd5b506103656117c9565b34801561057657600080fd5b506102e46117cf565b34801561058b57600080fd5b5061047b600480359060248035600160a060020a03169160443563ffffffff16916064356bffffffffffffffffffffffff1691608435918201910135611c50565b3480156105d857600080fd5b50610365611f51565b3480156105ed57600080fd5b506102e4600435611f5a565b34801561060557600080fd5b506102fe60043561201a565b34801561061d57600080fd5b506102e46004803560248101910135612044565b34801561063d57600080fd5b506102e4600160a060020a0360043516612375565b34801561065e57600080fd5b5061047b600160a060020a0360043516612417565b61047b60048035600160a060020a0316906024803563ffffffff16916044356bffffffffffffffffffffffff169160643590810191013561244a565b3480156106bb57600080fd5b5061047b61270f565b3480156106d057600080fd5b506102e4612715565b3480156106e557600080fd5b506106ee612839565b604051808260068111156106fe57fe5b60ff16815260200191505060405180910390f35b34801561071e57600080fd5b506102e46bffffffffffffffffffffffff60043516612849565b34801561074457600080fd5b506102e463ffffffff6004351661297b565b34801561076257600080fd5b506102e4612ca6565b34801561077757600080fd5b506102e4600160a060020a03600435166024351515612dad565b34801561079d57600080fd5b506102e463ffffffff60043516612e31565b3480156107bb57600080fd5b506102fe600435612efb565b3480156107d357600080fd5b50610365612f16565b3480156107e857600080fd5b506102e4612f24565b3480156107fd57600080fd5b506102e463ffffffff6004351661302d565b34801561081b57600080fd5b506102e4600160a060020a03600435166132ad565b34801561083c57600080fd5b5061047b61333a565b34801561085157600080fd5b50604080516020601f6064356004818101359283018490048402850184019095528184526102e494600160a060020a0381358116956024803590921695604435953695608494019181908401838280828437509497506133409650505050505050565b61047b600160a060020a0360048035821691602480359091169163ffffffff60443516916bffffffffffffffffffffffff606435169160843591820191013561334b565b34801561090457600080fd5b506102e46004351515613625565b34801561091e57600080fd5b506102fe61368e565b34801561093357600080fd5b506102e461369d565b6102e4600435613746565b34801561095357600080fd5b50610968600160a060020a036004351661392a565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156109a457818101518382015260200161098c565b505050509050019250505060405180910390f35b3480156109c457600080fd5b506102fe613996565b3480156109d957600080fd5b506102e46139a5565b3480156109ee57600080fd5b506109fa600435613a5c565b6040518086600160a060020a0316600160a060020a031681526020018563ffffffff1663ffffffff168152602001846bffffffffffffffffffffffff166bffffffffffffffffffffffff1681526020018367ffffffffffffffff1667ffffffffffffffff16815260200180602001828103825283818151815260200191508051906020019080838360005b83811015610a9d578181015183820152602001610a85565b50505050905090810190601f168015610aca5780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390f35b348015610ae857600080fd5b50610365600160a060020a0360043581169060243516613b76565b348015610b0f57600080fd5b506104f0600435613ba4565b348015610b2757600080fd5b50610b33600435613bc7565b6040805160ff9485168152928416602084015292168183015290519081900360600190f35b348015610b6457600080fd5b506102fe613bfa565b348015610b7957600080fd5b50610b82613c0f565b6040805161ffff978816815295871660208701529386168585015291851660608501528416608084015290921660a082015290519081900360c00190f35b348015610bcc57600080fd5b506102e4613c5b565b348015610be157600080fd5b5061047b613cff565b348015610bf657600080fd5b5061047b613d05565b600090815260146020526040902054600160a060020a031690565b6000610c258261201a565b9050600160a060020a038381169082161415610c4057600080fd5b33600160a060020a0382161480610c5c5750610c5c8133613b76565b1515610c6757600080fd5b6000828152601460205260408082208054600160a060020a031916600160a060020a0387811691821790925591518593918516917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591a4505050565b601660209081526000928352604080842090915290825290205460ff1681565b601754620100009004600160a060020a03163314610d39576040805160e560020a62461bcd02815260206004820152600b602482015260008051602061455b833981519152604482015290519081900360640190fd5b600760009054906101000a9004600160a060020a0316600160a060020a031663cadc027b6040518163ffffffff1660e060020a028152600401600060405180830381600087803b158015610d8c57600080fd5b505af1158015610da0573d6000803e3d6000fd5b50505050565b601360205260009081526040902054600160a060020a031681565b601754620100009004600160a060020a03163314610e17576040805160e560020a62461bcd02815260206004820152600b602482015260008051602061455b833981519152604482015290519081900360640190fd5b600760009054906101000a9004600160a060020a0316600160a060020a03166337dfffcc6040518163ffffffff1660e060020a028152600401600060405180830381600087803b158015610d8c57600080fd5b601754620100009004600160a060020a03163314610ec0576040805160e560020a62461bcd02815260206004820152600b602482015260008051602061455b833981519152604482015290519081900360640190fd5b6017805460ff191682151590811761ff001916610100918202179182905560ff910416151560011415610ef25742601c555b50565b60056020526000908152604090205460ff1681565b60175460ff1615610f53576040805160e560020a62461bcd02815260206004820152601360248201526000805160206145bb833981519152604482015290519081900360640190fd5b610f5d3382613d0b565b1515610f6857600080fd5b600160a060020a0383161515610f7d57600080fd5b600160a060020a0382161515610f9257600080fd5b600160a060020a038381169083161415610fab57600080fd5b610fb58382613d6a565b610fbf8382613dcc565b610fc98282613ee6565b8082600160a060020a031684600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b601754620100009004600160a060020a03163314611065576040805160e560020a62461bcd02815260206004820152600b602482015260008051602061455b833981519152604482015290519081900360640190fd5b601254811061107357600080fd5b600060075460a060020a900460ff16600681111561108d57fe5b14806110b05750600160075460a060020a900460ff1660068111156110ae57fe5b145b15156110bb57600080fd5b60088190556007805460a060020a60ff02191660a060020a179055600980546bffffffffffffffffffffffff191690556110f3613f54565b610ef2613f63565b6017546000908190620100009004600160a060020a03163314611156576040805160e560020a62461bcd02815260206004820152600b602482015260008051602061455b833981519152604482015290519081900360640190fd5b60018060075460a060020a900460ff16600681111561117157fe5b146111b4576040805160e560020a62461bcd028152602060048201819052602482015260008051602061459b833981519152604482015290519081900360640190fd5b60125460095463ffffffff640100000000909104811686011611156111d857600080fd5b60085460009081526003602052604090205460095461ffff9091169350640100000000900463ffffffff1691505b60095463ffffffff64010000000090910481168501168210156112a65760008281526003602052604090205461ffff16831080611261575060008281526003602052604090205461ffff168314801561126157506008548211155b1561129b5760098054600163ffffffff6801000000000000000080840482169290920116026bffffffff0000000000000000199091161790555b600190910190611206565b6009805463ffffffff640100000000808304821688018216810267ffffffff00000000199093169290921792839055601254919092049091161415610da05760095468010000000000000000810463ffffffff16780100000000000000000000000000000000000000000000000090910461ffff161461132557600080fd5b50506007805460a060020a60ff021916740200000000000000000000000000000000000000001790555050565b60046020526000908152604090205481565b601754600090620100009004600160a060020a031633146113bd576040805160e560020a62461bcd02815260206004820152600b602482015260008051602061455b833981519152604482015290519081900360640190fd5b81905080600160a060020a031663037a9d306040518163ffffffff1660e060020a028152600401602060405180830381600087803b1580156113fe57600080fd5b505af1158015611412573d6000803e3d6000fd5b505050506040513d602081101561142857600080fd5b5051151561143557600080fd5b60078054600160a060020a03928316600160a060020a03199182161790915560188054939092169216919091179055565b6114828383836020604051908101604052806000815250613340565b505050565b60036020526000908152604090205461ffff1681565b600060608160068060075460a060020a900460ff1660068111156114bd57fe5b14611500576040805160e560020a62461bcd028152602060048201819052602482015260008051602061459b833981519152604482015290519081900360640190fd5b33600090815260156020908152604080832080548251818502810185019093528083529397509092909183018282801561155957602002820191906000526020600020905b815481526020019060010190808311611545575b50505050509250600091505b82518210156115d65760046000848481518110151561158057fe5b906020019060200201518152602001908152602001600020548401935060006004600085858151811015156115b157fe5b6020908102909101810151825281019190915260400160002055600190910190611565565b600084116115e357600080fd5b33600160a060020a03166108fc611618620f424061160c8860015461413390919063ffffffff16565b9063ffffffff61415c16565b6040518115909202916000818181858888f19350505050158015611640573d6000803e3d6000fd5b5050505050565b600090815260136020526040902054600160a060020a0316151590565b6018546000908190600160a060020a031633146116cb576040805160e560020a62461bcd02815260206004820152601060248201527f4f6e6c792064617461536f757263652e00000000000000000000000000000000604482015290519081900360640190fd5b5081905060005b601481101561148257600f80546003841691906000196014859003019081106116f757fe5b6000918252602090912001805460ff191660ff92909216919091179055600f80546004600160a060020a03851604600116919060148490036000190190811061173c57fe5b6000918252602090912001805460ff929092166101000261ff0019909216919091179055600f80546008600160a060020a03851604601f16919060001960148590030190811061178857fe5b6000918252602090912001805460ff92909216620100000262ff000019909216919091179055610100600160a060020a0390921691909104906001016116d2565b60015b90565b60006060600080600080600080600080601760029054906101000a9004600160a060020a0316600160a060020a031633600160a060020a031614151561184d576040805160e560020a62461bcd02815260206004820152600b602482015260008051602061455b833981519152604482015290519081900360640190fd5b60038060075460a060020a900460ff16600681111561186857fe5b146118ab576040805160e560020a62461bcd028152602060048201819052602482015260008051602061459b833981519152604482015290519081900360640190fd5b60408051601e8082526103e0820190925260009c5090602082016103c0803883395050601254919b5060009a508a9650600d95505060c911156118ed57600a93505b600954608060020a900463ffffffff16841115611be757600954600a80549091608060020a900463ffffffff1690811061192357fe5b60009182526020909120601082040154600f9091166002026101000a900461ffff1692505b6000831115611bab57600e805463ffffffff871690811061196557fe5b6000918252602080832090910154808352600390915260409091205490985061ffff16965060001990920191821580156119b2575060095463ffffffff608060020a909104166000198501145b15611a725785871415611a2857600954600b90608060020a900463ffffffff16601581106119dc57fe5b600a91828204019190066003029054906101000a900462ffffff1662ffffff168b019a50878a8a61ffff16815181101515611a1357fe5b60209081029091010152600190980197611a72565b600954600b90608060020a900463ffffffff1660158110611a4557fe5b600a808204929092015460008b8152600460205260409020929091066003026101000a900462ffffff1690555b63ffffffff851615801590611aad57508587141580611aad575082158015611aad575060095463ffffffff608060020a909104166000198501145b15611b3a57600091505b8861ffff16821015611b0e57611ad78b61ffff8b1663ffffffff61415c16565b600460008c85815181101515611ae957fe5b6020908102909101810151825281019190915260400160002055600190910190611ab7565b60408051601e8082526103e0820190925260009c5090602082016103c080388339019050509950600098505b600954600b90608060020a900463ffffffff1660158110611b5757fe5b600a91828204019190066003029054906101000a900462ffffff1662ffffff168b019a50878a8a61ffff16815181101515611b8e57fe5b602090810290910101526001988901988796509490940193611948565b60098054600163ffffffff608060020a808404821692909201160273ffffffff00000000000000000000000000000000199091161790556118ed565b5050600780547404000000000000000000000000000000000000000060a060020a60ff021990911617905550506009805477ffffffff0000000000000000000000000000000000000000191663ffffffff9290921660a060020a02919091179055505050505050565b6017546000908190819060ff1615611ca0576040805160e560020a62461bcd02815260206004820152601360248201526000805160206145bb833981519152604482015290519081900360640190fd5b331515611ce5576040805160e560020a62461bcd02815260206004820152601b602482015260008051602061453b833981519152604482015290519081900360640190fd5b33600090815260156020526040902054606411611d72576040805160e560020a62461bcd02815260206004820152602860248201527f53656e6465722063616e6e6f742068617665206d6f7265207468616e2031303060448201527f20746f6b656e732e000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b635bdb14f04210611dbb576040805160e560020a62461bcd028152602060048201526016602482015260008051602061457b833981519152604482015290519081900360640190fd5b6064841115611dc957600080fd5b604080518a81528151908190036020908101909120600081815260059092529190205490925060ff16600114611e49576040805160e560020a62461bcd02815260206004820152600f60248201527f496e76616c6964207365637265742e0000000000000000000000000000000000604482015290519081900360640190fd5b600082815260056020908152604091829020805460ff191690558151601f8701829004820281018201909252858252611e9c918a918a918a918a908a908190840183828082843750614171945050505050565b9050611ea83382614395565b604080513380825260208201849052600160a060020a038b1660608301526bffffffffffffffffffffffff8916608083015263ffffffff8a1660a083015260c09282018381529282018790527fcc7ceaf1ba8bfaf7a8d8aaa8f7026b92859b0a0974c9badd135b883073d4a92b9290918491899189918e918d918f919060e0820187878082843760405192018290039a509098505050505050505050a198975050505050505050565b60175460ff1681565b601754620100009004600160a060020a03163314611fb0576040805160e560020a62461bcd02815260206004820152600b602482015260008051602061455b833981519152604482015290519081900360640190fd5b60028060075460a060020a900460ff166006811115611fcb57fe5b1461200e576040805160e560020a62461bcd028152602060048201819052602482015260008051602061459b833981519152604482015290519081900360640190fd5b81611482600e82614410565b600081815260136020526040812054600160a060020a031680151561203e57600080fd5b92915050565b600080600080600080601760029054906101000a9004600160a060020a0316600160a060020a031633600160a060020a03161415156120bb576040805160e560020a62461bcd02815260206004820152600b602482015260008051602061455b833981519152604482015290519081900360640190fd5b60028060075460a060020a900460ff1660068111156120d657fe5b14612119576040805160e560020a62461bcd028152602060048201819052602482015260008051602061459b833981519152604482015290519081900360640190fd5b600954600e546801000000000000000090910463ffffffff16908901111561214057600080fd5b600096505b60001988018710156122005788888881811061215d57fe5b9050602002013563ffffffff1663ffffffff169550888888600101818110151561218357fe5b6020908102929092013563ffffffff16600081815260039093526040808420548a855293205490975061ffff9283169216919091119050806121ea57506000858152600360205260408082205488835291205461ffff90811691161480156121ea57508486105b15156121f557600080fd5b600190960195612145565b600e54156122a857600e8054600019810190811061221a57fe5b9060005260206000200154935088886000818110151561223657fe5b6020908102929092013563ffffffff166000818152600390935260408084205488855293205490955061ffff92831692169190911190508061229d57506000838152600360205260408082205486835291205461ffff908116911614801561229d57508284105b15156122a857600080fd5b600091505b878210156122f757600e8989848181106122c357fe5b835460018082018655600095865260209586902092909502939093013563ffffffff169201919091555091909101906122ad565b600954600e546801000000000000000090910463ffffffff16141561236a57600854600e8054600019810190811061232b57fe5b906000526020600020015414151561234257600080fd5b6007805460a060020a60ff021916740300000000000000000000000000000000000000001790555b505050505050505050565b601754620100009004600160a060020a031633146123cb576040805160e560020a62461bcd02815260206004820152600b602482015260008051602061455b833981519152604482015290519081900360640190fd5b600160a060020a03811615156123e057600080fd5b60178054600160a060020a03909216620100000275ffffffffffffffffffffffffffffffffffffffff000019909216919091179055565b6000600160a060020a038216151561242e57600080fd5b50600160a060020a031660009081526015602052604090205490565b601754600090819060ff1615612498576040805160e560020a62461bcd02815260206004820152601360248201526000805160206145bb833981519152604482015290519081900360640190fd5b6124a06143b4565b3410156124f7576040805160e560020a62461bcd02815260206004820152601760248201527f4574682073656e74206973206e6f7420656e6f7567682e000000000000000000604482015290519081900360640190fd5b33151561253c576040805160e560020a62461bcd02815260206004820152601b602482015260008051602061453b833981519152604482015290519081900360640190fd5b336000908152601560205260409020546064116125c9576040805160e560020a62461bcd02815260206004820152602860248201527f53656e6465722063616e6e6f742068617665206d6f7265207468616e2031303060448201527f20746f6b656e732e000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b635bdb14f04210612612576040805160e560020a62461bcd028152602060048201526016602482015260008051602061457b833981519152604482015290519081900360640190fd5b606483111561262057600080fd5b61265c87878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843750614171945050505050565b90506126683382614395565b604080513380825260208201849052600160a060020a038a1660608301526bffffffffffffffffffffffff8816608083015263ffffffff891660a083015260c09282018381529282018690527fc9b6356917c8e6595e04f058f37ae084434790be9b87f82ffe091de4fa9ae6239290918491889188918d918c918e919060e0820187878082843760405192018290039a509098505050505050505050a19695505050505050565b60015481565b601754600090620100009004600160a060020a0316331461276e576040805160e560020a62461bcd02815260206004820152600b602482015260008051602061455b833981519152604482015290519081900360640190fd5b60058060075460a060020a900460ff16600681111561278957fe5b146127cc576040805160e560020a62461bcd028152602060048201819052602482015260008051602061459b833981519152604482015290519081900360640190fd5b303191506127e6606461160c84600a63ffffffff61413316565b6002556127ff606461160c84605a63ffffffff61413316565b6001556007805460a060020a60ff0219167406000000000000000000000000000000000000000017905542601b55612835614404565b5050565b60075460a060020a900460ff1681565b601854600090600160a060020a031633146128ae576040805160e560020a62461bcd02815260206004820152601060248201527f4f6e6c792064617461536f757263652e00000000000000000000000000000000604482015290519081900360640190fd5b506011805461ffff80841661ffff199092169190911763ffff00001916620100006bffffffffffffffffffffffff94851681900483811682029290921765ffff000000001916918516819004838116640100000000029290921767ffff00000000000019169185168190048381166601000000000000029290921769ffff000000000000000019169185168190048381166801000000000000000002929092176bffff0000000000000000000019169190941693909304166a010000000000000000000002919091179055565b60175460009081908190620100009004600160a060020a031633146129d8576040805160e560020a62461bcd02815260206004820152600b602482015260008051602061455b833981519152604482015290519081900360640190fd5b60048060075460a060020a900460ff1660068111156129f357fe5b14612a36576040805160e560020a62461bcd028152602060048201819052602482015260008051602061459b833981519152604482015290519081900360640190fd5b60095463ffffffff680100000000000000008204811660a060020a90920481168701161115612a6457600080fd5b600954600a80549091608060020a900463ffffffff16908110612a8357fe5b600091825260208220601082040154600f9091166002026101000a900461ffff16945092505b8463ffffffff16831015612bc65761ffff84161515612b39576009805473ffffffff00000000000000000000000000000000198116608060020a9182900463ffffffff908116600101811683029190911792839055600a805490939290920416908110612b1257fe5b90600052602060002090601091828204019190066002029054906101000a900461ffff1693505b600954600e8054909160a060020a900463ffffffff168501908110612b5a57fe5b600091825260209091200154600954909250600b90608060020a900463ffffffff1660158110612b8657fe5b600a80820492909201546000858152600460205260409020929091066003026101000a900462ffffff169055600019939093019260019290920191612aa9565b6009805463ffffffff60a060020a8083048216890182160277ffffffff0000000000000000000000000000000000000000199092169190911791829055600a805487939192608060020a909204909116908110612c1f57fe5b6000918252602090912060108204018054600f9092166002026101000a61ffff81810219909316939092169190910291909117905560095468010000000000000000810463ffffffff90811660a060020a909204161415611640576007805460a060020a60ff02191674050000000000000000000000000000000000000000179055611640565b601754610100900460ff161515612d07576040805160e560020a62461bcd02815260206004820152601b60248201527f4f6e6c792069662067616d65206861732066696e616c697a65642e0000000000604482015290519081900360640190fd5b601754620100009004600160a060020a03163314612d5d576040805160e560020a62461bcd02815260206004820152600b602482015260008051602061455b833981519152604482015290519081900360640190fd5b601c5415801590612d755750601c54620d2f00014210155b1515612d8057600080fd5b6040513390303180156108fc02916000818181858888f19350505050158015610ef2573d6000803e3d6000fd5b600160a060020a038216331415612dc357600080fd5b336000818152601660209081526040808320600160a060020a03871680855290835292819020805460ff1916861515908117909155815190815290519293927f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31929181900390910190a35050565b6018546000908190600160a060020a03163314612e98576040805160e560020a62461bcd02815260206004820152601060248201527f4f6e6c792064617461536f757263652e00000000000000000000000000000000604482015290519081900360640190fd5b5081905060005b60058110156114825760108054603f84169190600019600585900301908110612ec457fe5b6000918252602090912001805461ffff191661ffff92909216919091179055604063ffffffff929092169190910490600101612e9f565b601460205260009081526040902054600160a060020a031681565b601754610100900460ff1681565b601754600090620100009004600160a060020a03163314612f7d576040805160e560020a62461bcd02815260206004820152600b602482015260008051602061455b833981519152604482015290519081900360640190fd5b601b5415801590612f955750601b546213c680014210155b1515612feb576040805160e560020a62461bcd02815260206004820152601a60248201527f4f6e6c792069662067616d65206861732066696e69736865642e000000000000604482015290519081900360640190fd5b50601754604051303191620100009004600160a060020a03169082156108fc029083906000818181858888f19350505050158015612835573d6000803e3d6000fd5b601b5460009081901561303f57600080fd5b60125460095463ffffffff6401000000009091048116850116111561306357600080fd5b60095463ffffffff1691505b60095463ffffffff90811684011682101561328a57732e2ae45a3e2ff04a441e043be45dfba3f7a083ed63f9ebe6cb6012848154811015156130ad57fe5b600091825260209091206003909102015460128054600160a060020a0390921691869081106130d857fe5b906000526020600020906003020160000160149054906101000a900463ffffffff1660128681548110151561310957fe5b906000526020600020906003020160010160009054906101000a90046bffffffffffffffffffffffff16600f6011601060006040518863ffffffff1660e060020a0281526004018088600160a060020a0316600160a060020a031681526020018763ffffffff1663ffffffff168152602001866bffffffffffffffffffffffff166bffffffffffffffffffffffff16815260200185815260200184815260200183815260200180602001828103825283818154815260200191508054801561321057602002820191906000526020600020906000905b825461010083900a900460ff1615158152602060019283018181049485019490930390920291018084116131df5790505b50509850505050505050505060206040518083038186803b15801561323457600080fd5b505af4158015613248573d6000803e3d6000fd5b505050506040513d602081101561325e57600080fd5b50516000838152600360205260409020805461ffff191661ffff8316179055600190920191905061306f565b50506009805463ffffffff19811663ffffffff9182169390930116919091179055565b601754620100009004600160a060020a03163314613303576040805160e560020a62461bcd02815260206004820152600b602482015260008051602061455b833981519152604482015290519081900360640190fd5b600160a060020a038116151561331857600080fd5b60198054600160a060020a031916600160a060020a0392909216919091179055565b60025481565b610da0848484610f0a565b601754600090819060ff1615613399576040805160e560020a62461bcd02815260206004820152601360248201526000805160206145bb833981519152604482015290519081900360640190fd5b6133a16143b4565b3410156133f8576040805160e560020a62461bcd02815260206004820152601760248201527f4574682073656e74206973206e6f7420656e6f7567682e000000000000000000604482015290519081900360640190fd5b33151561343d576040805160e560020a62461bcd02815260206004820152601b602482015260008051602061453b833981519152604482015290519081900360640190fd5b600160a060020a0388166000908152601560205260409020546064116134d3576040805160e560020a62461bcd02815260206004820152602860248201527f53656e6465722063616e6e6f742068617665206d6f7265207468616e2031303060448201527f20746f6b656e732e000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b635bdb14f0421061351c576040805160e560020a62461bcd028152602060048201526016602482015260008051602061457b833981519152604482015290519081900360640190fd5b606483111561352a57600080fd5b61356687878787878080601f01602080910402602001604051908101604052809392919081815260200183838082843750614171945050505050565b90506135728882614395565b6040805133808252600160a060020a03808c16602084015292820184905291891660808201526bffffffffffffffffffffffff871660a082015263ffffffff881660c082015260e0606082018181529082018690527fd224a9a732ef51c0945b6f3d79bda4f9b5ef8b81a967d7ea8e63575c9e0c7f9492918b918591899189918e918d918f91610100820187878082843760405192018290039b50909950505050505050505050a1979650505050505050565b601754620100009004600160a060020a0316331461367b576040805160e560020a62461bcd02815260206004820152600b602482015260008051602061455b833981519152604482015290519081900360640190fd5b6017805460ff1916911515919091179055565b601854600160a060020a031681565b601754620100009004600160a060020a031633146136f3576040805160e560020a62461bcd02815260206004820152600b602482015260008051602061455b833981519152604482015290519081900360640190fd5b600760009054906101000a9004600160a060020a0316600160a060020a03166313bb13116040518163ffffffff1660e060020a028152600401600060405180830381600087803b158015610d8c57600080fd5b601754620100009004600160a060020a0316331461379c576040805160e560020a62461bcd02815260206004820152600b602482015260008051602061455b833981519152604482015290519081900360640190fd5b60175460ff16156137e5576040805160e560020a62461bcd02815260206004820152601360248201526000805160206145bb833981519152604482015290519081900360640190fd5b6137ed6143b4565b341015613844576040805160e560020a62461bcd02815260206004820152601760248201527f4574682073656e74206973206e6f7420656e6f7567682e000000000000000000604482015290519081900360640190fd5b331515613889576040805160e560020a62461bcd02815260206004820152601b602482015260008051602061453b833981519152604482015290519081900360640190fd5b635bdb14f042106138d2576040805160e560020a62461bcd028152602060048201526016602482015260008051602061457b833981519152604482015290519081900360640190fd5b600081815260056020908152604091829020805460ff19166001179055815133815290810183905281517f5af1975c023a376dd6e2d2a7d941656d6014c52ec7793a6fcbc82358099b6803929181900390910190a150565b600160a060020a03811660009081526015602090815260409182902080548351818402810184019094528084526060939283018282801561398a57602002820191906000526020600020905b815481526020019060010190808311613976575b50505050509050919050565b601954600160a060020a031681565b601754600090610100900460ff161515613a09576040805160e560020a62461bcd02815260206004820152601b60248201527f4f6e6c792069662067616d65206861732066696e616c697a65642e0000000000604482015290519081900360640190fd5b50336000908152601560205260408120805466b1a2bc2ec500000291613a2f9190614434565b604051339082156108fc029083906000818181858888f19350505050158015612835573d6000803e3d6000fd5b60008060008060606000601287815481101515613a7557fe5b6000918252602091829020600391909102018054600180830154600280850180546040805161010096831615969096026000190190911692909204601f8101889004880285018801909252818452600160a060020a0385169c5060a060020a90940463ffffffff169a506bffffffffffffffffffffffff821699506c0100000000000000000000000090910467ffffffffffffffff16975092945092909190830182828015613b655780601f10613b3a57610100808354040283529160200191613b65565b820191906000526020600020905b815481529060010190602001808311613b4857829003601f168201915b505050505091505091939590929450565b600160a060020a03918216600090815260166020908152604080832093909416825291909152205460ff1690565b6010805482908110613bb257fe5b60009182526020909120015461ffff16905081565b600f805482908110613bd557fe5b60009182526020909120015460ff808216925061010082048116916201000090041683565b601754620100009004600160a060020a031681565b60115461ffff808216916201000081048216916401000000008204811691660100000000000081048216916801000000000000000082048116916a010000000000000000000090041686565b601754600090620100009004600160a060020a03163314613cb4576040805160e560020a62461bcd02815260206004820152600b602482015260008051602061455b833981519152604482015290519081900360640190fd5b5060028054600091829055601754604051919262010000909104600160a060020a0316916108fc84150291849190818181858888f19350505050158015612835573d6000803e3d6000fd5b601c5481565b601b5481565b600080613d178361201a565b905080600160a060020a031684600160a060020a03161480613d52575083600160a060020a0316613d4784610bff565b600160a060020a0316145b80613d625750613d628185613b76565b949350505050565b81600160a060020a0316613d7d8261201a565b600160a060020a031614613d9057600080fd5b600081815260146020526040902054600160a060020a0316156128355760009081526014602052604090208054600160a060020a031916905550565b60008083600160a060020a0316613de28461201a565b600160a060020a031614613df557600080fd5b600160a060020a038416600090815260156020526040902054606411613e1a57600080fd5b505060008181526013602090815260408083208054600160a060020a0319169055600160a060020a038516835260159091528120905b8154811015613eb957828282815481101515613e6857fe5b90600052602060002001541415613eb157815482906000198101908110613e8b57fe5b90600052602060002001548282815481101515613ea457fe5b6000918252602090912001555b600101613e50565b815482906000198101908110613ecb57fe5b60009182526020822001558154611640836000198301614410565b600081815260136020526040902054600160a060020a031615613f0857600080fd5b60008181526013602090815260408083208054600160a060020a03909616600160a060020a03199096168617905593825260158152928120805460018101825590825292902090910155565b6017805460ff19166001179055565b613f6b614452565b600073fab06e5f52820a397f1b9c79e59c84897e168813633b345a876012805490506040518263ffffffff1660e060020a028152600401808281526020019150506102a06040518083038186803b158015613fc557600080fd5b505af4158015613fd9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506102a0811015613fff57600080fd5b509150600090505b60158110156140625781816015811061401c57fe5b6020020151600b826015811061402e57fe5b600a91828204019190066003026101000a81548162ffffff021916908362ffffff1602179055508080600101915050614007565b73fab06e5f52820a397f1b9c79e59c84897e16881363ec8263996012805490506040518263ffffffff1660e060020a0281526004018082815260200191505060206040518083038186803b1580156140b957600080fd5b505af41580156140cd573d6000803e3d6000fd5b505050506040513d60208110156140e357600080fd5b50516009805461ffff90921678010000000000000000000000000000000000000000000000000279ffff000000000000000000000000000000000000000000000000199092169190911790555050565b60008215156141445750600061203e565b5081810281838281151561415457fe5b041461203e57fe5b6000818381151561416957fe5b049392505050565b600061417b614472565b506040805160a081018252600160a060020a03878116825263ffffffff87811660208085019182526bffffffffffffffffffffffff8981169686019687524267ffffffffffffffff90811660608801908152608088018b815260128054600180820180845560009384528c517fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec3444600390940293840180549b51600160a060020a0319909c1691909d161777ffffffff0000000000000000000000000000000000000000191660a060020a9a909b1699909902999099178a559a517fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec34458c01805494516bffffffffffffffffffffffff19909516919096161773ffffffffffffffff00000000000000000000000019166c010000000000000000000000009390941692909202929092179092555180519697919694959394889493614302937fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec3446019201906144a2565b50505003905063ffffffff8116811461438b576040805160e560020a62461bcd02815260206004820152602560248201527f4661696c656420746f20636f6e7665727420746f6b656e496420746f2075696e60448201527f743235362e000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b9695505050505050565b600160a060020a03821615156143aa57600080fd5b6128358282613ee6565b6000635bd088f042106143d0575067011c37937e0800006143da565b5066b1a2bc2ec500005b66b1a2bc2ec5000081101580156143f9575067011c37937e0800008111155b15156117cc57600080fd5b6017805460ff19169055565b81548183558181111561148257600083815260209020611482918101908301614520565b5080546000825590600052602060002090810190610ef29190614520565b6102a0604051908101604052806015906020820280388339509192915050565b6040805160a081018252600080825260208201819052918101829052606080820192909252608081019190915290565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106144e357805160ff1916838001178555614510565b82800160010185558215614510579182015b828111156145105782518255916020019190600101906144f5565b5061451c929150614520565b5090565b6117cc91905b8082111561451c5760008155600101614526560053656e6465722063616e6e6f74206265203020616464726573732e00000000004f6e6c792061646d696e2e0000000000000000000000000000000000000000004576656e7420616c726561647920737461727465642e00000000000000000000506f696e74732076616c69646174696f6e20737461676520696e76616c69642e4f6e6c79206966206e6f74207061757365642e00000000000000000000000000a165627a7a72305820e1378936021c34c8727a49e5ce6ccb1e23120da769c9f755a61123be90acb2f90029

Libraries Used

PayoutDistribution : 0xfab06e5f52820a397f1b9c79e59c84897e168813Unverified
PointsCalculator : 0x2e2ae45a3e2ff04a441e043be45dfba3f7a083edUnverified

Swarm Source

bzzr://e1378936021c34c8727a49e5ce6ccb1e23120da769c9f755a61123be90acb2f9
Block Transaction Difficulty Gas Used Reward
Block Uncle Number Difficulty Gas Used Reward
Loading
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.