false
false
0

Contract Address Details

0x06c400321919DBCf6402f3B3afF58F78067dfdF2

Contract Name
Lottery
Creator
0x222e67–26b482 at 0xad08d4–e2a409
Balance
0 CLO
Tokens
Fetching tokens...
Transactions
2 Transactions
Transfers
0 Transfers
Gas Used
103,330
Last Balance Update
18596944
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

Verify & Publish
0x6080604052600080546001600160a01b0319163317815561025860035561012c600455601e6005556064600655683635c9adc5dea000006007556008805460ff19908116601417909155600991909155600d80548216905560108054909116600117905534801561006f57600080fd5b506119038061007f6000396000f3fe6080604052600436106102135760003560e01c80639a74e1ed11610118578063d1205e26116100a0578063e2eb41ff1161006f578063e2eb41ff14610600578063e6e4cdce14610630578063ef0c67e114610660578063f714922014610676578063ff48fd421461068b57600080fd5b8063d1205e261461059f578063dbca930f146105b5578063e0371472146105d5578063e168cf86146105eb57600080fd5b8063b8b34132116100e7578063b8b341321461053d578063b9802e3e14610552578063c15d80c314610567578063ce253f0d1461057d578063d0e30db01461059757600080fd5b80639a74e1ed146104d25780639f24eb67146104f2578063a2022a1614610508578063a5b860041461052857600080fd5b80635d799f871161019b5780637c3682af1161016a5780637c3682af146103df5780637cab348f146103ff5780638d9510d4146104075780638da5cb5b1461043f5780638f8e02701461045f57600080fd5b80635d799f87146103685780636021caab146103885780636893b419146103b4578063709c4e91146103ca57600080fd5b80632d02c681116101e25780632d02c681146102d25780633152fd0d146102e8578063319c068c146103085780633debbed51461031e5780634631dd941461033e57600080fd5b8063043c348a146102535780630fcc56f71461027c578063214ab7d61461029c578063278ecde1146102b257600080fd5b3661024e576102206106ab565b60ff166000036102345761023261076f565b005b61023c6106ab565b60ff1660010361024e576102326108e0565b600080fd5b34801561025f57600080fd5b5061026960095481565b6040519081526020015b60405180910390f35b34801561028857600080fd5b50610232610297366004611688565b610cba565b3480156102a857600080fd5b50610269600c5481565b3480156102be57600080fd5b506102326102cd366004611688565b610d11565b3480156102de57600080fd5b50610269600b5481565b3480156102f457600080fd5b506102326103033660046116b6565b610ee7565b34801561031457600080fd5b50610269600a5481565b34801561032a57600080fd5b506102326103393660046116b6565b610f20565b34801561034a57600080fd5b506010546103589060ff1681565b6040519015158152602001610273565b34801561037457600080fd5b506102326103833660046116d3565b610f59565b34801561039457600080fd5b506008546103a29060ff1681565b60405160ff9091168152602001610273565b3480156103c057600080fd5b5061026960065481565b3480156103d657600080fd5b50610358611058565b3480156103eb57600080fd5b506103586103fa3660046116b6565b6110d8565b61023261076f565b34801561041357600080fd5b50600254610427906001600160a01b031681565b6040516001600160a01b039091168152602001610273565b34801561044b57600080fd5b50600054610427906001600160a01b031681565b34801561046b57600080fd5b506104bd61047a36600461171d565b6001600160a01b039290921660009081526011602090815260408083209383526002909301815282822060ff909416825292909252902080546001909101549091565b60408051928352602083019190915201610273565b3480156104de57600080fd5b50600154610427906001600160a01b031681565b3480156104fe57600080fd5b5061026960055481565b34801561051457600080fd5b506102326105233660046116b6565b6111b8565b34801561053457600080fd5b506103a26106ab565b34801561054957600080fd5b506102326114a9565b34801561055e57600080fd5b50600a54610269565b34801561057357600080fd5b5061026960035481565b34801561058957600080fd5b50600d546103589060ff1681565b6102326108e0565b3480156105ab57600080fd5b50610269600f5481565b3480156105c157600080fd5b506102326105d036600461175b565b6114db565b3480156105e157600080fd5b5061026960075481565b3480156105f757600080fd5b50600954610269565b34801561060c57600080fd5b5061026961061b3660046116b6565b60116020526000908152604090206001015481565b34801561063c57600080fd5b5061035861064b366004611688565b600e6020526000908152604090205460ff1681565b34801561066c57600080fd5b5061026960045481565b34801561068257600080fd5b50610269611518565b34801561069757600080fd5b506102326106a63660046117a1565b6115fa565b6000806000905042600b54111580156106d35750600354600b546106cf91906117d9565b4211155b156106e057506001919050565b42600b5410801561070c5750600454600354600b546106ff91906117d9565b61070991906117d9565b42105b1561071957506002919050565b600b541580159061072b575042600b54105b80156107525750600454600354600b5461074591906117d9565b61074f91906117d9565b42115b80156107615750600d5460ff16155b1561076a575060035b919050565b600a5415806107805750600d5460ff165b6108285760405162461bcd60e51b815260206004820152606260248201527f43616e6e6f742073746172742061206e657720726f756e64207768696c65207260448201527f657761726420666f72207468652070726576696f7573206f6e65206973206e6f60648201527f7420706169642e2043616c6c2066696e6973685f726f756e642066756e63746960848201526137b760f11b60a482015260c4015b60405180910390fd5b600a8054906000610838836117f2565b9091555050600a546040517fa2b5357eea32aeb35142ba36b087f9fe674f34f8b57ce94d30e9f4f572195bcf90600090a242600b556000600f819055600d805460ff1916905560015460408051630880a2a160e21b815290516001600160a01b03909216926322028a849260048084019382900301818387803b1580156108be57600080fd5b505af11580156108d2573d6000803e3d6000fd5b505050506108de6108e0565b565b6007543410156109325760405162461bcd60e51b815260206004820181905260248201527f4d696e696d756d2062657420636f6e646974696f6e206973206e6f74206d6574604482015260640161081f565b600854336000908152601160209081526040808320600a54845290915290205460ff918216911610806109785750600a5433600090815260116020526040902060010154105b6109d05760405162461bcd60e51b815260206004820152602360248201527f546f6f206d756368206465706f7369747320647572696e67207468697320726f6044820152621d5b9960ea1b606482015260840161081f565b6109d86106ab565b60ff16600114610a485760405162461bcd60e51b815260206004820152603560248201527f4465706f7369747320617265206f6e6c7920616c6c6f77656420647572696e6760448201527420746865206465706f736974696e6720706861736560581b606482015260840161081f565b60095415610aae57600954600c54610a6090346117d9565b1115610aae5760405162461bcd60e51b815260206004820152601f60248201527f526f756e6420726577617264207468726573686f6c6420657863656564656400604482015260640161081f565b600a54336000908152601160205260409020600101541015610afa57600a543360009081526011602090815260408083206001810185905593835292905220805460ff19169055610b3f565b336000908152601160209081526040808320600a5484529091528120805460ff1691610b258361180b565b91906101000a81548160ff021916908360ff160217905550505b600f54336000908152601160209081526040808320600a5484526002810183528184209083528184205460ff1684529091529020819055610b819034906117d9565b336000908152601160209081526040808320600a5484526002810183528184209083528184205460ff168452909152812060010191909155600f8054349290610bcb9084906117d9565b90915550506006543490610bf4906103e890610be7908461182a565b610bf19190611857565b50565b6103e860065434610c05919061182a565b610c0f9190611857565b610c19908261186b565b9050610c3e6103e860055434610c2f919061182a565b610c399190611857565b61161c565b6103e860055434610c4f919061182a565b610c599190611857565b610c63908261186b565b905080600c6000828254610c7791906117d9565b9091555050604080513481526020810183905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a15910160405180910390a250565b6000546001600160a01b03163314610cd157600080fd5b60105460ff16610ce057600080fd5b604051339082156108fc029083906000818181858888f19350505050158015610d0d573d6000803e3d6000fd5b5050565b6000818152600e602052604090205460ff16610d815760405162461bcd60e51b815260206004820152602960248201527f4f6e6c7920726566756e6473206f66204641494c454420726f756e64732061726044820152681948185b1b1bddd95960ba1b606482015260840161081f565b6000805b33600090815260116020908152604080832086845290915290205460ff90811690821611610e0557336000908152601160209081526040808320868452600201825280832060ff8516845290915290208054600190910154610de7919061186b565b610df190836117d9565b915080610dfd8161180b565b915050610d85565b5060055481906103e890610e19908361182a565b610e239190611857565b610e2d908361186b565b91506103e860065482610e40919061182a565b610e4a9190611857565b610e54908361186b565b336000818152601160209081526040808320888452600301909152808220805460ff1916600117905551929450909184156108fc0291859190818181858888f19350505050158015610eaa573d6000803e3d6000fd5b50604051828152839033907f73f04af9dcc582a923ec15d3eea990fe34adabfff2879e28d44572e01a54abb69060200160405180910390a3505050565b6000546001600160a01b03163314610efe57600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b03163314610f3757600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b03163314610f7057600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015610fb7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fdb919061187e565b60405163a9059cbb60e01b81526001600160a01b038481166004830152602482018390529192509084169063a9059cbb906044016020604051808303816000875af115801561102e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110529190611897565b50505050565b600080600160009054906101000a90046001600160a01b03166001600160a01b031663685823566040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d2919061187e565b11905090565b600080805b6001600160a01b0384166000908152601160209081526040808320600a54845290915290205460ff908116908216116111b157611118611518565b6001600160a01b0385166000908152601160209081526040808320600a548452600201825280832060ff86168452909152902054108015611195575061115c611518565b6001600160a01b0385166000908152601160209081526040808320600a548452600201825280832060ff86168452909152902060010154115b1561119f57600191505b806111a98161180b565b9150506110dd565b5092915050565b600454600354600b546111cb91906117d9565b6111d591906117d9565b42116112495760405162461bcd60e51b815260206004820152603960248201527f526f756e642063616e2062652066696e6973686564206166746572207468652060448201527f656e74726f70792072657665616c207068617365206f6e6c7900000000000000606482015260840161081f565b611251611058565b156113c65760005b6001600160a01b0382166000908152601160209081526040808320600a54845290915290205460ff9081169082161161136f57611294611518565b6001600160a01b0383166000908152601160209081526040808320600a548452600201825280832060ff8616845290915290205410801561131257506112d8611518565b6001600160a01b0383166000908152601160209081526040808320600a548452600201825280832060ff8616845290915290206001015410155b1561135d57600c546040516001600160a01b0384169180156108fc02916000818181858888f1935050505015801561134e573d6000803e3d6000fd5b50600d805460ff191660011790555b806113678161180b565b915050611259565b50806001600160a01b0316600a547fdac8947072807383f3f208c42a54bc2f876bd71ab3f5e8f8de8af9dfb9819bb3600c546113a9611518565b6040805192835260208301919091520160405180910390a3611431565b600a80546000908152600e602090815260408083208054600160ff199182168117909255600d805490911690911790559254835183815291820183905291927fdac8947072807383f3f208c42a54bc2f876bd71ab3f5e8f8de8af9dfb9819bb3910160405180910390a35b600d5460ff16610bf15760405162461bcd60e51b815260206004820152603960248201527f5468652070726f76696465642061646472657373206973206e6f74206120776960448201527f6e6e6572206f66207468652063757272656e7420726f756e6400000000000000606482015260840161081f565b60105460ff166114b857600080fd5b6000546001600160a01b031633146114cf57600080fd5b6010805460ff19169055565b6000546001600160a01b031633146114f257600080fd5b6007949094556008805460ff191660ff9490941693909317909255600955600355600455565b600080600160009054906101000a90046001600160a01b03166001600160a01b031663658f17886040518163ffffffff1660e01b8152600401602060405180830381865afa15801561156e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611592919061187e565b90506000600454600354600b546115a991906117d9565b6115b391906117d9565b600754600f5493820202600090810393919250908311156115e257600f546115db90846118b9565b90506115f3565b82600f546115f091906118b9565b90505b9392505050565b6000546001600160a01b0316331461161157600080fd5b600591909155600655565b600160009054906101000a90046001600160a01b03166001600160a01b0316632b807d37826040518263ffffffff1660e01b81526004016000604051808303818588803b15801561166c57600080fd5b505af1158015611680573d6000803e3d6000fd5b505050505050565b60006020828403121561169a57600080fd5b5035919050565b6001600160a01b0381168114610bf157600080fd5b6000602082840312156116c857600080fd5b81356115f3816116a1565b600080604083850312156116e657600080fd5b82356116f1816116a1565b91506020830135611701816116a1565b809150509250929050565b803560ff8116811461076a57600080fd5b60008060006060848603121561173257600080fd5b833561173d816116a1565b9250602084013591506117526040850161170c565b90509250925092565b600080600080600060a0868803121561177357600080fd5b853594506117836020870161170c565b94979496505050506040830135926060810135926080909101359150565b600080604083850312156117b457600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b808201808211156117ec576117ec6117c3565b92915050565b600060018201611804576118046117c3565b5060010190565b600060ff821660ff8103611821576118216117c3565b60010192915050565b80820281158282048414176117ec576117ec6117c3565b634e487b7160e01b600052601260045260246000fd5b60008261186657611866611841565b500490565b818103818111156117ec576117ec6117c3565b60006020828403121561189057600080fd5b5051919050565b6000602082840312156118a957600080fd5b815180151581146115f357600080fd5b6000826118c8576118c8611841565b50069056fea26469706673582212201bc7f87fa8dbcf16ded5cdb22d23ba56bcddc4afb39312ea363ddae8946715bc64736f6c63430008130033

Deployed ByteCode

0x6080604052600436106102135760003560e01c80639a74e1ed11610118578063d1205e26116100a0578063e2eb41ff1161006f578063e2eb41ff14610600578063e6e4cdce14610630578063ef0c67e114610660578063f714922014610676578063ff48fd421461068b57600080fd5b8063d1205e261461059f578063dbca930f146105b5578063e0371472146105d5578063e168cf86146105eb57600080fd5b8063b8b34132116100e7578063b8b341321461053d578063b9802e3e14610552578063c15d80c314610567578063ce253f0d1461057d578063d0e30db01461059757600080fd5b80639a74e1ed146104d25780639f24eb67146104f2578063a2022a1614610508578063a5b860041461052857600080fd5b80635d799f871161019b5780637c3682af1161016a5780637c3682af146103df5780637cab348f146103ff5780638d9510d4146104075780638da5cb5b1461043f5780638f8e02701461045f57600080fd5b80635d799f87146103685780636021caab146103885780636893b419146103b4578063709c4e91146103ca57600080fd5b80632d02c681116101e25780632d02c681146102d25780633152fd0d146102e8578063319c068c146103085780633debbed51461031e5780634631dd941461033e57600080fd5b8063043c348a146102535780630fcc56f71461027c578063214ab7d61461029c578063278ecde1146102b257600080fd5b3661024e576102206106ab565b60ff166000036102345761023261076f565b005b61023c6106ab565b60ff1660010361024e576102326108e0565b600080fd5b34801561025f57600080fd5b5061026960095481565b6040519081526020015b60405180910390f35b34801561028857600080fd5b50610232610297366004611688565b610cba565b3480156102a857600080fd5b50610269600c5481565b3480156102be57600080fd5b506102326102cd366004611688565b610d11565b3480156102de57600080fd5b50610269600b5481565b3480156102f457600080fd5b506102326103033660046116b6565b610ee7565b34801561031457600080fd5b50610269600a5481565b34801561032a57600080fd5b506102326103393660046116b6565b610f20565b34801561034a57600080fd5b506010546103589060ff1681565b6040519015158152602001610273565b34801561037457600080fd5b506102326103833660046116d3565b610f59565b34801561039457600080fd5b506008546103a29060ff1681565b60405160ff9091168152602001610273565b3480156103c057600080fd5b5061026960065481565b3480156103d657600080fd5b50610358611058565b3480156103eb57600080fd5b506103586103fa3660046116b6565b6110d8565b61023261076f565b34801561041357600080fd5b50600254610427906001600160a01b031681565b6040516001600160a01b039091168152602001610273565b34801561044b57600080fd5b50600054610427906001600160a01b031681565b34801561046b57600080fd5b506104bd61047a36600461171d565b6001600160a01b039290921660009081526011602090815260408083209383526002909301815282822060ff909416825292909252902080546001909101549091565b60408051928352602083019190915201610273565b3480156104de57600080fd5b50600154610427906001600160a01b031681565b3480156104fe57600080fd5b5061026960055481565b34801561051457600080fd5b506102326105233660046116b6565b6111b8565b34801561053457600080fd5b506103a26106ab565b34801561054957600080fd5b506102326114a9565b34801561055e57600080fd5b50600a54610269565b34801561057357600080fd5b5061026960035481565b34801561058957600080fd5b50600d546103589060ff1681565b6102326108e0565b3480156105ab57600080fd5b50610269600f5481565b3480156105c157600080fd5b506102326105d036600461175b565b6114db565b3480156105e157600080fd5b5061026960075481565b3480156105f757600080fd5b50600954610269565b34801561060c57600080fd5b5061026961061b3660046116b6565b60116020526000908152604090206001015481565b34801561063c57600080fd5b5061035861064b366004611688565b600e6020526000908152604090205460ff1681565b34801561066c57600080fd5b5061026960045481565b34801561068257600080fd5b50610269611518565b34801561069757600080fd5b506102326106a63660046117a1565b6115fa565b6000806000905042600b54111580156106d35750600354600b546106cf91906117d9565b4211155b156106e057506001919050565b42600b5410801561070c5750600454600354600b546106ff91906117d9565b61070991906117d9565b42105b1561071957506002919050565b600b541580159061072b575042600b54105b80156107525750600454600354600b5461074591906117d9565b61074f91906117d9565b42115b80156107615750600d5460ff16155b1561076a575060035b919050565b600a5415806107805750600d5460ff165b6108285760405162461bcd60e51b815260206004820152606260248201527f43616e6e6f742073746172742061206e657720726f756e64207768696c65207260448201527f657761726420666f72207468652070726576696f7573206f6e65206973206e6f60648201527f7420706169642e2043616c6c2066696e6973685f726f756e642066756e63746960848201526137b760f11b60a482015260c4015b60405180910390fd5b600a8054906000610838836117f2565b9091555050600a546040517fa2b5357eea32aeb35142ba36b087f9fe674f34f8b57ce94d30e9f4f572195bcf90600090a242600b556000600f819055600d805460ff1916905560015460408051630880a2a160e21b815290516001600160a01b03909216926322028a849260048084019382900301818387803b1580156108be57600080fd5b505af11580156108d2573d6000803e3d6000fd5b505050506108de6108e0565b565b6007543410156109325760405162461bcd60e51b815260206004820181905260248201527f4d696e696d756d2062657420636f6e646974696f6e206973206e6f74206d6574604482015260640161081f565b600854336000908152601160209081526040808320600a54845290915290205460ff918216911610806109785750600a5433600090815260116020526040902060010154105b6109d05760405162461bcd60e51b815260206004820152602360248201527f546f6f206d756368206465706f7369747320647572696e67207468697320726f6044820152621d5b9960ea1b606482015260840161081f565b6109d86106ab565b60ff16600114610a485760405162461bcd60e51b815260206004820152603560248201527f4465706f7369747320617265206f6e6c7920616c6c6f77656420647572696e6760448201527420746865206465706f736974696e6720706861736560581b606482015260840161081f565b60095415610aae57600954600c54610a6090346117d9565b1115610aae5760405162461bcd60e51b815260206004820152601f60248201527f526f756e6420726577617264207468726573686f6c6420657863656564656400604482015260640161081f565b600a54336000908152601160205260409020600101541015610afa57600a543360009081526011602090815260408083206001810185905593835292905220805460ff19169055610b3f565b336000908152601160209081526040808320600a5484529091528120805460ff1691610b258361180b565b91906101000a81548160ff021916908360ff160217905550505b600f54336000908152601160209081526040808320600a5484526002810183528184209083528184205460ff1684529091529020819055610b819034906117d9565b336000908152601160209081526040808320600a5484526002810183528184209083528184205460ff168452909152812060010191909155600f8054349290610bcb9084906117d9565b90915550506006543490610bf4906103e890610be7908461182a565b610bf19190611857565b50565b6103e860065434610c05919061182a565b610c0f9190611857565b610c19908261186b565b9050610c3e6103e860055434610c2f919061182a565b610c399190611857565b61161c565b6103e860055434610c4f919061182a565b610c599190611857565b610c63908261186b565b905080600c6000828254610c7791906117d9565b9091555050604080513481526020810183905233917f90890809c654f11d6e72a28fa60149770a0d11ec6c92319d6ceb2bb0a4ea1a15910160405180910390a250565b6000546001600160a01b03163314610cd157600080fd5b60105460ff16610ce057600080fd5b604051339082156108fc029083906000818181858888f19350505050158015610d0d573d6000803e3d6000fd5b5050565b6000818152600e602052604090205460ff16610d815760405162461bcd60e51b815260206004820152602960248201527f4f6e6c7920726566756e6473206f66204641494c454420726f756e64732061726044820152681948185b1b1bddd95960ba1b606482015260840161081f565b6000805b33600090815260116020908152604080832086845290915290205460ff90811690821611610e0557336000908152601160209081526040808320868452600201825280832060ff8516845290915290208054600190910154610de7919061186b565b610df190836117d9565b915080610dfd8161180b565b915050610d85565b5060055481906103e890610e19908361182a565b610e239190611857565b610e2d908361186b565b91506103e860065482610e40919061182a565b610e4a9190611857565b610e54908361186b565b336000818152601160209081526040808320888452600301909152808220805460ff1916600117905551929450909184156108fc0291859190818181858888f19350505050158015610eaa573d6000803e3d6000fd5b50604051828152839033907f73f04af9dcc582a923ec15d3eea990fe34adabfff2879e28d44572e01a54abb69060200160405180910390a3505050565b6000546001600160a01b03163314610efe57600080fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b03163314610f3757600080fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b03163314610f7057600080fd5b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015610fb7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fdb919061187e565b60405163a9059cbb60e01b81526001600160a01b038481166004830152602482018390529192509084169063a9059cbb906044016020604051808303816000875af115801561102e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110529190611897565b50505050565b600080600160009054906101000a90046001600160a01b03166001600160a01b031663685823566040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d2919061187e565b11905090565b600080805b6001600160a01b0384166000908152601160209081526040808320600a54845290915290205460ff908116908216116111b157611118611518565b6001600160a01b0385166000908152601160209081526040808320600a548452600201825280832060ff86168452909152902054108015611195575061115c611518565b6001600160a01b0385166000908152601160209081526040808320600a548452600201825280832060ff86168452909152902060010154115b1561119f57600191505b806111a98161180b565b9150506110dd565b5092915050565b600454600354600b546111cb91906117d9565b6111d591906117d9565b42116112495760405162461bcd60e51b815260206004820152603960248201527f526f756e642063616e2062652066696e6973686564206166746572207468652060448201527f656e74726f70792072657665616c207068617365206f6e6c7900000000000000606482015260840161081f565b611251611058565b156113c65760005b6001600160a01b0382166000908152601160209081526040808320600a54845290915290205460ff9081169082161161136f57611294611518565b6001600160a01b0383166000908152601160209081526040808320600a548452600201825280832060ff8616845290915290205410801561131257506112d8611518565b6001600160a01b0383166000908152601160209081526040808320600a548452600201825280832060ff8616845290915290206001015410155b1561135d57600c546040516001600160a01b0384169180156108fc02916000818181858888f1935050505015801561134e573d6000803e3d6000fd5b50600d805460ff191660011790555b806113678161180b565b915050611259565b50806001600160a01b0316600a547fdac8947072807383f3f208c42a54bc2f876bd71ab3f5e8f8de8af9dfb9819bb3600c546113a9611518565b6040805192835260208301919091520160405180910390a3611431565b600a80546000908152600e602090815260408083208054600160ff199182168117909255600d805490911690911790559254835183815291820183905291927fdac8947072807383f3f208c42a54bc2f876bd71ab3f5e8f8de8af9dfb9819bb3910160405180910390a35b600d5460ff16610bf15760405162461bcd60e51b815260206004820152603960248201527f5468652070726f76696465642061646472657373206973206e6f74206120776960448201527f6e6e6572206f66207468652063757272656e7420726f756e6400000000000000606482015260840161081f565b60105460ff166114b857600080fd5b6000546001600160a01b031633146114cf57600080fd5b6010805460ff19169055565b6000546001600160a01b031633146114f257600080fd5b6007949094556008805460ff191660ff9490941693909317909255600955600355600455565b600080600160009054906101000a90046001600160a01b03166001600160a01b031663658f17886040518163ffffffff1660e01b8152600401602060405180830381865afa15801561156e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611592919061187e565b90506000600454600354600b546115a991906117d9565b6115b391906117d9565b600754600f5493820202600090810393919250908311156115e257600f546115db90846118b9565b90506115f3565b82600f546115f091906118b9565b90505b9392505050565b6000546001600160a01b0316331461161157600080fd5b600591909155600655565b600160009054906101000a90046001600160a01b03166001600160a01b0316632b807d37826040518263ffffffff1660e01b81526004016000604051808303818588803b15801561166c57600080fd5b505af1158015611680573d6000803e3d6000fd5b505050505050565b60006020828403121561169a57600080fd5b5035919050565b6001600160a01b0381168114610bf157600080fd5b6000602082840312156116c857600080fd5b81356115f3816116a1565b600080604083850312156116e657600080fd5b82356116f1816116a1565b91506020830135611701816116a1565b809150509250929050565b803560ff8116811461076a57600080fd5b60008060006060848603121561173257600080fd5b833561173d816116a1565b9250602084013591506117526040850161170c565b90509250925092565b600080600080600060a0868803121561177357600080fd5b853594506117836020870161170c565b94979496505050506040830135926060810135926080909101359150565b600080604083850312156117b457600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b808201808211156117ec576117ec6117c3565b92915050565b600060018201611804576118046117c3565b5060010190565b600060ff821660ff8103611821576118216117c3565b60010192915050565b80820281158282048414176117ec576117ec6117c3565b634e487b7160e01b600052601260045260246000fd5b60008261186657611866611841565b500490565b818103818111156117ec576117ec6117c3565b60006020828403121561189057600080fd5b5051919050565b6000602082840312156118a957600080fd5b815180151581146115f357600080fd5b6000826118c8576118c8611841565b50069056fea26469706673582212201bc7f87fa8dbcf16ded5cdb22d23ba56bcddc4afb39312ea363ddae8946715bc64736f6c63430008130033