false
false
0

Contract Address Details

0x12F0A4aE09E0596320E9Ee58cFF8bCbA8CA24FeE

Contract Name
Lottery
Creator
0x267258–a347de at 0x78abfc–3415dd
Balance
0 CLO
Tokens
Fetching tokens...
Transactions
Fetching transactions...
Transfers
Fetching transfers...
Gas Used
Fetching gas used...
Last Balance Update
16286374
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.0+commit.c7dfd78e




Optimization runs
200
EVM Version
default




Verified at
2024-09-26T15:32:29.573150Z

Contract source code

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;
// import "hardhat/console.sol";

abstract contract Entropy_interface {
    function get_entropy() public virtual view returns (uint256);
    function new_round() virtual external;
}

contract Lottery {
    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 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
    uint256 public token_reward_fee     = 100;  // This reward goes to staked tokens reward pool
    
    uint256 public min_allowed_bet      = 0.1 ether; // 1K CLO for now
    uint8   public max_allowed_deposits = 20;          // A user can make 20 bets during a single round
    
    uint256 public current_round;
    uint256 public round_start_timestamp;
    uint256 public round_reward;
    uint256 private nonce = 0;
    bool    public round_reward_paid = false;
    
    mapping (uint256 => bool) public round_successful; // Allows "refunds" of not succesful rounds.
    
    uint256 public current_interval_end; // Used for winner calculations
    
    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
    {
    }
    
    function get_round() public view returns (uint256)
    {
        return current_round;
    }
    
    function get_phase() public view returns (uint8)
    {
        // 0 - the lottery is not active     / pending reward claim or new round start
        // 1 - a lottery round is in progress/ acquiring deposits
        // 2 - deposits are acquired         / entropy revealing phase
        
        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;
        }
        
        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(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_with_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_with_fees -= msg.value * token_reward_fee / 1000;
        
        //send_entropy_reward(msg.value * entropy_fee / 1000);
        _reward_with_fees -= msg.value * entropy_fee / 1000;
        
        round_reward += _reward_with_fees;
    }
    
    function refund(uint256 _round) external
    {
        require(current_round > _round, "Only refunds of finished rounds are allowed");
        require(!round_successful[_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;
        }
        
        // Subtract the entropy fee
        _reward -= _reward * entropy_fee / 1000;
        
        players[msg.sender].round_refunded[_round] = true;
        payable(msg.sender).transfer(_reward);
    }
    
    function send_entropy_reward(uint256 _reward) internal
    {
        //entropy_contract.transfer(msg.value * entropy_fee / 1000);
        
        entropy_contract.transfer(_reward);
    }
    
    function send_token_reward(uint256 _reward) internal
    {
        //reward_pool_contract.transfer(msg.value * token_reward_fee / 1000);
        reward_pool_contract.transfer(_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++;
        round_start_timestamp = block.timestamp;
        current_interval_end  = 0;
        round_reward_paid     = false;
        
        //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 + 4 days > 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
            round_successful[current_round] = true;
            
            // 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() && RNG() < players[_winner].win_conditions[current_round][i].interval_end)
                {
                    // console.log("\n%s\n%s\n%s", players[_winner].win_conditions[current_round][i].interval_start, RNG(), players[_winner].win_conditions[current_round][i].interval_end);
                    _winner.transfer(round_reward);
                    round_reward_paid = true;
                }
            }
        }
        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_reward_paid = true;
        }
        
        require(round_reward_paid, "The provided address is not a winner of the current round");
    }
    
    function pay_fees() internal
    {
        
    }

    function RNG() public returns (uint256)
    {
        // Primitive random number generator dependant on both `entropy` and `interval` for testing reasons
        uint256 _entropy = Entropy_interface(entropy_contract).get_entropy();
        uint256 _result;
        // `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;
    }
    
    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 new_round_entropy() external {
        Entropy_interface(entropy_contract).new_round();
    }
}
        

Contract ABI

[{"type":"function","stateMutability":"nonpayable","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":"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":"payable","outputs":[],"name":"deposit","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"deposits_phase_duration","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":"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":"uint8","name":"","internalType":"uint8"}],"name":"max_allowed_deposits","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"min_allowed_bet","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"new_round_entropy","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":"view","outputs":[{"type":"address","name":"","internalType":"address payable"}],"name":"reward_pool_contract","inputs":[]},{"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":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"round_successful","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"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

Verify & Publish
0x6080604052600080546001600160a01b031916331781556203f48060035562015180600455601e600555606460065567016345785d8a00006007556008805460ff19908116601417909155600c91909155600d8054909116905534801561006557600080fd5b50611113806100756000396000f3fe6080604052600436106101a05760003560e01c80638efdee23116100ec578063ce253f0d1161008a578063e037147211610064578063e0371472146103eb578063e2eb41ff14610400578063ef0c67e114610420578063f714922014610435576101a7565b8063ce253f0d146103b9578063d0e30db0146103ce578063d1205e26146103d6576101a7565b8063a2022a16116100c6578063a2022a161461035a578063a5b860041461037a578063b9802e3e1461038f578063c15d80c3146103a4576101a7565b80638efdee23146103105780639a74e1ed146103305780639f24eb6714610345576101a7565b80636021caab116101595780637cab348f116101335780637cab348f146102bc5780637e1eeb0a146102c45780638d9510d4146102d95780638da5cb5b146102fb576101a7565b80636021caab146102635780636893b41914610285578063709c4e911461029a576101a7565b8063214ab7d6146101ac578063278ecde1146101d75780632d02c681146101f95780633152fd0d1461020e578063319c068c1461022e5780633debbed514610243576101a7565b366101a757005b600080fd5b3480156101b857600080fd5b506101c161044a565b6040516101ce9190610fd4565b60405180910390f35b3480156101e357600080fd5b506101f76101f2366004610cdc565b610450565b005b34801561020557600080fd5b506101c16105af565b34801561021a57600080fd5b506101f7610229366004610cb9565b6105b5565b34801561023a57600080fd5b506101c16105ee565b34801561024f57600080fd5b506101f761025e366004610cb9565b6105f4565b34801561026f57600080fd5b5061027861062d565b6040516101ce9190610fdd565b34801561029157600080fd5b506101c1610636565b3480156102a657600080fd5b506102af61063c565b6040516101ce9190610d20565b6101f7610641565b3480156102d057600080fd5b506101f76106a0565b3480156102e557600080fd5b506102ee61070a565b6040516101ce9190610d0c565b34801561030757600080fd5b506102ee610719565b34801561031c57600080fd5b506102af61032b366004610cdc565b610728565b34801561033c57600080fd5b506102ee61073d565b34801561035157600080fd5b506101c161074c565b34801561036657600080fd5b506101f7610375366004610cb9565b610752565b34801561038657600080fd5b50610278610913565b34801561039b57600080fd5b506101c1610982565b3480156103b057600080fd5b506101c1610988565b3480156103c557600080fd5b506102af61098e565b6101f7610997565b3480156103e257600080fd5b506101c1610bd0565b3480156103f757600080fd5b506101c1610bd6565b34801561040c57600080fd5b506101c161041b366004610cb9565b610bdc565b34801561042c57600080fd5b506101c1610bf1565b34801561044157600080fd5b506101c1610bf7565b600b5481565b806009541161047a5760405162461bcd60e51b815260040161047190610e16565b60405180910390fd5b6000818152600e602052604090205460ff16156104a95760405162461bcd60e51b815260040161047190610e61565b6000805b33600090815260106020908152604080832086845290915290205460ff908116908216101561052e57336000908152601060209081526040808320868452600201825280832060ff85168452909152902080546001909101546105109190611036565b61051a9083610feb565b91508061052681611068565b9150506104ad565b506103e8600554826105409190611017565b61054a9190611003565b6105549082611036565b336000818152601060209081526040808320878452600301909152808220805460ff1916600117905551929350909183156108fc0291849190818181858888f193505050501580156105aa573d6000803e3d6000fd5b505050565b600a5481565b6000546001600160a01b031633146105cc57600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60095481565b6000546001600160a01b0316331461060b57600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b60085460ff1681565b60065481565b600190565b60095415806106525750600d5460ff165b61066e5760405162461bcd60e51b815260040161047190610d88565b6009805490600061067e8361104d565b909155505042600a556000600f55600d805460ff1916905561069e610997565b565b600160009054906101000a90046001600160a01b03166001600160a01b03166322028a846040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156106f057600080fd5b505af1158015610704573d6000803e3d6000fd5b50505050565b6002546001600160a01b031681565b6000546001600160a01b031681565b600e6020526000908152604090205460ff1681565b6001546001600160a01b031681565b60055481565b600454600354600a546107659190610feb565b61076f9190610feb565b61077c4262054600610feb565b116107995760405162461bcd60e51b815260040161047190610f77565b6107a161063c565b156108e0576009546000908152600e60205260408120805460ff191660011790555b6001600160a01b0382166000908152601060209081526040808320600954845290915290205460ff90811690821610156108da576107ff610bf7565b6001600160a01b03831660009081526010602090815260408083206009548452600201825280832060ff861684529091529020541180159061087d57506001600160a01b03821660009081526010602090815260408083206009548452600201825280832060ff8516845290915290206001015461087b610bf7565b105b156108c857600b546040516001600160a01b0384169180156108fc02916000818181858888f193505050501580156108b9573d6000803e3d6000fd5b50600d805460ff191660011790555b806108d281611068565b9150506107c3565b506108ee565b600d805460ff191660011790555b600d5460ff166109105760405162461bcd60e51b815260040161047190610d2b565b50565b6000806000905042600a541115801561093a5750600354600a546109379190610feb565b42105b156109475750600161097d565b42600a54111580156109745750600454600354600a546109679190610feb565b6109719190610feb565b42105b1561097d575060025b905090565b60095490565b60035481565b600d5460ff1681565b60075434116109b85760405162461bcd60e51b815260040161047190610eed565b600854336000908152601060209081526040808320600954845290915290205460ff918216911610806109fe575060095433600090815260106020526040902060010154105b610a1a5760405162461bcd60e51b815260040161047190610eaa565b610a22610913565b60ff16600114610a445760405162461bcd60e51b815260040161047190610f22565b600954336000908152601060205260409020600101541015610a90576009543360009081526010602090815260408083206001810185905593835292905220805460ff19169055610ad5565b33600090815260106020908152604080832060095484529091528120805460ff1691610abb83611068565b91906101000a81548160ff021916908360ff160217905550505b600f5433600090815260106020908152604080832060095484526002810183528184209083528184205460ff1684529091529020819055610b17903490610feb565b33600090815260106020908152604080832060095484526002810183528184209083528184205460ff168452909152812060010191909155600f8054349290610b61908490610feb565b909155505060065434906103e890610b799083611017565b610b839190611003565b610b8d9082611036565b90506103e860055434610ba09190611017565b610baa9190611003565b610bb49082611036565b905080600b6000828254610bc89190610feb565b909155505050565b600f5481565b60075481565b60106020526000908152604090206001015481565b60045481565b600080600160009054906101000a90046001600160a01b03166001600160a01b031663658f17886040518163ffffffff1660e01b815260040160206040518083038186803b158015610c4857600080fd5b505afa158015610c5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c809190610cf4565b90506000600f54821115610ca257600f54610c9b9083611088565b9050610cb3565b81600f54610cb09190611088565b90505b91505090565b600060208284031215610cca578081fd5b8135610cd5816110c8565b9392505050565b600060208284031215610ced578081fd5b5035919050565b600060208284031215610d05578081fd5b5051919050565b6001600160a01b0391909116815260200190565b901515815260200190565b60208082526039908201527f5468652070726f76696465642061646472657373206973206e6f74206120776960408201527f6e6e6572206f66207468652063757272656e7420726f756e6400000000000000606082015260800190565b60208082526062908201527f43616e6e6f742073746172742061206e657720726f756e64207768696c65207260408201527f657761726420666f72207468652070726576696f7573206f6e65206973206e6f60608201527f7420706169642e2043616c6c2066696e6973685f726f756e642066756e63746960808201526137b760f11b60a082015260c00190565b6020808252602b908201527f4f6e6c7920726566756e6473206f662066696e697368656420726f756e64732060408201526a185c9948185b1b1bddd95960aa1b606082015260800190565b60208082526029908201527f4f6e6c7920726566756e6473206f66204641494c454420726f756e64732061726040820152681948185b1b1bddd95960ba1b606082015260800190565b60208082526023908201527f546f6f206d756368206465706f7369747320647572696e67207468697320726f6040820152621d5b9960ea1b606082015260800190565b6020808252818101527f4d696e696d756d2062657420636f6e646974696f6e206973206e6f74206d6574604082015260600190565b60208082526035908201527f4465706f7369747320617265206f6e6c7920616c6c6f77656420647572696e6760408201527420746865206465706f736974696e6720706861736560581b606082015260800190565b60208082526039908201527f526f756e642063616e2062652066696e6973686564206166746572207468652060408201527f656e74726f70792072657665616c207068617365206f6e6c7900000000000000606082015260800190565b90815260200190565b60ff91909116815260200190565b60008219821115610ffe57610ffe61109c565b500190565b600082611012576110126110b2565b500490565b60008160001904831182151516156110315761103161109c565b500290565b6000828210156110485761104861109c565b500390565b60006000198214156110615761106161109c565b5060010190565b600060ff821660ff81141561107f5761107f61109c565b60010192915050565b600082611097576110976110b2565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b6001600160a01b038116811461091057600080fdfea264697066735822122026f61a4f4851eae30e4ea6af36e05cd2da1ea1ac65030ad8e05299f43761bea364736f6c63430008000033

Deployed ByteCode

0x6080604052600436106101a05760003560e01c80638efdee23116100ec578063ce253f0d1161008a578063e037147211610064578063e0371472146103eb578063e2eb41ff14610400578063ef0c67e114610420578063f714922014610435576101a7565b8063ce253f0d146103b9578063d0e30db0146103ce578063d1205e26146103d6576101a7565b8063a2022a16116100c6578063a2022a161461035a578063a5b860041461037a578063b9802e3e1461038f578063c15d80c3146103a4576101a7565b80638efdee23146103105780639a74e1ed146103305780639f24eb6714610345576101a7565b80636021caab116101595780637cab348f116101335780637cab348f146102bc5780637e1eeb0a146102c45780638d9510d4146102d95780638da5cb5b146102fb576101a7565b80636021caab146102635780636893b41914610285578063709c4e911461029a576101a7565b8063214ab7d6146101ac578063278ecde1146101d75780632d02c681146101f95780633152fd0d1461020e578063319c068c1461022e5780633debbed514610243576101a7565b366101a757005b600080fd5b3480156101b857600080fd5b506101c161044a565b6040516101ce9190610fd4565b60405180910390f35b3480156101e357600080fd5b506101f76101f2366004610cdc565b610450565b005b34801561020557600080fd5b506101c16105af565b34801561021a57600080fd5b506101f7610229366004610cb9565b6105b5565b34801561023a57600080fd5b506101c16105ee565b34801561024f57600080fd5b506101f761025e366004610cb9565b6105f4565b34801561026f57600080fd5b5061027861062d565b6040516101ce9190610fdd565b34801561029157600080fd5b506101c1610636565b3480156102a657600080fd5b506102af61063c565b6040516101ce9190610d20565b6101f7610641565b3480156102d057600080fd5b506101f76106a0565b3480156102e557600080fd5b506102ee61070a565b6040516101ce9190610d0c565b34801561030757600080fd5b506102ee610719565b34801561031c57600080fd5b506102af61032b366004610cdc565b610728565b34801561033c57600080fd5b506102ee61073d565b34801561035157600080fd5b506101c161074c565b34801561036657600080fd5b506101f7610375366004610cb9565b610752565b34801561038657600080fd5b50610278610913565b34801561039b57600080fd5b506101c1610982565b3480156103b057600080fd5b506101c1610988565b3480156103c557600080fd5b506102af61098e565b6101f7610997565b3480156103e257600080fd5b506101c1610bd0565b3480156103f757600080fd5b506101c1610bd6565b34801561040c57600080fd5b506101c161041b366004610cb9565b610bdc565b34801561042c57600080fd5b506101c1610bf1565b34801561044157600080fd5b506101c1610bf7565b600b5481565b806009541161047a5760405162461bcd60e51b815260040161047190610e16565b60405180910390fd5b6000818152600e602052604090205460ff16156104a95760405162461bcd60e51b815260040161047190610e61565b6000805b33600090815260106020908152604080832086845290915290205460ff908116908216101561052e57336000908152601060209081526040808320868452600201825280832060ff85168452909152902080546001909101546105109190611036565b61051a9083610feb565b91508061052681611068565b9150506104ad565b506103e8600554826105409190611017565b61054a9190611003565b6105549082611036565b336000818152601060209081526040808320878452600301909152808220805460ff1916600117905551929350909183156108fc0291849190818181858888f193505050501580156105aa573d6000803e3d6000fd5b505050565b600a5481565b6000546001600160a01b031633146105cc57600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60095481565b6000546001600160a01b0316331461060b57600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b60085460ff1681565b60065481565b600190565b60095415806106525750600d5460ff165b61066e5760405162461bcd60e51b815260040161047190610d88565b6009805490600061067e8361104d565b909155505042600a556000600f55600d805460ff1916905561069e610997565b565b600160009054906101000a90046001600160a01b03166001600160a01b03166322028a846040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156106f057600080fd5b505af1158015610704573d6000803e3d6000fd5b50505050565b6002546001600160a01b031681565b6000546001600160a01b031681565b600e6020526000908152604090205460ff1681565b6001546001600160a01b031681565b60055481565b600454600354600a546107659190610feb565b61076f9190610feb565b61077c4262054600610feb565b116107995760405162461bcd60e51b815260040161047190610f77565b6107a161063c565b156108e0576009546000908152600e60205260408120805460ff191660011790555b6001600160a01b0382166000908152601060209081526040808320600954845290915290205460ff90811690821610156108da576107ff610bf7565b6001600160a01b03831660009081526010602090815260408083206009548452600201825280832060ff861684529091529020541180159061087d57506001600160a01b03821660009081526010602090815260408083206009548452600201825280832060ff8516845290915290206001015461087b610bf7565b105b156108c857600b546040516001600160a01b0384169180156108fc02916000818181858888f193505050501580156108b9573d6000803e3d6000fd5b50600d805460ff191660011790555b806108d281611068565b9150506107c3565b506108ee565b600d805460ff191660011790555b600d5460ff166109105760405162461bcd60e51b815260040161047190610d2b565b50565b6000806000905042600a541115801561093a5750600354600a546109379190610feb565b42105b156109475750600161097d565b42600a54111580156109745750600454600354600a546109679190610feb565b6109719190610feb565b42105b1561097d575060025b905090565b60095490565b60035481565b600d5460ff1681565b60075434116109b85760405162461bcd60e51b815260040161047190610eed565b600854336000908152601060209081526040808320600954845290915290205460ff918216911610806109fe575060095433600090815260106020526040902060010154105b610a1a5760405162461bcd60e51b815260040161047190610eaa565b610a22610913565b60ff16600114610a445760405162461bcd60e51b815260040161047190610f22565b600954336000908152601060205260409020600101541015610a90576009543360009081526010602090815260408083206001810185905593835292905220805460ff19169055610ad5565b33600090815260106020908152604080832060095484529091528120805460ff1691610abb83611068565b91906101000a81548160ff021916908360ff160217905550505b600f5433600090815260106020908152604080832060095484526002810183528184209083528184205460ff1684529091529020819055610b17903490610feb565b33600090815260106020908152604080832060095484526002810183528184209083528184205460ff168452909152812060010191909155600f8054349290610b61908490610feb565b909155505060065434906103e890610b799083611017565b610b839190611003565b610b8d9082611036565b90506103e860055434610ba09190611017565b610baa9190611003565b610bb49082611036565b905080600b6000828254610bc89190610feb565b909155505050565b600f5481565b60075481565b60106020526000908152604090206001015481565b60045481565b600080600160009054906101000a90046001600160a01b03166001600160a01b031663658f17886040518163ffffffff1660e01b815260040160206040518083038186803b158015610c4857600080fd5b505afa158015610c5c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c809190610cf4565b90506000600f54821115610ca257600f54610c9b9083611088565b9050610cb3565b81600f54610cb09190611088565b90505b91505090565b600060208284031215610cca578081fd5b8135610cd5816110c8565b9392505050565b600060208284031215610ced578081fd5b5035919050565b600060208284031215610d05578081fd5b5051919050565b6001600160a01b0391909116815260200190565b901515815260200190565b60208082526039908201527f5468652070726f76696465642061646472657373206973206e6f74206120776960408201527f6e6e6572206f66207468652063757272656e7420726f756e6400000000000000606082015260800190565b60208082526062908201527f43616e6e6f742073746172742061206e657720726f756e64207768696c65207260408201527f657761726420666f72207468652070726576696f7573206f6e65206973206e6f60608201527f7420706169642e2043616c6c2066696e6973685f726f756e642066756e63746960808201526137b760f11b60a082015260c00190565b6020808252602b908201527f4f6e6c7920726566756e6473206f662066696e697368656420726f756e64732060408201526a185c9948185b1b1bddd95960aa1b606082015260800190565b60208082526029908201527f4f6e6c7920726566756e6473206f66204641494c454420726f756e64732061726040820152681948185b1b1bddd95960ba1b606082015260800190565b60208082526023908201527f546f6f206d756368206465706f7369747320647572696e67207468697320726f6040820152621d5b9960ea1b606082015260800190565b6020808252818101527f4d696e696d756d2062657420636f6e646974696f6e206973206e6f74206d6574604082015260600190565b60208082526035908201527f4465706f7369747320617265206f6e6c7920616c6c6f77656420647572696e6760408201527420746865206465706f736974696e6720706861736560581b606082015260800190565b60208082526039908201527f526f756e642063616e2062652066696e6973686564206166746572207468652060408201527f656e74726f70792072657665616c207068617365206f6e6c7900000000000000606082015260800190565b90815260200190565b60ff91909116815260200190565b60008219821115610ffe57610ffe61109c565b500190565b600082611012576110126110b2565b500490565b60008160001904831182151516156110315761103161109c565b500290565b6000828210156110485761104861109c565b500390565b60006000198214156110615761106161109c565b5060010190565b600060ff821660ff81141561107f5761107f61109c565b60010192915050565b600082611097576110976110b2565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b6001600160a01b038116811461091057600080fdfea264697066735822122026f61a4f4851eae30e4ea6af36e05cd2da1ea1ac65030ad8e05299f43761bea364736f6c63430008000033