Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- RandomNumberGenerator
- Optimization enabled
- true
- Compiler version
- v0.8.17+commit.8df45f5f
- Optimization runs
- 200
- EVM Version
- default
- Verified at
- 2024-09-26T15:33:51.886303Z
Contract source code
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
// helper methods for interacting with ERC223 tokens and sending CLO that do not consistently return true/false
library TransferHelper {
function safeApprove(address token, address to, uint value) internal {
// bytes4(keccak256(bytes('approve(address,uint256)')));
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: APPROVE_FAILED');
}
function safeTransfer(address token, address to, uint value) internal {
// bytes4(keccak256(bytes('transfer(address,uint256)')));
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FAILED');
}
function safeTransferFrom(address token, address from, address to, uint value) internal {
// bytes4(keccak256(bytes('transferFrom(address,address,uint256)')));
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FROM_FAILED');
}
function safeTransferCLO(address to, uint value) internal {
(bool success,) = to.call{value:value}(new bytes(0));
require(success, 'TransferHelper: CLO_TRANSFER_FAILED');
}
}
/**
* @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 {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_owner = msg.sender;
emit OwnershipTransferred(address(0), msg.sender);
}
/**
* @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() == msg.sender, "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);
}
}
interface ISoyLottery {
/**
* @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;
/**
* @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) external;
/**
* @notice Draw the final number, calculate reward in Soy 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
* @param _amount: amount to inject in Soy token
* @dev Callable by operator
*/
function injectFunds(uint256 _lotteryId, uint256 _amount) external;
/**
* @notice Start the lottery
* @dev Callable by operator
* @param _endTime: endTime of the lottery
* @param _priceTicketInSoy: price of a ticket in Soy
* @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 _priceTicketInSoy,
uint256 _discountDivisor,
uint256[6] calldata _rewardsBreakdown,
uint256 _treasuryFee
) external;
/**
* @notice View current lottery id
*/
function viewCurrentLotteryId() external returns (uint256);
}
interface IRandomNumberGenerator {
/**
* Requests randomness from a user-provided seed
*/
function getRandomNumber(uint256 _seed) external;
/**
* View latest lotteryId numbers
*/
function viewLatestLotteryId() external view returns (uint256);
/**
* Views random result
*/
function viewRandomResult() external view returns (uint32);
}
contract RandomNumberGenerator is IRandomNumberGenerator, Ownable {
using TransferHelper for address;
address public SoyLottery;
address public operator;
uint32 public randomResult;
uint256 public latestLotteryId;
struct Entropy {
uint256 requestId; // equal to lottery ID that made request
uint256 seed; // seed from request
bytes32 blockHash1; // the prior request block hash
uint256 commitBlock; // block number of commit
bytes32 secretHash; // hash of secret random number
}
Entropy public entropy;
modifier onlyOperator() {
require(operator == msg.sender, "Only operator");
_;
}
event GetRandomNumber(uint256 requestId, address requestor);
event RandomNumber(uint256 rnd);
/**
* @notice Request randomness from a user-provided seed
* @param _seed: seed provided by the Soy lottery
*/
function getRandomNumber(uint256 _seed) external override {
require(msg.sender == SoyLottery, "Only SoyLottery");
uint256 requestId = ISoyLottery(SoyLottery).viewCurrentLotteryId();
entropy.requestId = requestId;
entropy.seed = _seed;
entropy.blockHash1 = blockhash(block.number-1);
entropy.commitBlock = 0; // clear last record of block number
emit GetRandomNumber(requestId, msg.sender);
}
// Step 1: commit hash (keccak256) of big random number
function commitSecret(bytes32 secretHash) external onlyOperator {
require(entropy.commitBlock == 0, "Already committed");
entropy.commitBlock = block.number;
entropy.secretHash = secretHash;
}
// Step 2: reveal secret at least in 2 block after commitment and not longer than 255 blocks after.
// generate random number
function revealSecret(uint256 requestId, uint256 secret) external onlyOperator {
require(entropy.requestId == requestId, "Wrong requestId");
require(keccak256(abi.encodePacked(secret)) == entropy.secretHash, "Wrong secret");
uint256 commitBlock = entropy.commitBlock;
require(commitBlock != 0 && commitBlock + 1 < block.number, "Reveal not allowed"); // allow reveal at least in 2 blocks after commitment
if (block.number - commitBlock > 256) {
entropy.commitBlock = 0; // allow to repeat commitment
emit RandomNumber(0); // random number generating is failed
return;
}
bytes32 blockHash2 = blockhash(commitBlock + 1); // hash of next block after commitment
uint256 randomness = uint256(keccak256(abi.encodePacked(entropy.seed, entropy.blockHash1, blockHash2, secret)));
//randomResult = uint32(1000000 + (randomness % 1000000));
randomResult = uint32(1000 + (randomness % 1000));
latestLotteryId = ISoyLottery(SoyLottery).viewCurrentLotteryId();
emit RandomNumber(randomResult);
}
/**
* @notice Set the address for the SoyLottery
* @param _SoyLottery: address of the Soy lottery
*/
function setLotteryAddress(address _SoyLottery) external onlyOwner {
SoyLottery = _SoyLottery;
}
/**
* @notice Set the address of operator
* @param _operator: address of operator
*/
function setOperatorAddress(address _operator) external onlyOwner {
operator = _operator;
}
/**
* @notice It allows the admin to withdraw 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 withdrawTokens(address _tokenAddress, uint256 _tokenAmount) external onlyOwner {
_tokenAddress.safeTransfer(address(msg.sender), _tokenAmount);
}
/**
* @notice View latestLotteryId
*/
function viewLatestLotteryId() external view override returns (uint256) {
return latestLotteryId;
}
/**
* @notice View random result
*/
function viewRandomResult() external view override returns (uint32) {
return randomResult;
}
}
Contract ABI
[{"type":"event","name":"GetRandomNumber","inputs":[{"type":"uint256","name":"requestId","internalType":"uint256","indexed":false},{"type":"address","name":"requestor","internalType":"address","indexed":false}],"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":"RandomNumber","inputs":[{"type":"uint256","name":"rnd","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"SoyLottery","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"commitSecret","inputs":[{"type":"bytes32","name":"secretHash","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"requestId","internalType":"uint256"},{"type":"uint256","name":"seed","internalType":"uint256"},{"type":"bytes32","name":"blockHash1","internalType":"bytes32"},{"type":"uint256","name":"commitBlock","internalType":"uint256"},{"type":"bytes32","name":"secretHash","internalType":"bytes32"}],"name":"entropy","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"getRandomNumber","inputs":[{"type":"uint256","name":"_seed","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"latestLotteryId","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"operator","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint32","name":"","internalType":"uint32"}],"name":"randomResult","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"revealSecret","inputs":[{"type":"uint256","name":"requestId","internalType":"uint256"},{"type":"uint256","name":"secret","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setLotteryAddress","inputs":[{"type":"address","name":"_SoyLottery","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setOperatorAddress","inputs":[{"type":"address","name":"_operator","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"viewLatestLotteryId","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint32","name":"","internalType":"uint32"}],"name":"viewRandomResult","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"withdrawTokens","inputs":[{"type":"address","name":"_tokenAddress","internalType":"address"},{"type":"uint256","name":"_tokenAmount","internalType":"uint256"}]}]
Contract Creation Code
0x608060405234801561001057600080fd5b50600080546001600160a01b0319163390811782556040519091907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3610b928061005f6000396000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c8063715018a611610097578063b37217a411610066578063b37217a414610227578063eed8e1ee1461023a578063fa75251614610251578063fbe5d9171461026457600080fd5b8063715018a6146101e6578063883b0bce146101ee5780638da5cb5b14610201578063a1c4f55a1461021257600080fd5b80632f1d5a60116100d35780632f1d5a601461015257806342619f661461016557806347ce07cc14610191578063570ca735146101d357600080fd5b806306b091f9146100fa5780632a332b2a1461010f5780632a57c92e14610122575b600080fd5b61010d6101083660046109d2565b61026c565b005b61010d61011d3660046109fc565b6102c6565b600154610135906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b61010d6101603660046109fc565b610321565b60025461017c90600160a01b900463ffffffff1681565b60405163ffffffff9091168152602001610149565b6004546005546006546007546008546101ab949392919085565b604080519586526020860194909452928401919091526060830152608082015260a001610149565b600254610135906001600160a01b031681565b61010d61037c565b61010d6101fc366004610a1e565b6103ff565b6000546001600160a01b0316610135565b600254600160a01b900463ffffffff1661017c565b61010d610235366004610a40565b6106ed565b61024360035481565b604051908152602001610149565b61010d61025f366004610a40565b610804565b600354610243565b3361027f6000546001600160a01b031690565b6001600160a01b0316146102ae5760405162461bcd60e51b81526004016102a590610a59565b60405180910390fd5b6102c26001600160a01b038316338361089b565b5050565b336102d96000546001600160a01b031690565b6001600160a01b0316146102ff5760405162461bcd60e51b81526004016102a590610a59565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b336103346000546001600160a01b031690565b6001600160a01b03161461035a5760405162461bcd60e51b81526004016102a590610a59565b600280546001600160a01b0319166001600160a01b0392909216919091179055565b3361038f6000546001600160a01b031690565b6001600160a01b0316146103b55760405162461bcd60e51b81526004016102a590610a59565b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6002546001600160a01b031633146104495760405162461bcd60e51b815260206004820152600d60248201526c27b7363c9037b832b930ba37b960991b60448201526064016102a5565b600454821461048c5760405162461bcd60e51b815260206004820152600f60248201526e15dc9bdb99c81c995c5d595cdd1259608a1b60448201526064016102a5565b60085460408051602081018490520160405160208183030381529060405280519060200120146104ed5760405162461bcd60e51b815260206004820152600c60248201526b15dc9bdb99c81cd958dc995d60a21b60448201526064016102a5565b6007548015801590610508575043610506826001610aa4565b105b6105495760405162461bcd60e51b815260206004820152601260248201527114995d99585b081b9bdd08185b1b1bddd95960721b60448201526064016102a5565b6101006105568243610abd565b111561059b57600060078190556040519081527fec6cdc8e735e4069f6e89062582f3e5532a8e71373e7ef2962fa916cf2af21f29060200160405180910390a1505050565b60006105a8826001610aa4565b60055460065460408051602081019390935282015290406060820181905260808201859052915060009060a00160408051601f19818403018152919052805160209091012090506105fb6103e882610ad0565b610607906103e8610aa4565b600260146101000a81548163ffffffff021916908363ffffffff160217905550600160009054906101000a90046001600160a01b03166001600160a01b03166380a061606040518163ffffffff1660e01b81526004016020604051808303816000875af115801561067c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106a09190610af2565b600355600254604051600160a01b90910463ffffffff1681527fec6cdc8e735e4069f6e89062582f3e5532a8e71373e7ef2962fa916cf2af21f29060200160405180910390a15050505050565b6001546001600160a01b031633146107395760405162461bcd60e51b815260206004820152600f60248201526e4f6e6c7920536f794c6f747465727960881b60448201526064016102a5565b60015460408051630405030b60e51b815290516000926001600160a01b0316916380a06160916004808301926020929190829003018187875af1158015610784573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107a89190610af2565b6004819055600583905590506107bf600143610abd565b406006556000600755604080518281523360208201527ff46c6105c0f3cb1a924510084fd3100a12d09ad7f4c945729975018dd5e838ad910160405180910390a15050565b6002546001600160a01b0316331461084e5760405162461bcd60e51b815260206004820152600d60248201526c27b7363c9037b832b930ba37b960991b60448201526064016102a5565b600754156108925760405162461bcd60e51b8152602060048201526011602482015270105b1c9958591e4818dbdb5b5a5d1d1959607a1b60448201526064016102a5565b43600755600855565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916108f79190610b0b565b6000604051808303816000865af19150503d8060008114610934576040519150601f19603f3d011682016040523d82523d6000602084013e610939565b606091505b50915091508180156109635750805115806109635750808060200190518101906109639190610b3a565b6109af5760405162461bcd60e51b815260206004820152601f60248201527f5472616e7366657248656c7065723a205452414e534645525f4641494c45440060448201526064016102a5565b5050505050565b80356001600160a01b03811681146109cd57600080fd5b919050565b600080604083850312156109e557600080fd5b6109ee836109b6565b946020939093013593505050565b600060208284031215610a0e57600080fd5b610a17826109b6565b9392505050565b60008060408385031215610a3157600080fd5b50508035926020909101359150565b600060208284031215610a5257600080fd5b5035919050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b634e487b7160e01b600052601160045260246000fd5b80820180821115610ab757610ab7610a8e565b92915050565b81810381811115610ab757610ab7610a8e565b600082610aed57634e487b7160e01b600052601260045260246000fd5b500690565b600060208284031215610b0457600080fd5b5051919050565b6000825160005b81811015610b2c5760208186018101518583015201610b12565b506000920191825250919050565b600060208284031215610b4c57600080fd5b81518015158114610a1757600080fdfea2646970667358221220e8f3e7b478f0fe6182f4ef77be37c8739a87fe3cf5d34408745af0f7528d72f964736f6c63430008110033
Deployed ByteCode
0x608060405234801561001057600080fd5b50600436106100f55760003560e01c8063715018a611610097578063b37217a411610066578063b37217a414610227578063eed8e1ee1461023a578063fa75251614610251578063fbe5d9171461026457600080fd5b8063715018a6146101e6578063883b0bce146101ee5780638da5cb5b14610201578063a1c4f55a1461021257600080fd5b80632f1d5a60116100d35780632f1d5a601461015257806342619f661461016557806347ce07cc14610191578063570ca735146101d357600080fd5b806306b091f9146100fa5780632a332b2a1461010f5780632a57c92e14610122575b600080fd5b61010d6101083660046109d2565b61026c565b005b61010d61011d3660046109fc565b6102c6565b600154610135906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b61010d6101603660046109fc565b610321565b60025461017c90600160a01b900463ffffffff1681565b60405163ffffffff9091168152602001610149565b6004546005546006546007546008546101ab949392919085565b604080519586526020860194909452928401919091526060830152608082015260a001610149565b600254610135906001600160a01b031681565b61010d61037c565b61010d6101fc366004610a1e565b6103ff565b6000546001600160a01b0316610135565b600254600160a01b900463ffffffff1661017c565b61010d610235366004610a40565b6106ed565b61024360035481565b604051908152602001610149565b61010d61025f366004610a40565b610804565b600354610243565b3361027f6000546001600160a01b031690565b6001600160a01b0316146102ae5760405162461bcd60e51b81526004016102a590610a59565b60405180910390fd5b6102c26001600160a01b038316338361089b565b5050565b336102d96000546001600160a01b031690565b6001600160a01b0316146102ff5760405162461bcd60e51b81526004016102a590610a59565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b336103346000546001600160a01b031690565b6001600160a01b03161461035a5760405162461bcd60e51b81526004016102a590610a59565b600280546001600160a01b0319166001600160a01b0392909216919091179055565b3361038f6000546001600160a01b031690565b6001600160a01b0316146103b55760405162461bcd60e51b81526004016102a590610a59565b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6002546001600160a01b031633146104495760405162461bcd60e51b815260206004820152600d60248201526c27b7363c9037b832b930ba37b960991b60448201526064016102a5565b600454821461048c5760405162461bcd60e51b815260206004820152600f60248201526e15dc9bdb99c81c995c5d595cdd1259608a1b60448201526064016102a5565b60085460408051602081018490520160405160208183030381529060405280519060200120146104ed5760405162461bcd60e51b815260206004820152600c60248201526b15dc9bdb99c81cd958dc995d60a21b60448201526064016102a5565b6007548015801590610508575043610506826001610aa4565b105b6105495760405162461bcd60e51b815260206004820152601260248201527114995d99585b081b9bdd08185b1b1bddd95960721b60448201526064016102a5565b6101006105568243610abd565b111561059b57600060078190556040519081527fec6cdc8e735e4069f6e89062582f3e5532a8e71373e7ef2962fa916cf2af21f29060200160405180910390a1505050565b60006105a8826001610aa4565b60055460065460408051602081019390935282015290406060820181905260808201859052915060009060a00160408051601f19818403018152919052805160209091012090506105fb6103e882610ad0565b610607906103e8610aa4565b600260146101000a81548163ffffffff021916908363ffffffff160217905550600160009054906101000a90046001600160a01b03166001600160a01b03166380a061606040518163ffffffff1660e01b81526004016020604051808303816000875af115801561067c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106a09190610af2565b600355600254604051600160a01b90910463ffffffff1681527fec6cdc8e735e4069f6e89062582f3e5532a8e71373e7ef2962fa916cf2af21f29060200160405180910390a15050505050565b6001546001600160a01b031633146107395760405162461bcd60e51b815260206004820152600f60248201526e4f6e6c7920536f794c6f747465727960881b60448201526064016102a5565b60015460408051630405030b60e51b815290516000926001600160a01b0316916380a06160916004808301926020929190829003018187875af1158015610784573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107a89190610af2565b6004819055600583905590506107bf600143610abd565b406006556000600755604080518281523360208201527ff46c6105c0f3cb1a924510084fd3100a12d09ad7f4c945729975018dd5e838ad910160405180910390a15050565b6002546001600160a01b0316331461084e5760405162461bcd60e51b815260206004820152600d60248201526c27b7363c9037b832b930ba37b960991b60448201526064016102a5565b600754156108925760405162461bcd60e51b8152602060048201526011602482015270105b1c9958591e4818dbdb5b5a5d1d1959607a1b60448201526064016102a5565b43600755600855565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916108f79190610b0b565b6000604051808303816000865af19150503d8060008114610934576040519150601f19603f3d011682016040523d82523d6000602084013e610939565b606091505b50915091508180156109635750805115806109635750808060200190518101906109639190610b3a565b6109af5760405162461bcd60e51b815260206004820152601f60248201527f5472616e7366657248656c7065723a205452414e534645525f4641494c45440060448201526064016102a5565b5050505050565b80356001600160a01b03811681146109cd57600080fd5b919050565b600080604083850312156109e557600080fd5b6109ee836109b6565b946020939093013593505050565b600060208284031215610a0e57600080fd5b610a17826109b6565b9392505050565b60008060408385031215610a3157600080fd5b50508035926020909101359150565b600060208284031215610a5257600080fd5b5035919050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b634e487b7160e01b600052601160045260246000fd5b80820180821115610ab757610ab7610a8e565b92915050565b81810381811115610ab757610ab7610a8e565b600082610aed57634e487b7160e01b600052601260045260246000fd5b500690565b600060208284031215610b0457600080fd5b5051919050565b6000825160005b81811015610b2c5760208186018101518583015201610b12565b506000920191825250919050565b600060208284031215610b4c57600080fd5b81518015158114610a1757600080fdfea2646970667358221220e8f3e7b478f0fe6182f4ef77be37c8739a87fe3cf5d34408745af0f7528d72f964736f6c63430008110033