Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- Lottery
- Optimization enabled
- true
- Compiler version
- v0.8.19+commit.7dd6d404
- Optimization runs
- 200
- EVM Version
- default
- Verified at
- 2024-09-26T15:32:28.715456Z
Contract source code
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @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);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 value) 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 a `value` amount of tokens 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 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 value) external returns (bool);
}
abstract contract Entropy_interface {
function get_entropy() public virtual view returns (uint256);
function new_round() virtual external;
function deposit_entropy_reward() external virtual payable;
function get_entropy_collateral() public view virtual returns (uint256);
function get_number_of_revealed() public view virtual returns(uint256);
}
contract Lottery {
event NewRound(uint256 indexed round_id);
event RoundFinished(uint256 indexed round_id, address indexed winner, uint256 reward, uint256 rng);
event Deposit(address indexed depositor, uint256 amount_deposited, uint256 amount_credited);
event Refund(address indexed receiver, uint256 indexed round_id, uint256 amount);
address public owner = msg.sender;
address payable public entropy_contract;
address payable public reward_pool_contract; // Token rewards go to the special "staking contract"
//uint256 public deposits_phase_duration = 3 days; // The length of a phase when deposits are accepted;
//uint256 public entropy_phase_duration = 1 days; // The length of a phase when entropy providers reveal their entropy inputs;
uint256 public deposits_phase_duration = 10 minutes;
uint256 public entropy_phase_duration = 5 minutes;
uint256 public entropy_fee = 30; // (will be divided by 1000 during calculations i.e. 1 means 0.1%) | this reward goes to the entropy providers reward pool
// 30 is 3%
uint256 public token_reward_fee = 100; // This reward goes to staked tokens reward pool
// 100 is 10%
uint256 public min_allowed_bet = 1000 ether; // 1K CLO for now
uint8 public max_allowed_deposits = 20; // A user can make 20 bets during a single round
uint256 public max_deposit_pool_threshold = 0; // Specifies the maximal amount the lottery will accept.
// After the amount is reached
// the lottery will no longer accept deposits.
// 0 means "unlimited".
uint256 public current_round;
uint256 public round_start_timestamp;
uint256 public round_reward;
bool public round_reward_paid = false;
mapping (uint256 => bool) public round_failed; // Allows "refunds" of not succesful rounds.
uint256 public current_interval_end; // Used for winner calculations
bool public debug_mode = true;
modifier only_debug
{
require(debug_mode);
_;
}
struct interval
{
uint256 interval_start;
uint256 interval_end;
}
struct player
{
mapping (uint256 => uint8) num_deposits;
uint256 last_round;
mapping (uint256 => mapping (uint8 => interval)) win_conditions; // This player is considered to be a winner when RNG provides a number that matches this intervals
mapping (uint256 => bool) round_refunded;
}
mapping (address => player) public players;
receive() external payable
{
if(get_phase() == 0)
{
start_new_round();
}
else if(get_phase() == 1)
{
deposit();
}
else
{
revert();
}
}
function get_round() public view returns (uint256)
{
return current_round;
}
function get_max_deposit_threshold() public view returns (uint256)
{
return max_deposit_pool_threshold;
}
function get_win_conditions(address _player, uint256 _round, uint8 _depoindex) public view returns(uint256 _start, uint256 _end)
{
_start = players[_player].win_conditions[_round][_depoindex].interval_start;
_end = players[_player].win_conditions[_round][_depoindex].interval_end;
}
function is_winner(address _user) public view returns (bool)
{
bool winner = false;
for (uint8 i = 0; i <= players[_user].num_deposits[current_round]; i++)
{
if(players[_user].win_conditions[current_round][i].interval_start < RNG() && players[_user].win_conditions[current_round][i].interval_end > RNG())
{
winner = true;
}
}
return winner;
}
function get_phase() public view returns (uint8)
{
// 0 - the lottery is not active / pending new round start
// 1 - a lottery round is in progress / acquiring deposits
// 2 - deposits are acquired / entropy revealing phase
// 3 - entropy is revealed, but winner is not paid / it is the time to pay the winner
// 4 - round is finished and the winner is paid / anyone can start a new round
uint8 _status = 0;
if(round_start_timestamp <= block.timestamp && block.timestamp <= round_start_timestamp + deposits_phase_duration)
{
_status = 1;
}
else if (round_start_timestamp < block.timestamp && block.timestamp < round_start_timestamp + deposits_phase_duration + entropy_phase_duration)
{
_status = 2;
}
else if (round_start_timestamp != 0 && round_start_timestamp < block.timestamp && block.timestamp > round_start_timestamp + deposits_phase_duration + entropy_phase_duration && !round_reward_paid)
{
_status = 3;
}
/*
else if (round_start_timestamp < block.timestamp && block.timestamp > round_start_timestamp + deposits_phase_duration + entropy_phase_duration && round_reward_paid)
{
_status = 4;
}
*/
return _status;
}
function deposit() public payable
{
require (msg.value >= min_allowed_bet, "Minimum bet condition is not met");
require (players[msg.sender].num_deposits[current_round] < max_allowed_deposits || players[msg.sender].last_round < current_round, "Too much deposits during this round");
require (get_phase() == 1, "Deposits are only allowed during the depositing phase");
if(max_deposit_pool_threshold != 0)
{
require(msg.value + round_reward <= max_deposit_pool_threshold, "Round reward threshold exceeded");
}
if(players[msg.sender].last_round < current_round)
{
players[msg.sender].last_round = current_round;
players[msg.sender].num_deposits[current_round] = 0;
}
else
{
players[msg.sender].num_deposits[current_round]++;
}
// Assign the "winning interval" for the player
players[msg.sender].win_conditions[current_round][players[msg.sender].num_deposits[current_round]].interval_start = current_interval_end;
players[msg.sender].win_conditions[current_round][players[msg.sender].num_deposits[current_round]].interval_end = current_interval_end + msg.value;
current_interval_end += msg.value;
uint256 _reward_after_fees = msg.value;
// TODO: replace it with SafeMath
// TODO: update the contract to only send rewards upon completion of the round
send_token_reward(msg.value * token_reward_fee / 1000);
_reward_after_fees -= (msg.value * token_reward_fee / 1000);
send_entropy_reward(msg.value * entropy_fee / 1000);
_reward_after_fees -= msg.value * entropy_fee / 1000;
round_reward += _reward_after_fees;
emit Deposit(msg.sender, msg.value, _reward_after_fees);
}
function refund(uint256 _round) external
{
//require(current_round > _round, "Only refunds of finished rounds are allowed");
require(round_failed[_round], "Only refunds of FAILED rounds are allowed");
// Calculating the refund amount
uint256 _reward = 0;
for (uint8 i = 0; i <= players[msg.sender].num_deposits[_round]; i++)
{
_reward += players[msg.sender].win_conditions[_round][i].interval_end - players[msg.sender].win_conditions[_round][i].interval_start;
}
uint256 _reward_before_fees = _reward;
// Subtract the entropy fee
_reward -= _reward_before_fees * entropy_fee / 1000;
_reward -= _reward_before_fees * token_reward_fee / 1000;
players[msg.sender].round_refunded[_round] = true;
payable(msg.sender).transfer(_reward);
emit Refund(msg.sender, _round, _reward);
}
function send_entropy_reward(uint256 _reward) internal
{
//entropy_contract.transfer(msg.value * entropy_fee / 1000);
//entropy_contract.transfer(_reward);
Entropy_interface(entropy_contract).deposit_entropy_reward{value: _reward}();
}
function send_token_reward(uint256 _reward) internal
{
//reward_pool_contract.transfer(msg.value * token_reward_fee / 1000);
//reward_pool_contract.transfer(_reward);
reward_pool_contract.call{value: _reward};
}
function start_new_round() public payable
{
require(current_round == 0 || round_reward_paid, "Cannot start a new round while reward for the previous one is not paid. Call finish_round function");
current_round++;
emit NewRound(current_round);
round_start_timestamp = block.timestamp;
current_interval_end = 0;
round_reward_paid = false;
Entropy_interface(entropy_contract).new_round();
//require_entropy_provider(msg.sender); // Request the starter of a new round to also provide initial entropy
// Initiate the first deposit of the round
deposit();
}
function finish_round(address payable _winner) public
{
// Important: finishing an active round does not automatically start a new one
require(block.timestamp > round_start_timestamp + deposits_phase_duration + entropy_phase_duration, "Round can be finished after the entropy reveal phase only");
//require(check_entropy_criteria(), "There is not enough entropy to ensure a fair winner calculation");
if(check_entropy_criteria())
{
// Round is succsefully completed and there was enough entropy provided
// Paying the winner
// Safe loop, cannot be more than 20 iterations
for (uint8 i = 0; i <= players[_winner].num_deposits[current_round]; i++)
{
if(players[_winner].win_conditions[current_round][i].interval_start < RNG() && players[_winner].win_conditions[current_round][i].interval_end >= RNG())
{
_winner.transfer(round_reward);
round_reward_paid = true;
}
}
emit RoundFinished(current_round, _winner, round_reward, RNG());
}
else
{
// Round is completed without sufficient entropy => allow refunds and increase the round counter
// round_successful[current_round] = false; // This values are `false` by default in solidity
round_failed[current_round] = true;
round_reward_paid = true;
emit RoundFinished(current_round, address(0), 0, 0);
}
require(round_reward_paid, "The provided address is not a winner of the current round");
}
function pay_fees() internal
{
}
function RNG() public view returns (uint256)
{
// Primitive random number generator dependant on both `entropy` and `interval` for testing reasons
uint256 _entropy = Entropy_interface(entropy_contract).get_entropy();
uint256 _timestamp = round_start_timestamp + deposits_phase_duration + entropy_phase_duration;
uint256 _result;
assembly
{
let x := sload(min_allowed_bet.slot)
_entropy := mul(_entropy, _timestamp)
_entropy := mul(_entropy, x)
_entropy := mul(_entropy, 115792089237316195423570985008687907853269984665640564039457584007913129639935)
}
// `entropy` is a random value; can be greater or less than `current_interval_end`
if(_entropy > current_interval_end)
{
_result = _entropy % current_interval_end;
}
else
{
_result = current_interval_end % _entropy;
}
return _result;
}
function check_entropy_criteria() public returns (bool)
{
// Needs to check the sufficiency of entropy for the round reward prizepool size
//return true;
return Entropy_interface(entropy_contract).get_number_of_revealed() > 0;
}
modifier only_owner
{
require(msg.sender == owner);
_;
}
modifier only_entropy_contract
{
require(msg.sender == entropy_contract);
_;
}
function set_entropy_contract(address payable _new_contract) public only_owner
{
entropy_contract = _new_contract;
}
function set_reward_contract(address payable _new_contract) public only_owner
{
reward_pool_contract = _new_contract;
}
function rescueERC20(address token, address to) external only_owner {
uint256 value = IERC20(token).balanceOf(address(this));
IERC20(token).transfer(to, value);
}
function configure(uint256 _min_bet, uint8 _max_deposits, uint256 _max_deposit_threshold, uint256 _deposit_phase_duration, uint256 _reveal_phase_duration) public only_owner
{
min_allowed_bet = _min_bet;
max_allowed_deposits = _max_deposits;
max_deposit_pool_threshold = _max_deposit_threshold;
deposits_phase_duration = _deposit_phase_duration;
entropy_phase_duration = _reveal_phase_duration;
}
function configureFees(uint256 _entropy_fee, uint256 _token_reward_fee) public only_owner
{
entropy_fee = _entropy_fee;
token_reward_fee = _token_reward_fee;
}
function forceWithdraw(uint256 _amount) only_owner only_debug public
{
payable(msg.sender).transfer(_amount);
}
function disableDebug() only_debug only_owner public
{
debug_mode = false;
}
}
Contract ABI
[{"type":"event","name":"Deposit","inputs":[{"type":"address","name":"depositor","internalType":"address","indexed":true},{"type":"uint256","name":"amount_deposited","internalType":"uint256","indexed":false},{"type":"uint256","name":"amount_credited","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"NewRound","inputs":[{"type":"uint256","name":"round_id","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"Refund","inputs":[{"type":"address","name":"receiver","internalType":"address","indexed":true},{"type":"uint256","name":"round_id","internalType":"uint256","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"RoundFinished","inputs":[{"type":"uint256","name":"round_id","internalType":"uint256","indexed":true},{"type":"address","name":"winner","internalType":"address","indexed":true},{"type":"uint256","name":"reward","internalType":"uint256","indexed":false},{"type":"uint256","name":"rng","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"RNG","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"check_entropy_criteria","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"configure","inputs":[{"type":"uint256","name":"_min_bet","internalType":"uint256"},{"type":"uint8","name":"_max_deposits","internalType":"uint8"},{"type":"uint256","name":"_max_deposit_threshold","internalType":"uint256"},{"type":"uint256","name":"_deposit_phase_duration","internalType":"uint256"},{"type":"uint256","name":"_reveal_phase_duration","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"configureFees","inputs":[{"type":"uint256","name":"_entropy_fee","internalType":"uint256"},{"type":"uint256","name":"_token_reward_fee","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"current_interval_end","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"current_round","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"debug_mode","inputs":[]},{"type":"function","stateMutability":"payable","outputs":[],"name":"deposit","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"deposits_phase_duration","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"disableDebug","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address payable"}],"name":"entropy_contract","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"entropy_fee","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"entropy_phase_duration","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"finish_round","inputs":[{"type":"address","name":"_winner","internalType":"address payable"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"forceWithdraw","inputs":[{"type":"uint256","name":"_amount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"get_max_deposit_threshold","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"get_phase","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"get_round","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"_start","internalType":"uint256"},{"type":"uint256","name":"_end","internalType":"uint256"}],"name":"get_win_conditions","inputs":[{"type":"address","name":"_player","internalType":"address"},{"type":"uint256","name":"_round","internalType":"uint256"},{"type":"uint8","name":"_depoindex","internalType":"uint8"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"is_winner","inputs":[{"type":"address","name":"_user","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"max_allowed_deposits","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"max_deposit_pool_threshold","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"min_allowed_bet","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"last_round","internalType":"uint256"}],"name":"players","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"refund","inputs":[{"type":"uint256","name":"_round","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"rescueERC20","inputs":[{"type":"address","name":"token","internalType":"address"},{"type":"address","name":"to","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address payable"}],"name":"reward_pool_contract","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"round_failed","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"round_reward","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"round_reward_paid","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"round_start_timestamp","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"set_entropy_contract","inputs":[{"type":"address","name":"_new_contract","internalType":"address payable"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"set_reward_contract","inputs":[{"type":"address","name":"_new_contract","internalType":"address payable"}]},{"type":"function","stateMutability":"payable","outputs":[],"name":"start_new_round","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"token_reward_fee","inputs":[]},{"type":"receive","stateMutability":"payable"}]
Contract Creation Code
0x6080604052600080546001600160a01b0319163317815561025860035561012c600455601e6005556064600655683635c9adc5dea000006007556008805460ff19908116601417909155600991909155600d80548216905560108054909116600117905534801561006f57600080fd5b506119038061007f6000396000f3fe6080604052600436106102135760003560e01c80639a74e1ed11610118578063d1205e26116100a0578063e2eb41ff1161006f578063e2eb41ff14610600578063e6e4cdce14610630578063ef0c67e114610660578063f714922014610676578063ff48fd421461068b57600080fd5b8063d1205e261461059f578063dbca930f146105b5578063e0371472146105d5578063e168cf86146105eb57600080fd5b8063b8b34132116100e7578063b8b341321461053d578063b9802e3e14610552578063c15d80c314610567578063ce253f0d1461057d578063d0e30db01461059757600080fd5b80639a74e1ed146104d25780639f24eb67146104f2578063a2022a1614610508578063a5b860041461052857600080fd5b80635d799f871161019b5780637c3682af1161016a5780637c3682af146103df5780637cab348f146103ff5780638d9510d4146104075780638da5cb5b1461043f5780638f8e02701461045f57600080fd5b80635d799f87146103685780636021caab146103885780636893b419146103b4578063709c4e91146103ca57600080fd5b80632d02c681116101e25780632d02c681146102d25780633152fd0d146102e8578063319c068c146103085780633debbed51461031e5780634631dd941461033e57600080fd5b8063043c348a146102535780630fcc56f71461027c578063214ab7d61461029c578063278ecde1146102b257600080fd5b3661024e576102206106ab565b60ff166000036102345761023261076f565b005b61023c6106ab565b60ff1660010361024e576102326108e0565b600080fd5b34801561025f57600080fd5b5061026960095481565b6040519081526020015b60405180910390f35b34801561028857600080fd5b50610232610297366004611688565b610cba565b3480156102a857600080fd5b50610269600c5481565b3480156102be57600080fd5b506102326102cd366004611688565b610d11565b3480156102de57600080fd5b50610269600b5481565b3480156102f457600080fd5b506102326103033660046116b6565b610ee7565b34801561031457600080fd5b50610269600a5481565b34801561032a57600080fd5b506102326103393660046116b6565b610f20565b34801561034a57600080fd5b506010546103589060ff1681565b6040519015158152602001610273565b34801561037457600080fd5b506102326103833660046116d3565b610f59565b34801561039457600080fd5b506008546103a29060ff1681565b60405160ff9091168152602001610273565b3480156103c057600080fd5b5061026960065481565b3480156103d657600080fd5b50610358611058565b3480156103eb57600080fd5b506103586103fa3660046116b6565b6110d8565b61023261076f565b34801561041357600080fd5b50600254610427906001600160a01b031681565b6040516001600160a01b039091168152602001610273565b34801561044b57600080fd5b50600054610427906001600160a01b031681565b34801561046b57600080fd5b506104bd61047a36600461171d565b6001600160a01b039290921660009081526011602090815260408083209383526002909301815282822060ff909416825292909252902080546001909101549091565b60408051928352602083019190915201610273565b3480156104de57600080fd5b50600154610427906001600160a01b031681565b3480156104fe57600080fd5b5061026960055481565b34801561051457600080fd5b506102326105233660046116b6565b6111b8565b34801561053457600080fd5b506103a26106ab565b34801561054957600080fd5b506102326114a9565b34801561055e57600080fd5b50600a54610269565b34801561057357600080fd5b5061026960035481565b34801561058957600080fd5b50600d546103589060ff1681565b6102326108e0565b3480156105ab57600080fd5b50610269600f5481565b3480156105c157600080fd5b506102326105d036600461175b565b6114db565b3480156105e157600080fd5b5061026960075481565b3480156105f757600080fd5b50600954610269565b34801561060c57600080fd5b5061026961061b3660046116b6565b60116020526000908152604090206001015481565b34801561063c57600080fd5b5061035861064b366004611688565b600e6020526000908152604090205460ff1681565b34801561066c57600080fd5b5061026960045481565b34801561068257600080fd5b50610269611518565b34801561069757600080fd5b506102326106a63660046117a1565b6115fa565b6000806000905042600b54111580156106d35750600354600b546106cf91906117d9565b4211155b156106e057506001919050565b42600b5410801561070c5750600454600354600b546106ff91906117d9565b61070991906117d9565b42105b1561071957506002919050565b600b541580159061072b575042600b54105b80156107525750600454600354600b5461074591906117d9565b61074f91906117d9565b42115b80156107615750600d5460ff16155b1561076a575060035b919050565b600a5415806107805750600d5460ff165b6108285760405162461bcd60e51b815260206004820152606260248201527f43616e6e6f742073746172742061206e657720726f756e64207768696c65207260448201527f657761726420666f72207468652070726576696f7573206f6e65206973206e6f60648201527f7420706169642e2043616c6c2066696e6973685f726f756e642066756e63746960848201526137b760f11b60a482015260c4015b60405180910390fd5b600a8054906000610838836117f2565b9091555050600a546040517fa2b5357eea32aeb35142ba36b087f9fe674f34f8b57ce94d30e9f4f572195bcf90600090a242600b556000600f819055600d805460ff1916905560015460408051630880a2a160e21b815290516001600160a01b03909216926322028a849260048084019382900301818387803b1580156108be57600080fd5b505af11580156108d2573d6000803e3d6000fd5b505050506108de6108e0565b565b6007543410156109325760405162461bcd60e51b815260206004820181905260248201527f4d696e696d756d2062657420636f6e646974696f6e206973206e6f74206d6574604482015260640161081f565b600854336000908152601160209081526040808320600a54845290915290205460ff918216911610806109785750600a5433600090815260116020526040902060010154105b6109d05760405162461bcd60e51b815260206004820152602360248201527f546f6f206d756368206465706f7369747320647572696e67207468697320726f6044820152621d5b9960ea1b606482015260840161081f565b6109d86106ab565b60ff16600114610a485760405162461bcd60e51b815260206004820152603560248201527f4465706f7369747320617265206f6e6c7920616c6c6f77656420647572696e6760448201527420746865206465706f736974696e6720706861736560581b606482015260840161081f565b60095415610aae57600954600c54610a6090346117d9565b1115610aae5760405162461bcd60e51b815260206004820152601f60248201527f526f756e6420726577617264207468726573686f6c6420657863656564656400604482015260640161081f565b600a54336000908152601160205260409020600101541015610afa57600a543360009081526011602090815260408083206001810185905593835292905220805460ff19169055610b3f565b336000908152601160209081526040808320600a5484529091528120805460ff1691610b258361180b565b91906101000a81548160ff021916908360ff160217905550505b600f54336000908152601160209081526040808320600a5484526002810183528184209083528184205460ff1684529091529020819055610b819034906117d9565b336000908152601160209081526040808320600a5484526002810183528184209083528184205460ff168452909152812060010191909155600f8054349290610bcb9084906117d9565b90915550506006543490610bf4906103e890610be7908461182a565b610bf19190611857565b50565b6103e860065434610c05919061182a565b610c0f9190611857565b610c19908261186b565b9050610c3e6103e860055434610c2f919061182a565b610c399190611857565b61161c565b6103e860055434610c4f919061182a565b610c599190611857565b610c63908261186b565b905080600c6000828254610c7791906117d9565b9091555050604080513481526020810183905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a15910160405180910390a250565b6000546001600160a01b03163314610cd157600080fd5b60105460ff16610ce057600080fd5b604051339082156108fc029083906000818181858888f19350505050158015610d0d573d6000803e3d6000fd5b5050565b6000818152600e602052604090205460ff16610d815760405162461bcd60e51b815260206004820152602960248201527f4f6e6c7920726566756e6473206f66204641494c454420726f756e64732061726044820152681948185b1b1bddd95960ba1b606482015260840161081f565b6000805b33600090815260116020908152604080832086845290915290205460ff90811690821611610e0557336000908152601160209081526040808320868452600201825280832060ff8516845290915290208054600190910154610de7919061186b565b610df190836117d9565b915080610dfd8161180b565b915050610d85565b5060055481906103e890610e19908361182a565b610e239190611857565b610e2d908361186b565b91506103e860065482610e40919061182a565b610e4a9190611857565b610e54908361186b565b336000818152601160209081526040808320888452600301909152808220805460ff1916600117905551929450909184156108fc0291859190818181858888f19350505050158015610eaa573d6000803e3d6000fd5b50604051828152839033907f73f04af9dcc582a923ec15d3eea990fe34adabfff2879e28d44572e01a54abb69060200160405180910390a3505050565b6000546001600160a01b03163314610efe57600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b03163314610f3757600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b03163314610f7057600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015610fb7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fdb919061187e565b60405163a9059cbb60e01b81526001600160a01b038481166004830152602482018390529192509084169063a9059cbb906044016020604051808303816000875af115801561102e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110529190611897565b50505050565b600080600160009054906101000a90046001600160a01b03166001600160a01b031663685823566040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d2919061187e565b11905090565b600080805b6001600160a01b0384166000908152601160209081526040808320600a54845290915290205460ff908116908216116111b157611118611518565b6001600160a01b0385166000908152601160209081526040808320600a548452600201825280832060ff86168452909152902054108015611195575061115c611518565b6001600160a01b0385166000908152601160209081526040808320600a548452600201825280832060ff86168452909152902060010154115b1561119f57600191505b806111a98161180b565b9150506110dd565b5092915050565b600454600354600b546111cb91906117d9565b6111d591906117d9565b42116112495760405162461bcd60e51b815260206004820152603960248201527f526f756e642063616e2062652066696e6973686564206166746572207468652060448201527f656e74726f70792072657665616c207068617365206f6e6c7900000000000000606482015260840161081f565b611251611058565b156113c65760005b6001600160a01b0382166000908152601160209081526040808320600a54845290915290205460ff9081169082161161136f57611294611518565b6001600160a01b0383166000908152601160209081526040808320600a548452600201825280832060ff8616845290915290205410801561131257506112d8611518565b6001600160a01b0383166000908152601160209081526040808320600a548452600201825280832060ff8616845290915290206001015410155b1561135d57600c546040516001600160a01b0384169180156108fc02916000818181858888f1935050505015801561134e573d6000803e3d6000fd5b50600d805460ff191660011790555b806113678161180b565b915050611259565b50806001600160a01b0316600a547fdac8947072807383f3f208c42a54bc2f876bd71ab3f5e8f8de8af9dfb9819bb3600c546113a9611518565b6040805192835260208301919091520160405180910390a3611431565b600a80546000908152600e602090815260408083208054600160ff199182168117909255600d805490911690911790559254835183815291820183905291927fdac8947072807383f3f208c42a54bc2f876bd71ab3f5e8f8de8af9dfb9819bb3910160405180910390a35b600d5460ff16610bf15760405162461bcd60e51b815260206004820152603960248201527f5468652070726f76696465642061646472657373206973206e6f74206120776960448201527f6e6e6572206f66207468652063757272656e7420726f756e6400000000000000606482015260840161081f565b60105460ff166114b857600080fd5b6000546001600160a01b031633146114cf57600080fd5b6010805460ff19169055565b6000546001600160a01b031633146114f257600080fd5b6007949094556008805460ff191660ff9490941693909317909255600955600355600455565b600080600160009054906101000a90046001600160a01b03166001600160a01b031663658f17886040518163ffffffff1660e01b8152600401602060405180830381865afa15801561156e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611592919061187e565b90506000600454600354600b546115a991906117d9565b6115b391906117d9565b600754600f5493820202600090810393919250908311156115e257600f546115db90846118b9565b90506115f3565b82600f546115f091906118b9565b90505b9392505050565b6000546001600160a01b0316331461161157600080fd5b600591909155600655565b600160009054906101000a90046001600160a01b03166001600160a01b0316632b807d37826040518263ffffffff1660e01b81526004016000604051808303818588803b15801561166c57600080fd5b505af1158015611680573d6000803e3d6000fd5b505050505050565b60006020828403121561169a57600080fd5b5035919050565b6001600160a01b0381168114610bf157600080fd5b6000602082840312156116c857600080fd5b81356115f3816116a1565b600080604083850312156116e657600080fd5b82356116f1816116a1565b91506020830135611701816116a1565b809150509250929050565b803560ff8116811461076a57600080fd5b60008060006060848603121561173257600080fd5b833561173d816116a1565b9250602084013591506117526040850161170c565b90509250925092565b600080600080600060a0868803121561177357600080fd5b853594506117836020870161170c565b94979496505050506040830135926060810135926080909101359150565b600080604083850312156117b457600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b808201808211156117ec576117ec6117c3565b92915050565b600060018201611804576118046117c3565b5060010190565b600060ff821660ff8103611821576118216117c3565b60010192915050565b80820281158282048414176117ec576117ec6117c3565b634e487b7160e01b600052601260045260246000fd5b60008261186657611866611841565b500490565b818103818111156117ec576117ec6117c3565b60006020828403121561189057600080fd5b5051919050565b6000602082840312156118a957600080fd5b815180151581146115f357600080fd5b6000826118c8576118c8611841565b50069056fea26469706673582212201bc7f87fa8dbcf16ded5cdb22d23ba56bcddc4afb39312ea363ddae8946715bc64736f6c63430008130033
Deployed ByteCode
0x6080604052600436106102135760003560e01c80639a74e1ed11610118578063d1205e26116100a0578063e2eb41ff1161006f578063e2eb41ff14610600578063e6e4cdce14610630578063ef0c67e114610660578063f714922014610676578063ff48fd421461068b57600080fd5b8063d1205e261461059f578063dbca930f146105b5578063e0371472146105d5578063e168cf86146105eb57600080fd5b8063b8b34132116100e7578063b8b341321461053d578063b9802e3e14610552578063c15d80c314610567578063ce253f0d1461057d578063d0e30db01461059757600080fd5b80639a74e1ed146104d25780639f24eb67146104f2578063a2022a1614610508578063a5b860041461052857600080fd5b80635d799f871161019b5780637c3682af1161016a5780637c3682af146103df5780637cab348f146103ff5780638d9510d4146104075780638da5cb5b1461043f5780638f8e02701461045f57600080fd5b80635d799f87146103685780636021caab146103885780636893b419146103b4578063709c4e91146103ca57600080fd5b80632d02c681116101e25780632d02c681146102d25780633152fd0d146102e8578063319c068c146103085780633debbed51461031e5780634631dd941461033e57600080fd5b8063043c348a146102535780630fcc56f71461027c578063214ab7d61461029c578063278ecde1146102b257600080fd5b3661024e576102206106ab565b60ff166000036102345761023261076f565b005b61023c6106ab565b60ff1660010361024e576102326108e0565b600080fd5b34801561025f57600080fd5b5061026960095481565b6040519081526020015b60405180910390f35b34801561028857600080fd5b50610232610297366004611688565b610cba565b3480156102a857600080fd5b50610269600c5481565b3480156102be57600080fd5b506102326102cd366004611688565b610d11565b3480156102de57600080fd5b50610269600b5481565b3480156102f457600080fd5b506102326103033660046116b6565b610ee7565b34801561031457600080fd5b50610269600a5481565b34801561032a57600080fd5b506102326103393660046116b6565b610f20565b34801561034a57600080fd5b506010546103589060ff1681565b6040519015158152602001610273565b34801561037457600080fd5b506102326103833660046116d3565b610f59565b34801561039457600080fd5b506008546103a29060ff1681565b60405160ff9091168152602001610273565b3480156103c057600080fd5b5061026960065481565b3480156103d657600080fd5b50610358611058565b3480156103eb57600080fd5b506103586103fa3660046116b6565b6110d8565b61023261076f565b34801561041357600080fd5b50600254610427906001600160a01b031681565b6040516001600160a01b039091168152602001610273565b34801561044b57600080fd5b50600054610427906001600160a01b031681565b34801561046b57600080fd5b506104bd61047a36600461171d565b6001600160a01b039290921660009081526011602090815260408083209383526002909301815282822060ff909416825292909252902080546001909101549091565b60408051928352602083019190915201610273565b3480156104de57600080fd5b50600154610427906001600160a01b031681565b3480156104fe57600080fd5b5061026960055481565b34801561051457600080fd5b506102326105233660046116b6565b6111b8565b34801561053457600080fd5b506103a26106ab565b34801561054957600080fd5b506102326114a9565b34801561055e57600080fd5b50600a54610269565b34801561057357600080fd5b5061026960035481565b34801561058957600080fd5b50600d546103589060ff1681565b6102326108e0565b3480156105ab57600080fd5b50610269600f5481565b3480156105c157600080fd5b506102326105d036600461175b565b6114db565b3480156105e157600080fd5b5061026960075481565b3480156105f757600080fd5b50600954610269565b34801561060c57600080fd5b5061026961061b3660046116b6565b60116020526000908152604090206001015481565b34801561063c57600080fd5b5061035861064b366004611688565b600e6020526000908152604090205460ff1681565b34801561066c57600080fd5b5061026960045481565b34801561068257600080fd5b50610269611518565b34801561069757600080fd5b506102326106a63660046117a1565b6115fa565b6000806000905042600b54111580156106d35750600354600b546106cf91906117d9565b4211155b156106e057506001919050565b42600b5410801561070c5750600454600354600b546106ff91906117d9565b61070991906117d9565b42105b1561071957506002919050565b600b541580159061072b575042600b54105b80156107525750600454600354600b5461074591906117d9565b61074f91906117d9565b42115b80156107615750600d5460ff16155b1561076a575060035b919050565b600a5415806107805750600d5460ff165b6108285760405162461bcd60e51b815260206004820152606260248201527f43616e6e6f742073746172742061206e657720726f756e64207768696c65207260448201527f657761726420666f72207468652070726576696f7573206f6e65206973206e6f60648201527f7420706169642e2043616c6c2066696e6973685f726f756e642066756e63746960848201526137b760f11b60a482015260c4015b60405180910390fd5b600a8054906000610838836117f2565b9091555050600a546040517fa2b5357eea32aeb35142ba36b087f9fe674f34f8b57ce94d30e9f4f572195bcf90600090a242600b556000600f819055600d805460ff1916905560015460408051630880a2a160e21b815290516001600160a01b03909216926322028a849260048084019382900301818387803b1580156108be57600080fd5b505af11580156108d2573d6000803e3d6000fd5b505050506108de6108e0565b565b6007543410156109325760405162461bcd60e51b815260206004820181905260248201527f4d696e696d756d2062657420636f6e646974696f6e206973206e6f74206d6574604482015260640161081f565b600854336000908152601160209081526040808320600a54845290915290205460ff918216911610806109785750600a5433600090815260116020526040902060010154105b6109d05760405162461bcd60e51b815260206004820152602360248201527f546f6f206d756368206465706f7369747320647572696e67207468697320726f6044820152621d5b9960ea1b606482015260840161081f565b6109d86106ab565b60ff16600114610a485760405162461bcd60e51b815260206004820152603560248201527f4465706f7369747320617265206f6e6c7920616c6c6f77656420647572696e6760448201527420746865206465706f736974696e6720706861736560581b606482015260840161081f565b60095415610aae57600954600c54610a6090346117d9565b1115610aae5760405162461bcd60e51b815260206004820152601f60248201527f526f756e6420726577617264207468726573686f6c6420657863656564656400604482015260640161081f565b600a54336000908152601160205260409020600101541015610afa57600a543360009081526011602090815260408083206001810185905593835292905220805460ff19169055610b3f565b336000908152601160209081526040808320600a5484529091528120805460ff1691610b258361180b565b91906101000a81548160ff021916908360ff160217905550505b600f54336000908152601160209081526040808320600a5484526002810183528184209083528184205460ff1684529091529020819055610b819034906117d9565b336000908152601160209081526040808320600a5484526002810183528184209083528184205460ff168452909152812060010191909155600f8054349290610bcb9084906117d9565b90915550506006543490610bf4906103e890610be7908461182a565b610bf19190611857565b50565b6103e860065434610c05919061182a565b610c0f9190611857565b610c19908261186b565b9050610c3e6103e860055434610c2f919061182a565b610c399190611857565b61161c565b6103e860055434610c4f919061182a565b610c599190611857565b610c63908261186b565b905080600c6000828254610c7791906117d9565b9091555050604080513481526020810183905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a15910160405180910390a250565b6000546001600160a01b03163314610cd157600080fd5b60105460ff16610ce057600080fd5b604051339082156108fc029083906000818181858888f19350505050158015610d0d573d6000803e3d6000fd5b5050565b6000818152600e602052604090205460ff16610d815760405162461bcd60e51b815260206004820152602960248201527f4f6e6c7920726566756e6473206f66204641494c454420726f756e64732061726044820152681948185b1b1bddd95960ba1b606482015260840161081f565b6000805b33600090815260116020908152604080832086845290915290205460ff90811690821611610e0557336000908152601160209081526040808320868452600201825280832060ff8516845290915290208054600190910154610de7919061186b565b610df190836117d9565b915080610dfd8161180b565b915050610d85565b5060055481906103e890610e19908361182a565b610e239190611857565b610e2d908361186b565b91506103e860065482610e40919061182a565b610e4a9190611857565b610e54908361186b565b336000818152601160209081526040808320888452600301909152808220805460ff1916600117905551929450909184156108fc0291859190818181858888f19350505050158015610eaa573d6000803e3d6000fd5b50604051828152839033907f73f04af9dcc582a923ec15d3eea990fe34adabfff2879e28d44572e01a54abb69060200160405180910390a3505050565b6000546001600160a01b03163314610efe57600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b03163314610f3757600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b03163314610f7057600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015610fb7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fdb919061187e565b60405163a9059cbb60e01b81526001600160a01b038481166004830152602482018390529192509084169063a9059cbb906044016020604051808303816000875af115801561102e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110529190611897565b50505050565b600080600160009054906101000a90046001600160a01b03166001600160a01b031663685823566040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d2919061187e565b11905090565b600080805b6001600160a01b0384166000908152601160209081526040808320600a54845290915290205460ff908116908216116111b157611118611518565b6001600160a01b0385166000908152601160209081526040808320600a548452600201825280832060ff86168452909152902054108015611195575061115c611518565b6001600160a01b0385166000908152601160209081526040808320600a548452600201825280832060ff86168452909152902060010154115b1561119f57600191505b806111a98161180b565b9150506110dd565b5092915050565b600454600354600b546111cb91906117d9565b6111d591906117d9565b42116112495760405162461bcd60e51b815260206004820152603960248201527f526f756e642063616e2062652066696e6973686564206166746572207468652060448201527f656e74726f70792072657665616c207068617365206f6e6c7900000000000000606482015260840161081f565b611251611058565b156113c65760005b6001600160a01b0382166000908152601160209081526040808320600a54845290915290205460ff9081169082161161136f57611294611518565b6001600160a01b0383166000908152601160209081526040808320600a548452600201825280832060ff8616845290915290205410801561131257506112d8611518565b6001600160a01b0383166000908152601160209081526040808320600a548452600201825280832060ff8616845290915290206001015410155b1561135d57600c546040516001600160a01b0384169180156108fc02916000818181858888f1935050505015801561134e573d6000803e3d6000fd5b50600d805460ff191660011790555b806113678161180b565b915050611259565b50806001600160a01b0316600a547fdac8947072807383f3f208c42a54bc2f876bd71ab3f5e8f8de8af9dfb9819bb3600c546113a9611518565b6040805192835260208301919091520160405180910390a3611431565b600a80546000908152600e602090815260408083208054600160ff199182168117909255600d805490911690911790559254835183815291820183905291927fdac8947072807383f3f208c42a54bc2f876bd71ab3f5e8f8de8af9dfb9819bb3910160405180910390a35b600d5460ff16610bf15760405162461bcd60e51b815260206004820152603960248201527f5468652070726f76696465642061646472657373206973206e6f74206120776960448201527f6e6e6572206f66207468652063757272656e7420726f756e6400000000000000606482015260840161081f565b60105460ff166114b857600080fd5b6000546001600160a01b031633146114cf57600080fd5b6010805460ff19169055565b6000546001600160a01b031633146114f257600080fd5b6007949094556008805460ff191660ff9490941693909317909255600955600355600455565b600080600160009054906101000a90046001600160a01b03166001600160a01b031663658f17886040518163ffffffff1660e01b8152600401602060405180830381865afa15801561156e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611592919061187e565b90506000600454600354600b546115a991906117d9565b6115b391906117d9565b600754600f5493820202600090810393919250908311156115e257600f546115db90846118b9565b90506115f3565b82600f546115f091906118b9565b90505b9392505050565b6000546001600160a01b0316331461161157600080fd5b600591909155600655565b600160009054906101000a90046001600160a01b03166001600160a01b0316632b807d37826040518263ffffffff1660e01b81526004016000604051808303818588803b15801561166c57600080fd5b505af1158015611680573d6000803e3d6000fd5b505050505050565b60006020828403121561169a57600080fd5b5035919050565b6001600160a01b0381168114610bf157600080fd5b6000602082840312156116c857600080fd5b81356115f3816116a1565b600080604083850312156116e657600080fd5b82356116f1816116a1565b91506020830135611701816116a1565b809150509250929050565b803560ff8116811461076a57600080fd5b60008060006060848603121561173257600080fd5b833561173d816116a1565b9250602084013591506117526040850161170c565b90509250925092565b600080600080600060a0868803121561177357600080fd5b853594506117836020870161170c565b94979496505050506040830135926060810135926080909101359150565b600080604083850312156117b457600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b808201808211156117ec576117ec6117c3565b92915050565b600060018201611804576118046117c3565b5060010190565b600060ff821660ff8103611821576118216117c3565b60010192915050565b80820281158282048414176117ec576117ec6117c3565b634e487b7160e01b600052601260045260246000fd5b60008261186657611866611841565b500490565b818103818111156117ec576117ec6117c3565b60006020828403121561189057600080fd5b5051919050565b6000602082840312156118a957600080fd5b815180151581146115f357600080fd5b6000826118c8576118c8611841565b50069056fea26469706673582212201bc7f87fa8dbcf16ded5cdb22d23ba56bcddc4afb39312ea363ddae8946715bc64736f6c63430008130033