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