Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
This contract has been partially verified via Sourcify.
- Contract name:
- lottery
- Optimization enabled
- true
- Compiler version
- v0.8.19+commit.7dd6d404
- Optimization runs
- 800
- EVM Version
- default
- Verified at
- 2024-07-11T13:40:16.574890Z
Constructor Arguments
0x000000000000000000000000c670060ded5057fbec4d55ccd4446901a3e6e3f0
Arg [0] (address) : 0xc670060ded5057fbec4d55ccd4446901a3e6e3f0
Contract source code
// SPDX-License-Identifier: MIT /* . . . .. . .+*... .. :+#%*-.. . -*#%@@%=.. .. . .+##@@#%@@*:.. . . :*%%@%===#@@#-.. .. :*%%@#-=%#=*%@%+:.. . :*%@%+-+%%#*+*%@@*:.. .-*%@%=-#@@@%#***#%@#-.... ...+#%@#-=%@%@@%%+****#@%+:.. . =@@@*-*@@@%%@%++%*+++#@@*. . #@@#=#@@@@@%#+*%##*+=+%@@+. . .%@@+*@@@@@@@%#%###**++#@@#. . . .%@%+#@@@@@@@@%%###*+++#@@#. . . .%@%+#%*%@@@@@%%%%*-:+*#@@#. . . .%@%=*@#+%@@@@%%%*-:-+*+@@#. . . .%@#-+@@#=#@@@%%#-:=+*+=%@%. . .*%*-+@@@#=*%@@#-:+**#=-%@%. . .+@#-+@%%@#=+%#-:*##**=-%@%. . .=@%=+@#+%@%==--*#%*+#==%@#. . .+@@=*@@#+%%%+=#%%**@%==@@#. . #@@*##%@#*@%%%%%*#@@***@@%. . . #@@%%%*%@@@@%%@@%@%+##%@@#.. . -@@@%@@#%@@@@@@@@#+##%@@@= . ..+@@@@@@#%@@@@@@**%%@@@@+.. . -%@@@@%##@@@%*#%@@@@%- . . .*@@@@*+%@%*#@@@@@*. . . -%@@@++%*+#@@@%= . .. :#@@@#++#@@@#: .. . .+@@@@@@@@+. . .. :#@@@@#: .. .. .+@@+. . . == . .. .. .. Website: https://EVM.bet Twitter: https://x.com/EvmGames */ pragma solidity 0.8.19; /* * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } } /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred( address indexed previousOwner, address indexed newOwner ); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { address msgSender = _msgSender(); _owner = msgSender; emit OwnershipTransferred(address(0), msgSender); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(owner() == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { emit OwnershipTransferred(_owner, address(0)); _owner = address(0); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require( newOwner != address(0), "Ownable: new owner is the zero address" ); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } } /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and make it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } } /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval( address indexed owner, address indexed spender, uint256 value ); } /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; // solhint-disable-next-line no-inline-assembly assembly { size := extcodesize(account) } return size > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require( address(this).balance >= amount, "Address: insufficient balance" ); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (bool success, ) = recipient.call{value: amount}(""); require( success, "Address: unable to send value, recipient may have reverted" ); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain`call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue( target, data, value, "Address: low-level call with value failed" ); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require( address(this).balance >= value, "Address: insufficient balance for call" ); require(isContract(target), "Address: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.call{value: value}( data ); return _verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall( target, data, "Address: low-level static call failed" ); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.staticcall(data); return _verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall( target, data, "Address: low-level delegate call failed" ); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.delegatecall(data); return _verifyCallResult(success, returndata, errorMessage); } function _verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) private pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly // solhint-disable-next-line no-inline-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } } /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; function safeTransfer( IERC20 token, address to, uint256 value ) internal { _callOptionalReturn( token, abi.encodeWithSelector(token.transfer.selector, to, value) ); } function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { _callOptionalReturn( token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value) ); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20 token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' // solhint-disable-next-line max-line-length require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn( token, abi.encodeWithSelector(token.approve.selector, spender, value) ); } function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn( token, abi.encodeWithSelector( token.approve.selector, spender, newAllowance ) ); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require( oldAllowance >= value, "SafeERC20: decreased allowance below zero" ); uint256 newAllowance = oldAllowance - value; _callOptionalReturn( token, abi.encodeWithSelector( token.approve.selector, spender, newAllowance ) ); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall( data, "SafeERC20: low-level call failed" ); if (returndata.length > 0) { // Return data is optional // solhint-disable-next-line max-line-length require( abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed" ); } } } interface IRandomizer { /** * Requests randomness */ function getRandomNumber(uint32 _callbackGasLimit, uint256 amountOfGas) external; /** * View latest lotteryId numbers */ function viewLatestLotteryId() external view returns (uint256); /** * Views random result */ function viewRandomResult() external view returns (uint32); } interface ILottery { /** * @notice Buy tickets for the current lottery * @param _lotteryId: lotteryId * @param _ticketNumbers: array of ticket numbers between 1,000,000 and 1,999,999 * @dev Callable by users */ function buyTickets(uint256 _lotteryId, uint32[] calldata _ticketNumbers) external payable; /** * @notice Claim a set of winning tickets for a lottery * @param _lotteryId: lottery id * @param _ticketIds: array of ticket ids * @param _brackets: array of brackets for the ticket ids * @dev Callable by users only, not contract! */ function claimTickets( uint256 _lotteryId, uint256[] calldata _ticketIds, uint32[] calldata _brackets ) external; /** * @notice Close lottery * @param _lotteryId: lottery id * @dev Callable by operator */ function closeLottery( uint256 _lotteryId, uint32 _callbackGasLimit, uint256 amountOfGas ) external; /** * @notice Draw the final number, calculate reward in METIS per group, and make lottery claimable * @param _lotteryId: lottery id * @param _autoInjection: reinjects funds into next lottery (vs. withdrawing all) * @dev Callable by operator */ function drawFinalNumberAndMakeLotteryClaimable( uint256 _lotteryId, bool _autoInjection ) external; /** * @notice Inject funds * @param _lotteryId: lottery id * msg.value: amount to inject in base token * @dev Callable by operator */ function injectFunds(uint256 _lotteryId) external payable; /** * @notice Start the lottery * @dev Callable by operator * @param _endTime: endTime of the lottery * @param _priceTicketInMetis: price of a ticket in METIS * @param _discountDivisor: the divisor to calculate the discount magnitude for bulks * @param _rewardsBreakdown: breakdown of rewards per bracket (must sum to 10,000) * @param _treasuryFee: treasury fee (10,000 = 100%, 100 = 1%) */ function startLottery( uint256 _endTime, uint256 _priceTicketInMetis, uint256 _discountDivisor, uint256[6] calldata _rewardsBreakdown, uint256 _treasuryFee ) external; /** * @notice View current lottery id */ function viewCurrentLotteryId() external returns (uint256); } /** @title Lottery. * @notice It is a contract for a lottery system using * randomness provided by SCRT Network. */ contract lottery is ReentrancyGuard, ILottery, Ownable { using SafeERC20 for IERC20; address public injectorAddress; address public operatorAddress; address public treasuryAddress; uint256 public currentLotteryId; uint256 public currentTicketId; uint256 public maxNumberTicketsPerBuyOrClaim = 100; uint256 public maxPriceTicket = 1 ether; uint256 public minPriceTicket = 0.00001 ether; uint256 public pendingInjectionNextLottery; uint256 public constant MIN_DISCOUNT_DIVISOR = 300; uint256 public constant MIN_LENGTH_LOTTERY = 5 minutes; // 5 minutes uint256 public constant MAX_LENGTH_LOTTERY = 4 days + 5 minutes; // 4 days uint256 public constant MAX_TREASURY_FEE = 3000; // 30% IRandomizer public randomizer; enum Status { Pending, Open, Close, Claimable } struct Lottery { Status status; uint256 startTime; uint256 endTime; uint256 priceTicketInMetis; uint256 discountDivisor; uint256[6] rewardsBreakdown; // 0: 1 matching number // 5: 6 matching numbers uint256 treasuryFee; // 500: 5% // 200: 2% // 50: 0.5% uint256[6] MetisPerBracket; uint256[6] countWinnersPerBracket; uint256 firstTicketId; uint256 firstTicketIdNextLottery; uint256 amountCollectedInMetis; uint32 finalNumber; } struct Ticket { uint32 number; address owner; } // Mapping are cheaper than arrays mapping(uint256 => Lottery) private _lotteries; mapping(uint256 => Ticket) private _tickets; // Bracket calculator is used for verifying claims for ticket prizes mapping(uint32 => uint32) private _bracketCalculator; // Keeps track of number of ticket per unique combination for each lotteryId mapping(uint256 => mapping(uint32 => uint256)) private _numberTicketsPerLotteryId; // Keep track of user ticket ids for a given lotteryId mapping(address => mapping(uint256 => uint256[])) private _userTicketIdsPerLotteryId; modifier notContract() { require(!_isContract(msg.sender), "Contract not allowed"); require(msg.sender == tx.origin, "Proxy contract not allowed"); _; } modifier onlyOperator() { require(msg.sender == operatorAddress, "Not operator"); _; } modifier onlyOwnerOrInjector() { require( (msg.sender == owner()) || (msg.sender == injectorAddress), "Not owner or injector" ); _; } event AdminTokenRecovery(address token, uint256 amount); event LotteryClose( uint256 indexed lotteryId, uint256 firstTicketIdNextLottery ); event LotteryInjection(uint256 indexed lotteryId, uint256 injectedAmount); event LotteryOpen( uint256 indexed lotteryId, uint256 startTime, uint256 endTime, uint256 priceTicketInMetis, uint256 firstTicketId, uint256 injectedAmount ); event LotteryNumberDrawn( uint256 indexed lotteryId, uint256 finalNumber, uint256 countWinningTickets ); event NewOperatorAndTreasuryAndInjectorAddresses( address operator, address treasury, address injector ); event NewRandomizer(address indexed randomizer); event TicketsPurchase( address indexed buyer, uint256 indexed lotteryId, uint256 numberTickets ); event TicketsClaim( address indexed claimer, uint256 amount, uint256 indexed lotteryId, uint256 numberTickets ); /** * @notice Constructor * @dev RandomNumberGenerator must be deployed prior to this contract * @param _randomizerAddress: address of the Randomizer contract used to work with SCRT.network's VRF */ constructor(address _randomizerAddress) { randomizer = IRandomizer(_randomizerAddress); // Initializes a mapping _bracketCalculator[0] = 1; _bracketCalculator[1] = 11; _bracketCalculator[2] = 111; _bracketCalculator[3] = 1111; _bracketCalculator[4] = 11111; _bracketCalculator[5] = 111111; } /** * @notice Buy tickets for the current lottery * @param _lotteryId: lotteryId * @param _ticketNumbers: array of ticket numbers between 1,000,000 and 1,999,999 * @dev Callable by users */ function buyTickets(uint256 _lotteryId, uint32[] calldata _ticketNumbers) external payable override notContract nonReentrant { require(_ticketNumbers.length != 0, "No ticket specified"); require( _ticketNumbers.length <= maxNumberTicketsPerBuyOrClaim, "Too many tickets" ); require( _lotteries[_lotteryId].status == Status.Open, "Lottery is not open" ); require( block.timestamp < _lotteries[_lotteryId].endTime, "Lottery is over" ); // Calculate number of METIS to this contract uint256 amountMetisToPay = _calculateTotalPriceForBulkTickets( _lotteries[_lotteryId].discountDivisor, _lotteries[_lotteryId].priceTicketInMetis, _ticketNumbers.length ); require(msg.value >= amountMetisToPay, "Insufficient Ticket Fee"); if (amountMetisToPay > msg.value) { address(msg.sender).call{value: msg.value - amountMetisToPay}; } // Increment the total amount collected for the lottery round _lotteries[_lotteryId].amountCollectedInMetis += amountMetisToPay; for (uint256 i = 0; i < _ticketNumbers.length; i++) { uint32 thisTicketNumber = _ticketNumbers[i]; require( (thisTicketNumber >= 1000000) && (thisTicketNumber <= 1999999), "Outside range" ); _numberTicketsPerLotteryId[_lotteryId][ 1 + (thisTicketNumber % 10) ]++; _numberTicketsPerLotteryId[_lotteryId][ 11 + (thisTicketNumber % 100) ]++; _numberTicketsPerLotteryId[_lotteryId][ 111 + (thisTicketNumber % 1000) ]++; _numberTicketsPerLotteryId[_lotteryId][ 1111 + (thisTicketNumber % 10000) ]++; _numberTicketsPerLotteryId[_lotteryId][ 11111 + (thisTicketNumber % 100000) ]++; _numberTicketsPerLotteryId[_lotteryId][ 111111 + (thisTicketNumber % 1000000) ]++; _userTicketIdsPerLotteryId[msg.sender][_lotteryId].push( currentTicketId ); _tickets[currentTicketId] = Ticket({ number: thisTicketNumber, owner: msg.sender }); // Increase lottery ticket number currentTicketId++; } emit TicketsPurchase(msg.sender, _lotteryId, _ticketNumbers.length); } /** * @notice Claim a set of winning tickets for a lottery * @param _lotteryId: lottery id * @param _ticketIds: array of ticket ids * @param _brackets: array of brackets for the ticket ids * @dev Callable by users only, not contract! */ function claimTickets( uint256 _lotteryId, uint256[] calldata _ticketIds, uint32[] calldata _brackets ) external override notContract nonReentrant { require(_ticketIds.length == _brackets.length, "Not same length"); require(_ticketIds.length != 0, "Length must be >0"); require( _ticketIds.length <= maxNumberTicketsPerBuyOrClaim, "Too many tickets" ); require( _lotteries[_lotteryId].status == Status.Claimable, "Lottery not claimable" ); // Initializes the rewardInMetisToTransfer uint256 rewardInMetisToTransfer; for (uint256 i = 0; i < _ticketIds.length; i++) { require(_brackets[i] < 6, "Bracket out of range"); // Must be between 0 and 5 uint256 thisTicketId = _ticketIds[i]; require( _lotteries[_lotteryId].firstTicketIdNextLottery > thisTicketId, "TicketId too high" ); require( _lotteries[_lotteryId].firstTicketId <= thisTicketId, "TicketId too low" ); require( msg.sender == _tickets[thisTicketId].owner, "Not the owner" ); // Update the lottery ticket owner to 0x address _tickets[thisTicketId].owner = address(0); uint256 rewardForTicketId = _calculateRewardsForTicketId( _lotteryId, thisTicketId, _brackets[i] ); // Check user is claiming the correct bracket require(rewardForTicketId != 0, "No prize for this bracket"); if (_brackets[i] != 5) { require( _calculateRewardsForTicketId( _lotteryId, thisTicketId, _brackets[i] + 1 ) == 0, "Bracket must be higher" ); } // Increment the reward to transfer rewardInMetisToTransfer += rewardForTicketId; } // Transfer money to msg.sender (bool success, ) = address(msg.sender).call{ value: rewardInMetisToTransfer }(""); require(success, "Failed to send rewardInMetisToTransfer"); emit TicketsClaim( msg.sender, rewardInMetisToTransfer, _lotteryId, _ticketIds.length ); } /** * @notice Close lottery * @param _lotteryId: lottery id * @param _callbackGasLimit: gas limit to be used by SecretVRF callback * @param amountOfGas: amount of gas paid for SecretVRF callback * @dev Callable by operator */ function closeLottery( uint256 _lotteryId, uint32 _callbackGasLimit, uint256 amountOfGas ) external override onlyOperator nonReentrant { require( _lotteries[_lotteryId].status == Status.Open, "Lottery not open" ); require( block.timestamp > _lotteries[_lotteryId].endTime, "Lottery not over" ); _lotteries[_lotteryId].firstTicketIdNextLottery = currentTicketId; // Request a random number from the generator based on a seed randomizer.getRandomNumber(_callbackGasLimit, amountOfGas); _lotteries[_lotteryId].status = Status.Close; emit LotteryClose(_lotteryId, currentTicketId); } /** * @notice Draw the final number, calculate reward in METIS per group, and make lottery claimable * @param _lotteryId: lottery id * @param _autoInjection: reinjects funds into next lottery (vs. withdrawing all) * @dev Callable by operator */ function drawFinalNumberAndMakeLotteryClaimable( uint256 _lotteryId, bool _autoInjection ) external override onlyOperator nonReentrant { require( _lotteries[_lotteryId].status == Status.Close, "Lottery not closed" ); require( _lotteryId == randomizer.viewLatestLotteryId(), "Numbers not drawn" ); // Calculate the finalNumber based on the randomResult generated by SCRT Network's fallback uint32 finalNumber = randomizer.viewRandomResult(); // Initialize a number to count addresses in the previous bracket uint256 numberAddressesInPreviousBracket; // Calculate the amount to share post-treasury fee uint256 amountToShareToWinners = ( ((_lotteries[_lotteryId].amountCollectedInMetis) * (10000 - _lotteries[_lotteryId].treasuryFee)) ) / 10000; // Initializes the amount to withdraw to treasury uint256 amountToWithdrawToTreasury; // Calculate prizes for each bracket starting from the highest one for (uint32 i = 0; i < 6; i++) { uint32 j = 5 - i; uint32 transformedWinningNumber = _bracketCalculator[j] + (finalNumber % (uint32(10)**(j + 1))); _lotteries[_lotteryId].countWinnersPerBracket[j] = _numberTicketsPerLotteryId[_lotteryId][ transformedWinningNumber ] - numberAddressesInPreviousBracket; // A. If number of users for this _bracket number is superior to 0 if ( (_numberTicketsPerLotteryId[_lotteryId][ transformedWinningNumber ] - numberAddressesInPreviousBracket) != 0 ) { // B. If rewards at this bracket are > 0, calculate, else, report the numberAddresses from previous bracket if (_lotteries[_lotteryId].rewardsBreakdown[j] != 0) { _lotteries[_lotteryId].MetisPerBracket[j] = ((_lotteries[_lotteryId].rewardsBreakdown[j] * amountToShareToWinners) / (_numberTicketsPerLotteryId[_lotteryId][ transformedWinningNumber ] - numberAddressesInPreviousBracket)) / 10000; // Update numberAddressesInPreviousBracket numberAddressesInPreviousBracket = _numberTicketsPerLotteryId[ _lotteryId ][transformedWinningNumber]; } // A. No METIS to distribute, they are added to the amount to withdraw to treasury address } else { _lotteries[_lotteryId].MetisPerBracket[j] = 0; amountToWithdrawToTreasury += (_lotteries[_lotteryId].rewardsBreakdown[j] * amountToShareToWinners) / 10000; } } // Update internal statuses for lottery _lotteries[_lotteryId].finalNumber = finalNumber; _lotteries[_lotteryId].status = Status.Claimable; if (_autoInjection) { pendingInjectionNextLottery = amountToWithdrawToTreasury; amountToWithdrawToTreasury = 0; } amountToWithdrawToTreasury += (_lotteries[_lotteryId] .amountCollectedInMetis - amountToShareToWinners); // Transfer METIS to treasury address (bool success, ) = treasuryAddress.call{ value: amountToWithdrawToTreasury }(""); require(success, "Transfer to treasury failed"); emit LotteryNumberDrawn( currentLotteryId, finalNumber, numberAddressesInPreviousBracket ); } /** * @notice Change the random generator * @dev The calls to functions are used to verify the new generator implements them properly. * It is necessary to wait for the VRF response before starting a round. * Callable only by the contract owner * @param _randomizerAddress: address of the random generator */ function changeRandomizer( address _randomizerAddress, uint32 _callbackGasLimit, uint256 amountOfGas ) external onlyOwner { require( _lotteries[currentLotteryId].status == Status.Claimable, "Lottery not in claimable" ); // Request a random number from the new randomizer IRandomizer(_randomizerAddress).getRandomNumber( _callbackGasLimit, amountOfGas ); // Calculate the finalNumber based on the randomResult generated by SCRT Network's fallback IRandomizer(_randomizerAddress).viewRandomResult(); randomizer = IRandomizer(_randomizerAddress); emit NewRandomizer(_randomizerAddress); } /** * @notice Inject funds * @param _lotteryId: lottery id * msg.value: amount to inject in base token * @dev Callable by owner or injector address */ function injectFunds(uint256 _lotteryId) external payable override onlyOwnerOrInjector { require( _lotteries[_lotteryId].status == Status.Open, "Lottery not open" ); _lotteries[_lotteryId].amountCollectedInMetis += msg.value; emit LotteryInjection(_lotteryId, msg.value); } /** * @notice Start the lottery * @dev Callable by operator * @param _endTime: endTime of the lottery * @param _priceTicketInMetis: price of a ticket in METIS * @param _discountDivisor: the divisor to calculate the discount magnitude for bulks * @param _rewardsBreakdown: breakdown of rewards per bracket (must sum to 10,000) * @param _treasuryFee: treasury fee (10,000 = 100%, 100 = 1%) */ function startLottery( uint256 _endTime, uint256 _priceTicketInMetis, uint256 _discountDivisor, uint256[6] calldata _rewardsBreakdown, uint256 _treasuryFee ) external override onlyOperator { require( (currentLotteryId == 0) || (_lotteries[currentLotteryId].status == Status.Claimable), "Not time to start lottery" ); require( ((_endTime - block.timestamp) > MIN_LENGTH_LOTTERY) && ((_endTime - block.timestamp) < MAX_LENGTH_LOTTERY), "Lottery length outside of range" ); require( (_priceTicketInMetis >= minPriceTicket) && (_priceTicketInMetis <= maxPriceTicket), "Outside of limits" ); require( _discountDivisor >= MIN_DISCOUNT_DIVISOR, "Discount divisor too low" ); require(_treasuryFee <= MAX_TREASURY_FEE, "Treasury fee too high"); require( (_rewardsBreakdown[0] + _rewardsBreakdown[1] + _rewardsBreakdown[2] + _rewardsBreakdown[3] + _rewardsBreakdown[4] + _rewardsBreakdown[5]) == 10000, "Rewards must equal 10000" ); currentLotteryId++; _lotteries[currentLotteryId] = Lottery({ status: Status.Open, startTime: block.timestamp, endTime: _endTime, priceTicketInMetis: _priceTicketInMetis, discountDivisor: _discountDivisor, rewardsBreakdown: _rewardsBreakdown, treasuryFee: _treasuryFee, MetisPerBracket: [ uint256(0), uint256(0), uint256(0), uint256(0), uint256(0), uint256(0) ], countWinnersPerBracket: [ uint256(0), uint256(0), uint256(0), uint256(0), uint256(0), uint256(0) ], firstTicketId: currentTicketId, firstTicketIdNextLottery: currentTicketId, amountCollectedInMetis: pendingInjectionNextLottery, finalNumber: 0 }); emit LotteryOpen( currentLotteryId, block.timestamp, _endTime, _priceTicketInMetis, currentTicketId, pendingInjectionNextLottery ); pendingInjectionNextLottery = 0; } /** * @notice It allows the admin to recover wrong tokens sent to the contract * @param _tokenAddress: the address of the token to withdraw * @param _tokenAmount: the number of token amount to withdraw * @dev Only callable by owner. */ function recoverWrongTokens(address _tokenAddress, uint256 _tokenAmount) external onlyOwner { IERC20(_tokenAddress).safeTransfer(address(msg.sender), _tokenAmount); emit AdminTokenRecovery(_tokenAddress, _tokenAmount); } /** * @notice Set METIS price ticket upper/lower limit * @dev Only callable by owner * @param _minPriceTicket: minimum price of a ticket in METIS * @param _maxPriceTicket: maximum price of a ticket in METIS */ function setMinAndMaxTicketPriceInMetis( uint256 _minPriceTicket, uint256 _maxPriceTicket ) external onlyOwner { require( _minPriceTicket <= _maxPriceTicket, "minPrice must be < maxPrice" ); minPriceTicket = _minPriceTicket; maxPriceTicket = _maxPriceTicket; } /** * @notice Set max number of tickets * @dev Only callable by owner */ function setMaxNumberTicketsPerBuy(uint256 _maxNumberTicketsPerBuy) external onlyOwner { require(_maxNumberTicketsPerBuy != 0, "Must be > 0"); maxNumberTicketsPerBuyOrClaim = _maxNumberTicketsPerBuy; } /** * @notice Set operator, treasury, and injector addresses * @dev Only callable by owner * @param _operatorAddress: address of the operator * @param _treasuryAddress: address of the treasury * @param _injectorAddress: address of the injector */ function setOperatorAndTreasuryAndInjectorAddresses( address _operatorAddress, address _treasuryAddress, address _injectorAddress ) external onlyOwner { require(_operatorAddress != address(0), "Cannot be zero address"); require(_treasuryAddress != address(0), "Cannot be zero address"); require(_injectorAddress != address(0), "Cannot be zero address"); operatorAddress = _operatorAddress; treasuryAddress = _treasuryAddress; injectorAddress = _injectorAddress; emit NewOperatorAndTreasuryAndInjectorAddresses( _operatorAddress, _treasuryAddress, _injectorAddress ); } /** * @notice Calculate price of a set of tickets * @param _discountDivisor: divisor for the discount * @param _priceTicket price of a ticket (in METIS) * @param _numberTickets number of tickets to buy */ function calculateTotalPriceForBulkTickets( uint256 _discountDivisor, uint256 _priceTicket, uint256 _numberTickets ) external pure returns (uint256) { require( _discountDivisor >= MIN_DISCOUNT_DIVISOR, "Must be >= MIN_DISCOUNT_DIVISOR" ); require(_numberTickets != 0, "Number of tickets must be > 0"); return _calculateTotalPriceForBulkTickets( _discountDivisor, _priceTicket, _numberTickets ); } /** * @notice View current lottery id */ function viewCurrentLotteryId() external view override returns (uint256) { return currentLotteryId; } /** * @notice View lottery information * @param _lotteryId: lottery id */ function viewLottery(uint256 _lotteryId) external view returns (Lottery memory) { return _lotteries[_lotteryId]; } /** * @notice View ticker statuses and numbers for an array of ticket ids * @param _ticketIds: array of _ticketId */ function viewNumbersAndStatusesForTicketIds(uint256[] calldata _ticketIds) external view returns (uint32[] memory, bool[] memory) { uint256 length = _ticketIds.length; uint32[] memory ticketNumbers = new uint32[](length); bool[] memory ticketStatuses = new bool[](length); for (uint256 i = 0; i < length; i++) { ticketNumbers[i] = _tickets[_ticketIds[i]].number; if (_tickets[_ticketIds[i]].owner == address(0)) { ticketStatuses[i] = true; } else { ticketStatuses[i] = false; } } return (ticketNumbers, ticketStatuses); } /** * @notice View rewards for a given ticket, providing a bracket, and lottery id * @dev Computations are mostly offchain. This is used to verify a ticket! * @param _lotteryId: lottery id * @param _ticketId: ticket id * @param _bracket: bracket for the ticketId to verify the claim and calculate rewards */ function viewRewardsForTicketId( uint256 _lotteryId, uint256 _ticketId, uint32 _bracket ) external view returns (uint256) { // Check lottery is in claimable status if (_lotteries[_lotteryId].status != Status.Claimable) { return 0; } // Check ticketId is within range if ( (_lotteries[_lotteryId].firstTicketIdNextLottery < _ticketId) && (_lotteries[_lotteryId].firstTicketId >= _ticketId) ) { return 0; } return _calculateRewardsForTicketId(_lotteryId, _ticketId, _bracket); } /** * @notice View user ticket ids, numbers, and statuses of user for a given lottery * @param _user: user address * @param _lotteryId: lottery id * @param _cursor: cursor to start where to retrieve the tickets * @param _size: the number of tickets to retrieve */ function viewUserInfoForLotteryId( address _user, uint256 _lotteryId, uint256 _cursor, uint256 _size ) external view returns ( uint256[] memory, uint32[] memory, bool[] memory, uint256 ) { uint256 length = _size; uint256 numberTicketsBoughtAtLotteryId = _userTicketIdsPerLotteryId[ _user ][_lotteryId].length; if (length > (numberTicketsBoughtAtLotteryId - _cursor)) { length = numberTicketsBoughtAtLotteryId - _cursor; } uint256[] memory lotteryTicketIds = new uint256[](length); uint32[] memory ticketNumbers = new uint32[](length); bool[] memory ticketStatuses = new bool[](length); for (uint256 i = 0; i < length; i++) { lotteryTicketIds[i] = _userTicketIdsPerLotteryId[_user][_lotteryId][ i + _cursor ]; ticketNumbers[i] = _tickets[lotteryTicketIds[i]].number; // True = ticket claimed if (_tickets[lotteryTicketIds[i]].owner == address(0)) { ticketStatuses[i] = true; } else { // ticket not claimed (includes the ones that cannot be claimed) ticketStatuses[i] = false; } } return ( lotteryTicketIds, ticketNumbers, ticketStatuses, _cursor + length ); } /** * @notice Calculate rewards for a given ticket * @param _lotteryId: lottery id * @param _ticketId: ticket id * @param _bracket: bracket for the ticketId to verify the claim and calculate rewards */ function _calculateRewardsForTicketId( uint256 _lotteryId, uint256 _ticketId, uint32 _bracket ) internal view returns (uint256) { // Retrieve the winning number combination uint32 userNumber = _lotteries[_lotteryId].finalNumber; // Retrieve the user number combination from the ticketId uint32 winningTicketNumber = _tickets[_ticketId].number; // Apply transformation to verify the claim provided by the user is true uint32 transformedWinningNumber = _bracketCalculator[_bracket] + (winningTicketNumber % (uint32(10)**(_bracket + 1))); uint32 transformedUserNumber = _bracketCalculator[_bracket] + (userNumber % (uint32(10)**(_bracket + 1))); // Confirm that the two transformed numbers are the same, if not throw if (transformedWinningNumber == transformedUserNumber) { return _lotteries[_lotteryId].MetisPerBracket[_bracket]; } else { return 0; } } /** * @notice Calculate final price for bulk of tickets * @param _discountDivisor: divisor for the discount (the smaller it is, the greater the discount is) * @param _priceTicket: price of a ticket * @param _numberTickets: number of tickets purchased */ function _calculateTotalPriceForBulkTickets( uint256 _discountDivisor, uint256 _priceTicket, uint256 _numberTickets ) internal pure returns (uint256) { return (_priceTicket * _numberTickets * (_discountDivisor + 1 - _numberTickets)) / _discountDivisor; } /** * @notice Check if an address is a contract */ function _isContract(address _addr) internal view returns (bool) { uint256 size; assembly { size := extcodesize(_addr) } return size > 0; } }
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_randomizerAddress","internalType":"address"}]},{"type":"event","name":"AdminTokenRecovery","inputs":[{"type":"address","name":"token","internalType":"address","indexed":false},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"LotteryClose","inputs":[{"type":"uint256","name":"lotteryId","internalType":"uint256","indexed":true},{"type":"uint256","name":"firstTicketIdNextLottery","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"LotteryInjection","inputs":[{"type":"uint256","name":"lotteryId","internalType":"uint256","indexed":true},{"type":"uint256","name":"injectedAmount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"LotteryNumberDrawn","inputs":[{"type":"uint256","name":"lotteryId","internalType":"uint256","indexed":true},{"type":"uint256","name":"finalNumber","internalType":"uint256","indexed":false},{"type":"uint256","name":"countWinningTickets","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"LotteryOpen","inputs":[{"type":"uint256","name":"lotteryId","internalType":"uint256","indexed":true},{"type":"uint256","name":"startTime","internalType":"uint256","indexed":false},{"type":"uint256","name":"endTime","internalType":"uint256","indexed":false},{"type":"uint256","name":"priceTicketInMetis","internalType":"uint256","indexed":false},{"type":"uint256","name":"firstTicketId","internalType":"uint256","indexed":false},{"type":"uint256","name":"injectedAmount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"NewOperatorAndTreasuryAndInjectorAddresses","inputs":[{"type":"address","name":"operator","internalType":"address","indexed":false},{"type":"address","name":"treasury","internalType":"address","indexed":false},{"type":"address","name":"injector","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"NewRandomizer","inputs":[{"type":"address","name":"randomizer","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"TicketsClaim","inputs":[{"type":"address","name":"claimer","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false},{"type":"uint256","name":"lotteryId","internalType":"uint256","indexed":true},{"type":"uint256","name":"numberTickets","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"TicketsPurchase","inputs":[{"type":"address","name":"buyer","internalType":"address","indexed":true},{"type":"uint256","name":"lotteryId","internalType":"uint256","indexed":true},{"type":"uint256","name":"numberTickets","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"MAX_LENGTH_LOTTERY","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"MAX_TREASURY_FEE","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"MIN_DISCOUNT_DIVISOR","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"MIN_LENGTH_LOTTERY","inputs":[]},{"type":"function","stateMutability":"payable","outputs":[],"name":"buyTickets","inputs":[{"type":"uint256","name":"_lotteryId","internalType":"uint256"},{"type":"uint32[]","name":"_ticketNumbers","internalType":"uint32[]"}]},{"type":"function","stateMutability":"pure","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"calculateTotalPriceForBulkTickets","inputs":[{"type":"uint256","name":"_discountDivisor","internalType":"uint256"},{"type":"uint256","name":"_priceTicket","internalType":"uint256"},{"type":"uint256","name":"_numberTickets","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"changeRandomizer","inputs":[{"type":"address","name":"_randomizerAddress","internalType":"address"},{"type":"uint32","name":"_callbackGasLimit","internalType":"uint32"},{"type":"uint256","name":"amountOfGas","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"claimTickets","inputs":[{"type":"uint256","name":"_lotteryId","internalType":"uint256"},{"type":"uint256[]","name":"_ticketIds","internalType":"uint256[]"},{"type":"uint32[]","name":"_brackets","internalType":"uint32[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"closeLottery","inputs":[{"type":"uint256","name":"_lotteryId","internalType":"uint256"},{"type":"uint32","name":"_callbackGasLimit","internalType":"uint32"},{"type":"uint256","name":"amountOfGas","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"currentLotteryId","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"currentTicketId","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"drawFinalNumberAndMakeLotteryClaimable","inputs":[{"type":"uint256","name":"_lotteryId","internalType":"uint256"},{"type":"bool","name":"_autoInjection","internalType":"bool"}]},{"type":"function","stateMutability":"payable","outputs":[],"name":"injectFunds","inputs":[{"type":"uint256","name":"_lotteryId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"injectorAddress","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"maxNumberTicketsPerBuyOrClaim","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"maxPriceTicket","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"minPriceTicket","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"operatorAddress","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"pendingInjectionNextLottery","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IRandomizer"}],"name":"randomizer","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"recoverWrongTokens","inputs":[{"type":"address","name":"_tokenAddress","internalType":"address"},{"type":"uint256","name":"_tokenAmount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setMaxNumberTicketsPerBuy","inputs":[{"type":"uint256","name":"_maxNumberTicketsPerBuy","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setMinAndMaxTicketPriceInMetis","inputs":[{"type":"uint256","name":"_minPriceTicket","internalType":"uint256"},{"type":"uint256","name":"_maxPriceTicket","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setOperatorAndTreasuryAndInjectorAddresses","inputs":[{"type":"address","name":"_operatorAddress","internalType":"address"},{"type":"address","name":"_treasuryAddress","internalType":"address"},{"type":"address","name":"_injectorAddress","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"startLottery","inputs":[{"type":"uint256","name":"_endTime","internalType":"uint256"},{"type":"uint256","name":"_priceTicketInMetis","internalType":"uint256"},{"type":"uint256","name":"_discountDivisor","internalType":"uint256"},{"type":"uint256[6]","name":"_rewardsBreakdown","internalType":"uint256[6]"},{"type":"uint256","name":"_treasuryFee","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"treasuryAddress","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"viewCurrentLotteryId","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"","internalType":"struct lottery.Lottery","components":[{"type":"uint8","name":"status","internalType":"enum lottery.Status"},{"type":"uint256","name":"startTime","internalType":"uint256"},{"type":"uint256","name":"endTime","internalType":"uint256"},{"type":"uint256","name":"priceTicketInMetis","internalType":"uint256"},{"type":"uint256","name":"discountDivisor","internalType":"uint256"},{"type":"uint256[6]","name":"rewardsBreakdown","internalType":"uint256[6]"},{"type":"uint256","name":"treasuryFee","internalType":"uint256"},{"type":"uint256[6]","name":"MetisPerBracket","internalType":"uint256[6]"},{"type":"uint256[6]","name":"countWinnersPerBracket","internalType":"uint256[6]"},{"type":"uint256","name":"firstTicketId","internalType":"uint256"},{"type":"uint256","name":"firstTicketIdNextLottery","internalType":"uint256"},{"type":"uint256","name":"amountCollectedInMetis","internalType":"uint256"},{"type":"uint32","name":"finalNumber","internalType":"uint32"}]}],"name":"viewLottery","inputs":[{"type":"uint256","name":"_lotteryId","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint32[]","name":"","internalType":"uint32[]"},{"type":"bool[]","name":"","internalType":"bool[]"}],"name":"viewNumbersAndStatusesForTicketIds","inputs":[{"type":"uint256[]","name":"_ticketIds","internalType":"uint256[]"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"viewRewardsForTicketId","inputs":[{"type":"uint256","name":"_lotteryId","internalType":"uint256"},{"type":"uint256","name":"_ticketId","internalType":"uint256"},{"type":"uint32","name":"_bracket","internalType":"uint32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256[]","name":"","internalType":"uint256[]"},{"type":"uint32[]","name":"","internalType":"uint32[]"},{"type":"bool[]","name":"","internalType":"bool[]"},{"type":"uint256","name":"","internalType":"uint256"}],"name":"viewUserInfoForLotteryId","inputs":[{"type":"address","name":"_user","internalType":"address"},{"type":"uint256","name":"_lotteryId","internalType":"uint256"},{"type":"uint256","name":"_cursor","internalType":"uint256"},{"type":"uint256","name":"_size","internalType":"uint256"}]}]
Contract Creation Code
0x60806040526064600755670de0b6b3a76400006008556509184e72a0006009553480156200002c57600080fd5b5060405162004190380380620041908339810160408190526200004f91620001d0565b6001600081815581546001600160a01b031916339081179092556040518291907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a350600b80546001600160a01b039092166001600160a01b0319909216919091178155600e6020527fe710864318d4a32f37d6ce54cb3fadbef648dd12d8dbdf53973564d56b7f881c805463ffffffff199081166001179091557fa7c5ba7114a813b50159add3a36832908dc83db71d0b9a24c2ad0f83be958207805482169092179091557f9adb202b1492743bc00c81d33cdc6423fa8c79109027eb6a845391e8fc1f048180548216606f1790557fe0283e559c29e31ee7f56467acc9dd307779c843a883aeeb3bf5c6128c908144805482166104571790557fa1d6913cd9e08c872be3e7525cca82e4fc0fc298a783f19022be725b19be685a80548216612b6717905560056000527fb9bec7e2561f624fe753ff070f1599b306cbf59fafd4e8d5a8184a1ea1841bce80549091166201b20717905562000202565b600060208284031215620001e357600080fd5b81516001600160a01b0381168114620001fb57600080fd5b9392505050565b613f7e80620002126000396000f3fe6080604052600436106102195760003560e01c80638da5cb5b1161011d578063c802c4a3116100b0578063e359ebec1161007f578063f10fb58411610064578063f10fb584146105b9578063f2b3c809146105d9578063f2fde38b146105ef57600080fd5b8063e359ebec14610586578063e605529d1461059957600080fd5b8063c802c4a31461050f578063c914914f1461052f578063da4ca0391461054f578063db19da0d1461056f57600080fd5b8063c38de539116100ec578063c38de53914610499578063c4937ab9146104b9578063c5f956af146104d9578063c6be8994146104f957600080fd5b80638da5cb5b1461040d5780638fc3539a1461042b5780639c38465314610459578063b1829b821461047957600080fd5b80633f138d4b116101b05780636be4097c1161017f5780637cb583bd116101645780637cb583bd1461025757806380a06160146103e557806388303dbd146103fa57600080fd5b80636be4097c146103ba578063715018a6146103d057600080fd5b80633f138d4b1461034e578063670c182b1461036e578063686465b8146103845780636b8737881461039a57600080fd5b80631fe86c6b116101ec5780631fe86c6b146102c95780632423807a146102df5780632781bb7c1461030c5780632e530cae1461032e57600080fd5b806305531eeb1461021e57806307fb5a9c14610257578063127effb21461027b57806312a9769d146102b3575b600080fd5b34801561022a57600080fd5b5061023e6102393660046135ff565b61060f565b60405161024e94939291906136ab565b60405180910390f35b34801561026357600080fd5b5061026d61012c81565b60405190815260200161024e565b34801561028757600080fd5b5060035461029b906001600160a01b031681565b6040516001600160a01b03909116815260200161024e565b3480156102bf57600080fd5b5061026d600a5481565b3480156102d557600080fd5b5061026d60075481565b3480156102eb57600080fd5b506102ff6102fa36600461371f565b6108fa565b60405161024e9190613799565b34801561031857600080fd5b5061032c610327366004613872565b610a5b565b005b34801561033a57600080fd5b5061026d6103493660046138aa565b610ca4565b34801561035a57600080fd5b5061032c6103693660046138e3565b610d2b565b34801561037a57600080fd5b5061026d60085481565b34801561039057600080fd5b5061026d60065481565b3480156103a657600080fd5b5061032c6103b536600461371f565b610ddf565b3480156103c657600080fd5b5061026d60055481565b3480156103dc57600080fd5b5061032c610e8e565b3480156103f157600080fd5b5060055461026d565b61032c610408366004613952565b610f32565b34801561041957600080fd5b506001546001600160a01b031661029b565b34801561043757600080fd5b5061044b61044636600461399e565b6115ca565b60405161024e9291906139e0565b34801561046557600080fd5b5060025461029b906001600160a01b031681565b34801561048557600080fd5b5061032c610494366004613a0e565b611783565b3480156104a557600080fd5b5061032c6104b4366004613a6b565b611ca0565b3480156104c557600080fd5b5061026d6104d4366004613a9b565b612308565b3480156104e557600080fd5b5060045461029b906001600160a01b031681565b34801561050557600080fd5b5061026d60095481565b34801561051b57600080fd5b5061032c61052a366004613ac7565b6123b7565b34801561053b57600080fd5b5061032c61054a366004613af5565b61259b565b34801561055b57600080fd5b5061032c61056a366004613b6f565b612c5a565b34801561057b57600080fd5b5061026d6205472c81565b61032c61059436600461371f565b612e3a565b3480156105a557600080fd5b5061032c6105b4366004613bb2565b612f6c565b3480156105c557600080fd5b50600b5461029b906001600160a01b031681565b3480156105e557600080fd5b5061026d610bb881565b3480156105fb57600080fd5b5061032c61060a366004613bd4565b613021565b6001600160a01b0384166000908152601060209081526040808320868452909152812054606091829182919085906106478882613c05565b82111561065b576106588882613c05565b91505b60008267ffffffffffffffff81111561067657610676613c1e565b60405190808252806020026020018201604052801561069f578160200160208202803683370190505b50905060008367ffffffffffffffff8111156106bd576106bd613c1e565b6040519080825280602002602001820160405280156106e6578160200160208202803683370190505b50905060008467ffffffffffffffff81111561070457610704613c1e565b60405190808252806020026020018201604052801561072d578160200160208202803683370190505b50905060005b858110156108d457601060008f6001600160a01b03166001600160a01b0316815260200190815260200160002060008e81526020019081526020016000208c8261077d9190613c34565b8154811061078d5761078d613c47565b90600052602060002001548482815181106107aa576107aa613c47565b602002602001018181525050600d60008583815181106107cc576107cc613c47565b6020026020010151815260200190815260200160002060000160009054906101000a900463ffffffff1683828151811061080857610808613c47565b602002602001019063ffffffff16908163ffffffff168152505060006001600160a01b0316600d600086848151811061084357610843613c47565b60209081029190910181015182528101919091526040016000205464010000000090046001600160a01b03160361089d57600182828151811061088857610888613c47565b911515602092830291909101909101526108c2565b60008282815181106108b1576108b1613c47565b911515602092830291909101909101525b806108cc81613c5d565b915050610733565b508282826108e2888f613c34565b98509850985098505050505050945094509450949050565b6109026134f1565b6000828152600c60205260409081902081516101a081019092528054829060ff16600381111561093457610934613738565b600381111561094557610945613738565b81526001820154602082015260028201546040808301919091526003830154606083015260048301546080830152805160c081019182905260a09092019190600584019060069082845b81548152602001906001019080831161098f575050509183525050600b82015460208201526040805160c081018252910190600c830160068282826020028201915b8154815260200190600101908083116109d15750505091835250506040805160c081019182905260209092019190601284019060069082845b815481526020019060010190808311610a0a5750505091835250506018820154602082015260198201546040820152601a8201546060820152601b9091015463ffffffff1660809091015292915050565b6003546001600160a01b03163314610aa95760405162461bcd60e51b815260206004820152600c60248201526b2737ba1037b832b930ba37b960a11b60448201526064015b60405180910390fd5b600260005403610afb5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610aa0565b600260005560016000848152600c602052604090205460ff166003811115610b2557610b25613738565b14610b655760405162461bcd60e51b815260206004820152601060248201526f2637ba3a32b93c903737ba1037b832b760811b6044820152606401610aa0565b6000838152600c60205260409020600201544211610bc55760405162461bcd60e51b815260206004820152601060248201527f4c6f7474657279206e6f74206f766572000000000000000000000000000000006044820152606401610aa0565b6006546000848152600c60205260409081902060190191909155600b54905163931afbe560e01b815263ffffffff84166004820152602481018390526001600160a01b039091169063931afbe590604401600060405180830381600087803b158015610c3057600080fd5b505af1158015610c44573d6000803e3d6000fd5b5050506000848152600c6020908152604091829020805460ff1916600217905560065491519182528592507f3728e75294796694d59d2ffced9c394279baf7b9ebd2702db43f5f04bac67929910160405180910390a25050600160005550565b600060036000858152600c602052604090205460ff166003811115610ccb57610ccb613738565b14610cd857506000610d24565b6000848152600c602052604090206019015483118015610d0957506000848152600c60205260409020601801548311155b15610d1657506000610d24565b610d21848484613153565b90505b9392505050565b6001546001600160a01b03163314610d855760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610aa0565b610d996001600160a01b038316338361325e565b604080516001600160a01b0384168152602081018390527f74545154aac348a3eac92596bd1971957ca94795f4e954ec5f613b55fab78129910160405180910390a15050565b6001546001600160a01b03163314610e395760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610aa0565b80600003610e895760405162461bcd60e51b815260206004820152600b60248201527f4d757374206265203e20300000000000000000000000000000000000000000006044820152606401610aa0565b600755565b6001546001600160a01b03163314610ee85760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610aa0565b6001546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600180546001600160a01b0319169055565b333b15610f815760405162461bcd60e51b815260206004820152601460248201527f436f6e7472616374206e6f7420616c6c6f7765640000000000000000000000006044820152606401610aa0565b333214610fd05760405162461bcd60e51b815260206004820152601a60248201527f50726f787920636f6e7472616374206e6f7420616c6c6f7765640000000000006044820152606401610aa0565b6002600054036110225760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610aa0565b600260009081558190036110785760405162461bcd60e51b815260206004820152601360248201527f4e6f207469636b657420737065636966696564000000000000000000000000006044820152606401610aa0565b6007548111156110bd5760405162461bcd60e51b815260206004820152601060248201526f546f6f206d616e79207469636b65747360801b6044820152606401610aa0565b60016000848152600c602052604090205460ff1660038111156110e2576110e2613738565b1461112f5760405162461bcd60e51b815260206004820152601360248201527f4c6f7474657279206973206e6f74206f70656e000000000000000000000000006044820152606401610aa0565b6000838152600c6020526040902060020154421061118f5760405162461bcd60e51b815260206004820152600f60248201527f4c6f7474657279206973206f76657200000000000000000000000000000000006044820152606401610aa0565b6000838152600c6020526040812060048101546003909101546111b39190846132ca565b9050803410156112055760405162461bcd60e51b815260206004820152601760248201527f496e73756666696369656e74205469636b6574204665650000000000000000006044820152606401610aa0565b3481111561121b57336112188234613c05565b50505b6000848152600c60205260408120601a01805483929061123c908490613c34565b90915550600090505b8281101561158757600084848381811061126157611261613c47565b90506020020160208101906112769190613c76565b9050620f42408163ffffffff161015801561129a5750621e847f8163ffffffff1611155b6112e65760405162461bcd60e51b815260206004820152600d60248201527f4f7574736964652072616e6765000000000000000000000000000000000000006044820152606401610aa0565b6000868152600f6020526040812090611300600a84613ca9565b61130b906001613ccc565b63ffffffff1681526020810191909152604001600090812080549161132f83613c5d565b90915550506000868152600f602052604081209061134e606484613ca9565b61135990600b613ccc565b63ffffffff1681526020810191909152604001600090812080549161137d83613c5d565b90915550506000868152600f602052604081209061139d6103e884613ca9565b6113a890606f613ccc565b63ffffffff168152602081019190915260400160009081208054916113cc83613c5d565b90915550506000868152600f60205260408120906113ec61271084613ca9565b6113f890610457613ccc565b63ffffffff1681526020810191909152604001600090812080549161141c83613c5d565b90915550506000868152600f602052604081209061143d620186a084613ca9565b61144990612b67613ccc565b63ffffffff1681526020810191909152604001600090812080549161146d83613c5d565b90915550506000868152600f602052604081209061148e620f424084613ca9565b61149b906201b207613ccc565b63ffffffff168152602081019190915260400160009081208054916114bf83613c5d565b90915550503360008181526010602090815260408083208a84528252808320600680548254600181018455928652848620909201919091558151808301835263ffffffff808816825281850196875282548652600d9094529184209151825495516001600160a01b0316640100000000027fffffffffffffffff000000000000000000000000000000000000000000000000909616931692909217939093179092558154919061156e83613c5d565b919050555050808061157f90613c5d565b915050611245565b50604051828152849033907fd7d247b583de1023852eef87b48f54354dbec771d01bc2cc49e96094efc322b99060200160405180910390a3505060016000555050565b6060808260008167ffffffffffffffff8111156115e9576115e9613c1e565b604051908082528060200260200182016040528015611612578160200160208202803683370190505b50905060008267ffffffffffffffff81111561163057611630613c1e565b604051908082528060200260200182016040528015611659578160200160208202803683370190505b50905060005b8381101561177457600d600089898481811061167d5761167d613c47565b90506020020135815260200190815260200160002060000160009054906101000a900463ffffffff168382815181106116b8576116b8613c47565b63ffffffff909216602092830291909101909101526000600d818a8a858181106116e4576116e4613c47565b602090810292909201358352508101919091526040016000205464010000000090046001600160a01b03160361173d57600182828151811061172857611728613c47565b91151560209283029190910190910152611762565b600082828151811061175157611751613c47565b911515602092830291909101909101525b8061176c81613c5d565b91505061165f565b509093509150505b9250929050565b6003546001600160a01b031633146117cc5760405162461bcd60e51b815260206004820152600c60248201526b2737ba1037b832b930ba37b960a11b6044820152606401610aa0565b6005541580611800575060036005546000908152600c602052604090205460ff1660038111156117fe576117fe613738565b145b61184c5760405162461bcd60e51b815260206004820152601960248201527f4e6f742074696d6520746f207374617274206c6f7474657279000000000000006044820152606401610aa0565b61012c6118594287613c05565b11801561187157506205472c61186f4287613c05565b105b6118bd5760405162461bcd60e51b815260206004820152601f60248201527f4c6f7474657279206c656e677468206f757473696465206f662072616e6765006044820152606401610aa0565b60095484101580156118d157506008548411155b61191d5760405162461bcd60e51b815260206004820152601160248201527f4f757473696465206f66206c696d6974730000000000000000000000000000006044820152606401610aa0565b61012c83101561196f5760405162461bcd60e51b815260206004820152601860248201527f446973636f756e742064697669736f7220746f6f206c6f7700000000000000006044820152606401610aa0565b610bb88111156119c15760405162461bcd60e51b815260206004820152601560248201527f54726561737572792066656520746f6f206869676800000000000000000000006044820152606401610aa0565b60a08201356080830135606084013560408501356119e460208701358735613c34565b6119ee9190613c34565b6119f89190613c34565b611a029190613c34565b611a0c9190613c34565b61271014611a5c5760405162461bcd60e51b815260206004820152601860248201527f52657761726473206d75737420657175616c20313030303000000000000000006044820152606401610aa0565b60058054906000611a6c83613c5d565b9091555050604080516101a0810190915280600181526020014281526020018681526020018581526020018481526020018360068060200260405190810160405280929190826006602002808284376000920182905250928452505060208083018590526040805160c080820183528482528184018590528183018590526060808301869052608080840187905260a080850188905285890194909452845180840186528781528087018890528086018890528083018890528082018890528085018890529188019190915260065490870181905291860191909152600a549085015260e09093018290526005548252600c90522081518154829060ff19166001836003811115611b7f57611b7f613738565b02179055506020820151600182015560408201516002820155606082015160038201556080820151600482015560a0820151611bc19060058301906006613572565b5060c0820151600b82015560e0820151611be190600c8301906006613572565b50610100820151611bf89060128301906006613572565b5061012082015160188201556101408201516019820155610160820151601a82015561018090910151601b909101805463ffffffff191663ffffffff909216919091179055600554600654600a5460408051428152602081018a9052908101889052606081019290925260808201527f367e70f8c0e0c0a6504d92172bda155c02022d532fc85b5d66a9c49e31c8bc779060a00160405180910390a250506000600a55505050565b6003546001600160a01b03163314611ce95760405162461bcd60e51b815260206004820152600c60248201526b2737ba1037b832b930ba37b960a11b6044820152606401610aa0565b600260005403611d3b5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610aa0565b60026000818155838152600c602052604090205460ff166003811115611d6357611d63613738565b14611db05760405162461bcd60e51b815260206004820152601260248201527f4c6f7474657279206e6f7420636c6f73656400000000000000000000000000006044820152606401610aa0565b600b60009054906101000a90046001600160a01b03166001600160a01b031663fbe5d9176040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e03573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e279190613ce9565b8214611e755760405162461bcd60e51b815260206004820152601160248201527f4e756d62657273206e6f7420647261776e0000000000000000000000000000006044820152606401610aa0565b600b54604080516350e27aad60e11b815290516000926001600160a01b03169163a1c4f55a9160048083019260209291908290030181865afa158015611ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ee39190613d02565b6000848152600c60205260408120600b015491925090819061271090611f099082613c05565b6000878152600c60205260409020601a0154611f259190613d1f565b611f2f9190613d36565b90506000805b60068163ffffffff1610156121aa576000611f51826005613d4a565b90506000611f60826001613ccc565b611f6b90600a613e78565b611f759088613ca9565b63ffffffff8084166000908152600e6020526040902054611f97929116613ccc565b60008a8152600f6020908152604080832063ffffffff85168452909152902054909150611fc5908790613c05565b60008a8152600c6020526040902060120163ffffffff841660068110611fed57611fed613c47565b01556000898152600f6020908152604080832063ffffffff8516845290915290205461201a908790613c05565b1561211a576000898152600c6020526040902060050163ffffffff83166006811061204757612047613c47565b015415612115576000898152600f6020908152604080832063ffffffff851684529091529020546127109061207d908890613c05565b60008b8152600c60205260409020879060050163ffffffff8616600681106120a7576120a7613c47565b01546120b39190613d1f565b6120bd9190613d36565b6120c79190613d36565b60008a8152600c602081905260409091200163ffffffff8416600681106120f0576120f0613c47565b01556000898152600f6020908152604080832063ffffffff8516845290915290205495505b612195565b6000898152600c6020819052604082200163ffffffff84166006811061214257612142613c47565b01556000898152600c6020526040902061271090869060050163ffffffff85166006811061217257612172613c47565b015461217e9190613d1f565b6121889190613d36565b6121929085613c34565b93505b505080806121a290613e95565b915050611f35565b506000868152600c60205260409020601b8101805463ffffffff871663ffffffff19909116179055805460ff1916600317905584156121e957600a5560005b6000868152600c60205260409020601a0154612206908390613c05565b6122109082613c34565b6004546040519192506000916001600160a01b039091169083908381818185875af1925050503d8060008114612262576040519150601f19603f3d011682016040523d82523d6000602084013e612267565b606091505b50509050806122b85760405162461bcd60e51b815260206004820152601b60248201527f5472616e7366657220746f207472656173757279206661696c656400000000006044820152606401610aa0565b6005546040805163ffffffff88168152602081018790527f98e31a6607b8b15b4d5b91de54f4c09ffe4c4cf162aa532c70b5213754e2e703910160405180910390a2505060016000555050505050565b600061012c84101561235c5760405162461bcd60e51b815260206004820152601f60248201527f4d757374206265203e3d204d494e5f444953434f554e545f44495649534f52006044820152606401610aa0565b816000036123ac5760405162461bcd60e51b815260206004820152601d60248201527f4e756d626572206f66207469636b657473206d757374206265203e20300000006044820152606401610aa0565b610d218484846132ca565b6001546001600160a01b031633146124115760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610aa0565b60036005546000908152600c602052604090205460ff16600381111561243957612439613738565b146124865760405162461bcd60e51b815260206004820152601860248201527f4c6f7474657279206e6f7420696e20636c61696d61626c6500000000000000006044820152606401610aa0565b60405163931afbe560e01b815263ffffffff83166004820152602481018290526001600160a01b0384169063931afbe590604401600060405180830381600087803b1580156124d457600080fd5b505af11580156124e8573d6000803e3d6000fd5b50505050826001600160a01b031663a1c4f55a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561252a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061254e9190613d02565b50600b80546001600160a01b0319166001600160a01b0385169081179091556040517f453043396644e1a2577114bba3c0e058997aa12fb4ab5894e0446fb3b83fefff90600090a2505050565b333b156125ea5760405162461bcd60e51b815260206004820152601460248201527f436f6e7472616374206e6f7420616c6c6f7765640000000000000000000000006044820152606401610aa0565b3332146126395760405162461bcd60e51b815260206004820152601a60248201527f50726f787920636f6e7472616374206e6f7420616c6c6f7765640000000000006044820152606401610aa0565b60026000540361268b5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610aa0565b60026000558281146126df5760405162461bcd60e51b815260206004820152600f60248201527f4e6f742073616d65206c656e67746800000000000000000000000000000000006044820152606401610aa0565b60008390036127305760405162461bcd60e51b815260206004820152601160248201527f4c656e677468206d757374206265203e300000000000000000000000000000006044820152606401610aa0565b6007548311156127755760405162461bcd60e51b815260206004820152601060248201526f546f6f206d616e79207469636b65747360801b6044820152606401610aa0565b60036000868152600c602052604090205460ff16600381111561279a5761279a613738565b146127e75760405162461bcd60e51b815260206004820152601560248201527f4c6f7474657279206e6f7420636c61696d61626c6500000000000000000000006044820152606401610aa0565b6000805b84811015612b5057600684848381811061280757612807613c47565b905060200201602081019061281c9190613c76565b63ffffffff161061286f5760405162461bcd60e51b815260206004820152601460248201527f427261636b6574206f7574206f662072616e67650000000000000000000000006044820152606401610aa0565b600086868381811061288357612883613c47565b90506020020135905080600c60008a815260200190815260200160002060190154116128f15760405162461bcd60e51b815260206004820152601160248201527f5469636b6574496420746f6f20686967680000000000000000000000000000006044820152606401610aa0565b6000888152600c60205260409020601801548110156129525760405162461bcd60e51b815260206004820152601060248201527f5469636b6574496420746f6f206c6f77000000000000000000000000000000006044820152606401610aa0565b6000818152600d602052604090205464010000000090046001600160a01b031633146129c05760405162461bcd60e51b815260206004820152600d60248201527f4e6f7420746865206f776e6572000000000000000000000000000000000000006044820152606401610aa0565b6000818152600d6020526040812080547fffffffffffffffff0000000000000000000000000000000000000000ffffffff169055612a258983888887818110612a0b57612a0b613c47565b9050602002016020810190612a209190613c76565b613153565b905080600003612a775760405162461bcd60e51b815260206004820152601960248201527f4e6f207072697a6520666f72207468697320627261636b6574000000000000006044820152606401610aa0565b858584818110612a8957612a89613c47565b9050602002016020810190612a9e9190613c76565b63ffffffff16600514612b2f57612ae28983888887818110612ac257612ac2613c47565b9050602002016020810190612ad79190613c76565b612a20906001613ccc565b15612b2f5760405162461bcd60e51b815260206004820152601660248201527f427261636b6574206d75737420626520686967686572000000000000000000006044820152606401610aa0565b612b398185613c34565b935050508080612b4890613c5d565b9150506127eb565b50604051600090339083908381818185875af1925050503d8060008114612b93576040519150601f19603f3d011682016040523d82523d6000602084013e612b98565b606091505b5050905080612c0f5760405162461bcd60e51b815260206004820152602660248201527f4661696c656420746f2073656e6420726577617264496e4d65746973546f547260448201527f616e7366657200000000000000000000000000000000000000000000000000006064820152608401610aa0565b6040805183815260208101879052889133917f0f5fca62da8fb5d95525b49e5eaa7b20bc6bd9e2f6b64b493442d1c0bd6ef486910160405180910390a3505060016000555050505050565b6001546001600160a01b03163314612cb45760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610aa0565b6001600160a01b038316612d0a5760405162461bcd60e51b815260206004820152601660248201527f43616e6e6f74206265207a65726f2061646472657373000000000000000000006044820152606401610aa0565b6001600160a01b038216612d605760405162461bcd60e51b815260206004820152601660248201527f43616e6e6f74206265207a65726f2061646472657373000000000000000000006044820152606401610aa0565b6001600160a01b038116612db65760405162461bcd60e51b815260206004820152601660248201527f43616e6e6f74206265207a65726f2061646472657373000000000000000000006044820152606401610aa0565b600380546001600160a01b038581166001600160a01b0319928316811790935560048054868316908416811790915560028054928616929093168217909255604080519384526020840192909252908201527f3e945b7660001d46cfd5e729545f7f0b6c65bdee54066a91c7acad703f1b731e9060600160405180910390a1505050565b6001546001600160a01b0316331480612e5d57506002546001600160a01b031633145b612ea95760405162461bcd60e51b815260206004820152601560248201527f4e6f74206f776e6572206f7220696e6a6563746f7200000000000000000000006044820152606401610aa0565b60016000828152600c602052604090205460ff166003811115612ece57612ece613738565b14612f0e5760405162461bcd60e51b815260206004820152601060248201526f2637ba3a32b93c903737ba1037b832b760811b6044820152606401610aa0565b6000818152600c60205260408120601a018054349290612f2f908490613c34565b909155505060405134815281907f1bbd659dd628a25f7ff2eabb69c74a56939c539728282275c1c9c1a2d3e340499060200160405180910390a250565b6001546001600160a01b03163314612fc65760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610aa0565b808211156130165760405162461bcd60e51b815260206004820152601b60248201527f6d696e5072696365206d757374206265203c206d6178507269636500000000006044820152606401610aa0565b600991909155600855565b6001546001600160a01b0316331461307b5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610aa0565b6001600160a01b0381166130f75760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610aa0565b6001546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000838152600c60209081526040808320601b0154858452600d90925282205463ffffffff918216911682613189856001613ccc565b61319490600a613e78565b61319e9083613ca9565b63ffffffff8087166000908152600e60205260409020546131c0929116613ccc565b905060006131cf866001613ccc565b6131da90600a613e78565b6131e49085613ca9565b63ffffffff8088166000908152600e6020526040902054613206929116613ccc565b90508063ffffffff168263ffffffff1603613251576000888152600c602081905260409091200163ffffffff87166006811061324457613244613c47565b0154945050505050610d24565b6000945050505050610d24565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1663a9059cbb60e01b1790526132c5908490613301565b505050565b600083826132d9826001613c34565b6132e39190613c05565b6132ed8486613d1f565b6132f79190613d1f565b610d219190613d36565b6000613356826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166133e69092919063ffffffff16565b8051909150156132c557808060200190518101906133749190613eb8565b6132c55760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610aa0565b6060610d21848460008585843b61343f5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610aa0565b600080866001600160a01b0316858760405161345b9190613ef9565b60006040518083038185875af1925050503d8060008114613498576040519150601f19603f3d011682016040523d82523d6000602084013e61349d565b606091505b50915091506134ad8282866134b8565b979650505050505050565b606083156134c7575081610d24565b8251156134d75782518084602001fd5b8160405162461bcd60e51b8152600401610aa09190613f15565b604080516101a081019091528060008152602001600081526020016000815260200160008152602001600081526020016135296135b0565b81526020016000815260200161353d6135b0565b815260200161354a6135b0565b8152602001600081526020016000815260200160008152602001600063ffffffff1681525090565b82600681019282156135a0579160200282015b828111156135a0578251825591602001919060010190613585565b506135ac9291506135ce565b5090565b6040518060c001604052806006906020820280368337509192915050565b5b808211156135ac57600081556001016135cf565b80356001600160a01b03811681146135fa57600080fd5b919050565b6000806000806080858703121561361557600080fd5b61361e856135e3565b966020860135965060408601359560600135945092505050565b600081518084526020808501945080840160005b8381101561366e57815163ffffffff168752958201959082019060010161364c565b509495945050505050565b600081518084526020808501945080840160005b8381101561366e57815115158752958201959082019060010161368d565b6080808252855190820181905260009060209060a0840190828901845b828110156136e4578151845292840192908401906001016136c8565b505050838103828501526136f88188613638565b915050828103604084015261370d8186613679565b91505082606083015295945050505050565b60006020828403121561373157600080fd5b5035919050565b634e487b7160e01b600052602160045260246000fd5b6004811061376c57634e487b7160e01b600052602160045260246000fd5b9052565b8060005b6006811015613793578151845260209384019390910190600101613774565b50505050565b6000610380820190506137ad82845161374e565b6020830151602083015260408301516040830152606083015160608301526080830151608083015260a08301516137e760a0840182613770565b5060c0830151610160818185015260e0850151915061018061380b81860184613770565b6101008601519250613821610240860184613770565b6101208601516103008601526101408601516103208601529085015161034085015284015163ffffffff811661036085015290505b5092915050565b63ffffffff8116811461386f57600080fd5b50565b60008060006060848603121561388757600080fd5b8335925060208401356138998161385d565b929592945050506040919091013590565b6000806000606084860312156138bf57600080fd5b833592506020840135915060408401356138d88161385d565b809150509250925092565b600080604083850312156138f657600080fd5b6138ff836135e3565b946020939093013593505050565b60008083601f84011261391f57600080fd5b50813567ffffffffffffffff81111561393757600080fd5b6020830191508360208260051b850101111561177c57600080fd5b60008060006040848603121561396757600080fd5b83359250602084013567ffffffffffffffff81111561398557600080fd5b6139918682870161390d565b9497909650939450505050565b600080602083850312156139b157600080fd5b823567ffffffffffffffff8111156139c857600080fd5b6139d48582860161390d565b90969095509350505050565b6040815260006139f36040830185613638565b8281036020840152613a058185613679565b95945050505050565b60008060008060006101408688031215613a2757600080fd5b853594506020860135935060408601359250610120860187811115613a4b57600080fd5b94979396509194606001933592915050565b801515811461386f57600080fd5b60008060408385031215613a7e57600080fd5b823591506020830135613a9081613a5d565b809150509250929050565b600080600060608486031215613ab057600080fd5b505081359360208301359350604090920135919050565b600080600060608486031215613adc57600080fd5b613ae5846135e3565b925060208401356138998161385d565b600080600080600060608688031215613b0d57600080fd5b85359450602086013567ffffffffffffffff80821115613b2c57600080fd5b613b3889838a0161390d565b90965094506040880135915080821115613b5157600080fd5b50613b5e8882890161390d565b969995985093965092949392505050565b600080600060608486031215613b8457600080fd5b613b8d846135e3565b9250613b9b602085016135e3565b9150613ba9604085016135e3565b90509250925092565b60008060408385031215613bc557600080fd5b50508035926020909101359150565b600060208284031215613be657600080fd5b610d24826135e3565b634e487b7160e01b600052601160045260246000fd5b81810381811115613c1857613c18613bef565b92915050565b634e487b7160e01b600052604160045260246000fd5b80820180821115613c1857613c18613bef565b634e487b7160e01b600052603260045260246000fd5b600060018201613c6f57613c6f613bef565b5060010190565b600060208284031215613c8857600080fd5b8135610d248161385d565b634e487b7160e01b600052601260045260246000fd5b600063ffffffff80841680613cc057613cc0613c93565b92169190910692915050565b63ffffffff81811683821601908082111561385657613856613bef565b600060208284031215613cfb57600080fd5b5051919050565b600060208284031215613d1457600080fd5b8151610d248161385d565b8082028115828204841417613c1857613c18613bef565b600082613d4557613d45613c93565b500490565b63ffffffff82811682821603908082111561385657613856613bef565b600181815b80851115613da4578163ffffffff04821115613d8a57613d8a613bef565b80851615613d9757918102915b93841c9390800290613d6c565b509250929050565b600082613dbb57506001613c18565b81613dc857506000613c18565b8160018114613dde5760028114613de857613e19565b6001915050613c18565b60ff841115613df957613df9613bef565b6001841b915063ffffffff821115613e1357613e13613bef565b50613c18565b5060208310610133831016604e8410600b8410161715613e50575081810a63ffffffff811115613e4b57613e4b613bef565b613c18565b613e5a8383613d67565b8063ffffffff04821115613e7057613e70613bef565b029392505050565b600063ffffffff613e8d818516828516613dac565b949350505050565b600063ffffffff808316818103613eae57613eae613bef565b6001019392505050565b600060208284031215613eca57600080fd5b8151610d2481613a5d565b60005b83811015613ef0578181015183820152602001613ed8565b50506000910152565b60008251613f0b818460208701613ed5565b9190910192915050565b6020815260008251806020840152613f34816040850160208701613ed5565b601f01601f1916919091016040019291505056fea26469706673582212207557279dbf5761dff95e74cb1dd27257566ae064e9c781b436c95eda3c6ee0b264736f6c63430008130033000000000000000000000000c670060ded5057fbec4d55ccd4446901a3e6e3f0
Deployed ByteCode
0x6080604052600436106102195760003560e01c80638da5cb5b1161011d578063c802c4a3116100b0578063e359ebec1161007f578063f10fb58411610064578063f10fb584146105b9578063f2b3c809146105d9578063f2fde38b146105ef57600080fd5b8063e359ebec14610586578063e605529d1461059957600080fd5b8063c802c4a31461050f578063c914914f1461052f578063da4ca0391461054f578063db19da0d1461056f57600080fd5b8063c38de539116100ec578063c38de53914610499578063c4937ab9146104b9578063c5f956af146104d9578063c6be8994146104f957600080fd5b80638da5cb5b1461040d5780638fc3539a1461042b5780639c38465314610459578063b1829b821461047957600080fd5b80633f138d4b116101b05780636be4097c1161017f5780637cb583bd116101645780637cb583bd1461025757806380a06160146103e557806388303dbd146103fa57600080fd5b80636be4097c146103ba578063715018a6146103d057600080fd5b80633f138d4b1461034e578063670c182b1461036e578063686465b8146103845780636b8737881461039a57600080fd5b80631fe86c6b116101ec5780631fe86c6b146102c95780632423807a146102df5780632781bb7c1461030c5780632e530cae1461032e57600080fd5b806305531eeb1461021e57806307fb5a9c14610257578063127effb21461027b57806312a9769d146102b3575b600080fd5b34801561022a57600080fd5b5061023e6102393660046135ff565b61060f565b60405161024e94939291906136ab565b60405180910390f35b34801561026357600080fd5b5061026d61012c81565b60405190815260200161024e565b34801561028757600080fd5b5060035461029b906001600160a01b031681565b6040516001600160a01b03909116815260200161024e565b3480156102bf57600080fd5b5061026d600a5481565b3480156102d557600080fd5b5061026d60075481565b3480156102eb57600080fd5b506102ff6102fa36600461371f565b6108fa565b60405161024e9190613799565b34801561031857600080fd5b5061032c610327366004613872565b610a5b565b005b34801561033a57600080fd5b5061026d6103493660046138aa565b610ca4565b34801561035a57600080fd5b5061032c6103693660046138e3565b610d2b565b34801561037a57600080fd5b5061026d60085481565b34801561039057600080fd5b5061026d60065481565b3480156103a657600080fd5b5061032c6103b536600461371f565b610ddf565b3480156103c657600080fd5b5061026d60055481565b3480156103dc57600080fd5b5061032c610e8e565b3480156103f157600080fd5b5060055461026d565b61032c610408366004613952565b610f32565b34801561041957600080fd5b506001546001600160a01b031661029b565b34801561043757600080fd5b5061044b61044636600461399e565b6115ca565b60405161024e9291906139e0565b34801561046557600080fd5b5060025461029b906001600160a01b031681565b34801561048557600080fd5b5061032c610494366004613a0e565b611783565b3480156104a557600080fd5b5061032c6104b4366004613a6b565b611ca0565b3480156104c557600080fd5b5061026d6104d4366004613a9b565b612308565b3480156104e557600080fd5b5060045461029b906001600160a01b031681565b34801561050557600080fd5b5061026d60095481565b34801561051b57600080fd5b5061032c61052a366004613ac7565b6123b7565b34801561053b57600080fd5b5061032c61054a366004613af5565b61259b565b34801561055b57600080fd5b5061032c61056a366004613b6f565b612c5a565b34801561057b57600080fd5b5061026d6205472c81565b61032c61059436600461371f565b612e3a565b3480156105a557600080fd5b5061032c6105b4366004613bb2565b612f6c565b3480156105c557600080fd5b50600b5461029b906001600160a01b031681565b3480156105e557600080fd5b5061026d610bb881565b3480156105fb57600080fd5b5061032c61060a366004613bd4565b613021565b6001600160a01b0384166000908152601060209081526040808320868452909152812054606091829182919085906106478882613c05565b82111561065b576106588882613c05565b91505b60008267ffffffffffffffff81111561067657610676613c1e565b60405190808252806020026020018201604052801561069f578160200160208202803683370190505b50905060008367ffffffffffffffff8111156106bd576106bd613c1e565b6040519080825280602002602001820160405280156106e6578160200160208202803683370190505b50905060008467ffffffffffffffff81111561070457610704613c1e565b60405190808252806020026020018201604052801561072d578160200160208202803683370190505b50905060005b858110156108d457601060008f6001600160a01b03166001600160a01b0316815260200190815260200160002060008e81526020019081526020016000208c8261077d9190613c34565b8154811061078d5761078d613c47565b90600052602060002001548482815181106107aa576107aa613c47565b602002602001018181525050600d60008583815181106107cc576107cc613c47565b6020026020010151815260200190815260200160002060000160009054906101000a900463ffffffff1683828151811061080857610808613c47565b602002602001019063ffffffff16908163ffffffff168152505060006001600160a01b0316600d600086848151811061084357610843613c47565b60209081029190910181015182528101919091526040016000205464010000000090046001600160a01b03160361089d57600182828151811061088857610888613c47565b911515602092830291909101909101526108c2565b60008282815181106108b1576108b1613c47565b911515602092830291909101909101525b806108cc81613c5d565b915050610733565b508282826108e2888f613c34565b98509850985098505050505050945094509450949050565b6109026134f1565b6000828152600c60205260409081902081516101a081019092528054829060ff16600381111561093457610934613738565b600381111561094557610945613738565b81526001820154602082015260028201546040808301919091526003830154606083015260048301546080830152805160c081019182905260a09092019190600584019060069082845b81548152602001906001019080831161098f575050509183525050600b82015460208201526040805160c081018252910190600c830160068282826020028201915b8154815260200190600101908083116109d15750505091835250506040805160c081019182905260209092019190601284019060069082845b815481526020019060010190808311610a0a5750505091835250506018820154602082015260198201546040820152601a8201546060820152601b9091015463ffffffff1660809091015292915050565b6003546001600160a01b03163314610aa95760405162461bcd60e51b815260206004820152600c60248201526b2737ba1037b832b930ba37b960a11b60448201526064015b60405180910390fd5b600260005403610afb5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610aa0565b600260005560016000848152600c602052604090205460ff166003811115610b2557610b25613738565b14610b655760405162461bcd60e51b815260206004820152601060248201526f2637ba3a32b93c903737ba1037b832b760811b6044820152606401610aa0565b6000838152600c60205260409020600201544211610bc55760405162461bcd60e51b815260206004820152601060248201527f4c6f7474657279206e6f74206f766572000000000000000000000000000000006044820152606401610aa0565b6006546000848152600c60205260409081902060190191909155600b54905163931afbe560e01b815263ffffffff84166004820152602481018390526001600160a01b039091169063931afbe590604401600060405180830381600087803b158015610c3057600080fd5b505af1158015610c44573d6000803e3d6000fd5b5050506000848152600c6020908152604091829020805460ff1916600217905560065491519182528592507f3728e75294796694d59d2ffced9c394279baf7b9ebd2702db43f5f04bac67929910160405180910390a25050600160005550565b600060036000858152600c602052604090205460ff166003811115610ccb57610ccb613738565b14610cd857506000610d24565b6000848152600c602052604090206019015483118015610d0957506000848152600c60205260409020601801548311155b15610d1657506000610d24565b610d21848484613153565b90505b9392505050565b6001546001600160a01b03163314610d855760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610aa0565b610d996001600160a01b038316338361325e565b604080516001600160a01b0384168152602081018390527f74545154aac348a3eac92596bd1971957ca94795f4e954ec5f613b55fab78129910160405180910390a15050565b6001546001600160a01b03163314610e395760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610aa0565b80600003610e895760405162461bcd60e51b815260206004820152600b60248201527f4d757374206265203e20300000000000000000000000000000000000000000006044820152606401610aa0565b600755565b6001546001600160a01b03163314610ee85760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610aa0565b6001546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600180546001600160a01b0319169055565b333b15610f815760405162461bcd60e51b815260206004820152601460248201527f436f6e7472616374206e6f7420616c6c6f7765640000000000000000000000006044820152606401610aa0565b333214610fd05760405162461bcd60e51b815260206004820152601a60248201527f50726f787920636f6e7472616374206e6f7420616c6c6f7765640000000000006044820152606401610aa0565b6002600054036110225760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610aa0565b600260009081558190036110785760405162461bcd60e51b815260206004820152601360248201527f4e6f207469636b657420737065636966696564000000000000000000000000006044820152606401610aa0565b6007548111156110bd5760405162461bcd60e51b815260206004820152601060248201526f546f6f206d616e79207469636b65747360801b6044820152606401610aa0565b60016000848152600c602052604090205460ff1660038111156110e2576110e2613738565b1461112f5760405162461bcd60e51b815260206004820152601360248201527f4c6f7474657279206973206e6f74206f70656e000000000000000000000000006044820152606401610aa0565b6000838152600c6020526040902060020154421061118f5760405162461bcd60e51b815260206004820152600f60248201527f4c6f7474657279206973206f76657200000000000000000000000000000000006044820152606401610aa0565b6000838152600c6020526040812060048101546003909101546111b39190846132ca565b9050803410156112055760405162461bcd60e51b815260206004820152601760248201527f496e73756666696369656e74205469636b6574204665650000000000000000006044820152606401610aa0565b3481111561121b57336112188234613c05565b50505b6000848152600c60205260408120601a01805483929061123c908490613c34565b90915550600090505b8281101561158757600084848381811061126157611261613c47565b90506020020160208101906112769190613c76565b9050620f42408163ffffffff161015801561129a5750621e847f8163ffffffff1611155b6112e65760405162461bcd60e51b815260206004820152600d60248201527f4f7574736964652072616e6765000000000000000000000000000000000000006044820152606401610aa0565b6000868152600f6020526040812090611300600a84613ca9565b61130b906001613ccc565b63ffffffff1681526020810191909152604001600090812080549161132f83613c5d565b90915550506000868152600f602052604081209061134e606484613ca9565b61135990600b613ccc565b63ffffffff1681526020810191909152604001600090812080549161137d83613c5d565b90915550506000868152600f602052604081209061139d6103e884613ca9565b6113a890606f613ccc565b63ffffffff168152602081019190915260400160009081208054916113cc83613c5d565b90915550506000868152600f60205260408120906113ec61271084613ca9565b6113f890610457613ccc565b63ffffffff1681526020810191909152604001600090812080549161141c83613c5d565b90915550506000868152600f602052604081209061143d620186a084613ca9565b61144990612b67613ccc565b63ffffffff1681526020810191909152604001600090812080549161146d83613c5d565b90915550506000868152600f602052604081209061148e620f424084613ca9565b61149b906201b207613ccc565b63ffffffff168152602081019190915260400160009081208054916114bf83613c5d565b90915550503360008181526010602090815260408083208a84528252808320600680548254600181018455928652848620909201919091558151808301835263ffffffff808816825281850196875282548652600d9094529184209151825495516001600160a01b0316640100000000027fffffffffffffffff000000000000000000000000000000000000000000000000909616931692909217939093179092558154919061156e83613c5d565b919050555050808061157f90613c5d565b915050611245565b50604051828152849033907fd7d247b583de1023852eef87b48f54354dbec771d01bc2cc49e96094efc322b99060200160405180910390a3505060016000555050565b6060808260008167ffffffffffffffff8111156115e9576115e9613c1e565b604051908082528060200260200182016040528015611612578160200160208202803683370190505b50905060008267ffffffffffffffff81111561163057611630613c1e565b604051908082528060200260200182016040528015611659578160200160208202803683370190505b50905060005b8381101561177457600d600089898481811061167d5761167d613c47565b90506020020135815260200190815260200160002060000160009054906101000a900463ffffffff168382815181106116b8576116b8613c47565b63ffffffff909216602092830291909101909101526000600d818a8a858181106116e4576116e4613c47565b602090810292909201358352508101919091526040016000205464010000000090046001600160a01b03160361173d57600182828151811061172857611728613c47565b91151560209283029190910190910152611762565b600082828151811061175157611751613c47565b911515602092830291909101909101525b8061176c81613c5d565b91505061165f565b509093509150505b9250929050565b6003546001600160a01b031633146117cc5760405162461bcd60e51b815260206004820152600c60248201526b2737ba1037b832b930ba37b960a11b6044820152606401610aa0565b6005541580611800575060036005546000908152600c602052604090205460ff1660038111156117fe576117fe613738565b145b61184c5760405162461bcd60e51b815260206004820152601960248201527f4e6f742074696d6520746f207374617274206c6f7474657279000000000000006044820152606401610aa0565b61012c6118594287613c05565b11801561187157506205472c61186f4287613c05565b105b6118bd5760405162461bcd60e51b815260206004820152601f60248201527f4c6f7474657279206c656e677468206f757473696465206f662072616e6765006044820152606401610aa0565b60095484101580156118d157506008548411155b61191d5760405162461bcd60e51b815260206004820152601160248201527f4f757473696465206f66206c696d6974730000000000000000000000000000006044820152606401610aa0565b61012c83101561196f5760405162461bcd60e51b815260206004820152601860248201527f446973636f756e742064697669736f7220746f6f206c6f7700000000000000006044820152606401610aa0565b610bb88111156119c15760405162461bcd60e51b815260206004820152601560248201527f54726561737572792066656520746f6f206869676800000000000000000000006044820152606401610aa0565b60a08201356080830135606084013560408501356119e460208701358735613c34565b6119ee9190613c34565b6119f89190613c34565b611a029190613c34565b611a0c9190613c34565b61271014611a5c5760405162461bcd60e51b815260206004820152601860248201527f52657761726473206d75737420657175616c20313030303000000000000000006044820152606401610aa0565b60058054906000611a6c83613c5d565b9091555050604080516101a0810190915280600181526020014281526020018681526020018581526020018481526020018360068060200260405190810160405280929190826006602002808284376000920182905250928452505060208083018590526040805160c080820183528482528184018590528183018590526060808301869052608080840187905260a080850188905285890194909452845180840186528781528087018890528086018890528083018890528082018890528085018890529188019190915260065490870181905291860191909152600a549085015260e09093018290526005548252600c90522081518154829060ff19166001836003811115611b7f57611b7f613738565b02179055506020820151600182015560408201516002820155606082015160038201556080820151600482015560a0820151611bc19060058301906006613572565b5060c0820151600b82015560e0820151611be190600c8301906006613572565b50610100820151611bf89060128301906006613572565b5061012082015160188201556101408201516019820155610160820151601a82015561018090910151601b909101805463ffffffff191663ffffffff909216919091179055600554600654600a5460408051428152602081018a9052908101889052606081019290925260808201527f367e70f8c0e0c0a6504d92172bda155c02022d532fc85b5d66a9c49e31c8bc779060a00160405180910390a250506000600a55505050565b6003546001600160a01b03163314611ce95760405162461bcd60e51b815260206004820152600c60248201526b2737ba1037b832b930ba37b960a11b6044820152606401610aa0565b600260005403611d3b5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610aa0565b60026000818155838152600c602052604090205460ff166003811115611d6357611d63613738565b14611db05760405162461bcd60e51b815260206004820152601260248201527f4c6f7474657279206e6f7420636c6f73656400000000000000000000000000006044820152606401610aa0565b600b60009054906101000a90046001600160a01b03166001600160a01b031663fbe5d9176040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e03573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e279190613ce9565b8214611e755760405162461bcd60e51b815260206004820152601160248201527f4e756d62657273206e6f7420647261776e0000000000000000000000000000006044820152606401610aa0565b600b54604080516350e27aad60e11b815290516000926001600160a01b03169163a1c4f55a9160048083019260209291908290030181865afa158015611ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ee39190613d02565b6000848152600c60205260408120600b015491925090819061271090611f099082613c05565b6000878152600c60205260409020601a0154611f259190613d1f565b611f2f9190613d36565b90506000805b60068163ffffffff1610156121aa576000611f51826005613d4a565b90506000611f60826001613ccc565b611f6b90600a613e78565b611f759088613ca9565b63ffffffff8084166000908152600e6020526040902054611f97929116613ccc565b60008a8152600f6020908152604080832063ffffffff85168452909152902054909150611fc5908790613c05565b60008a8152600c6020526040902060120163ffffffff841660068110611fed57611fed613c47565b01556000898152600f6020908152604080832063ffffffff8516845290915290205461201a908790613c05565b1561211a576000898152600c6020526040902060050163ffffffff83166006811061204757612047613c47565b015415612115576000898152600f6020908152604080832063ffffffff851684529091529020546127109061207d908890613c05565b60008b8152600c60205260409020879060050163ffffffff8616600681106120a7576120a7613c47565b01546120b39190613d1f565b6120bd9190613d36565b6120c79190613d36565b60008a8152600c602081905260409091200163ffffffff8416600681106120f0576120f0613c47565b01556000898152600f6020908152604080832063ffffffff8516845290915290205495505b612195565b6000898152600c6020819052604082200163ffffffff84166006811061214257612142613c47565b01556000898152600c6020526040902061271090869060050163ffffffff85166006811061217257612172613c47565b015461217e9190613d1f565b6121889190613d36565b6121929085613c34565b93505b505080806121a290613e95565b915050611f35565b506000868152600c60205260409020601b8101805463ffffffff871663ffffffff19909116179055805460ff1916600317905584156121e957600a5560005b6000868152600c60205260409020601a0154612206908390613c05565b6122109082613c34565b6004546040519192506000916001600160a01b039091169083908381818185875af1925050503d8060008114612262576040519150601f19603f3d011682016040523d82523d6000602084013e612267565b606091505b50509050806122b85760405162461bcd60e51b815260206004820152601b60248201527f5472616e7366657220746f207472656173757279206661696c656400000000006044820152606401610aa0565b6005546040805163ffffffff88168152602081018790527f98e31a6607b8b15b4d5b91de54f4c09ffe4c4cf162aa532c70b5213754e2e703910160405180910390a2505060016000555050505050565b600061012c84101561235c5760405162461bcd60e51b815260206004820152601f60248201527f4d757374206265203e3d204d494e5f444953434f554e545f44495649534f52006044820152606401610aa0565b816000036123ac5760405162461bcd60e51b815260206004820152601d60248201527f4e756d626572206f66207469636b657473206d757374206265203e20300000006044820152606401610aa0565b610d218484846132ca565b6001546001600160a01b031633146124115760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610aa0565b60036005546000908152600c602052604090205460ff16600381111561243957612439613738565b146124865760405162461bcd60e51b815260206004820152601860248201527f4c6f7474657279206e6f7420696e20636c61696d61626c6500000000000000006044820152606401610aa0565b60405163931afbe560e01b815263ffffffff83166004820152602481018290526001600160a01b0384169063931afbe590604401600060405180830381600087803b1580156124d457600080fd5b505af11580156124e8573d6000803e3d6000fd5b50505050826001600160a01b031663a1c4f55a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561252a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061254e9190613d02565b50600b80546001600160a01b0319166001600160a01b0385169081179091556040517f453043396644e1a2577114bba3c0e058997aa12fb4ab5894e0446fb3b83fefff90600090a2505050565b333b156125ea5760405162461bcd60e51b815260206004820152601460248201527f436f6e7472616374206e6f7420616c6c6f7765640000000000000000000000006044820152606401610aa0565b3332146126395760405162461bcd60e51b815260206004820152601a60248201527f50726f787920636f6e7472616374206e6f7420616c6c6f7765640000000000006044820152606401610aa0565b60026000540361268b5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610aa0565b60026000558281146126df5760405162461bcd60e51b815260206004820152600f60248201527f4e6f742073616d65206c656e67746800000000000000000000000000000000006044820152606401610aa0565b60008390036127305760405162461bcd60e51b815260206004820152601160248201527f4c656e677468206d757374206265203e300000000000000000000000000000006044820152606401610aa0565b6007548311156127755760405162461bcd60e51b815260206004820152601060248201526f546f6f206d616e79207469636b65747360801b6044820152606401610aa0565b60036000868152600c602052604090205460ff16600381111561279a5761279a613738565b146127e75760405162461bcd60e51b815260206004820152601560248201527f4c6f7474657279206e6f7420636c61696d61626c6500000000000000000000006044820152606401610aa0565b6000805b84811015612b5057600684848381811061280757612807613c47565b905060200201602081019061281c9190613c76565b63ffffffff161061286f5760405162461bcd60e51b815260206004820152601460248201527f427261636b6574206f7574206f662072616e67650000000000000000000000006044820152606401610aa0565b600086868381811061288357612883613c47565b90506020020135905080600c60008a815260200190815260200160002060190154116128f15760405162461bcd60e51b815260206004820152601160248201527f5469636b6574496420746f6f20686967680000000000000000000000000000006044820152606401610aa0565b6000888152600c60205260409020601801548110156129525760405162461bcd60e51b815260206004820152601060248201527f5469636b6574496420746f6f206c6f77000000000000000000000000000000006044820152606401610aa0565b6000818152600d602052604090205464010000000090046001600160a01b031633146129c05760405162461bcd60e51b815260206004820152600d60248201527f4e6f7420746865206f776e6572000000000000000000000000000000000000006044820152606401610aa0565b6000818152600d6020526040812080547fffffffffffffffff0000000000000000000000000000000000000000ffffffff169055612a258983888887818110612a0b57612a0b613c47565b9050602002016020810190612a209190613c76565b613153565b905080600003612a775760405162461bcd60e51b815260206004820152601960248201527f4e6f207072697a6520666f72207468697320627261636b6574000000000000006044820152606401610aa0565b858584818110612a8957612a89613c47565b9050602002016020810190612a9e9190613c76565b63ffffffff16600514612b2f57612ae28983888887818110612ac257612ac2613c47565b9050602002016020810190612ad79190613c76565b612a20906001613ccc565b15612b2f5760405162461bcd60e51b815260206004820152601660248201527f427261636b6574206d75737420626520686967686572000000000000000000006044820152606401610aa0565b612b398185613c34565b935050508080612b4890613c5d565b9150506127eb565b50604051600090339083908381818185875af1925050503d8060008114612b93576040519150601f19603f3d011682016040523d82523d6000602084013e612b98565b606091505b5050905080612c0f5760405162461bcd60e51b815260206004820152602660248201527f4661696c656420746f2073656e6420726577617264496e4d65746973546f547260448201527f616e7366657200000000000000000000000000000000000000000000000000006064820152608401610aa0565b6040805183815260208101879052889133917f0f5fca62da8fb5d95525b49e5eaa7b20bc6bd9e2f6b64b493442d1c0bd6ef486910160405180910390a3505060016000555050505050565b6001546001600160a01b03163314612cb45760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610aa0565b6001600160a01b038316612d0a5760405162461bcd60e51b815260206004820152601660248201527f43616e6e6f74206265207a65726f2061646472657373000000000000000000006044820152606401610aa0565b6001600160a01b038216612d605760405162461bcd60e51b815260206004820152601660248201527f43616e6e6f74206265207a65726f2061646472657373000000000000000000006044820152606401610aa0565b6001600160a01b038116612db65760405162461bcd60e51b815260206004820152601660248201527f43616e6e6f74206265207a65726f2061646472657373000000000000000000006044820152606401610aa0565b600380546001600160a01b038581166001600160a01b0319928316811790935560048054868316908416811790915560028054928616929093168217909255604080519384526020840192909252908201527f3e945b7660001d46cfd5e729545f7f0b6c65bdee54066a91c7acad703f1b731e9060600160405180910390a1505050565b6001546001600160a01b0316331480612e5d57506002546001600160a01b031633145b612ea95760405162461bcd60e51b815260206004820152601560248201527f4e6f74206f776e6572206f7220696e6a6563746f7200000000000000000000006044820152606401610aa0565b60016000828152600c602052604090205460ff166003811115612ece57612ece613738565b14612f0e5760405162461bcd60e51b815260206004820152601060248201526f2637ba3a32b93c903737ba1037b832b760811b6044820152606401610aa0565b6000818152600c60205260408120601a018054349290612f2f908490613c34565b909155505060405134815281907f1bbd659dd628a25f7ff2eabb69c74a56939c539728282275c1c9c1a2d3e340499060200160405180910390a250565b6001546001600160a01b03163314612fc65760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610aa0565b808211156130165760405162461bcd60e51b815260206004820152601b60248201527f6d696e5072696365206d757374206265203c206d6178507269636500000000006044820152606401610aa0565b600991909155600855565b6001546001600160a01b0316331461307b5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610aa0565b6001600160a01b0381166130f75760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610aa0565b6001546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000838152600c60209081526040808320601b0154858452600d90925282205463ffffffff918216911682613189856001613ccc565b61319490600a613e78565b61319e9083613ca9565b63ffffffff8087166000908152600e60205260409020546131c0929116613ccc565b905060006131cf866001613ccc565b6131da90600a613e78565b6131e49085613ca9565b63ffffffff8088166000908152600e6020526040902054613206929116613ccc565b90508063ffffffff168263ffffffff1603613251576000888152600c602081905260409091200163ffffffff87166006811061324457613244613c47565b0154945050505050610d24565b6000945050505050610d24565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1663a9059cbb60e01b1790526132c5908490613301565b505050565b600083826132d9826001613c34565b6132e39190613c05565b6132ed8486613d1f565b6132f79190613d1f565b610d219190613d36565b6000613356826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166133e69092919063ffffffff16565b8051909150156132c557808060200190518101906133749190613eb8565b6132c55760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610aa0565b6060610d21848460008585843b61343f5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610aa0565b600080866001600160a01b0316858760405161345b9190613ef9565b60006040518083038185875af1925050503d8060008114613498576040519150601f19603f3d011682016040523d82523d6000602084013e61349d565b606091505b50915091506134ad8282866134b8565b979650505050505050565b606083156134c7575081610d24565b8251156134d75782518084602001fd5b8160405162461bcd60e51b8152600401610aa09190613f15565b604080516101a081019091528060008152602001600081526020016000815260200160008152602001600081526020016135296135b0565b81526020016000815260200161353d6135b0565b815260200161354a6135b0565b8152602001600081526020016000815260200160008152602001600063ffffffff1681525090565b82600681019282156135a0579160200282015b828111156135a0578251825591602001919060010190613585565b506135ac9291506135ce565b5090565b6040518060c001604052806006906020820280368337509192915050565b5b808211156135ac57600081556001016135cf565b80356001600160a01b03811681146135fa57600080fd5b919050565b6000806000806080858703121561361557600080fd5b61361e856135e3565b966020860135965060408601359560600135945092505050565b600081518084526020808501945080840160005b8381101561366e57815163ffffffff168752958201959082019060010161364c565b509495945050505050565b600081518084526020808501945080840160005b8381101561366e57815115158752958201959082019060010161368d565b6080808252855190820181905260009060209060a0840190828901845b828110156136e4578151845292840192908401906001016136c8565b505050838103828501526136f88188613638565b915050828103604084015261370d8186613679565b91505082606083015295945050505050565b60006020828403121561373157600080fd5b5035919050565b634e487b7160e01b600052602160045260246000fd5b6004811061376c57634e487b7160e01b600052602160045260246000fd5b9052565b8060005b6006811015613793578151845260209384019390910190600101613774565b50505050565b6000610380820190506137ad82845161374e565b6020830151602083015260408301516040830152606083015160608301526080830151608083015260a08301516137e760a0840182613770565b5060c0830151610160818185015260e0850151915061018061380b81860184613770565b6101008601519250613821610240860184613770565b6101208601516103008601526101408601516103208601529085015161034085015284015163ffffffff811661036085015290505b5092915050565b63ffffffff8116811461386f57600080fd5b50565b60008060006060848603121561388757600080fd5b8335925060208401356138998161385d565b929592945050506040919091013590565b6000806000606084860312156138bf57600080fd5b833592506020840135915060408401356138d88161385d565b809150509250925092565b600080604083850312156138f657600080fd5b6138ff836135e3565b946020939093013593505050565b60008083601f84011261391f57600080fd5b50813567ffffffffffffffff81111561393757600080fd5b6020830191508360208260051b850101111561177c57600080fd5b60008060006040848603121561396757600080fd5b83359250602084013567ffffffffffffffff81111561398557600080fd5b6139918682870161390d565b9497909650939450505050565b600080602083850312156139b157600080fd5b823567ffffffffffffffff8111156139c857600080fd5b6139d48582860161390d565b90969095509350505050565b6040815260006139f36040830185613638565b8281036020840152613a058185613679565b95945050505050565b60008060008060006101408688031215613a2757600080fd5b853594506020860135935060408601359250610120860187811115613a4b57600080fd5b94979396509194606001933592915050565b801515811461386f57600080fd5b60008060408385031215613a7e57600080fd5b823591506020830135613a9081613a5d565b809150509250929050565b600080600060608486031215613ab057600080fd5b505081359360208301359350604090920135919050565b600080600060608486031215613adc57600080fd5b613ae5846135e3565b925060208401356138998161385d565b600080600080600060608688031215613b0d57600080fd5b85359450602086013567ffffffffffffffff80821115613b2c57600080fd5b613b3889838a0161390d565b90965094506040880135915080821115613b5157600080fd5b50613b5e8882890161390d565b969995985093965092949392505050565b600080600060608486031215613b8457600080fd5b613b8d846135e3565b9250613b9b602085016135e3565b9150613ba9604085016135e3565b90509250925092565b60008060408385031215613bc557600080fd5b50508035926020909101359150565b600060208284031215613be657600080fd5b610d24826135e3565b634e487b7160e01b600052601160045260246000fd5b81810381811115613c1857613c18613bef565b92915050565b634e487b7160e01b600052604160045260246000fd5b80820180821115613c1857613c18613bef565b634e487b7160e01b600052603260045260246000fd5b600060018201613c6f57613c6f613bef565b5060010190565b600060208284031215613c8857600080fd5b8135610d248161385d565b634e487b7160e01b600052601260045260246000fd5b600063ffffffff80841680613cc057613cc0613c93565b92169190910692915050565b63ffffffff81811683821601908082111561385657613856613bef565b600060208284031215613cfb57600080fd5b5051919050565b600060208284031215613d1457600080fd5b8151610d248161385d565b8082028115828204841417613c1857613c18613bef565b600082613d4557613d45613c93565b500490565b63ffffffff82811682821603908082111561385657613856613bef565b600181815b80851115613da4578163ffffffff04821115613d8a57613d8a613bef565b80851615613d9757918102915b93841c9390800290613d6c565b509250929050565b600082613dbb57506001613c18565b81613dc857506000613c18565b8160018114613dde5760028114613de857613e19565b6001915050613c18565b60ff841115613df957613df9613bef565b6001841b915063ffffffff821115613e1357613e13613bef565b50613c18565b5060208310610133831016604e8410600b8410161715613e50575081810a63ffffffff811115613e4b57613e4b613bef565b613c18565b613e5a8383613d67565b8063ffffffff04821115613e7057613e70613bef565b029392505050565b600063ffffffff613e8d818516828516613dac565b949350505050565b600063ffffffff808316818103613eae57613eae613bef565b6001019392505050565b600060208284031215613eca57600080fd5b8151610d2481613a5d565b60005b83811015613ef0578181015183820152602001613ed8565b50506000910152565b60008251613f0b818460208701613ed5565b9190910192915050565b6020815260008251806020840152613f34816040850160208701613ed5565b601f01601f1916919091016040019291505056fea26469706673582212207557279dbf5761dff95e74cb1dd27257566ae064e9c781b436c95eda3c6ee0b264736f6c63430008130033