Source Code
Latest 25 from a total of 1,592 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Withdraw Rewards | 21735939 | 393 days ago | IN | 0 ETH | 0.00017329 | ||||
| Withdraw Rewards | 21735926 | 393 days ago | IN | 0 ETH | 0.00017123 | ||||
| Withdraw Rewards | 21735918 | 393 days ago | IN | 0 ETH | 0.00018067 | ||||
| Calculate Round ... | 21735908 | 393 days ago | IN | 0 ETH | 0.00032349 | ||||
| Calculate Round ... | 21735707 | 393 days ago | IN | 0 ETH | 0.00059664 | ||||
| Calculate Round ... | 21735684 | 393 days ago | IN | 0 ETH | 0.00075093 | ||||
| Calculate Round ... | 21735661 | 393 days ago | IN | 0 ETH | 0.00028151 | ||||
| Provide Missing ... | 21735652 | 393 days ago | IN | 0 ETH | 0.00013137 | ||||
| Buy Entries | 21726442 | 395 days ago | IN | 0 ETH | 0.00143924 | ||||
| Buy Entries | 21726439 | 395 days ago | IN | 0 ETH | 0.00148906 | ||||
| Buy Entries | 21726336 | 395 days ago | IN | 0 ETH | 0.00219244 | ||||
| Reuse Non Withdr... | 21726333 | 395 days ago | IN | 0 ETH | 0.00020478 | ||||
| Reuse Non Withdr... | 21726328 | 395 days ago | IN | 0 ETH | 0.0003684 | ||||
| Create New Round | 21726324 | 395 days ago | IN | 0 ETH | 0.00033421 | ||||
| Withdraw Stake | 18640003 | 826 days ago | IN | 0 ETH | 0.00085738 | ||||
| Withdraw Stake | 18639924 | 826 days ago | IN | 0 ETH | 0.00092847 | ||||
| Withdraw Stake | 18639916 | 826 days ago | IN | 0 ETH | 0.00097022 | ||||
| Withdraw Stake | 18639903 | 826 days ago | IN | 0 ETH | 0.00099477 | ||||
| Withdraw Stake | 18639899 | 826 days ago | IN | 0 ETH | 0.00104008 | ||||
| Withdraw Stake | 18639895 | 826 days ago | IN | 0 ETH | 0.00103529 | ||||
| Accept Ownership | 15357285 | 1290 days ago | IN | 0 ETH | 0.0003106 | ||||
| Nominate New Own... | 15357282 | 1290 days ago | IN | 0 ETH | 0.00043986 | ||||
| Withdraw Rewards | 13543562 | 1577 days ago | IN | 0 ETH | 0.0099336 | ||||
| Withdraw Rewards | 13543540 | 1577 days ago | IN | 0 ETH | 0.00828189 | ||||
| Withdraw Rewards | 13543540 | 1577 days ago | IN | 0 ETH | 0.01331344 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
LotteryLikePool
Compiler Version
v0.6.12+commit.27d51765
Optimization Enabled:
No with 200 runs
Other Settings:
constantinople EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// 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);
}
}
}
}{
"remappings": [],
"optimizer": {
"enabled": false,
"runs": 200
},
"evmVersion": "constantinople",
"libraries": {
"": {}
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
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"}]Contract Creation Code
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
Loading...
Loading
Loading...
Loading
Net Worth in USD
$105.47
Net Worth in ETH
0.054538
Token Allocations
USDT
100.00%
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| ETH | 100.00% | $1 | 105.4688 | $105.47 |
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.