ETH Price: $1,933.87 (-4.00%)
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Token Holdings

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Withdraw Rewards217359392025-01-30 7:43:47393 days ago1738223027IN
0x1a22188b...c0FF50a91
0 ETH0.000173291.9786984
Withdraw Rewards217359262025-01-30 7:41:11393 days ago1738222871IN
0x1a22188b...c0FF50a91
0 ETH0.000171231.95519569
Withdraw Rewards217359182025-01-30 7:39:35393 days ago1738222775IN
0x1a22188b...c0FF50a91
0 ETH0.000180672.06302714
Calculate Round ...217359082025-01-30 7:37:35393 days ago1738222655IN
0x1a22188b...c0FF50a91
0 ETH0.000323491.93357015
Calculate Round ...217357072025-01-30 6:57:23393 days ago1738220243IN
0x1a22188b...c0FF50a91
0 ETH0.000596641.76185414
Calculate Round ...217356842025-01-30 6:52:47393 days ago1738219967IN
0x1a22188b...c0FF50a91
0 ETH0.000750931.78106084
Calculate Round ...217356612025-01-30 6:48:11393 days ago1738219691IN
0x1a22188b...c0FF50a91
0 ETH0.000281511.59632855
Provide Missing ...217356522025-01-30 6:46:23393 days ago1738219583IN
0x1a22188b...c0FF50a91
0 ETH0.000131371.8000386
Buy Entries217264422025-01-28 23:55:23395 days ago1738108523IN
0x1a22188b...c0FF50a91
0 ETH0.001439243.65757911
Buy Entries217264392025-01-28 23:54:47395 days ago1738108487IN
0x1a22188b...c0FF50a91
0 ETH0.001489063.78418936
Buy Entries217263362025-01-28 23:34:11395 days ago1738107251IN
0x1a22188b...c0FF50a91
0 ETH0.002192444.16006291
Reuse Non Withdr...217263332025-01-28 23:33:35395 days ago1738107215IN
0x1a22188b...c0FF50a91
0 ETH0.000204784.15529665
Reuse Non Withdr...217263282025-01-28 23:32:35395 days ago1738107155IN
0x1a22188b...c0FF50a91
0 ETH0.00036844.41293683
Create New Round217263242025-01-28 23:31:47395 days ago1738107107IN
0x1a22188b...c0FF50a91
0 ETH0.000334214.36914785
Withdraw Stake186400032023-11-24 7:13:47826 days ago1700810027IN
0x1a22188b...c0FF50a91
0 ETH0.0008573820.82188737
Withdraw Stake186399242023-11-24 6:57:35826 days ago1700809055IN
0x1a22188b...c0FF50a91
0 ETH0.0009284718.32867588
Withdraw Stake186399162023-11-24 6:55:59826 days ago1700808959IN
0x1a22188b...c0FF50a91
0 ETH0.0009702219.15288047
Withdraw Stake186399032023-11-24 6:53:23826 days ago1700808803IN
0x1a22188b...c0FF50a91
0 ETH0.0009947719.63747139
Withdraw Stake186398992023-11-24 6:52:35826 days ago1700808755IN
0x1a22188b...c0FF50a91
0 ETH0.0010400820.53187651
Withdraw Stake186398952023-11-24 6:51:47826 days ago1700808707IN
0x1a22188b...c0FF50a91
0 ETH0.0010352920.43738888
Accept Ownership153572852022-08-17 7:08:261290 days ago1660720106IN
0x1a22188b...c0FF50a91
0 ETH0.000310610.99206978
Nominate New Own...153572822022-08-17 7:07:251290 days ago1660720045IN
0x1a22188b...c0FF50a91
0 ETH0.000439869.21832612
Withdraw Rewards135435622021-11-03 11:16:161577 days ago1635938176IN
0x1a22188b...c0FF50a91
0 ETH0.0099336120
Withdraw Rewards135435402021-11-03 11:10:561577 days ago1635937856IN
0x1a22188b...c0FF50a91
0 ETH0.00828189117.50697142
Withdraw Rewards135435402021-11-03 11:10:561577 days ago1635937856IN
0x1a22188b...c0FF50a91
0 ETH0.01331344152.01462723
View all transactions

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
LotteryLikePool

Compiler Version
v0.6.12+commit.27d51765

Optimization Enabled:
No with 200 runs

Other Settings:
constantinople EvmVersion
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.12;
pragma experimental ABIEncoderV2;

import "openzeppelin-solidity/contracts/math/Math.sol";
import "openzeppelin-solidity/contracts/math/SafeMath.sol";
import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";
import "openzeppelin-solidity/contracts/token/ERC20/SafeERC20.sol";

import "./LinkedList.sol";
import "./TwoStageOwnable.sol";

contract LotteryLikePool is TwoStageOwnable {
    using SafeMath for uint256;
    using SafeERC20 for IERC20;
    using LinkedListLib for LinkedList;

    /// @notice Returns the time (in seconds) the owner has to verify the random seed
    function ownerSubmittingPeriod() public virtual pure returns (uint256) {
        return 1 days;
    }

    /// @notice Returns the time (in seconds) that the participants have to withdraw their rewards after round is closed
    function rewardWithdrawalPeriod() public virtual pure returns (uint256) {
        return 6 days;
    }

    /// @notice Returns duration of one round (in seconds)
    function roundPeriod() public virtual pure returns (uint256) {
        return 1 weeks;
    }

    /// @return Block number in which transaction applies
    /// @dev Method is virtual to override it for tests
    function getBlockNumber() internal virtual view returns (uint256) {
        return block.number;
    }

    /// @return Timestamp of block in which transaction applies
    /// @dev Method is virtual to override it for tests
    function getTimestamp() internal virtual view returns (uint256) {
        return block.timestamp;
    }

    /// @return Hash of specific block
    /// @dev Method is virtual to override it for tests
    function getBlockhash(uint256 blockNumber) internal virtual view returns (bytes32) {
        return blockhash(blockNumber);
    }

    struct ActiveEntryListElement {
        Entry entry;
        LinkedNode linkedNode;
    }

    /// @dev Represents entry (or entries) for a single round
    /// @param active True if entry is active and false otherwise.
    ///     All new entries are active. But entry can be deactivated during result calculation process
    /// @param amount Amount of entries. Equals to paid amount / 1e18
    /// @param from Sum of all previous active entries amounts
    /// @param pointer Pointer in active entries list
    /// @param to The same as `from` but with added amount
    /// @param account Address of entries owner
    struct Entry {
        bool active;
        uint256 amount;
        uint256 from;
        uint256 pointer;
        uint256 to;
        address account;
    }

    /// @dev Represents single participant of a single round
    /// @param active True if account is participant of round
    /// @param rewardPaid True if participant reward paid and false if they are not paid or participant has no rewards
    /// @param winner True if participant is winner
    /// @param entriesCount Sum of participant entries amounts
    /// @param reward Reward amount of participant
    struct RoundParticipant {
        bool active;
        bool rewardPaid;
        bool winner;
        uint256 entriesCount;
        uint256 reward;
    }

    /// @dev Represents common information of round
    /// @param closed True if round is closed and winners are defined
    /// @param closedAt Timestamp (in seconds) of round closing. Equals to `0` if round not closed
    /// @param endsAt Timestamp (in seconds) of round ending. When round ended buying entries for it not possible
    /// @param index Round index
    /// @param nonWithdrawnRewards Sum of rewards that has not been withdrawn.
    ///     Increases on every `increasePool` method call and reduced by method `withdrawRewards`.
    ///     When non withdrawn rewards are reused in other round `nonWithdrawnRewards` will be equals to 0
    ///     (reusing rewards are the same as withdrawing them and increasing pool of another round)
    /// @param totalEntries Sum of entries amounts
    /// @param totalReward Amount of rewards pool. Increases on every `increasePool` call. Never reduced
    /// @param participants Array of participants addresses
    /// @param winners Array of winners addresses
    struct RoundProps {
        bool closed;
        uint256 closedAt;
        uint256 endsAt;
        uint256 index;
        uint256 nonWithdrawnRewards;
        uint256 totalEntries;
        uint256 totalReward;
        address[] participants;
        address[] winners;
    }

    /// @dev Represents technical information about round results calculation process
    /// @param sealedSeedProvided True if sealed seed provided (see method `provideSealedSeed`)
    /// @param activeEntriesAmount Sum of active entries amounts. Reduces by gaps resolving
    /// @param gapPointer Pointer of entry that should be removed from active entries list
    /// @param iteratedEntriesCount Count of iterated entries
    /// @param passedIterationsCount Count of passed iterations
    /// @param seedRevealingBlockNumber Block number after which sealed seed can be revealed.
    ///     Hash of block with this number will be used to generate random seed.
    ///     Sealed seed can not be revealed after `seedRevealingBlockNumber` + 256
    /// @param sealedSeed Sealed seed - hash of original seed
    /// @param seed Seed of round that used to calculate results
    struct RoundCalculation {
        bool sealedSeedProvided;
        uint256 activeEntriesAmount;
        uint256 gapPointer;
        uint256 iteratedEntriesCount;
        uint256 passedIterationsCount;
        uint256 seedRevealingBlockNumber;
        bytes32 sealedSeed;
        bytes32 seed;
    }

    /// @dev Represents full round information
    /// @param props Common properties of round (see `RoundProps` struct for details)
    /// @param calculation Technical information about round results calculation process
    ///     (see `RoundCalculation` struct for details)
    /// @param activeEntries List of active entries. Used in calculation.
    ///     Not moved to `RoundCalculation` structure since linked list has mapping in it
    /// @param entries Array of all entries
    /// @param participants Map of participants. Key is participant address. Value is `RoundParticipant` structure
    struct Round {
        RoundProps props;
        RoundCalculation calculation;
        LinkedList activeEntries;
        Entry[] entries;
        mapping(address => RoundParticipant) participants;
    }

    /// @dev Total amount of tokens that have been spent buying entries but not withdrawn by owner
    uint256 private _totalStaked;

    /// @dev ERC20 staking token address. Used for buying entries
    IERC20 private _stakingToken;

    /// @dev ERC20 jackpot token address. Used for paying rewards
    IERC20 private _jackpotToken;

    /// @dev Rewards dividers for first 5 winners.
    ///     Reward can be calculated using `totalReward/rewardsDivider[winnerIndex]`
    uint256[5] private rewardsDivider = [2, 4, 8, 16, 16];

    /// @dev Array of all rounds. See `Round` structure for details
    Round[] private rounds;

    /// @notice Returns total amount of tokens that have been spent buying entries but not withdrawn by owner
    function totalStaked() public view returns (uint256) {
        return _totalStaked;
    }

    /// @notice Returns address of staking token (this is the one that used for buying entries)
    function stakingToken() public view returns (IERC20) {
        return _stakingToken;
    }

    /// @notice Returns address of jackpot token (this is the one that used for paying rewards)
    function jackpotToken() public view returns (IERC20) {
        return _jackpotToken;
    }

    /// @notice Returns count of already created rounds
    function roundsCount() public view returns (uint256) {
        return rounds.length;
    }

    /// @notice Returns all entries of specific round
    /// @param roundIndex Round index for which entries list should be returned
    function roundEntries(uint256 roundIndex) public view returns (Entry[] memory) {
        return _getRound(roundIndex).entries;
    }

    /// @notice Returns common round information. See struct `RoundProps` for details
    /// @param roundIndex Round index for which information should be returned
    function round(uint256 roundIndex) public view returns (RoundProps memory) {
        return _getRound(roundIndex).props;
    }

    /// @notice Returns information about round calculations. See struct `RoundCalculation` for details
    /// @param roundIndex Round index for which information should be returned
    function roundCalculation(uint256 roundIndex) public view returns (RoundCalculation memory) {
        return _getRound(roundIndex).calculation;
    }

    /// @notice Returns round participant inforation. See struct `RoundParticipant` for details
    /// @param roundIndex Round index for which inforation should be returned
    /// @param account Address of participant for which inforation should be returned
    function roundParticipant(uint256 roundIndex, address account) public view returns (RoundParticipant memory) {
        Round storage round_ = _getRound(roundIndex);
        return round_.participants[account];
    }

    /// @dev Returns list of currently active entries. May changes when calculation in process
    /// @return head Pointer of first active entry
    /// @return last Pointer of last active entry
    /// @return lastAllocation Pointer of last created entry
    /// @return length Count of active entries
    /// @return result Array of active entries and its list's element property
    function activeEntriesList(uint256 roundIndex)
        public
        view
        returns (
            uint256 head,
            uint256 last,
            uint256 lastAllocation,
            uint256 length,
            ActiveEntryListElement[] memory result
        )
    {
        Round storage round_ = _getRound(roundIndex);
        LinkedList storage list = round_.activeEntries;
        head = list.head;
        last = list.last;
        lastAllocation = list.it;
        length = list.length;
        result = new ActiveEntryListElement[](length);
        uint256 it = list.head;
        for (uint256 index = 0; index < length; index += 1) {
            LinkedNode memory node = list.getNode(it);
            result[index] = ActiveEntryListElement({entry: round_.entries[node.value], linkedNode: node});
            it = node.next;
        }
    }

    event EntriesPurchased(
        uint256 indexed roundIndex,
        address indexed purchaser,
        uint256 indexed entryIndex,
        uint256 amount
    );
    event JackpotIncreased(uint256 indexed roundIndex, address indexed payer, uint256 amount);
    event NonWithdrawnRewardsReused(uint256 indexed fromRoundIndex, uint256 indexed inRoundIndex);
    event MissingSeedProvided(uint256 indexed roundIndex, bytes32 seed);
    event NewRoundCreated(uint256 indexed index, uint256 endsAt);
    event SealedSeedProvided(uint256 indexed roundIndex, bytes32 sealedSeed, uint256 revealingBlockNumber);
    event SeedRevealed(uint256 indexed roundIndex, bytes32 revealedSeed, bytes32 savedSeed);
    event StakeWithdrawn(uint256 amount);
    event RewardWithdrawn(uint256 indexed roundIndex, address indexed winner, uint256 amount);
    event RoundClosed(uint256 indexed index);
    event RoundEnded(uint256 indexed index);
    event WinnerDefined(uint256 indexed roundIndex, address indexed account, uint256 rewardAmount);

    /// @param stakingToken_ ERC20 token that will be used to buy entries
    /// @param jackpotToken_ ERC20 token that will be used as rewards of rounds
    /// @param firstRoundEndsAt Timestamp (in seconds) when first created round will ends
    /// @param owner_ Address of owner
    constructor(
        IERC20 stakingToken_,
        IERC20 jackpotToken_,
        uint256 firstRoundEndsAt,
        address owner_
    ) public TwoStageOwnable(owner_) {
        _stakingToken = stakingToken_;
        _jackpotToken = jackpotToken_;
        rounds.push();
        rounds[0].props.endsAt = firstRoundEndsAt;
    }

    /// @notice Calculates specific round results
    /// @param roundIndex Index of round
    /// @param iterableEntries Array of entries indexes that expected to be iterated
    /// @param iterableEntriesOffset Count of skipped iterable entries. Needed to solve race conditions
    /// @param limit Max count of iterations that should be passed in transaction
    function calculateRoundResults(
        uint256 roundIndex,
        uint256[] memory iterableEntries,
        uint256 iterableEntriesOffset,
        uint256 limit
    ) external returns (bool success) {
        require(limit > 0, "Limit not positive");
        Round storage round_ = _getRound(roundIndex);
        require(round_.calculation.seed != bytes32(0), "Seed not revealed");
        require(!round_.props.closed, "Result already has been calculated");
        require(iterableEntriesOffset <= round_.calculation.iteratedEntriesCount, "Gap in iterable entries list");
        if (round_.calculation.gapPointer == 0) {
            // if there is first calculation call
            // or if there is no resolved gap in last iteration of previous calculation
            // then next iterable entries should be provided
            require(
                iterableEntries.length.add(iterableEntriesOffset) > round_.calculation.iteratedEntriesCount,
                "Nothing to calculate"
            );
        }
        _calculateResults(round_, iterableEntries, iterableEntriesOffset, limit);
        return true;
    }

    /// @notice Creates new round
    function createNewRound() public returns (bool success) {
        uint256 timestamp = getTimestamp();
        uint256 roundsCount_ = rounds.length;
        rounds.push();
        Round storage newRound = rounds[roundsCount_];
        Round storage previousRound = rounds[roundsCount_.sub(1)];
        uint256 newRoundEndsAt;
        uint256 roundPeriod_ = roundPeriod();
        if (previousRound.props.endsAt >= timestamp) newRoundEndsAt = previousRound.props.endsAt.add(roundPeriod_);
        else {
            uint256 passedWeeksCount = timestamp.sub(previousRound.props.endsAt).div(roundPeriod_);
            newRoundEndsAt = previousRound.props.endsAt.add(passedWeeksCount.add(1).mul(roundPeriod_));
        }
        newRound.props.endsAt = newRoundEndsAt;
        emit NewRoundCreated(roundsCount_, newRoundEndsAt);
        newRound.props.index = roundsCount_;
        return true;
    }

    /// @notice Method to buy entries. Should approve `amount` * 1e18 of staking token for using by this contract
    /// @param roundIndex Index of round to participate in. Round should not be ended
    /// @param amount Amount of entries to buy
    function buyEntries(uint256 roundIndex, uint256 amount) external onlyPositiveAmount(amount) returns (bool success) {
        _updateRound();
        address participant = msg.sender;
        Round storage round_ = _getRound(roundIndex);
        require(round_.props.endsAt > getTimestamp(), "Round already ended");
        uint256 newTotalAmount = round_.calculation.activeEntriesAmount.add(amount);
        Entry[] storage entries = round_.entries;
        uint256 newEntryIndex = entries.length;
        LinkedList storage roundActiveEntries = round_.activeEntries;
        uint256 pointer = roundActiveEntries.insert(roundActiveEntries.last, newEntryIndex);
        entries.push(
            Entry({
                active: true,
                amount: amount,
                from: round_.calculation.activeEntriesAmount,
                pointer: pointer,
                to: newTotalAmount,
                account: participant
            })
        );
        round_.calculation.activeEntriesAmount = newTotalAmount;
        round_.props.totalEntries = newTotalAmount;
        RoundParticipant storage roundParticipant_ = round_.participants[participant];
        roundParticipant_.entriesCount = roundParticipant_.entriesCount.add(amount);
        if (!roundParticipant_.active) {
            roundParticipant_.active = true;
            round_.props.participants.push(participant);
        }
        uint256 stakeAmount = amount.mul(10**18);
        _totalStaked = _totalStaked.add(stakeAmount);
        emit EntriesPurchased(roundIndex, participant, newEntryIndex, amount);
        _stakingToken.safeTransferFrom(participant, address(this), stakeAmount);
        return true;
    }

    /// @notice Increases round jackpot. Should approve `amount` of jackpot token for using by this contract
    /// @param roundIndex Index of round in which jackpot should be increased. Round should not be ended
    /// @param amount Amount of increasing
    function increaseJackpot(uint256 roundIndex, uint256 amount)
        public
        onlyPositiveAmount(amount)
        returns (bool success)
    {
        _updateRound();
        Round storage round_ = _getRound(roundIndex);
        require(round_.props.endsAt > getTimestamp(), "Round already ended");
        round_.props.totalReward = round_.props.totalReward.add(amount);
        round_.props.nonWithdrawnRewards = round_.props.nonWithdrawnRewards.add(amount);
        emit JackpotIncreased(roundIndex, msg.sender, amount);
        _jackpotToken.safeTransferFrom(msg.sender, address(this), amount);
        return true;
    }

    /// @notice Provides missing seed. Method added to fill case, when owner not provides seed by himself.
    ///     Conditions of successful providing:
    ///      * Seed should not been provided before it;
    ///      * If sealed seed provided by owner then more than 256 blocks should be produced after that;
    ///      * If sealed seed not provided owner submitting period should be ended.
    ///     Sets round seed to hash of previous block. Not the most honest implementation.
    ///     But since this is only a fuse in case the owner does not do his job, that's okay.
    /// @param roundIndex Round index for which missing seed provided
    function provideMissingSeed(uint256 roundIndex) public returns (bool success) {
        Round storage round_ = _getRound(roundIndex);
        uint256 blockNumber = getBlockNumber();
        require(round_.calculation.seed == bytes32(0), "Seed already provided");
        uint256 endsAt = round_.props.endsAt;
        if (round_.calculation.sealedSeedProvided) {
            bool revealingPhase = blockNumber > round_.calculation.seedRevealingBlockNumber;
            bool blockHashable = getBlockhash(round_.calculation.seedRevealingBlockNumber) != bytes32(0);
            require(revealingPhase && !blockHashable, "Less than 256 blocks passed from providing sealed seed");
        } else require(endsAt.add(ownerSubmittingPeriod()) < getTimestamp(), "Owner submitting period not passed");
        round_.calculation.sealedSeedProvided = true;
        bytes32 seed = getBlockhash(blockNumber.sub(1));
        round_.calculation.seed = seed;
        emit MissingSeedProvided(roundIndex, seed);
        return true;
    }

    /// @notice Provides sealed seed for random. Applicable only by contract owner
    /// @param roundIndex Round index for which sealed seed provided
    /// @param sealedSeed Keccak-256 hash of original seed. Original seed should be a random 32 bytes.
    ///     Original seed also should be remembered to provide it in `revealSealedSeed` method
    function provideSealedSeed(uint256 roundIndex, bytes32 sealedSeed) public onlyOwner returns (bool success) {
        Round storage round_ = _getRound(roundIndex);
        require(!round_.calculation.sealedSeedProvided, "Sealed seed already provided");
        require(round_.props.endsAt <= getTimestamp(), "Round not ended");
        round_.calculation.sealedSeedProvided = true;
        round_.calculation.sealedSeed = sealedSeed;
        uint256 revealingBlockNumber = getBlockNumber() + 1;
        round_.calculation.seedRevealingBlockNumber = revealingBlockNumber;
        emit SealedSeedProvided(roundIndex, sealedSeed, revealingBlockNumber);
        return true;
    }

    /// @notice Will reuse non withdrawn rewards as jackpot of the current one.
    ///     "From" round should be closed and reward withdrawal period should be passed.
    ///     Also appicable when round ended but there is no participants in it
    /// @param fromRoundIndex Round from which unwithdrawn rewards should be removed
    /// @param inRoundIndex Current round index
    function reuseNonWithdrawnRewards(uint256 fromRoundIndex, uint256 inRoundIndex) public returns (bool success) {
        _updateRound();
        uint256 timestamp = getTimestamp();
        RoundProps storage fromRoundProps = _getRound(fromRoundIndex).props;
        if (fromRoundProps.participants.length > 0) {
            require(fromRoundProps.closed, "From round not closed");
            uint256 applicableAt = fromRoundProps.closedAt.add(rewardWithdrawalPeriod());
            require(timestamp >= applicableAt, "Users can withdraw their rewards");
        } else require(timestamp >= fromRoundProps.endsAt, "Round not ended");
        uint256 reusedAmount = fromRoundProps.nonWithdrawnRewards;
        require(reusedAmount > 0, "Nothing to reuse");
        RoundProps storage inRoundProps = _getRound(inRoundIndex).props;
        require(timestamp < inRoundProps.endsAt, "In round already ended");
        require(timestamp >= _getRound(inRoundIndex.sub(1)).props.endsAt, "Able to reuse only for current round");
        fromRoundProps.nonWithdrawnRewards = 0;
        inRoundProps.totalReward = inRoundProps.totalReward.add(reusedAmount);
        inRoundProps.nonWithdrawnRewards = inRoundProps.nonWithdrawnRewards.add(reusedAmount);
        emit NonWithdrawnRewardsReused(fromRoundIndex, inRoundIndex);
        return true;
    }

    /// @notice Method to reveal sealed seed. Applicable only by contract owner.
    ///     Before revealing sealed seed it should be provided via `provideSealedSeed` method.
    ///     Applicable only next to 2 blocks after sealed seed has been provided but before next 256 blocks
    /// @param roundIndex Round index for which sealed seed should be revealed
    /// @param seed Original seed. See NatSpec for `provideSealedSeed` method
    function revealSealedSeed(uint256 roundIndex, bytes32 seed) public onlyOwner returns (bool success) {
        Round storage round_ = _getRound(roundIndex);
        require(round_.calculation.seed == bytes32(0), "Seed already revealed");
        require(round_.calculation.sealedSeedProvided, "Sealed seed not provided");
        uint256 seedRevealingBlockNumber = round_.calculation.seedRevealingBlockNumber;
        require(getBlockNumber() > seedRevealingBlockNumber, "Unable to reveal sealed seed on the same block");
        bytes32 revealingBlockHash = getBlockhash(seedRevealingBlockNumber);
        require(revealingBlockHash != bytes32(0), "More than 256 blocks passed from providing sealed seed");
        require(keccak256(abi.encodePacked(msg.sender, seed)) == round_.calculation.sealedSeed, "Invalid seed");
        bytes32 newSeed = keccak256(abi.encodePacked(revealingBlockHash, seed));
        round_.calculation.seed = newSeed;
        emit SeedRevealed(roundIndex, seed, newSeed);
        return true;
    }

    /// @notice Withdraws tokens, that have been spent buying entries. Applicable only by contract owner
    /// @param amount Amount of tokens to withdraw
    function withdrawStake(uint256 amount) external onlyOwner onlyPositiveAmount(amount) returns (bool success) {
        _totalStaked = _totalStaked.sub(amount, "Staking pool is extinguished");
        emit StakeWithdrawn(amount);
        _stakingToken.safeTransfer(owner, amount);
        return true;
    }

    /// @notice Withdraws rewards of specific round
    /// @param roundIndex Round index from which rewards should be withdrawn
    function withdrawRewards(uint256 roundIndex) external returns (bool success) {
        address caller = msg.sender;
        Round storage round_ = _getRound(roundIndex);
        RoundParticipant storage participant = round_.participants[caller];
        require(participant.winner, "Not a round winner");
        require(!participant.rewardPaid, "Round reward already paid");
        uint256 amount = participant.reward;
        require(amount > 0, "Reward amount is equal to zero");
        require(round_.props.nonWithdrawnRewards >= amount, "Reward reused as next jackpot");
        participant.rewardPaid = true;
        round_.props.nonWithdrawnRewards = round_.props.nonWithdrawnRewards.sub(amount);
        emit RewardWithdrawn(roundIndex, caller, amount);
        _jackpotToken.safeTransfer(caller, amount);
        return true;
    }

    /// @dev Creates new round if the last one is ended. Also emits `RoundEnded` event in this case
    function _updateRound() internal {
        uint256 lastRoundIndex = rounds.length.sub(1);
        if (rounds[lastRoundIndex].props.endsAt > getTimestamp()) return;
        emit RoundEnded(lastRoundIndex);
        createNewRound();
    }

    /// @dev Returns round by its index. Result is storage type so it can be modified to modify state.
    ///     Reverts an error when index greater than or equals to round count
    function _getRound(uint256 index) private view returns (Round storage) {
        require(index < rounds.length, "Round not found");
        return rounds[index];
    }

    /// @dev Calculates results of round
    /// @param round_ Storage type of round to calculate
    /// @param iterableEntries Array of entries indexes that expected to be iterated
    /// @param iterableEntriesOffset Number of entries that was skipped in `iterableEntries` array.
    ///     Needed to solve race conditions
    /// @param limit Max count of iteration to calculate
    function _calculateResults(
        Round storage round_,
        uint256[] memory iterableEntries,
        uint256 iterableEntriesOffset,
        uint256 limit
    ) private {
        uint256 passedIterationsCount = round_.calculation.passedIterationsCount;
        round_.calculation.passedIterationsCount = passedIterationsCount.add(1);
        // If previous iteration found entry to be removed
        //      or if it not resolves removing previously found removable entry
        if (round_.calculation.gapPointer > 0) {
            // process entry removing
            _processGap(round_);
            // and start new iteration if limit not reached
            if (limit > 1) _calculateResults(round_, iterableEntries, iterableEntriesOffset, limit - 1);
            return;
        }
        // Generate iteration seed by hashing round seed and iteration index
        uint256 random = uint256(keccak256(abi.encodePacked(round_.calculation.seed, passedIterationsCount)));
        uint256 iteratedEntriesCount = round_.calculation.iteratedEntriesCount;
        // If there is not enough indexes in `iterableEntries` list just finish calculation
        if (iterableEntries.length.add(iterableEntriesOffset) <= iteratedEntriesCount) return;
        // Get random number from 0 inclusive to total round entries exclusive
        random = random.mod(round_.calculation.activeEntriesAmount);
        // Get expected iterable entry
        uint256 potensionalIterableEntryIndex = iterableEntries[iteratedEntriesCount.sub(iterableEntriesOffset)];
        require(potensionalIterableEntryIndex < round_.entries.length, "Invalid iterable entry index");
        Entry storage potensionalIterableEntry = round_.entries[potensionalIterableEntryIndex];
        round_.calculation.iteratedEntriesCount = iteratedEntriesCount.add(1);
        // Expected iterable entry should be active (not removed from active list)
        require(potensionalIterableEntry.active, "Expected iterable entry not active");
        // Check that iterated entry is correct
        require(
            potensionalIterableEntry.from <= random && potensionalIterableEntry.to > random,
            "Invalid expected iterable entry"
        );
        address potensionalWinningAddress = potensionalIterableEntry.account;
        RoundParticipant storage roundParticipant_ = round_.participants[potensionalWinningAddress];
        // If entry owner not a winner
        if (!roundParticipant_.winner) {
            // make it winner
            bool shouldBreak = _processWinner(round_, roundParticipant_, potensionalWinningAddress);
            // and if he is the last winner (5th or no more non winners) just stop calculation
            if (shouldBreak) return;
        } else {
            // otherwise, if he is already winner mark his entry to remove
            round_.calculation.gapPointer = potensionalIterableEntry.pointer;
        }
        // If limit not reached start new iteration
        if (limit > 1) _calculateResults(round_, iterableEntries, iterableEntriesOffset, limit - 1);
    }

    /// @dev Process winner
    /// @param round_ Round in which winner is defined
    /// @param roundParticipant_ Round participant defined as a winner properties
    /// @param potensionalWinningAddress Address of participant
    /// @return shouldBreak True if this is the last round winner
    function _processWinner(
        Round storage round_,
        RoundParticipant storage roundParticipant_,
        address potensionalWinningAddress
    ) private returns (bool shouldBreak) {
        uint256 reward = round_.props.totalReward.div(rewardsDivider[round_.props.winners.length]);
        roundParticipant_.reward = reward;
        roundParticipant_.winner = true;
        round_.props.winners.push(potensionalWinningAddress);
        uint256 newCalculatedWinnersCount = round_.props.winners.length;
        emit WinnerDefined(round_.props.index, potensionalWinningAddress, reward);
        // If this is the last round winner (5th winner or no more non winners)
        if (newCalculatedWinnersCount >= 5 || newCalculatedWinnersCount >= round_.props.participants.length) {
            // close round
            emit RoundClosed(round_.props.index);
            round_.props.closed = true;
            round_.props.closedAt = getTimestamp();
            // and stop results calculations
            return true;
        }
        // else continue results calculation
        return false;
    }

    /// @dev Method to iterate entry removing
    /// @param round_ Round in which some entry should be removed
    function _processGap(Round storage round_) private {
        LinkedList storage list = round_.activeEntries;
        uint256 lastEntryIndex = list.get(list.last);
        Entry storage lastEntry = round_.entries[lastEntryIndex];
        LinkedNode memory gapNode = list.getNode(round_.calculation.gapPointer);
        Entry storage gap = round_.entries[gapNode.value];
        // If entry to remove is the last in active entries list
        if (list.last == round_.calculation.gapPointer) {
            // then just remove it
            round_.calculation.activeEntriesAmount = round_.calculation.activeEntriesAmount.sub(lastEntry.amount);
            list.remove(round_.calculation.gapPointer);
            round_.calculation.gapPointer = 0;
            gap.active = false;
            return;
        }
        RoundParticipant storage lastParticipant = round_.participants[lastEntry.account];
        // If owner of last entry in active entries list is a winner
        if (lastParticipant.winner) {
            // Just remove the last entry and continue processing removing
            round_.calculation.activeEntriesAmount = round_.calculation.activeEntriesAmount.sub(lastEntry.amount);
            list.remove(list.last);
            lastEntry.active = false;
            return;
        }
        // Otherwise we need to move last entry instead of removable entry
        // To do this moved entry amount should be calculated first
        //      that is minimal amount between removable entry amount and last entry remove
        uint256 transferAmount = Math.min(gap.amount, lastEntry.amount);
        round_.calculation.activeEntriesAmount = round_.calculation.activeEntriesAmount.sub(transferAmount);
        if (gapNode.prev > 0) {
            Entry storage prevEntry = round_.entries[list.get(gapNode.prev)];
            if (prevEntry.account == lastEntry.account) {
                // If owner of entry before removable one is the same as owner of last entry
                //      then just move amount from last entry to entry before removable one
                return _processTransitionToPrevGap(round_, prevEntry, gap, lastEntry, transferAmount, list);
            }
        }
        if (gapNode.next > 0 && gapNode.next != list.last) {
            Entry storage nextEntry = round_.entries[list.get(gapNode.next)];
            if (nextEntry.account == lastEntry.account) {
                // If owner of entry after removable one is the same as owner of last entry
                //      then just move amount from last entry to entry after removable one
                return _processTransitionToNextGap(round_, nextEntry, gap, lastEntry, transferAmount, list);
            }
        }
        // If neighboring entries has different owner
        //      just create new entry with this owner before the removable one and reduce removable entry amount
        uint256 newEntryIndex = round_.entries.length;
        uint256 newEntryFrom = gap.from;
        gap.from = gap.from.add(transferAmount);
        gap.amount = gap.amount.sub(transferAmount);
        lastEntry.amount = lastEntry.amount.sub(transferAmount);
        lastEntry.to = lastEntry.to.sub(transferAmount);
        uint256 pointer = list.insert(gapNode.prev, newEntryIndex);
        round_.entries.push(Entry(true, transferAmount, newEntryFrom, pointer, gap.from, lastEntry.account));
        // and remove last and removable entry if its amount is zero
        _finishGapTransfer(round_, gap, lastEntry, list);
    }

    /// @dev Moves entries amount from last entry to the first before removable one
    /// @param round_ Round in which this transition applies
    /// @param prevEntry First entry before removable one
    /// @param gap Removable entry
    /// @param lastEntry Last active entry
    /// @param transferAmount Amount that should be moved
    /// @param list List of active entries
    function _processTransitionToPrevGap(
        Round storage round_,
        Entry storage prevEntry,
        Entry storage gap,
        Entry storage lastEntry,
        uint256 transferAmount,
        LinkedList storage list
    ) private {
        prevEntry.amount = prevEntry.amount.add(transferAmount);
        prevEntry.to = prevEntry.to.add(transferAmount);
        gap.from = prevEntry.to;
        gap.amount = gap.amount.sub(transferAmount);
        lastEntry.to = lastEntry.to.sub(transferAmount);
        lastEntry.amount = lastEntry.amount.sub(transferAmount);
        _finishGapTransfer(round_, gap, lastEntry, list);
    }

    /// @dev Moves entries amount from last entry to the first after removable one
    /// @param round_ Round in which this transition applies
    /// @param nextEntry First entry after removable one
    /// @param gap Removable entry
    /// @param lastEntry Last active entry
    /// @param transferAmount Amount that should be moved
    /// @param list List of active entries
    function _processTransitionToNextGap(
        Round storage round_,
        Entry storage nextEntry,
        Entry storage gap,
        Entry storage lastEntry,
        uint256 transferAmount,
        LinkedList storage list
    ) private {
        nextEntry.amount = nextEntry.amount.add(transferAmount);
        nextEntry.from = nextEntry.from.sub(transferAmount);
        gap.to = nextEntry.from;
        gap.amount = gap.amount.sub(transferAmount);
        lastEntry.to = lastEntry.to.sub(transferAmount);
        lastEntry.amount = lastEntry.amount.sub(transferAmount);
        _finishGapTransfer(round_, gap, lastEntry, list);
    }

    /// @dev Finish iteration of removing entry
    /// @param round_ Round for which iteration was applied
    /// @param gap Removable entry
    /// @param lastEntry Last active entry
    /// @param list List of active entries
    function _finishGapTransfer(
        Round storage round_,
        Entry storage gap,
        Entry storage lastEntry,
        LinkedList storage list
    ) private {
        // If removable entry amount is zero (when its amount fully compensated by creation/transition amounts)
        if (gap.amount == 0) {
            // just remove removable entry
            gap.active = false;
            list.remove(round_.calculation.gapPointer);
            // and stop calculation removing
            round_.calculation.gapPointer = 0;
        }
        // If last entry is empty (fully moved instead of removable one)
        if (lastEntry.amount == 0) {
            // remove it
            lastEntry.active = false;
            list.remove(list.last);
        }
    }

    /// @dev Allows only positive amount (`> 0`)
    /// @param amount Amount to check
    modifier onlyPositiveAmount(uint256 amount) {
        require(amount > 0, "Amount is not positive");
        _;
    }
}

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

struct LinkedNode {
    bool inited;
    uint256 value;
    uint256 prev;
    uint256 next;
}

struct LinkedList {
    uint256 head;
    uint256 last;
    mapping(uint256 => LinkedNode) mem;
    uint256 it;
    uint256 length;
}

library LinkedListLib {
    function insert(
        LinkedList storage self,
        uint256 bearingPointer,
        uint256 value
    ) internal returns (uint256 pointer) {
        LinkedNode storage node = self.mem[bearingPointer];
        require(node.inited || bearingPointer == 0, "LinkedList insert: pointer out of scope");
        self.it += 1;
        LinkedNode storage newNode = self.mem[self.it];
        newNode.inited = true;
        newNode.value = value;
        newNode.prev = bearingPointer;
        newNode.next = bearingPointer == 0 ? self.head : node.next;
        node.next = self.it;
        self.mem[newNode.prev].next = self.it;
        self.mem[newNode.next].prev = self.it;
        if (bearingPointer == 0) self.head = self.it;
        if (bearingPointer == self.last) self.last = self.it;
        self.length += 1;
        return self.it;
    }

    function remove(LinkedList storage self, uint256 pointer) internal {
        LinkedNode storage node = self.mem[pointer];
        require(node.inited, "LinkedList remove: pointer out of scope");
        node.inited = false;
        self.mem[node.prev].next = node.next;
        self.mem[node.next].prev = node.prev;
        if (self.head == pointer) self.head = node.next;
        if (self.last == pointer) self.last = node.prev;
        self.length -= 1;
    }

    function get(LinkedList storage self, uint256 pointer) internal view returns (uint256 value) {
        LinkedNode storage node = self.mem[pointer];
        require(node.inited, "LinkedList get: pointer out of scope");
        return node.value;
    }

    function getNode(LinkedList storage self, uint256 pointer) internal view returns (LinkedNode memory) {
        LinkedNode storage node = self.mem[pointer];
        require(node.inited, "LinkedList getNode: pointer out of scope");
        return node;
    }
}

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

abstract contract TwoStageOwnable {
    address public nominatedOwner;
    address public owner;

    event OwnerChanged(address indexed newOwner);
    event OwnerNominated(address indexed nominatedOwner);

    constructor(address owner_) internal {
        require(owner_ != address(0), "Owner cannot be zero address");
        _setOwner(owner_);
    }

    function acceptOwnership() external returns (bool success) {
        require(msg.sender == nominatedOwner, "Not nominated to ownership");
        _setOwner(nominatedOwner);
        nominatedOwner = address(0);
        return true;
    }

    function nominateNewOwner(address owner_) external onlyOwner returns (bool success) {
        _nominateNewOwner(owner_);
        return true;
    }

    modifier onlyOwner {
        require(msg.sender == owner, "Ownable: caller is not the owner");
        _;
    }

    function _nominateNewOwner(address owner_) internal {
        nominatedOwner = owner_;
        emit OwnerNominated(owner_);
    }

    function _setOwner(address newOwner) internal {
        owner = newOwner;
        emit OwnerChanged(newOwner);
    }
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a >= b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow, so we distribute
        return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2);
    }
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return sub(a, b, "SafeMath: subtraction overflow");
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;

        return c;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return mod(a, b, "SafeMath: modulo by zero");
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts with custom message when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b != 0, errorMessage);
        return a % b;
    }
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "./IERC20.sol";
import "../../math/SafeMath.sol";
import "../../utils/Address.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using SafeMath for uint256;
    using Address for address;

    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(IERC20 token, address spender, uint256 value) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        // solhint-disable-next-line max-line-length
        require((value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 newAllowance = token.allowance(address(this), spender).add(value);
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
        if (returndata.length > 0) { // Return data is optional
            // solhint-disable-next-line max-line-length
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.2 <0.8.0;

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

        uint256 size;
        // solhint-disable-next-line no-inline-assembly
        assembly { size := extcodesize(account) }
        return size > 0;
    }

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

        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
        (bool success, ) = recipient.call{ value: amount }("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

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

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

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

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

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.call{ value: value }(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

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

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

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.staticcall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

Settings
{
  "remappings": [],
  "optimizer": {
    "enabled": false,
    "runs": 200
  },
  "evmVersion": "constantinople",
  "libraries": {
    "": {}
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  }
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"contract IERC20","name":"stakingToken_","type":"address"},{"internalType":"contract IERC20","name":"jackpotToken_","type":"address"},{"internalType":"uint256","name":"firstRoundEndsAt","type":"uint256"},{"internalType":"address","name":"owner_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"roundIndex","type":"uint256"},{"indexed":true,"internalType":"address","name":"purchaser","type":"address"},{"indexed":true,"internalType":"uint256","name":"entryIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"EntriesPurchased","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"roundIndex","type":"uint256"},{"indexed":true,"internalType":"address","name":"payer","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"JackpotIncreased","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"roundIndex","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"seed","type":"bytes32"}],"name":"MissingSeedProvided","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"endsAt","type":"uint256"}],"name":"NewRoundCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"fromRoundIndex","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"inRoundIndex","type":"uint256"}],"name":"NonWithdrawnRewardsReused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"nominatedOwner","type":"address"}],"name":"OwnerNominated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"roundIndex","type":"uint256"},{"indexed":true,"internalType":"address","name":"winner","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RewardWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"index","type":"uint256"}],"name":"RoundClosed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"index","type":"uint256"}],"name":"RoundEnded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"roundIndex","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"sealedSeed","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"revealingBlockNumber","type":"uint256"}],"name":"SealedSeedProvided","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"roundIndex","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"revealedSeed","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"savedSeed","type":"bytes32"}],"name":"SeedRevealed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"StakeWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"roundIndex","type":"uint256"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"rewardAmount","type":"uint256"}],"name":"WinnerDefined","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"roundIndex","type":"uint256"}],"name":"activeEntriesList","outputs":[{"internalType":"uint256","name":"head","type":"uint256"},{"internalType":"uint256","name":"last","type":"uint256"},{"internalType":"uint256","name":"lastAllocation","type":"uint256"},{"internalType":"uint256","name":"length","type":"uint256"},{"components":[{"components":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"from","type":"uint256"},{"internalType":"uint256","name":"pointer","type":"uint256"},{"internalType":"uint256","name":"to","type":"uint256"},{"internalType":"address","name":"account","type":"address"}],"internalType":"struct LotteryLikePool.Entry","name":"entry","type":"tuple"},{"components":[{"internalType":"bool","name":"inited","type":"bool"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"prev","type":"uint256"},{"internalType":"uint256","name":"next","type":"uint256"}],"internalType":"struct LinkedNode","name":"linkedNode","type":"tuple"}],"internalType":"struct LotteryLikePool.ActiveEntryListElement[]","name":"result","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"roundIndex","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"buyEntries","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"roundIndex","type":"uint256"},{"internalType":"uint256[]","name":"iterableEntries","type":"uint256[]"},{"internalType":"uint256","name":"iterableEntriesOffset","type":"uint256"},{"internalType":"uint256","name":"limit","type":"uint256"}],"name":"calculateRoundResults","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"createNewRound","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"roundIndex","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"increaseJackpot","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"jackpotToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner_","type":"address"}],"name":"nominateNewOwner","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"nominatedOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ownerSubmittingPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"roundIndex","type":"uint256"}],"name":"provideMissingSeed","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"roundIndex","type":"uint256"},{"internalType":"bytes32","name":"sealedSeed","type":"bytes32"}],"name":"provideSealedSeed","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"fromRoundIndex","type":"uint256"},{"internalType":"uint256","name":"inRoundIndex","type":"uint256"}],"name":"reuseNonWithdrawnRewards","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"roundIndex","type":"uint256"},{"internalType":"bytes32","name":"seed","type":"bytes32"}],"name":"revealSealedSeed","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardWithdrawalPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"roundIndex","type":"uint256"}],"name":"round","outputs":[{"components":[{"internalType":"bool","name":"closed","type":"bool"},{"internalType":"uint256","name":"closedAt","type":"uint256"},{"internalType":"uint256","name":"endsAt","type":"uint256"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"nonWithdrawnRewards","type":"uint256"},{"internalType":"uint256","name":"totalEntries","type":"uint256"},{"internalType":"uint256","name":"totalReward","type":"uint256"},{"internalType":"address[]","name":"participants","type":"address[]"},{"internalType":"address[]","name":"winners","type":"address[]"}],"internalType":"struct LotteryLikePool.RoundProps","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"roundIndex","type":"uint256"}],"name":"roundCalculation","outputs":[{"components":[{"internalType":"bool","name":"sealedSeedProvided","type":"bool"},{"internalType":"uint256","name":"activeEntriesAmount","type":"uint256"},{"internalType":"uint256","name":"gapPointer","type":"uint256"},{"internalType":"uint256","name":"iteratedEntriesCount","type":"uint256"},{"internalType":"uint256","name":"passedIterationsCount","type":"uint256"},{"internalType":"uint256","name":"seedRevealingBlockNumber","type":"uint256"},{"internalType":"bytes32","name":"sealedSeed","type":"bytes32"},{"internalType":"bytes32","name":"seed","type":"bytes32"}],"internalType":"struct LotteryLikePool.RoundCalculation","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"roundIndex","type":"uint256"}],"name":"roundEntries","outputs":[{"components":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"from","type":"uint256"},{"internalType":"uint256","name":"pointer","type":"uint256"},{"internalType":"uint256","name":"to","type":"uint256"},{"internalType":"address","name":"account","type":"address"}],"internalType":"struct LotteryLikePool.Entry[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"roundIndex","type":"uint256"},{"internalType":"address","name":"account","type":"address"}],"name":"roundParticipant","outputs":[{"components":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"bool","name":"rewardPaid","type":"bool"},{"internalType":"bool","name":"winner","type":"bool"},{"internalType":"uint256","name":"entriesCount","type":"uint256"},{"internalType":"uint256","name":"reward","type":"uint256"}],"internalType":"struct LotteryLikePool.RoundParticipant","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"roundPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"roundsCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakingToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalStaked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"roundIndex","type":"uint256"}],"name":"withdrawRewards","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawStake","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]

60806040526040518060a00160405280600260ff168152602001600460ff168152602001600860ff168152602001601060ff168152602001601060ff1681525060059060056200005192919062000264565b503480156200005f57600080fd5b506040516200633e3803806200633e833981810160405281019062000085919062000312565b80600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415620000f9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620000f090620003c0565b60405180910390fd5b6200010a81620001dd60201b60201c565b5083600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555082600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600a6001816001815401808255809150500390600052602060002090505081600a600081548110620001bb57fe5b9060005260206000209060180201600001600201819055505050505062000493565b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167fa2ea9883a321a3e97b8266c2b078bfeec6d50c711ed71f874a90d500ae2eaf3660405160405180910390a250565b82600581019282156200029b579160200282015b828111156200029a578251829060ff1690559160200191906001019062000278565b5b509050620002aa9190620002ae565b5090565b5b80821115620002c9576000816000905550600101620002af565b5090565b600081519050620002de8162000445565b92915050565b600081519050620002f5816200045f565b92915050565b6000815190506200030c8162000479565b92915050565b600080600080608085870312156200032957600080fd5b60006200033987828801620002e4565b94505060206200034c87828801620002e4565b93505060406200035f87828801620002fb565b92505060606200037287828801620002cd565b91505092959194509250565b60006200038d601c83620003e2565b91507f4f776e65722063616e6e6f74206265207a65726f2061646472657373000000006000830152602082019050919050565b60006020820190508181036000830152620003db816200037e565b9050919050565b600082825260208201905092915050565b600062000400826200041b565b9050919050565b60006200041482620003f3565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b6200045081620003f3565b81146200045c57600080fd5b50565b6200046a8162000407565b81146200047657600080fd5b50565b62000484816200043b565b81146200049057600080fd5b50565b615e9b80620004a36000396000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c806379ba5097116100de5780638ec9925e11610097578063cf17083911610071578063cf170839146104ed578063dce76e4d1461051d578063dd1264e614610551578063dd1e848e146105815761018e565b80638ec9925e146104815780639342c8f41461049f5780639f5cfe03146104cf5761018e565b806379ba5097146103bb5780637dee21e8146103d9578063805581e6146103f7578063817b1cd21461042757806387e7ae5c146104455780638da5cb5b146104635761018e565b806325d5971f1161014b5780633fabe0c0116101255780633fabe0c01461031f5780634b976c3b1461034f57806353a47bb71461037f57806372f702f31461039d5761018e565b806325d5971f146102a157806334d5f37b146102d15780633bfbec14146103015761018e565b806308be8700146101935780630de819b3146101c3578063112cee44146101f3578063126fe80d146102115780631627540c146102415780631e60ad3614610271575b600080fd5b6101ad60048036038101906101a891906141dc565b6105b1565b6040516101ba9190615513565b60405180910390f35b6101dd60048036038101906101d891906140e9565b610750565b6040516101ea9190615b14565b60405180910390f35b6101fb61081f565b6040516102089190615b51565b60405180910390f35b61022b600480360381019061022691906140c0565b61082a565b6040516102389190615af8565b60405180910390f35b61025b6004803603810190610256919061406e565b6108b2565b6040516102689190615513565b60405180910390f35b61028b600480360381019061028691906140c0565b610956565b60405161029891906154f1565b60405180910390f35b6102bb60048036038101906102b691906140c0565b610a5a565b6040516102c89190615513565b60405180910390f35b6102eb60048036038101906102e691906140c0565b610c32565b6040516102f89190615b2f565b60405180910390f35b610309610dcc565b6040516103169190615b51565b60405180910390f35b610339600480360381019061033491906141a0565b610dd7565b6040516103469190615513565b60405180910390f35b610369600480360381019061036491906141dc565b6110b0565b6040516103769190615513565b60405180910390f35b6103876114c1565b6040516103949190615476565b60405180910390f35b6103a56114e5565b6040516103b2919061559b565b60405180910390f35b6103c361150f565b6040516103d09190615513565b60405180910390f35b6103e1611611565b6040516103ee9190615b51565b60405180910390f35b610411600480360381019061040c91906141a0565b61161c565b60405161041e9190615513565b60405180910390f35b61042f6117ee565b60405161043c9190615b51565b60405180910390f35b61044d6117f8565b60405161045a9190615513565b60405180910390f35b61046b61198a565b6040516104789190615476565b60405180910390f35b6104896119b0565b604051610496919061559b565b60405180910390f35b6104b960048036038101906104b491906140c0565b6119da565b6040516104c69190615513565b60405180910390f35b6104d7611c56565b6040516104e49190615b51565b60405180910390f35b610507600480360381019061050291906140c0565b611c63565b6040516105149190615513565b60405180910390f35b610537600480360381019061053291906140c0565b611e5c565b604051610548959493929190615b6c565b60405180910390f35b61056b600480360381019061056691906141dc565b61202a565b6040516105789190615513565b60405180910390f35b61059b60048036038101906105969190614125565b6122ef565b6040516105a89190615513565b60405180910390f35b600081600081116105f7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105ee90615838565b60405180910390fd5b6105ff6124b2565b600061060a8561253f565b90506106146125aa565b81600001600201541161065c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161065390615898565b60405180910390fd5b6106768482600001600601546125b290919063ffffffff16565b816000016006018190555061069b8482600001600401546125b290919063ffffffff16565b81600001600401819055503373ffffffffffffffffffffffffffffffffffffffff16857f4130fbc98a3f18ae1e44c52a9645a7f92ba468ce7a05d81c0a89dc026c1b932c866040516106ed9190615b51565b60405180910390a3610744333086600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612607909392919063ffffffff16565b60019250505092915050565b610758613e29565b60006107638461253f565b90508060170160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060a00160405290816000820160009054906101000a900460ff161515151581526020016000820160019054906101000a900460ff161515151581526020016000820160029054906101000a900460ff161515151581526020016001820154815260200160028201548152505091505092915050565b600062093a80905090565b610832613e5e565b61083b8261253f565b600901604051806101000160405290816000820160009054906101000a900460ff161515151581526020016001820154815260200160028201548152602001600382015481526020016004820154815260200160058201548152602001600682015481526020016007820154815250509050919050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610944576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161093b90615938565b60405180910390fd5b61094d82612690565b60019050919050565b60606109618261253f565b601601805480602002602001604051908101604052809291908181526020016000905b82821015610a4f57838290600052602060002090600602016040518060c00160405290816000820160009054906101000a900460ff16151515158152602001600182015481526020016002820154815260200160038201548152602001600482015481526020016005820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152505081526020019060010190610984565b505050509050919050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610aec576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ae390615938565b60405180910390fd5b8160008111610b30576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b2790615838565b60405180910390fd5b610b7c836040518060400160405280601c81526020017f5374616b696e6720706f6f6c20697320657874696e67756973686564000000008152506002546127169092919063ffffffff16565b6002819055507fa78b9f12a7da0df7ced737c5f83d0c05723bb5f43aab37e233b862710414847283604051610bb19190615b51565b60405180910390a1610c28600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166127719092919063ffffffff16565b6001915050919050565b610c3a613eab565b610c438261253f565b600001604051806101200160405290816000820160009054906101000a900460ff1615151515815260200160018201548152602001600282015481526020016003820154815260200160048201548152602001600582015481526020016006820154815260200160078201805480602002602001604051908101604052809291908181526020018280548015610d2e57602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311610ce4575b5050505050815260200160088201805480602002602001604051908101604052809291908181526020018280548015610dbc57602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311610d72575b5050505050815250509050919050565b60006207e900905090565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610e69576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e6090615938565b60405180910390fd5b6000610e748461253f565b90506000801b816009016007015414610ec2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eb990615918565b60405180910390fd5b8060090160000160009054906101000a900460ff16610f16576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f0d906156f8565b60405180910390fd5b60008160090160050154905080610f2b6127f7565b11610f6b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f6290615678565b60405180910390fd5b6000610f76826127ff565b90506000801b811415610fbe576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fb5906158f8565b60405180910390fd5b82600901600601543386604051602001610fd99291906153db565b604051602081830303815290604052805190602001201461102f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161102690615998565b60405180910390fd5b60008186604051602001611044929190615407565b604051602081830303815290604052805190602001209050808460090160070181905550867f107e5672d914f9cb403cf5ba0b6cadca8ea3b77331f2a24210fbe3ef540ca558878360405161109a929190615549565b60405180910390a2600194505050505092915050565b600081600081116110f6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110ed90615838565b60405180910390fd5b6110fe6124b2565b6000339050600061110e8661253f565b90506111186125aa565b816000016002015411611160576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161115790615898565b60405180910390fd5b600061117c8683600901600101546125b290919063ffffffff16565b90506000826016019050600081805490509050600084601101905060006111b28260010154848461280a9092919063ffffffff16565b9050836040518060c001604052806001151581526020018c8152602001886009016001015481526020018381526020018781526020018973ffffffffffffffffffffffffffffffffffffffff16815250908060018154018082558091505060019003906000526020600020906006020160009091909190915060008201518160000160006101000a81548160ff0219169083151502179055506020820151816001015560408201518160020155606082015181600301556080820151816004015560a08201518160050160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505084866009016001018190555084866000016005018190555060008660170160008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506113308b82600101546125b290919063ffffffff16565b81600101819055508060000160009054906101000a900460ff166113d45760018160000160006101000a81548160ff02191690831515021790555086600001600701889080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b60006113f1670de0b6b3a76400008d6129aa90919063ffffffff16565b9050611408816002546125b290919063ffffffff16565b600281905550848973ffffffffffffffffffffffffffffffffffffffff168e7fef79519c5c873fe4437b5d7591c2ac60896fa489525254970cd9388f246d2fca8f6040516114569190615b51565b60405180910390a46114ad893083600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612607909392919063ffffffff16565b60019a505050505050505050505092915050565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146115a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161159790615978565b60405180910390fd5b6115c960008054906101000a900473ffffffffffffffffffffffffffffffffffffffff16612a1a565b60008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001905090565b600062015180905090565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146116ae576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116a590615938565b60405180910390fd5b60006116b98461253f565b90508060090160000160009054906101000a900460ff1615611710576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161170790615ad8565b60405180910390fd5b6117186125aa565b81600001600201541115611761576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161175890615ab8565b60405180910390fd5b60018160090160000160006101000a81548160ff021916908315150217905550828160090160060181905550600060016117996127f7565b019050808260090160050181905550847f02a2498943489e42740628e18ce0c039931c9820b2ee029fa881679440e9738d85836040516117da929190615572565b60405180910390a260019250505092915050565b6000600254905090565b6000806118036125aa565b90506000600a805490509050600a600181600181540180825580915050039060005260206000209050506000600a828154811061183c57fe5b906000526020600020906018020190506000600a611864600185612aa190919063ffffffff16565b8154811061186e57fe5b9060005260206000209060180201905060008061188961081f565b9050858360000160020154106118ba576118b38184600001600201546125b290919063ffffffff16565b915061192d565b60006118e8826118da86600001600201548a612aa190919063ffffffff16565b612aeb90919063ffffffff16565b9050611929611913836119056001856125b290919063ffffffff16565b6129aa90919063ffffffff16565b85600001600201546125b290919063ffffffff16565b9250505b818460000160020181905550847f9dabc2c637f100895272835b1380dc71381557c8025b8c7af70b855e64bd031a836040516119699190615b51565b60405180910390a28484600001600301819055506001965050505050505090565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008033905060006119eb8461253f565b905060008160170160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060000160029054906101000a900460ff16611a83576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a7a90615698565b60405180910390fd5b8060000160019054906101000a900460ff1615611ad5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611acc90615878565b60405180910390fd5b60008160020154905060008111611b21576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b18906156b8565b60405180910390fd5b8083600001600401541015611b6b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b6290615638565b60405180910390fd5b60018260000160016101000a81548160ff021916908315150217905550611ba2818460000160040154612aa190919063ffffffff16565b83600001600401819055508373ffffffffffffffffffffffffffffffffffffffff16867fb886382d42263e3c08a157dd29a33c435741f36625dbc3acb6fb8c19bbf7824783604051611bf49190615b51565b60405180910390a3611c498482600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166127719092919063ffffffff16565b6001945050505050919050565b6000600a80549050905090565b600080611c6f8361253f565b90506000611c7b6127f7565b90506000801b826009016007015414611cc9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cc090615798565b60405180910390fd5b6000826000016002015490508260090160000160009054906101000a900460ff1615611d6857600083600901600501548311905060008060001b611d1386600901600501546127ff565b14159050818015611d22575080155b611d61576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d5890615a58565b60405180910390fd5b5050611dcb565b611d706125aa565b611d8a611d7b611611565b836125b290919063ffffffff16565b10611dca576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611dc1906155d8565b60405180910390fd5b5b60018360090160000160006101000a81548160ff0219169083151502179055506000611e09611e04600185612aa190919063ffffffff16565b6127ff565b9050808460090160070181905550857f36882092d483bd52b047770e5cfcdf5e7e4697749bf2abf6f88eea7d569b5c4e82604051611e47919061552e565b60405180910390a26001945050505050919050565b60008060008060606000611e6f8761253f565b90506000816011019050806000015496508060010154955080600301549450806004015493508367ffffffffffffffff81118015611eac57600080fd5b50604051908082528060200260200182016040528015611ee657816020015b611ed3613ef9565b815260200190600190039081611ecb5790505b50925060008160000154905060005b8581101561201d57611f05613f1f565b611f188385612b3590919063ffffffff16565b9050604051806040016040528086601601836020015181548110611f3857fe5b90600052602060002090600602016040518060c00160405290816000820160009054906101000a900460ff16151515158152602001600182015481526020016002820154815260200160038201548152602001600482015481526020016005820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681525050815260200182815250868381518110611fff57fe5b60200260200101819052508060600151925050600181019050611ef5565b5050505091939590929450565b60006120346124b2565b600061203e6125aa565b9050600061204b8561253f565b600001905060008160070180549050111561211c578060000160009054906101000a900460ff166120b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120a890615818565b60405180910390fd5b60006120d16120be610dcc565b83600101546125b290919063ffffffff16565b905080831015612116576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161210d90615a98565b60405180910390fd5b50612164565b8060020154821015612163576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161215a90615ab8565b60405180910390fd5b5b600081600401549050600081116121b0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121a790615658565b60405180910390fd5b60006121bb8661253f565b600001905080600201548410612206576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121fd906159b8565b60405180910390fd5b61222261221d600188612aa190919063ffffffff16565b61253f565b6000016002015484101561226b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612262906158b8565b60405180910390fd5b6000836004018190555061228c8282600601546125b290919063ffffffff16565b81600601819055506122ab8282600401546125b290919063ffffffff16565b816004018190555085877fdf3f79258e7e555306e25bc8edefa1f545f767bc7817e5bfd89ce5380c9c832e60405160405180910390a3600194505050505092915050565b6000808211612333576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161232a90615618565b60405180910390fd5b600061233e8661253f565b90506000801b8160090160070154141561238d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612384906159f8565b60405180910390fd5b8060000160000160009054906101000a900460ff16156123e2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123d990615758565b60405180910390fd5b806009016003015484111561242c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612423906155f8565b60405180910390fd5b6000816009016002015414156124995780600901600301546124588587516125b290919063ffffffff16565b11612498576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161248f90615778565b60405180910390fd5b5b6124a581868686612bf5565b6001915050949350505050565b60006124cd6001600a80549050612aa190919063ffffffff16565b90506124d76125aa565b600a82815481106124e457fe5b9060005260206000209060180201600001600201541115612505575061253d565b807faa97d4a7b3afec5f55c25ca8593dde6929d4455fad650a16fa4334004293a61860405160405180910390a261253a6117f8565b50505b565b6000600a805490508210612588576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161257f90615958565b60405180910390fd5b600a828154811061259557fe5b90600052602060002090601802019050919050565b600042905090565b6000808284019050838110156125fd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125f490615718565b60405180910390fd5b8091505092915050565b61268a846323b872dd60e01b85858560405160240161262893929190615491565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050612f17565b50505050565b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce2260405160405180910390a250565b600083831115829061275e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161275591906155b6565b60405180910390fd5b5060008385039050809150509392505050565b6127f28363a9059cbb60e01b84846040516024016127909291906154c8565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050612f17565b505050565b600043905090565b600081409050919050565b60008084600201600085815260200190815260200160002090508060000160009054906101000a900460ff16806128415750600084145b612880576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612877906159d8565b60405180910390fd5b60018560030160008282540192505081905550600085600201600087600301548152602001908152602001600020905060018160000160006101000a81548160ff021916908315150217905550838160010181905550848160020181905550600085146128f15781600301546128f7565b85600001545b8160030181905550856003015482600301819055508560030154866002016000836002015481526020019081526020016000206003018190555085600301548660020160008360030154815260200190815260200160002060020181905550600085141561296d57856003015486600001819055505b856001015485141561298757856003015486600101819055505b600186600401600082825401925050819055508560030154925050509392505050565b6000808314156129bd5760009050612a14565b60008284029050828482816129ce57fe5b0414612a0f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a06906158d8565b60405180910390fd5b809150505b92915050565b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167fa2ea9883a321a3e97b8266c2b078bfeec6d50c711ed71f874a90d500ae2eaf3660405160405180910390a250565b6000612ae383836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612716565b905092915050565b6000612b2d83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250612fde565b905092915050565b612b3d613f1f565b600083600201600084815260200190815260200160002090508060000160009054906101000a900460ff16612ba7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b9e906156d8565b60405180910390fd5b806040518060800160405290816000820160009054906101000a900460ff16151515158152602001600182015481526020016002820154815260200160038201548152505091505092915050565b600084600901600401549050612c156001826125b290919063ffffffff16565b8560090160040181905550600085600901600201541115612c5857612c398561303f565b6001821115612c5257612c5185858560018603612bf5565b5b50612f11565b6000856009016007015482604051602001612c74929190615433565b6040516020818303038152906040528051906020012060001c905060008660090160030154905080612cb08688516125b290919063ffffffff16565b11612cbd57505050612f11565b612cd787600901600101548361363b90919063ffffffff16565b9150600086612cef8784612aa190919063ffffffff16565b81518110612cf957fe5b6020026020010151905087601601805490508110612d4c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d43906157b8565b60405180910390fd5b6000886016018281548110612d5d57fe5b90600052602060002090600602019050612d816001846125b290919063ffffffff16565b89600901600301819055508060000160009054906101000a900460ff16612ddd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612dd4906157d8565b60405180910390fd5b83816002015411158015612df45750838160040154115b612e33576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e2a90615738565b60405180910390fd5b60008160050160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060008a60170160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060000160029054906101000a900460ff16612edf576000612ec48c8385613685565b90508015612ed9575050505050505050612f11565b50612ef0565b82600301548b600901600201819055505b6001881115612f0957612f088b8b8b60018c03612bf5565b5b505050505050505b50505050565b6060612f79826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1661384e9092919063ffffffff16565b9050600081511115612fd95780806020019051810190612f999190614097565b612fd8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612fcf90615a78565b60405180910390fd5b5b505050565b60008083118290613025576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161301c91906155b6565b60405180910390fd5b50600083858161303157fe5b049050809150509392505050565b6000816011019050600061306082600101548361386690919063ffffffff16565b9050600083601601828154811061307357fe5b9060005260206000209060060201905061308b613f1f565b6130a5856009016002015485612b3590919063ffffffff16565b90506000856016018260200151815481106130bc57fe5b90600052602060002090600602019050856009016002015485600101541415613156576130fd83600101548760090160010154612aa190919063ffffffff16565b86600901600101819055506131228660090160020154866138df90919063ffffffff16565b6000866009016002018190555060008160000160006101000a81548160ff0219169083151502179055505050505050613638565b60008660170160008560050160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060000160029054906101000a900460ff161561323e576131f484600101548860090160010154612aa190919063ffffffff16565b87600901600101819055506132168660010154876138df90919063ffffffff16565b60008460000160006101000a81548160ff021916908315150217905550505050505050613638565b6000613252836001015486600101546139fc565b905061326e818960090160010154612aa190919063ffffffff16565b8860090160010181905550600084604001511115613356576000886016016132a386604001518a61386690919063ffffffff16565b815481106132ad57fe5b906000526020600020906006020190508560050160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168160050160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614156133545761334789828689868d613a15565b5050505050505050613638565b505b6000846060015111801561337257508660010154846060015114155b156134475760008860160161339486606001518a61386690919063ffffffff16565b8154811061339e57fe5b906000526020600020906006020190508560050160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168160050160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614156134455761343889828689868d613ad1565b5050505050505050613638565b505b6000886016018054905090506000846002015490506134738386600201546125b290919063ffffffff16565b8560020181905550613492838660010154612aa190919063ffffffff16565b85600101819055506134b1838860010154612aa190919063ffffffff16565b87600101819055506134d0838860040154612aa190919063ffffffff16565b876004018190555060006134f38760400151848c61280a9092919063ffffffff16565b90508a6016016040518060c00160405280600115158152602001868152602001848152602001838152602001886002015481526020018a60050160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815250908060018154018082558091505060019003906000526020600020906006020160009091909190915060008201518160000160006101000a81548160ff0219169083151502179055506020820151816001015560408201518160020155606082015181600301556080820151816004015560a08201518160050160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505061362d8b878a8d613b8d565b505050505050505050505b50565b600061367d83836040518060400160405280601881526020017f536166654d6174683a206d6f64756c6f206279207a65726f0000000000000000815250613c27565b905092915050565b6000806136ba60058660000160080180549050600581106136a257fe5b01548660000160060154612aeb90919063ffffffff16565b905080846002018190555060018460000160026101000a81548160ff02191690831515021790555084600001600801839080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000856000016008018054905090508373ffffffffffffffffffffffffffffffffffffffff1686600001600301547f51717f575c62af12c537bf652bd8c4fe4eb97454d8a29042b45342ba4002db4f846040516137a79190615b51565b60405180910390a36005811015806137c9575085600001600701805490508110155b156138405785600001600301547fe9f7d7fd0b133404f0ccff737d6f3594748e04bc5507adfaed35835ef989371160405160405180910390a260018660000160000160006101000a81548160ff02191690831515021790555061382a6125aa565b8660000160010181905550600192505050613847565b6000925050505b9392505050565b606061385d8484600085613c83565b90509392505050565b60008083600201600084815260200190815260200160002090508060000160009054906101000a900460ff166138d1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016138c890615858565b60405180910390fd5b806001015491505092915050565b600082600201600083815260200190815260200160002090508060000160009054906101000a900460ff16613949576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161394090615a38565b60405180910390fd5b60008160000160006101000a81548160ff021916908315150217905550806003015483600201600083600201548152602001908152602001600020600301819055508060020154836002016000836003015481526020019081526020016000206002018190555081836000015414156139ca57806003015483600001819055505b81836001015414156139e457806002015483600101819055505b60018360040160008282540392505081905550505050565b6000818310613a0b5781613a0d565b825b905092915050565b613a2c8286600101546125b290919063ffffffff16565b8560010181905550613a4b8286600401546125b290919063ffffffff16565b856004018190555084600401548460020181905550613a77828560010154612aa190919063ffffffff16565b8460010181905550613a96828460040154612aa190919063ffffffff16565b8360040181905550613ab5828460010154612aa190919063ffffffff16565b8360010181905550613ac986858584613b8d565b505050505050565b613ae88286600101546125b290919063ffffffff16565b8560010181905550613b07828660020154612aa190919063ffffffff16565b856002018190555084600201548460040181905550613b33828560010154612aa190919063ffffffff16565b8460010181905550613b52828460040154612aa190919063ffffffff16565b8360040181905550613b71828460010154612aa190919063ffffffff16565b8360010181905550613b8586858584613b8d565b505050505050565b600083600101541415613bdf5760008360000160006101000a81548160ff021916908315150217905550613bd18460090160020154826138df90919063ffffffff16565b600084600901600201819055505b600082600101541415613c215760008260000160006101000a81548160ff021916908315150217905550613c208160010154826138df90919063ffffffff16565b5b50505050565b6000808314158290613c6f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613c6691906155b6565b60405180910390fd5b50828481613c7957fe5b0690509392505050565b6060823073ffffffffffffffffffffffffffffffffffffffff16311015613cdf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613cd6906157f8565b60405180910390fd5b613ce885613daf565b613d27576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613d1e90615a18565b60405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff168587604051613d51919061545f565b60006040518083038185875af1925050503d8060008114613d8e576040519150601f19603f3d011682016040523d82523d6000602084013e613d93565b606091505b5091509150613da3828286613dc2565b92505050949350505050565b600080823b905060008111915050919050565b60608315613dd257829050613e22565b600083511115613de55782518084602001fd5b816040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613e1991906155b6565b60405180910390fd5b9392505050565b6040518060a0016040528060001515815260200160001515815260200160001515815260200160008152602001600081525090565b604051806101000160405280600015158152602001600081526020016000815260200160008152602001600081526020016000815260200160008019168152602001600080191681525090565b60405180610120016040528060001515815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160608152602001606081525090565b6040518060400160405280613f0c613f49565b8152602001613f19613f1f565b81525090565b60405180608001604052806000151581526020016000815260200160008152602001600081525090565b6040518060c0016040528060001515815260200160008152602001600081526020016000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff1681525090565b600081359050613fa681615e09565b92915050565b600082601f830112613fbd57600080fd5b8135613fd0613fcb82615bf3565b615bc6565b91508181835260208401935060208101905083856020840282011115613ff557600080fd5b60005b83811015614025578161400b8882614059565b845260208401935060208301925050600181019050613ff8565b5050505092915050565b60008151905061403e81615e20565b92915050565b60008135905061405381615e37565b92915050565b60008135905061406881615e4e565b92915050565b60006020828403121561408057600080fd5b600061408e84828501613f97565b91505092915050565b6000602082840312156140a957600080fd5b60006140b78482850161402f565b91505092915050565b6000602082840312156140d257600080fd5b60006140e084828501614059565b91505092915050565b600080604083850312156140fc57600080fd5b600061410a85828601614059565b925050602061411b85828601613f97565b9150509250929050565b6000806000806080858703121561413b57600080fd5b600061414987828801614059565b945050602085013567ffffffffffffffff81111561416657600080fd5b61417287828801613fac565b935050604061418387828801614059565b925050606061419487828801614059565b91505092959194509250565b600080604083850312156141b357600080fd5b60006141c185828601614059565b92505060206141d285828601614044565b9150509250929050565b600080604083850312156141ef57600080fd5b60006141fd85828601614059565b925050602061420e85828601614059565b9150509250929050565b60006142248383614278565b60208301905092915050565b600061423c83836150d0565b6101408301905092915050565b60006142558383615100565b60c08301905092915050565b61427261426d82615d0a565b615db3565b82525050565b61428181615cf8565b82525050565b61429081615cf8565b82525050565b60006142a182615c4b565b6142ab8185615ca9565b93506142b683615c1b565b8060005b838110156142e75781516142ce8882614218565b97506142d983615c82565b9250506001810190506142ba565b5085935050505092915050565b60006142ff82615c56565b6143098185615cba565b935061431483615c2b565b8060005b8381101561434557815161432c8882614230565b975061433783615c8f565b925050600181019050614318565b5085935050505092915050565b600061435d82615c61565b6143678185615ccb565b935061437283615c3b565b8060005b838110156143a357815161438a8882614249565b975061439583615c9c565b925050600181019050614376565b5085935050505092915050565b6143b981615d1c565b82525050565b6143c881615d1c565b82525050565b6143d781615d28565b82525050565b6143e681615d28565b82525050565b6143fd6143f882615d28565b615dc5565b82525050565b600061440e82615c6c565b6144188185615cdc565b9350614428818560208601615d80565b80840191505092915050565b61443d81615d5c565b82525050565b600061444e82615c77565b6144588185615ce7565b9350614468818560208601615d80565b61447181615deb565b840191505092915050565b6000614489602283615ce7565b91507f4f776e6572207375626d697474696e6720706572696f64206e6f74207061737360008301527f65640000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006144ef601c83615ce7565b91507f47617020696e206974657261626c6520656e7472696573206c697374000000006000830152602082019050919050565b600061452f601283615ce7565b91507f4c696d6974206e6f7420706f73697469766500000000000000000000000000006000830152602082019050919050565b600061456f601d83615ce7565b91507f52657761726420726575736564206173206e657874206a61636b706f740000006000830152602082019050919050565b60006145af601083615ce7565b91507f4e6f7468696e6720746f207265757365000000000000000000000000000000006000830152602082019050919050565b60006145ef602e83615ce7565b91507f556e61626c6520746f2072657665616c207365616c65642073656564206f6e2060008301527f7468652073616d6520626c6f636b0000000000000000000000000000000000006020830152604082019050919050565b6000614655601283615ce7565b91507f4e6f74206120726f756e642077696e6e657200000000000000000000000000006000830152602082019050919050565b6000614695601e83615ce7565b91507f52657761726420616d6f756e7420697320657175616c20746f207a65726f00006000830152602082019050919050565b60006146d5602883615ce7565b91507f4c696e6b65644c697374206765744e6f64653a20706f696e746572206f75742060008301527f6f662073636f70650000000000000000000000000000000000000000000000006020830152604082019050919050565b600061473b601883615ce7565b91507f5365616c65642073656564206e6f742070726f766964656400000000000000006000830152602082019050919050565b600061477b601b83615ce7565b91507f536166654d6174683a206164646974696f6e206f766572666c6f7700000000006000830152602082019050919050565b60006147bb601f83615ce7565b91507f496e76616c6964206578706563746564206974657261626c6520656e747279006000830152602082019050919050565b60006147fb602283615ce7565b91507f526573756c7420616c726561647920686173206265656e2063616c63756c617460008301527f65640000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000614861601483615ce7565b91507f4e6f7468696e6720746f2063616c63756c6174650000000000000000000000006000830152602082019050919050565b60006148a1601583615ce7565b91507f5365656420616c72656164792070726f766964656400000000000000000000006000830152602082019050919050565b60006148e1601c83615ce7565b91507f496e76616c6964206974657261626c6520656e74727920696e646578000000006000830152602082019050919050565b6000614921602283615ce7565b91507f4578706563746564206974657261626c6520656e747279206e6f74206163746960008301527f76650000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000614987602683615ce7565b91507f416464726573733a20696e73756666696369656e742062616c616e636520666f60008301527f722063616c6c00000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006149ed601583615ce7565b91507f46726f6d20726f756e64206e6f7420636c6f73656400000000000000000000006000830152602082019050919050565b6000614a2d601683615ce7565b91507f416d6f756e74206973206e6f7420706f736974697665000000000000000000006000830152602082019050919050565b6000614a6d602483615ce7565b91507f4c696e6b65644c697374206765743a20706f696e746572206f7574206f66207360008301527f636f7065000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000614ad3601983615ce7565b91507f526f756e642072657761726420616c72656164792070616964000000000000006000830152602082019050919050565b6000614b13601383615ce7565b91507f526f756e6420616c726561647920656e646564000000000000000000000000006000830152602082019050919050565b6000614b53602483615ce7565b91507f41626c6520746f207265757365206f6e6c7920666f722063757272656e74207260008301527f6f756e64000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000614bb9602183615ce7565b91507f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f60008301527f77000000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000614c1f603683615ce7565b91507f4d6f7265207468616e2032353620626c6f636b73207061737365642066726f6d60008301527f2070726f766964696e67207365616c65642073656564000000000000000000006020830152604082019050919050565b6000614c85601583615ce7565b91507f5365656420616c72656164792072657665616c656400000000000000000000006000830152602082019050919050565b6000614cc5602083615ce7565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b6000614d05600f83615ce7565b91507f526f756e64206e6f7420666f756e6400000000000000000000000000000000006000830152602082019050919050565b6000614d45601a83615ce7565b91507f4e6f74206e6f6d696e6174656420746f206f776e6572736869700000000000006000830152602082019050919050565b6000614d85600c83615ce7565b91507f496e76616c6964207365656400000000000000000000000000000000000000006000830152602082019050919050565b6000614dc5601683615ce7565b91507f496e20726f756e6420616c726561647920656e646564000000000000000000006000830152602082019050919050565b6000614e05602783615ce7565b91507f4c696e6b65644c69737420696e736572743a20706f696e746572206f7574206f60008301527f662073636f7065000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000614e6b601183615ce7565b91507f53656564206e6f742072657665616c65640000000000000000000000000000006000830152602082019050919050565b6000614eab601d83615ce7565b91507f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006000830152602082019050919050565b6000614eeb602783615ce7565b91507f4c696e6b65644c6973742072656d6f76653a20706f696e746572206f7574206f60008301527f662073636f7065000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000614f51603683615ce7565b91507f4c657373207468616e2032353620626c6f636b73207061737365642066726f6d60008301527f2070726f766964696e67207365616c65642073656564000000000000000000006020830152604082019050919050565b6000614fb7602a83615ce7565b91507f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008301527f6f742073756363656564000000000000000000000000000000000000000000006020830152604082019050919050565b600061501d602083615ce7565b91507f55736572732063616e20776974686472617720746865697220726577617264736000830152602082019050919050565b600061505d600f83615ce7565b91507f526f756e64206e6f7420656e64656400000000000000000000000000000000006000830152602082019050919050565b600061509d601c83615ce7565b91507f5365616c6564207365656420616c72656164792070726f7669646564000000006000830152602082019050919050565b610140820160008201516150e76000850182615100565b5060208201516150fa60c085018261517b565b50505050565b60c08201600082015161511660008501826143b0565b50602082015161512960208501826153a6565b50604082015161513c60408501826153a6565b50606082015161514f60608501826153a6565b50608082015161516260808501826153a6565b5060a082015161517560a0850182614278565b50505050565b60808201600082015161519160008501826143b0565b5060208201516151a460208501826153a6565b5060408201516151b760408501826153a6565b5060608201516151ca60608501826153a6565b50505050565b610100820160008201516151e760008501826143b0565b5060208201516151fa60208501826153a6565b50604082015161520d60408501826153a6565b50606082015161522060608501826153a6565b50608082015161523360808501826153a6565b5060a082015161524660a08501826153a6565b5060c082015161525960c08501826143ce565b5060e082015161526c60e08501826143ce565b50505050565b60a08201600082015161528860008501826143b0565b50602082015161529b60208501826143b0565b5060408201516152ae60408501826143b0565b5060608201516152c160608501826153a6565b5060808201516152d460808501826153a6565b50505050565b6000610120830160008301516152f360008601826143b0565b50602083015161530660208601826153a6565b50604083015161531960408601826153a6565b50606083015161532c60608601826153a6565b50608083015161533f60808601826153a6565b5060a083015161535260a08601826153a6565b5060c083015161536560c08601826153a6565b5060e083015184820360e086015261537d8282614296565b9150506101008301518482036101008601526153998282614296565b9150508091505092915050565b6153af81615d52565b82525050565b6153be81615d52565b82525050565b6153d56153d082615d52565b615de1565b82525050565b60006153e78285614261565b6014820191506153f782846143ec565b6020820191508190509392505050565b600061541382856143ec565b60208201915061542382846143ec565b6020820191508190509392505050565b600061543f82856143ec565b60208201915061544f82846153c4565b6020820191508190509392505050565b600061546b8284614403565b915081905092915050565b600060208201905061548b6000830184614287565b92915050565b60006060820190506154a66000830186614287565b6154b36020830185614287565b6154c060408301846153b5565b949350505050565b60006040820190506154dd6000830185614287565b6154ea60208301846153b5565b9392505050565b6000602082019050818103600083015261550b8184614352565b905092915050565b600060208201905061552860008301846143bf565b92915050565b600060208201905061554360008301846143dd565b92915050565b600060408201905061555e60008301856143dd565b61556b60208301846143dd565b9392505050565b600060408201905061558760008301856143dd565b61559460208301846153b5565b9392505050565b60006020820190506155b06000830184614434565b92915050565b600060208201905081810360008301526155d08184614443565b905092915050565b600060208201905081810360008301526155f18161447c565b9050919050565b60006020820190508181036000830152615611816144e2565b9050919050565b6000602082019050818103600083015261563181614522565b9050919050565b6000602082019050818103600083015261565181614562565b9050919050565b60006020820190508181036000830152615671816145a2565b9050919050565b60006020820190508181036000830152615691816145e2565b9050919050565b600060208201905081810360008301526156b181614648565b9050919050565b600060208201905081810360008301526156d181614688565b9050919050565b600060208201905081810360008301526156f1816146c8565b9050919050565b600060208201905081810360008301526157118161472e565b9050919050565b600060208201905081810360008301526157318161476e565b9050919050565b60006020820190508181036000830152615751816147ae565b9050919050565b60006020820190508181036000830152615771816147ee565b9050919050565b6000602082019050818103600083015261579181614854565b9050919050565b600060208201905081810360008301526157b181614894565b9050919050565b600060208201905081810360008301526157d1816148d4565b9050919050565b600060208201905081810360008301526157f181614914565b9050919050565b600060208201905081810360008301526158118161497a565b9050919050565b60006020820190508181036000830152615831816149e0565b9050919050565b6000602082019050818103600083015261585181614a20565b9050919050565b6000602082019050818103600083015261587181614a60565b9050919050565b6000602082019050818103600083015261589181614ac6565b9050919050565b600060208201905081810360008301526158b181614b06565b9050919050565b600060208201905081810360008301526158d181614b46565b9050919050565b600060208201905081810360008301526158f181614bac565b9050919050565b6000602082019050818103600083015261591181614c12565b9050919050565b6000602082019050818103600083015261593181614c78565b9050919050565b6000602082019050818103600083015261595181614cb8565b9050919050565b6000602082019050818103600083015261597181614cf8565b9050919050565b6000602082019050818103600083015261599181614d38565b9050919050565b600060208201905081810360008301526159b181614d78565b9050919050565b600060208201905081810360008301526159d181614db8565b9050919050565b600060208201905081810360008301526159f181614df8565b9050919050565b60006020820190508181036000830152615a1181614e5e565b9050919050565b60006020820190508181036000830152615a3181614e9e565b9050919050565b60006020820190508181036000830152615a5181614ede565b9050919050565b60006020820190508181036000830152615a7181614f44565b9050919050565b60006020820190508181036000830152615a9181614faa565b9050919050565b60006020820190508181036000830152615ab181615010565b9050919050565b60006020820190508181036000830152615ad181615050565b9050919050565b60006020820190508181036000830152615af181615090565b9050919050565b600061010082019050615b0e60008301846151d0565b92915050565b600060a082019050615b296000830184615272565b92915050565b60006020820190508181036000830152615b4981846152da565b905092915050565b6000602082019050615b6660008301846153b5565b92915050565b600060a082019050615b8160008301886153b5565b615b8e60208301876153b5565b615b9b60408301866153b5565b615ba860608301856153b5565b8181036080830152615bba81846142f4565b90509695505050505050565b6000604051905081810181811067ffffffffffffffff82111715615be957600080fd5b8060405250919050565b600067ffffffffffffffff821115615c0a57600080fd5b602082029050602081019050919050565b6000819050602082019050919050565b6000819050602082019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b6000615d0382615d32565b9050919050565b6000615d1582615d32565b9050919050565b60008115159050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b6000615d6782615d6e565b9050919050565b6000615d7982615d32565b9050919050565b60005b83811015615d9e578082015181840152602081019050615d83565b83811115615dad576000848401525b50505050565b6000615dbe82615dcf565b9050919050565b6000819050919050565b6000615dda82615dfc565b9050919050565b6000819050919050565b6000601f19601f8301169050919050565b60008160601b9050919050565b615e1281615cf8565b8114615e1d57600080fd5b50565b615e2981615d1c565b8114615e3457600080fd5b50565b615e4081615d28565b8114615e4b57600080fd5b50565b615e5781615d52565b8114615e6257600080fd5b5056fea2646970667358221220176a47206bcd8d6ba20ec26da49ce3da060e6ab2579cfe50d7acaa3bcd0c137464736f6c634300060c00330000000000000000000000003593d125a4f7849a1b059e64f4517a86dd60c95d000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7000000000000000000000000000000000000000000000000000000005febc300000000000000000000000000d4eee3d50588d7dee8dcc42635e50093e0aa8cc0

Deployed Bytecode

0x608060405234801561001057600080fd5b506004361061018e5760003560e01c806379ba5097116100de5780638ec9925e11610097578063cf17083911610071578063cf170839146104ed578063dce76e4d1461051d578063dd1264e614610551578063dd1e848e146105815761018e565b80638ec9925e146104815780639342c8f41461049f5780639f5cfe03146104cf5761018e565b806379ba5097146103bb5780637dee21e8146103d9578063805581e6146103f7578063817b1cd21461042757806387e7ae5c146104455780638da5cb5b146104635761018e565b806325d5971f1161014b5780633fabe0c0116101255780633fabe0c01461031f5780634b976c3b1461034f57806353a47bb71461037f57806372f702f31461039d5761018e565b806325d5971f146102a157806334d5f37b146102d15780633bfbec14146103015761018e565b806308be8700146101935780630de819b3146101c3578063112cee44146101f3578063126fe80d146102115780631627540c146102415780631e60ad3614610271575b600080fd5b6101ad60048036038101906101a891906141dc565b6105b1565b6040516101ba9190615513565b60405180910390f35b6101dd60048036038101906101d891906140e9565b610750565b6040516101ea9190615b14565b60405180910390f35b6101fb61081f565b6040516102089190615b51565b60405180910390f35b61022b600480360381019061022691906140c0565b61082a565b6040516102389190615af8565b60405180910390f35b61025b6004803603810190610256919061406e565b6108b2565b6040516102689190615513565b60405180910390f35b61028b600480360381019061028691906140c0565b610956565b60405161029891906154f1565b60405180910390f35b6102bb60048036038101906102b691906140c0565b610a5a565b6040516102c89190615513565b60405180910390f35b6102eb60048036038101906102e691906140c0565b610c32565b6040516102f89190615b2f565b60405180910390f35b610309610dcc565b6040516103169190615b51565b60405180910390f35b610339600480360381019061033491906141a0565b610dd7565b6040516103469190615513565b60405180910390f35b610369600480360381019061036491906141dc565b6110b0565b6040516103769190615513565b60405180910390f35b6103876114c1565b6040516103949190615476565b60405180910390f35b6103a56114e5565b6040516103b2919061559b565b60405180910390f35b6103c361150f565b6040516103d09190615513565b60405180910390f35b6103e1611611565b6040516103ee9190615b51565b60405180910390f35b610411600480360381019061040c91906141a0565b61161c565b60405161041e9190615513565b60405180910390f35b61042f6117ee565b60405161043c9190615b51565b60405180910390f35b61044d6117f8565b60405161045a9190615513565b60405180910390f35b61046b61198a565b6040516104789190615476565b60405180910390f35b6104896119b0565b604051610496919061559b565b60405180910390f35b6104b960048036038101906104b491906140c0565b6119da565b6040516104c69190615513565b60405180910390f35b6104d7611c56565b6040516104e49190615b51565b60405180910390f35b610507600480360381019061050291906140c0565b611c63565b6040516105149190615513565b60405180910390f35b610537600480360381019061053291906140c0565b611e5c565b604051610548959493929190615b6c565b60405180910390f35b61056b600480360381019061056691906141dc565b61202a565b6040516105789190615513565b60405180910390f35b61059b60048036038101906105969190614125565b6122ef565b6040516105a89190615513565b60405180910390f35b600081600081116105f7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105ee90615838565b60405180910390fd5b6105ff6124b2565b600061060a8561253f565b90506106146125aa565b81600001600201541161065c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161065390615898565b60405180910390fd5b6106768482600001600601546125b290919063ffffffff16565b816000016006018190555061069b8482600001600401546125b290919063ffffffff16565b81600001600401819055503373ffffffffffffffffffffffffffffffffffffffff16857f4130fbc98a3f18ae1e44c52a9645a7f92ba468ce7a05d81c0a89dc026c1b932c866040516106ed9190615b51565b60405180910390a3610744333086600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612607909392919063ffffffff16565b60019250505092915050565b610758613e29565b60006107638461253f565b90508060170160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060a00160405290816000820160009054906101000a900460ff161515151581526020016000820160019054906101000a900460ff161515151581526020016000820160029054906101000a900460ff161515151581526020016001820154815260200160028201548152505091505092915050565b600062093a80905090565b610832613e5e565b61083b8261253f565b600901604051806101000160405290816000820160009054906101000a900460ff161515151581526020016001820154815260200160028201548152602001600382015481526020016004820154815260200160058201548152602001600682015481526020016007820154815250509050919050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610944576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161093b90615938565b60405180910390fd5b61094d82612690565b60019050919050565b60606109618261253f565b601601805480602002602001604051908101604052809291908181526020016000905b82821015610a4f57838290600052602060002090600602016040518060c00160405290816000820160009054906101000a900460ff16151515158152602001600182015481526020016002820154815260200160038201548152602001600482015481526020016005820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152505081526020019060010190610984565b505050509050919050565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610aec576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ae390615938565b60405180910390fd5b8160008111610b30576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b2790615838565b60405180910390fd5b610b7c836040518060400160405280601c81526020017f5374616b696e6720706f6f6c20697320657874696e67756973686564000000008152506002546127169092919063ffffffff16565b6002819055507fa78b9f12a7da0df7ced737c5f83d0c05723bb5f43aab37e233b862710414847283604051610bb19190615b51565b60405180910390a1610c28600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166127719092919063ffffffff16565b6001915050919050565b610c3a613eab565b610c438261253f565b600001604051806101200160405290816000820160009054906101000a900460ff1615151515815260200160018201548152602001600282015481526020016003820154815260200160048201548152602001600582015481526020016006820154815260200160078201805480602002602001604051908101604052809291908181526020018280548015610d2e57602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311610ce4575b5050505050815260200160088201805480602002602001604051908101604052809291908181526020018280548015610dbc57602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311610d72575b5050505050815250509050919050565b60006207e900905090565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610e69576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e6090615938565b60405180910390fd5b6000610e748461253f565b90506000801b816009016007015414610ec2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eb990615918565b60405180910390fd5b8060090160000160009054906101000a900460ff16610f16576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f0d906156f8565b60405180910390fd5b60008160090160050154905080610f2b6127f7565b11610f6b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f6290615678565b60405180910390fd5b6000610f76826127ff565b90506000801b811415610fbe576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fb5906158f8565b60405180910390fd5b82600901600601543386604051602001610fd99291906153db565b604051602081830303815290604052805190602001201461102f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161102690615998565b60405180910390fd5b60008186604051602001611044929190615407565b604051602081830303815290604052805190602001209050808460090160070181905550867f107e5672d914f9cb403cf5ba0b6cadca8ea3b77331f2a24210fbe3ef540ca558878360405161109a929190615549565b60405180910390a2600194505050505092915050565b600081600081116110f6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110ed90615838565b60405180910390fd5b6110fe6124b2565b6000339050600061110e8661253f565b90506111186125aa565b816000016002015411611160576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161115790615898565b60405180910390fd5b600061117c8683600901600101546125b290919063ffffffff16565b90506000826016019050600081805490509050600084601101905060006111b28260010154848461280a9092919063ffffffff16565b9050836040518060c001604052806001151581526020018c8152602001886009016001015481526020018381526020018781526020018973ffffffffffffffffffffffffffffffffffffffff16815250908060018154018082558091505060019003906000526020600020906006020160009091909190915060008201518160000160006101000a81548160ff0219169083151502179055506020820151816001015560408201518160020155606082015181600301556080820151816004015560a08201518160050160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505084866009016001018190555084866000016005018190555060008660170160008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506113308b82600101546125b290919063ffffffff16565b81600101819055508060000160009054906101000a900460ff166113d45760018160000160006101000a81548160ff02191690831515021790555086600001600701889080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505b60006113f1670de0b6b3a76400008d6129aa90919063ffffffff16565b9050611408816002546125b290919063ffffffff16565b600281905550848973ffffffffffffffffffffffffffffffffffffffff168e7fef79519c5c873fe4437b5d7591c2ac60896fa489525254970cd9388f246d2fca8f6040516114569190615b51565b60405180910390a46114ad893083600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612607909392919063ffffffff16565b60019a505050505050505050505092915050565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146115a0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161159790615978565b60405180910390fd5b6115c960008054906101000a900473ffffffffffffffffffffffffffffffffffffffff16612a1a565b60008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506001905090565b600062015180905090565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146116ae576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116a590615938565b60405180910390fd5b60006116b98461253f565b90508060090160000160009054906101000a900460ff1615611710576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161170790615ad8565b60405180910390fd5b6117186125aa565b81600001600201541115611761576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161175890615ab8565b60405180910390fd5b60018160090160000160006101000a81548160ff021916908315150217905550828160090160060181905550600060016117996127f7565b019050808260090160050181905550847f02a2498943489e42740628e18ce0c039931c9820b2ee029fa881679440e9738d85836040516117da929190615572565b60405180910390a260019250505092915050565b6000600254905090565b6000806118036125aa565b90506000600a805490509050600a600181600181540180825580915050039060005260206000209050506000600a828154811061183c57fe5b906000526020600020906018020190506000600a611864600185612aa190919063ffffffff16565b8154811061186e57fe5b9060005260206000209060180201905060008061188961081f565b9050858360000160020154106118ba576118b38184600001600201546125b290919063ffffffff16565b915061192d565b60006118e8826118da86600001600201548a612aa190919063ffffffff16565b612aeb90919063ffffffff16565b9050611929611913836119056001856125b290919063ffffffff16565b6129aa90919063ffffffff16565b85600001600201546125b290919063ffffffff16565b9250505b818460000160020181905550847f9dabc2c637f100895272835b1380dc71381557c8025b8c7af70b855e64bd031a836040516119699190615b51565b60405180910390a28484600001600301819055506001965050505050505090565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008033905060006119eb8461253f565b905060008160170160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060000160029054906101000a900460ff16611a83576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a7a90615698565b60405180910390fd5b8060000160019054906101000a900460ff1615611ad5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611acc90615878565b60405180910390fd5b60008160020154905060008111611b21576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b18906156b8565b60405180910390fd5b8083600001600401541015611b6b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b6290615638565b60405180910390fd5b60018260000160016101000a81548160ff021916908315150217905550611ba2818460000160040154612aa190919063ffffffff16565b83600001600401819055508373ffffffffffffffffffffffffffffffffffffffff16867fb886382d42263e3c08a157dd29a33c435741f36625dbc3acb6fb8c19bbf7824783604051611bf49190615b51565b60405180910390a3611c498482600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166127719092919063ffffffff16565b6001945050505050919050565b6000600a80549050905090565b600080611c6f8361253f565b90506000611c7b6127f7565b90506000801b826009016007015414611cc9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cc090615798565b60405180910390fd5b6000826000016002015490508260090160000160009054906101000a900460ff1615611d6857600083600901600501548311905060008060001b611d1386600901600501546127ff565b14159050818015611d22575080155b611d61576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d5890615a58565b60405180910390fd5b5050611dcb565b611d706125aa565b611d8a611d7b611611565b836125b290919063ffffffff16565b10611dca576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611dc1906155d8565b60405180910390fd5b5b60018360090160000160006101000a81548160ff0219169083151502179055506000611e09611e04600185612aa190919063ffffffff16565b6127ff565b9050808460090160070181905550857f36882092d483bd52b047770e5cfcdf5e7e4697749bf2abf6f88eea7d569b5c4e82604051611e47919061552e565b60405180910390a26001945050505050919050565b60008060008060606000611e6f8761253f565b90506000816011019050806000015496508060010154955080600301549450806004015493508367ffffffffffffffff81118015611eac57600080fd5b50604051908082528060200260200182016040528015611ee657816020015b611ed3613ef9565b815260200190600190039081611ecb5790505b50925060008160000154905060005b8581101561201d57611f05613f1f565b611f188385612b3590919063ffffffff16565b9050604051806040016040528086601601836020015181548110611f3857fe5b90600052602060002090600602016040518060c00160405290816000820160009054906101000a900460ff16151515158152602001600182015481526020016002820154815260200160038201548152602001600482015481526020016005820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681525050815260200182815250868381518110611fff57fe5b60200260200101819052508060600151925050600181019050611ef5565b5050505091939590929450565b60006120346124b2565b600061203e6125aa565b9050600061204b8561253f565b600001905060008160070180549050111561211c578060000160009054906101000a900460ff166120b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120a890615818565b60405180910390fd5b60006120d16120be610dcc565b83600101546125b290919063ffffffff16565b905080831015612116576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161210d90615a98565b60405180910390fd5b50612164565b8060020154821015612163576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161215a90615ab8565b60405180910390fd5b5b600081600401549050600081116121b0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121a790615658565b60405180910390fd5b60006121bb8661253f565b600001905080600201548410612206576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121fd906159b8565b60405180910390fd5b61222261221d600188612aa190919063ffffffff16565b61253f565b6000016002015484101561226b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612262906158b8565b60405180910390fd5b6000836004018190555061228c8282600601546125b290919063ffffffff16565b81600601819055506122ab8282600401546125b290919063ffffffff16565b816004018190555085877fdf3f79258e7e555306e25bc8edefa1f545f767bc7817e5bfd89ce5380c9c832e60405160405180910390a3600194505050505092915050565b6000808211612333576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161232a90615618565b60405180910390fd5b600061233e8661253f565b90506000801b8160090160070154141561238d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612384906159f8565b60405180910390fd5b8060000160000160009054906101000a900460ff16156123e2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123d990615758565b60405180910390fd5b806009016003015484111561242c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612423906155f8565b60405180910390fd5b6000816009016002015414156124995780600901600301546124588587516125b290919063ffffffff16565b11612498576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161248f90615778565b60405180910390fd5b5b6124a581868686612bf5565b6001915050949350505050565b60006124cd6001600a80549050612aa190919063ffffffff16565b90506124d76125aa565b600a82815481106124e457fe5b9060005260206000209060180201600001600201541115612505575061253d565b807faa97d4a7b3afec5f55c25ca8593dde6929d4455fad650a16fa4334004293a61860405160405180910390a261253a6117f8565b50505b565b6000600a805490508210612588576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161257f90615958565b60405180910390fd5b600a828154811061259557fe5b90600052602060002090601802019050919050565b600042905090565b6000808284019050838110156125fd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125f490615718565b60405180910390fd5b8091505092915050565b61268a846323b872dd60e01b85858560405160240161262893929190615491565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050612f17565b50505050565b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce2260405160405180910390a250565b600083831115829061275e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161275591906155b6565b60405180910390fd5b5060008385039050809150509392505050565b6127f28363a9059cbb60e01b84846040516024016127909291906154c8565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050612f17565b505050565b600043905090565b600081409050919050565b60008084600201600085815260200190815260200160002090508060000160009054906101000a900460ff16806128415750600084145b612880576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612877906159d8565b60405180910390fd5b60018560030160008282540192505081905550600085600201600087600301548152602001908152602001600020905060018160000160006101000a81548160ff021916908315150217905550838160010181905550848160020181905550600085146128f15781600301546128f7565b85600001545b8160030181905550856003015482600301819055508560030154866002016000836002015481526020019081526020016000206003018190555085600301548660020160008360030154815260200190815260200160002060020181905550600085141561296d57856003015486600001819055505b856001015485141561298757856003015486600101819055505b600186600401600082825401925050819055508560030154925050509392505050565b6000808314156129bd5760009050612a14565b60008284029050828482816129ce57fe5b0414612a0f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a06906158d8565b60405180910390fd5b809150505b92915050565b80600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167fa2ea9883a321a3e97b8266c2b078bfeec6d50c711ed71f874a90d500ae2eaf3660405160405180910390a250565b6000612ae383836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612716565b905092915050565b6000612b2d83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250612fde565b905092915050565b612b3d613f1f565b600083600201600084815260200190815260200160002090508060000160009054906101000a900460ff16612ba7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b9e906156d8565b60405180910390fd5b806040518060800160405290816000820160009054906101000a900460ff16151515158152602001600182015481526020016002820154815260200160038201548152505091505092915050565b600084600901600401549050612c156001826125b290919063ffffffff16565b8560090160040181905550600085600901600201541115612c5857612c398561303f565b6001821115612c5257612c5185858560018603612bf5565b5b50612f11565b6000856009016007015482604051602001612c74929190615433565b6040516020818303038152906040528051906020012060001c905060008660090160030154905080612cb08688516125b290919063ffffffff16565b11612cbd57505050612f11565b612cd787600901600101548361363b90919063ffffffff16565b9150600086612cef8784612aa190919063ffffffff16565b81518110612cf957fe5b6020026020010151905087601601805490508110612d4c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d43906157b8565b60405180910390fd5b6000886016018281548110612d5d57fe5b90600052602060002090600602019050612d816001846125b290919063ffffffff16565b89600901600301819055508060000160009054906101000a900460ff16612ddd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612dd4906157d8565b60405180910390fd5b83816002015411158015612df45750838160040154115b612e33576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e2a90615738565b60405180910390fd5b60008160050160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060008a60170160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060000160029054906101000a900460ff16612edf576000612ec48c8385613685565b90508015612ed9575050505050505050612f11565b50612ef0565b82600301548b600901600201819055505b6001881115612f0957612f088b8b8b60018c03612bf5565b5b505050505050505b50505050565b6060612f79826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1661384e9092919063ffffffff16565b9050600081511115612fd95780806020019051810190612f999190614097565b612fd8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612fcf90615a78565b60405180910390fd5b5b505050565b60008083118290613025576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161301c91906155b6565b60405180910390fd5b50600083858161303157fe5b049050809150509392505050565b6000816011019050600061306082600101548361386690919063ffffffff16565b9050600083601601828154811061307357fe5b9060005260206000209060060201905061308b613f1f565b6130a5856009016002015485612b3590919063ffffffff16565b90506000856016018260200151815481106130bc57fe5b90600052602060002090600602019050856009016002015485600101541415613156576130fd83600101548760090160010154612aa190919063ffffffff16565b86600901600101819055506131228660090160020154866138df90919063ffffffff16565b6000866009016002018190555060008160000160006101000a81548160ff0219169083151502179055505050505050613638565b60008660170160008560050160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060000160029054906101000a900460ff161561323e576131f484600101548860090160010154612aa190919063ffffffff16565b87600901600101819055506132168660010154876138df90919063ffffffff16565b60008460000160006101000a81548160ff021916908315150217905550505050505050613638565b6000613252836001015486600101546139fc565b905061326e818960090160010154612aa190919063ffffffff16565b8860090160010181905550600084604001511115613356576000886016016132a386604001518a61386690919063ffffffff16565b815481106132ad57fe5b906000526020600020906006020190508560050160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168160050160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614156133545761334789828689868d613a15565b5050505050505050613638565b505b6000846060015111801561337257508660010154846060015114155b156134475760008860160161339486606001518a61386690919063ffffffff16565b8154811061339e57fe5b906000526020600020906006020190508560050160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168160050160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614156134455761343889828689868d613ad1565b5050505050505050613638565b505b6000886016018054905090506000846002015490506134738386600201546125b290919063ffffffff16565b8560020181905550613492838660010154612aa190919063ffffffff16565b85600101819055506134b1838860010154612aa190919063ffffffff16565b87600101819055506134d0838860040154612aa190919063ffffffff16565b876004018190555060006134f38760400151848c61280a9092919063ffffffff16565b90508a6016016040518060c00160405280600115158152602001868152602001848152602001838152602001886002015481526020018a60050160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815250908060018154018082558091505060019003906000526020600020906006020160009091909190915060008201518160000160006101000a81548160ff0219169083151502179055506020820151816001015560408201518160020155606082015181600301556080820151816004015560a08201518160050160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505061362d8b878a8d613b8d565b505050505050505050505b50565b600061367d83836040518060400160405280601881526020017f536166654d6174683a206d6f64756c6f206279207a65726f0000000000000000815250613c27565b905092915050565b6000806136ba60058660000160080180549050600581106136a257fe5b01548660000160060154612aeb90919063ffffffff16565b905080846002018190555060018460000160026101000a81548160ff02191690831515021790555084600001600801839080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000856000016008018054905090508373ffffffffffffffffffffffffffffffffffffffff1686600001600301547f51717f575c62af12c537bf652bd8c4fe4eb97454d8a29042b45342ba4002db4f846040516137a79190615b51565b60405180910390a36005811015806137c9575085600001600701805490508110155b156138405785600001600301547fe9f7d7fd0b133404f0ccff737d6f3594748e04bc5507adfaed35835ef989371160405160405180910390a260018660000160000160006101000a81548160ff02191690831515021790555061382a6125aa565b8660000160010181905550600192505050613847565b6000925050505b9392505050565b606061385d8484600085613c83565b90509392505050565b60008083600201600084815260200190815260200160002090508060000160009054906101000a900460ff166138d1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016138c890615858565b60405180910390fd5b806001015491505092915050565b600082600201600083815260200190815260200160002090508060000160009054906101000a900460ff16613949576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161394090615a38565b60405180910390fd5b60008160000160006101000a81548160ff021916908315150217905550806003015483600201600083600201548152602001908152602001600020600301819055508060020154836002016000836003015481526020019081526020016000206002018190555081836000015414156139ca57806003015483600001819055505b81836001015414156139e457806002015483600101819055505b60018360040160008282540392505081905550505050565b6000818310613a0b5781613a0d565b825b905092915050565b613a2c8286600101546125b290919063ffffffff16565b8560010181905550613a4b8286600401546125b290919063ffffffff16565b856004018190555084600401548460020181905550613a77828560010154612aa190919063ffffffff16565b8460010181905550613a96828460040154612aa190919063ffffffff16565b8360040181905550613ab5828460010154612aa190919063ffffffff16565b8360010181905550613ac986858584613b8d565b505050505050565b613ae88286600101546125b290919063ffffffff16565b8560010181905550613b07828660020154612aa190919063ffffffff16565b856002018190555084600201548460040181905550613b33828560010154612aa190919063ffffffff16565b8460010181905550613b52828460040154612aa190919063ffffffff16565b8360040181905550613b71828460010154612aa190919063ffffffff16565b8360010181905550613b8586858584613b8d565b505050505050565b600083600101541415613bdf5760008360000160006101000a81548160ff021916908315150217905550613bd18460090160020154826138df90919063ffffffff16565b600084600901600201819055505b600082600101541415613c215760008260000160006101000a81548160ff021916908315150217905550613c208160010154826138df90919063ffffffff16565b5b50505050565b6000808314158290613c6f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613c6691906155b6565b60405180910390fd5b50828481613c7957fe5b0690509392505050565b6060823073ffffffffffffffffffffffffffffffffffffffff16311015613cdf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613cd6906157f8565b60405180910390fd5b613ce885613daf565b613d27576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613d1e90615a18565b60405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff168587604051613d51919061545f565b60006040518083038185875af1925050503d8060008114613d8e576040519150601f19603f3d011682016040523d82523d6000602084013e613d93565b606091505b5091509150613da3828286613dc2565b92505050949350505050565b600080823b905060008111915050919050565b60608315613dd257829050613e22565b600083511115613de55782518084602001fd5b816040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613e1991906155b6565b60405180910390fd5b9392505050565b6040518060a0016040528060001515815260200160001515815260200160001515815260200160008152602001600081525090565b604051806101000160405280600015158152602001600081526020016000815260200160008152602001600081526020016000815260200160008019168152602001600080191681525090565b60405180610120016040528060001515815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160608152602001606081525090565b6040518060400160405280613f0c613f49565b8152602001613f19613f1f565b81525090565b60405180608001604052806000151581526020016000815260200160008152602001600081525090565b6040518060c0016040528060001515815260200160008152602001600081526020016000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff1681525090565b600081359050613fa681615e09565b92915050565b600082601f830112613fbd57600080fd5b8135613fd0613fcb82615bf3565b615bc6565b91508181835260208401935060208101905083856020840282011115613ff557600080fd5b60005b83811015614025578161400b8882614059565b845260208401935060208301925050600181019050613ff8565b5050505092915050565b60008151905061403e81615e20565b92915050565b60008135905061405381615e37565b92915050565b60008135905061406881615e4e565b92915050565b60006020828403121561408057600080fd5b600061408e84828501613f97565b91505092915050565b6000602082840312156140a957600080fd5b60006140b78482850161402f565b91505092915050565b6000602082840312156140d257600080fd5b60006140e084828501614059565b91505092915050565b600080604083850312156140fc57600080fd5b600061410a85828601614059565b925050602061411b85828601613f97565b9150509250929050565b6000806000806080858703121561413b57600080fd5b600061414987828801614059565b945050602085013567ffffffffffffffff81111561416657600080fd5b61417287828801613fac565b935050604061418387828801614059565b925050606061419487828801614059565b91505092959194509250565b600080604083850312156141b357600080fd5b60006141c185828601614059565b92505060206141d285828601614044565b9150509250929050565b600080604083850312156141ef57600080fd5b60006141fd85828601614059565b925050602061420e85828601614059565b9150509250929050565b60006142248383614278565b60208301905092915050565b600061423c83836150d0565b6101408301905092915050565b60006142558383615100565b60c08301905092915050565b61427261426d82615d0a565b615db3565b82525050565b61428181615cf8565b82525050565b61429081615cf8565b82525050565b60006142a182615c4b565b6142ab8185615ca9565b93506142b683615c1b565b8060005b838110156142e75781516142ce8882614218565b97506142d983615c82565b9250506001810190506142ba565b5085935050505092915050565b60006142ff82615c56565b6143098185615cba565b935061431483615c2b565b8060005b8381101561434557815161432c8882614230565b975061433783615c8f565b925050600181019050614318565b5085935050505092915050565b600061435d82615c61565b6143678185615ccb565b935061437283615c3b565b8060005b838110156143a357815161438a8882614249565b975061439583615c9c565b925050600181019050614376565b5085935050505092915050565b6143b981615d1c565b82525050565b6143c881615d1c565b82525050565b6143d781615d28565b82525050565b6143e681615d28565b82525050565b6143fd6143f882615d28565b615dc5565b82525050565b600061440e82615c6c565b6144188185615cdc565b9350614428818560208601615d80565b80840191505092915050565b61443d81615d5c565b82525050565b600061444e82615c77565b6144588185615ce7565b9350614468818560208601615d80565b61447181615deb565b840191505092915050565b6000614489602283615ce7565b91507f4f776e6572207375626d697474696e6720706572696f64206e6f74207061737360008301527f65640000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006144ef601c83615ce7565b91507f47617020696e206974657261626c6520656e7472696573206c697374000000006000830152602082019050919050565b600061452f601283615ce7565b91507f4c696d6974206e6f7420706f73697469766500000000000000000000000000006000830152602082019050919050565b600061456f601d83615ce7565b91507f52657761726420726575736564206173206e657874206a61636b706f740000006000830152602082019050919050565b60006145af601083615ce7565b91507f4e6f7468696e6720746f207265757365000000000000000000000000000000006000830152602082019050919050565b60006145ef602e83615ce7565b91507f556e61626c6520746f2072657665616c207365616c65642073656564206f6e2060008301527f7468652073616d6520626c6f636b0000000000000000000000000000000000006020830152604082019050919050565b6000614655601283615ce7565b91507f4e6f74206120726f756e642077696e6e657200000000000000000000000000006000830152602082019050919050565b6000614695601e83615ce7565b91507f52657761726420616d6f756e7420697320657175616c20746f207a65726f00006000830152602082019050919050565b60006146d5602883615ce7565b91507f4c696e6b65644c697374206765744e6f64653a20706f696e746572206f75742060008301527f6f662073636f70650000000000000000000000000000000000000000000000006020830152604082019050919050565b600061473b601883615ce7565b91507f5365616c65642073656564206e6f742070726f766964656400000000000000006000830152602082019050919050565b600061477b601b83615ce7565b91507f536166654d6174683a206164646974696f6e206f766572666c6f7700000000006000830152602082019050919050565b60006147bb601f83615ce7565b91507f496e76616c6964206578706563746564206974657261626c6520656e747279006000830152602082019050919050565b60006147fb602283615ce7565b91507f526573756c7420616c726561647920686173206265656e2063616c63756c617460008301527f65640000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000614861601483615ce7565b91507f4e6f7468696e6720746f2063616c63756c6174650000000000000000000000006000830152602082019050919050565b60006148a1601583615ce7565b91507f5365656420616c72656164792070726f766964656400000000000000000000006000830152602082019050919050565b60006148e1601c83615ce7565b91507f496e76616c6964206974657261626c6520656e74727920696e646578000000006000830152602082019050919050565b6000614921602283615ce7565b91507f4578706563746564206974657261626c6520656e747279206e6f74206163746960008301527f76650000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000614987602683615ce7565b91507f416464726573733a20696e73756666696369656e742062616c616e636520666f60008301527f722063616c6c00000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006149ed601583615ce7565b91507f46726f6d20726f756e64206e6f7420636c6f73656400000000000000000000006000830152602082019050919050565b6000614a2d601683615ce7565b91507f416d6f756e74206973206e6f7420706f736974697665000000000000000000006000830152602082019050919050565b6000614a6d602483615ce7565b91507f4c696e6b65644c697374206765743a20706f696e746572206f7574206f66207360008301527f636f7065000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000614ad3601983615ce7565b91507f526f756e642072657761726420616c72656164792070616964000000000000006000830152602082019050919050565b6000614b13601383615ce7565b91507f526f756e6420616c726561647920656e646564000000000000000000000000006000830152602082019050919050565b6000614b53602483615ce7565b91507f41626c6520746f207265757365206f6e6c7920666f722063757272656e74207260008301527f6f756e64000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000614bb9602183615ce7565b91507f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f60008301527f77000000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000614c1f603683615ce7565b91507f4d6f7265207468616e2032353620626c6f636b73207061737365642066726f6d60008301527f2070726f766964696e67207365616c65642073656564000000000000000000006020830152604082019050919050565b6000614c85601583615ce7565b91507f5365656420616c72656164792072657665616c656400000000000000000000006000830152602082019050919050565b6000614cc5602083615ce7565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b6000614d05600f83615ce7565b91507f526f756e64206e6f7420666f756e6400000000000000000000000000000000006000830152602082019050919050565b6000614d45601a83615ce7565b91507f4e6f74206e6f6d696e6174656420746f206f776e6572736869700000000000006000830152602082019050919050565b6000614d85600c83615ce7565b91507f496e76616c6964207365656400000000000000000000000000000000000000006000830152602082019050919050565b6000614dc5601683615ce7565b91507f496e20726f756e6420616c726561647920656e646564000000000000000000006000830152602082019050919050565b6000614e05602783615ce7565b91507f4c696e6b65644c69737420696e736572743a20706f696e746572206f7574206f60008301527f662073636f7065000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000614e6b601183615ce7565b91507f53656564206e6f742072657665616c65640000000000000000000000000000006000830152602082019050919050565b6000614eab601d83615ce7565b91507f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006000830152602082019050919050565b6000614eeb602783615ce7565b91507f4c696e6b65644c6973742072656d6f76653a20706f696e746572206f7574206f60008301527f662073636f7065000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000614f51603683615ce7565b91507f4c657373207468616e2032353620626c6f636b73207061737365642066726f6d60008301527f2070726f766964696e67207365616c65642073656564000000000000000000006020830152604082019050919050565b6000614fb7602a83615ce7565b91507f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008301527f6f742073756363656564000000000000000000000000000000000000000000006020830152604082019050919050565b600061501d602083615ce7565b91507f55736572732063616e20776974686472617720746865697220726577617264736000830152602082019050919050565b600061505d600f83615ce7565b91507f526f756e64206e6f7420656e64656400000000000000000000000000000000006000830152602082019050919050565b600061509d601c83615ce7565b91507f5365616c6564207365656420616c72656164792070726f7669646564000000006000830152602082019050919050565b610140820160008201516150e76000850182615100565b5060208201516150fa60c085018261517b565b50505050565b60c08201600082015161511660008501826143b0565b50602082015161512960208501826153a6565b50604082015161513c60408501826153a6565b50606082015161514f60608501826153a6565b50608082015161516260808501826153a6565b5060a082015161517560a0850182614278565b50505050565b60808201600082015161519160008501826143b0565b5060208201516151a460208501826153a6565b5060408201516151b760408501826153a6565b5060608201516151ca60608501826153a6565b50505050565b610100820160008201516151e760008501826143b0565b5060208201516151fa60208501826153a6565b50604082015161520d60408501826153a6565b50606082015161522060608501826153a6565b50608082015161523360808501826153a6565b5060a082015161524660a08501826153a6565b5060c082015161525960c08501826143ce565b5060e082015161526c60e08501826143ce565b50505050565b60a08201600082015161528860008501826143b0565b50602082015161529b60208501826143b0565b5060408201516152ae60408501826143b0565b5060608201516152c160608501826153a6565b5060808201516152d460808501826153a6565b50505050565b6000610120830160008301516152f360008601826143b0565b50602083015161530660208601826153a6565b50604083015161531960408601826153a6565b50606083015161532c60608601826153a6565b50608083015161533f60808601826153a6565b5060a083015161535260a08601826153a6565b5060c083015161536560c08601826153a6565b5060e083015184820360e086015261537d8282614296565b9150506101008301518482036101008601526153998282614296565b9150508091505092915050565b6153af81615d52565b82525050565b6153be81615d52565b82525050565b6153d56153d082615d52565b615de1565b82525050565b60006153e78285614261565b6014820191506153f782846143ec565b6020820191508190509392505050565b600061541382856143ec565b60208201915061542382846143ec565b6020820191508190509392505050565b600061543f82856143ec565b60208201915061544f82846153c4565b6020820191508190509392505050565b600061546b8284614403565b915081905092915050565b600060208201905061548b6000830184614287565b92915050565b60006060820190506154a66000830186614287565b6154b36020830185614287565b6154c060408301846153b5565b949350505050565b60006040820190506154dd6000830185614287565b6154ea60208301846153b5565b9392505050565b6000602082019050818103600083015261550b8184614352565b905092915050565b600060208201905061552860008301846143bf565b92915050565b600060208201905061554360008301846143dd565b92915050565b600060408201905061555e60008301856143dd565b61556b60208301846143dd565b9392505050565b600060408201905061558760008301856143dd565b61559460208301846153b5565b9392505050565b60006020820190506155b06000830184614434565b92915050565b600060208201905081810360008301526155d08184614443565b905092915050565b600060208201905081810360008301526155f18161447c565b9050919050565b60006020820190508181036000830152615611816144e2565b9050919050565b6000602082019050818103600083015261563181614522565b9050919050565b6000602082019050818103600083015261565181614562565b9050919050565b60006020820190508181036000830152615671816145a2565b9050919050565b60006020820190508181036000830152615691816145e2565b9050919050565b600060208201905081810360008301526156b181614648565b9050919050565b600060208201905081810360008301526156d181614688565b9050919050565b600060208201905081810360008301526156f1816146c8565b9050919050565b600060208201905081810360008301526157118161472e565b9050919050565b600060208201905081810360008301526157318161476e565b9050919050565b60006020820190508181036000830152615751816147ae565b9050919050565b60006020820190508181036000830152615771816147ee565b9050919050565b6000602082019050818103600083015261579181614854565b9050919050565b600060208201905081810360008301526157b181614894565b9050919050565b600060208201905081810360008301526157d1816148d4565b9050919050565b600060208201905081810360008301526157f181614914565b9050919050565b600060208201905081810360008301526158118161497a565b9050919050565b60006020820190508181036000830152615831816149e0565b9050919050565b6000602082019050818103600083015261585181614a20565b9050919050565b6000602082019050818103600083015261587181614a60565b9050919050565b6000602082019050818103600083015261589181614ac6565b9050919050565b600060208201905081810360008301526158b181614b06565b9050919050565b600060208201905081810360008301526158d181614b46565b9050919050565b600060208201905081810360008301526158f181614bac565b9050919050565b6000602082019050818103600083015261591181614c12565b9050919050565b6000602082019050818103600083015261593181614c78565b9050919050565b6000602082019050818103600083015261595181614cb8565b9050919050565b6000602082019050818103600083015261597181614cf8565b9050919050565b6000602082019050818103600083015261599181614d38565b9050919050565b600060208201905081810360008301526159b181614d78565b9050919050565b600060208201905081810360008301526159d181614db8565b9050919050565b600060208201905081810360008301526159f181614df8565b9050919050565b60006020820190508181036000830152615a1181614e5e565b9050919050565b60006020820190508181036000830152615a3181614e9e565b9050919050565b60006020820190508181036000830152615a5181614ede565b9050919050565b60006020820190508181036000830152615a7181614f44565b9050919050565b60006020820190508181036000830152615a9181614faa565b9050919050565b60006020820190508181036000830152615ab181615010565b9050919050565b60006020820190508181036000830152615ad181615050565b9050919050565b60006020820190508181036000830152615af181615090565b9050919050565b600061010082019050615b0e60008301846151d0565b92915050565b600060a082019050615b296000830184615272565b92915050565b60006020820190508181036000830152615b4981846152da565b905092915050565b6000602082019050615b6660008301846153b5565b92915050565b600060a082019050615b8160008301886153b5565b615b8e60208301876153b5565b615b9b60408301866153b5565b615ba860608301856153b5565b8181036080830152615bba81846142f4565b90509695505050505050565b6000604051905081810181811067ffffffffffffffff82111715615be957600080fd5b8060405250919050565b600067ffffffffffffffff821115615c0a57600080fd5b602082029050602081019050919050565b6000819050602082019050919050565b6000819050602082019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b6000615d0382615d32565b9050919050565b6000615d1582615d32565b9050919050565b60008115159050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b6000615d6782615d6e565b9050919050565b6000615d7982615d32565b9050919050565b60005b83811015615d9e578082015181840152602081019050615d83565b83811115615dad576000848401525b50505050565b6000615dbe82615dcf565b9050919050565b6000819050919050565b6000615dda82615dfc565b9050919050565b6000819050919050565b6000601f19601f8301169050919050565b60008160601b9050919050565b615e1281615cf8565b8114615e1d57600080fd5b50565b615e2981615d1c565b8114615e3457600080fd5b50565b615e4081615d28565b8114615e4b57600080fd5b50565b615e5781615d52565b8114615e6257600080fd5b5056fea2646970667358221220176a47206bcd8d6ba20ec26da49ce3da060e6ab2579cfe50d7acaa3bcd0c137464736f6c634300060c0033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

0000000000000000000000003593d125a4f7849a1b059e64f4517a86dd60c95d000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7000000000000000000000000000000000000000000000000000000005febc300000000000000000000000000d4eee3d50588d7dee8dcc42635e50093e0aa8cc0

-----Decoded View---------------
Arg [0] : stakingToken_ (address): 0x3593D125a4f7849a1B059E64F4517A86Dd60c95d
Arg [1] : jackpotToken_ (address): 0xdAC17F958D2ee523a2206206994597C13D831ec7
Arg [2] : firstRoundEndsAt (uint256): 1609286400
Arg [3] : owner_ (address): 0xd4eeE3D50588D7dee8Dcc42635E50093E0AA8Cc0

-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 0000000000000000000000003593d125a4f7849a1b059e64f4517a86dd60c95d
Arg [1] : 000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7
Arg [2] : 000000000000000000000000000000000000000000000000000000005febc300
Arg [3] : 000000000000000000000000d4eee3d50588d7dee8dcc42635e50093e0aa8cc0


Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]

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.