Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- RNG
- Optimization enabled
- false
- Compiler version
- v0.8.27+commit.40a35a09
- EVM Version
- paris
- Verified at
- 2025-01-02T20:05:12.582047Z
Constructor Arguments
0000000000000000000000007fdbf4fe2dbbdf956c010b3dd83177cb86eb1b1400000000000000000000000000000000000000000000000000000000000000066da22a485fc06c9bce99691a2ff5af57b7fd20b09af4a6572f6a44473d6c151400000000000000000000000000000000000000000000000000000000002625a00000000000000000000000000000000000000000000000000000000000000003
Arg [0] (address) : 0x7fdbf4fe2dbbdf956c010b3dd83177cb86eb1b14
Arg [1] (uint64) : 6
Arg [2] (bytes32) : 6da22a485fc06c9bce99691a2ff5af57b7fd20b09af4a6572f6a44473d6c1514
Arg [3] (uint32) : 2500000
Arg [4] (uint16) : 3
contracts/RNG.sol
// SPDX-License-Identifier: MIT // An example of a consumer contract that relies on a subscription for funding. pragma solidity ^0.8.12; import "./interfaces/ErinaceusVRFInterface.sol"; import "./VRFConsumerBaseV2.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; contract RNG is VRFConsumerBaseV2, Ownable { using EnumerableSet for EnumerableSet.UintSet; event RequestFulfilled(uint256 requestId, uint256[] randomWords); struct RequestStatus { bool fulfilled; // whether the request has been successfully fulfilled bool exists; // whether a requestId exists uint256[] randomWords; } mapping (address => bool) public whitelisted; mapping(uint256 => RequestStatus) public s_requests; /* requestId --> requestStatus */ ErinaceusVRFInterface public coordinator; // Your subscription ID. uint64 s_subscriptionId; // past requests Id. uint256[] public requestIds; uint256 public lastRequestId; // The gas lane to use, which specifies the maximum gas price to bump to. // For a list of available gas lanes on each network, bytes32 keyHash; // Depends on the number of requested values that you want sent to the // fulfillRandomWords() function. Storing each word costs about 20,000 gas, // so 100,000 is a safe default for this example contract. Test and adjust // this limit based on the network that you select, the size of the request, // and the processing of the callback request in the fulfillRandomWords() // function. uint32 callbackGasLimit; uint16 requestConfirmations; mapping(uint256 => EnumerableSet.UintSet) private requestToNumbers; modifier onlyWhitelisted { require(whitelisted[msg.sender] || msg.sender == owner(), "RNG: only whitelited addresses"); _; } constructor( address coordinator_, uint64 subscriptionId_, bytes32 keyHash_, uint32 callbackGasLimit_, uint16 requestConfirmations_ ) VRFConsumerBaseV2(coordinator_) Ownable() { coordinator = ErinaceusVRFInterface(coordinator_); s_subscriptionId = subscriptionId_; keyHash = keyHash_; callbackGasLimit = callbackGasLimit_; requestConfirmations = requestConfirmations_; } function whitelistAddress(address _wallet, bool _whitelist) external onlyOwner { whitelisted[_wallet] = _whitelist; } // Assumes the subscription is funded sufficiently. function requestRandomWords() external onlyWhitelisted { // Will revert if subscription is not set and funded. uint256 requestId = coordinator.requestRandomWords( keyHash, s_subscriptionId, requestConfirmations, callbackGasLimit, 1 ); s_requests[requestId] = RequestStatus({ randomWords: new uint256[](0), exists: true, fulfilled: false }); requestIds.push(requestId); lastRequestId = requestId; } function fulfillRandomWords( uint256 requestId_, uint256[] memory randomWords_ ) internal override { require(s_requests[requestId_].exists, "RNG: request not found"); s_requests[requestId_].fulfilled = true; s_requests[requestId_].randomWords = randomWords_; emit RequestFulfilled(requestId_, randomWords_); } function getRequestStatus( uint256 requestId_ ) external view returns (bool fulfilled, uint256[] memory randomWords) { require(s_requests[requestId_].exists, "RNG: request not found"); RequestStatus memory request = s_requests[requestId_]; return (request.fulfilled, request.randomWords); } }
@openzeppelin/contracts/access/Ownable.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @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() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(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"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
@openzeppelin/contracts/utils/Context.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol) pragma solidity ^0.8.0; /** * @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) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
@openzeppelin/contracts/utils/structs/EnumerableSet.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableSet.sol) // This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. pragma solidity ^0.8.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ```solidity * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. * * [WARNING] * ==== * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure * unusable. * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. * * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an * array of EnumerableSet. * ==== */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping(bytes32 => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; if (lastIndex != toDeleteIndex) { bytes32 lastValue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastValue; // Update the index for the moved value set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex } // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { bytes32[] memory store = _values(set._inner); bytes32[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values in the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } }
contracts/VRFConsumerBaseV2.sol
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; /** **************************************************************************** * @notice Interface for contracts using VRF randomness * ***************************************************************************** * @dev PURPOSE * * @dev Reggie the Random Oracle (not his real job) wants to provide randomness * @dev to Vera the verifier in such a way that Vera can be sure he's not * @dev making his output up to suit himself. Reggie provides Vera a public key * @dev to which he knows the secret key. Each time Vera provides a seed to * @dev Reggie, he gives back a value which is computed completely * @dev deterministically from the seed and the secret key. * * @dev Reggie provides a proof by which Vera can verify that the output was * @dev correctly computed once Reggie tells it to her, but without that proof, * @dev the output is indistinguishable to her from a uniform random sample * @dev from the output space. * * @dev The purpose of this contract is to make it easy for unrelated contracts * @dev to talk to Vera the verifier about the work Reggie is doing, to provide * @dev simple access to a verifiable source of randomness. It ensures 2 things: * @dev 1. The fulfillment came from the ErinaceusVRF * @dev 2. The consumer contract implements fulfillRandomWords. * ***************************************************************************** * @dev USAGE * * @dev Calling contracts must inherit from VRFConsumerBase, and can * @dev initialize VRFConsumerBase's attributes in their constructor as * @dev shown: * * @dev contract VRFConsumer { * @dev constructor(<other arguments>, address _erinaceusVRF, address _link) * @dev VRFConsumerBase(_erinaceusVRF) public { * @dev <initialization with other arguments goes here> * @dev } * @dev } * * @dev The oracle will have given you an ID for the VRF keypair they have * @dev committed to (let's call it keyHash). Create subscription, fund it * @dev and your consumer contract as a consumer of it (see ErinaceusVRFInterface * @dev subscription management functions). * @dev Call requestRandomWords(keyHash, subId, minimumRequestConfirmations, * @dev callbackGasLimit, numWords), * @dev see (ErinaceusVRFInterface for a description of the arguments). * * @dev Once the ErinaceusVRF has received and validated the oracle's response * @dev to your request, it will call your contract's fulfillRandomWords method. * * @dev The randomness argument to fulfillRandomWords is a set of random words * @dev generated from your requestId and the blockHash of the request. * * @dev If your contract could have concurrent requests open, you can use the * @dev requestId returned from requestRandomWords to track which response is associated * @dev with which randomness request. * @dev See "SECURITY CONSIDERATIONS" for principles to keep in mind, * @dev if your contract could have multiple requests in flight simultaneously. * * @dev Colliding `requestId`s are cryptographically impossible as long as seeds * @dev differ. * * ***************************************************************************** * @dev SECURITY CONSIDERATIONS * * @dev A method with the ability to call your fulfillRandomness method directly * @dev could spoof a VRF response with any random value, so it's critical that * @dev it cannot be directly called by anything other than this base contract * @dev (specifically, by the VRFConsumerBase.rawFulfillRandomness method). * * @dev For your users to trust that your contract's random behavior is free * @dev from malicious interference, it's best if you can write it so that all * @dev behaviors implied by a VRF response are executed *during* your * @dev fulfillRandomness method. If your contract must store the response (or * @dev anything derived from it) and use it later, you must ensure that any * @dev user-significant behavior which depends on that stored value cannot be * @dev manipulated by a subsequent VRF request. * * @dev Similarly, both miners and the VRF oracle itself have some influence * @dev over the order in which VRF responses appear on the blockchain, so if * @dev your contract could have multiple VRF requests in flight simultaneously, * @dev you must ensure that the order in which the VRF responses arrive cannot * @dev be used to manipulate your contract's user-significant behavior. * * @dev Since the block hash of the block which contains the requestRandomness * @dev call is mixed into the input to the VRF *last*, a sufficiently powerful * @dev miner could, in principle, fork the blockchain to evict the block * @dev containing the request, forcing the request to be included in a * @dev different block with a different hash, and therefore a different input * @dev to the VRF. However, such an attack would incur a substantial economic * @dev cost. This cost scales with the number of blocks the VRF oracle waits * @dev until it calls responds to a request. It is for this reason that * @dev that you can signal to an oracle you'd like them to wait longer before * @dev responding to the request (however this is not enforced in the contract * @dev and so remains effective only in the case of unmodified oracle software). */ abstract contract VRFConsumerBaseV2 { error OnlyErinaceusCanFulfill(address have, address want); // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i address private immutable erinaceusVRF; /** * @param _erinaceusVRF address of ErinaceusVRF contract */ constructor(address _erinaceusVRF) { erinaceusVRF = _erinaceusVRF; } /** * @notice fulfillRandomness handles the VRF response. Your contract must * @notice implement it. See "SECURITY CONSIDERATIONS" above for important * @notice principles to keep in mind when implementing your fulfillRandomness * @notice method. * * @dev VRFConsumerBaseV2 expects its subcontracts to have a method with this * @dev signature, and will call it once it has verified the proof * @dev associated with the randomness. (It is triggered via a call to * @dev rawFulfillRandomness, below.) * * @param requestId The Id initially returned by requestRandomness * @param randomWords the VRF output expanded to the requested number of words */ // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal virtual; // rawFulfillRandomness is called by ErinaceusVRF when it receives a valid VRF // proof. rawFulfillRandomness then calls fulfillRandomness, after validating // the origin of the call function rawFulfillRandomWords(uint256 requestId, uint256[] memory randomWords) external { if (msg.sender != erinaceusVRF) { revert OnlyErinaceusCanFulfill(msg.sender, erinaceusVRF); } fulfillRandomWords(requestId, randomWords); } }
contracts/interfaces/ErinaceusVRFInterface.sol
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface ErinaceusVRFInterface { /** * @notice Get configuration relevant for making requests * @return minimumRequestConfirmations global min for request confirmations * @return maxGasLimit global max for request gas limit * @return s_provingKeyHashes list of registered key hashes */ function getRequestConfig() external view returns (uint16, uint32, bytes32[] memory); /** * @notice Request a set of random words. * @param keyHash - Corresponds to a particular oracle job which uses * that key for generating the VRF proof. Different keyHash's have different gas price * ceilings, so you can select a specific one to bound your maximum per request cost. * @param subId - The ID of the VRF subscription. Must be funded * with the minimum subscription balance required for the selected keyHash. * @param minimumRequestConfirmations - How many blocks you'd like the * oracle to wait before responding to the request. See SECURITY CONSIDERATIONS * for why you may want to request more. The acceptable range is * [minimumRequestBlockConfirmations, 200]. * @param callbackGasLimit - How much gas you'd like to receive in your * fulfillRandomWords callback. Note that gasleft() inside fulfillRandomWords * may be slightly less than this amount because of gas used calling the function * (argument decoding etc.), so you may need to request slightly more than you expect * to have inside fulfillRandomWords. The acceptable range is * [0, maxGasLimit] * @param numWords - The number of uint256 random values you'd like to receive * in your fulfillRandomWords callback. Note these numbers are expanded in a * secure way by the ErinaceusVRF from a single random value supplied by the oracle. * @return requestId - A unique identifier of the request. Can be used to match * a request to a response in fulfillRandomWords. */ function requestRandomWords( bytes32 keyHash, uint64 subId, uint16 minimumRequestConfirmations, uint32 callbackGasLimit, uint32 numWords ) external returns (uint256 requestId); /** * @notice Create a VRF subscription. * @return subId - A unique subscription id. * @dev You can manage the consumer set dynamically with addConsumer/removeConsumer. * @dev Note to fund the subscription, use transferAndCall. For example * @dev LINKTOKEN.transferAndCall( * @dev address(ERINACEUS), * @dev amount, * @dev abi.encode(subId)); */ function createSubscription() external returns (uint64 subId); /** * @notice Get a VRF subscription. * @param subId - ID of the subscription * @return balance - LINK balance of the subscription in juels. * @return reqCount - number of requests for this subscription, determines fee tier. * @return owner - owner of the subscription. * @return consumers - list of consumer address which are able to use this subscription. */ function getSubscription( uint64 subId ) external view returns (uint256 balance, uint256 reqCount, address owner, address[] memory consumers); /** * @notice Request subscription owner transfer. * @param subId - ID of the subscription * @param newOwner - proposed new owner of the subscription */ function requestSubscriptionOwnerTransfer(uint64 subId, address newOwner) external; /** * @notice Request subscription owner transfer. * @param subId - ID of the subscription * @dev will revert if original owner of subId has * not requested that msg.sender become the new owner. */ function acceptSubscriptionOwnerTransfer(uint64 subId) external; /** * @notice Add a consumer to a VRF subscription. * @param subId - ID of the subscription * @param consumer - New consumer which can use the subscription */ function addConsumer(uint64 subId, address consumer) external; /** * @notice Remove a consumer from a VRF subscription. * @param subId - ID of the subscription * @param consumer - Consumer to remove from the subscription */ function removeConsumer(uint64 subId, address consumer) external; /** * @notice Cancel a subscription * @param subId - ID of the subscription * @param to - Where to send the remaining LINK to */ function cancelSubscription(uint64 subId, address to) external; /* * @notice Check to see if there exists a request commitment consumers * for all consumers and keyhashes for a given sub. * @param subId - ID of the subscription * @return true if there exists at least one unfulfilled request for the subscription, false * otherwise. */ function pendingRequestExists(uint64 subId) external view returns (bool); }
Compiler Settings
{"outputSelection":{"*":{"*":["abi","evm.bytecode","evm.deployedBytecode","evm.methodIdentifiers","metadata"],"":["ast"]}},"optimizer":{"runs":200,"enabled":false},"libraries":{},"evmVersion":"paris"}
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"coordinator_","internalType":"address"},{"type":"uint64","name":"subscriptionId_","internalType":"uint64"},{"type":"bytes32","name":"keyHash_","internalType":"bytes32"},{"type":"uint32","name":"callbackGasLimit_","internalType":"uint32"},{"type":"uint16","name":"requestConfirmations_","internalType":"uint16"}]},{"type":"error","name":"OnlyErinaceusCanFulfill","inputs":[{"type":"address","name":"have","internalType":"address"},{"type":"address","name":"want","internalType":"address"}]},{"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":"RequestFulfilled","inputs":[{"type":"uint256","name":"requestId","internalType":"uint256","indexed":false},{"type":"uint256[]","name":"randomWords","internalType":"uint256[]","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract ErinaceusVRFInterface"}],"name":"coordinator","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"fulfilled","internalType":"bool"},{"type":"uint256[]","name":"randomWords","internalType":"uint256[]"}],"name":"getRequestStatus","inputs":[{"type":"uint256","name":"requestId_","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"lastRequestId","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"rawFulfillRandomWords","inputs":[{"type":"uint256","name":"requestId","internalType":"uint256"},{"type":"uint256[]","name":"randomWords","internalType":"uint256[]"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"requestIds","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"requestRandomWords","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"fulfilled","internalType":"bool"},{"type":"bool","name":"exists","internalType":"bool"}],"name":"s_requests","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"whitelistAddress","inputs":[{"type":"address","name":"_wallet","internalType":"address"},{"type":"bool","name":"_whitelist","internalType":"bool"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"whitelisted","inputs":[{"type":"address","name":"","internalType":"address"}]}]
Contract Creation Code
0x60a060405234801561001057600080fd5b5060405161185638038061185683398181016040528101906100329190610358565b848073ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff16815250505061008461007961013d60201b60201c565b61014560201b60201c565b84600360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555083600360146101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055508260068190555081600760006101000a81548163ffffffff021916908363ffffffff16021790555080600760046101000a81548161ffff021916908361ffff16021790555050505050506103d3565b600033905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006102398261020e565b9050919050565b6102498161022e565b811461025457600080fd5b50565b60008151905061026681610240565b92915050565b600067ffffffffffffffff82169050919050565b6102898161026c565b811461029457600080fd5b50565b6000815190506102a681610280565b92915050565b6000819050919050565b6102bf816102ac565b81146102ca57600080fd5b50565b6000815190506102dc816102b6565b92915050565b600063ffffffff82169050919050565b6102fb816102e2565b811461030657600080fd5b50565b600081519050610318816102f2565b92915050565b600061ffff82169050919050565b6103358161031e565b811461034057600080fd5b50565b6000815190506103528161032c565b92915050565b600080600080600060a0868803121561037457610373610209565b5b600061038288828901610257565b955050602061039388828901610297565b94505060406103a4888289016102cd565b93505060606103b588828901610309565b92505060806103c688828901610343565b9150509295509295909350565b6080516114616103f56000396000818161026501526102b901526114616000f3fe608060405234801561001057600080fd5b50600436106100b45760003560e01c8063b9a45aac11610071578063b9a45aac1461017c578063d8a4676f14610198578063d936547e146101c9578063e0c86289146101f9578063f2fde38b14610203578063fc2a88c31461021f576100b4565b80630a009097146100b95780631fe543e3146100d7578063715018a6146100f35780638796ba8c146100fd5780638da5cb5b1461012d578063a168fa891461014b575b600080fd5b6100c161023d565b6040516100ce9190610be4565b60405180910390f35b6100f160048036038101906100ec9190610da2565b610263565b005b6100fb610323565b005b61011760048036038101906101129190610dfe565b610337565b6040516101249190610e3a565b60405180910390f35b61013561035b565b6040516101429190610e76565b60405180910390f35b61016560048036038101906101609190610dfe565b610384565b604051610173929190610eac565b60405180910390f35b61019660048036038101906101919190610f2d565b6103c2565b005b6101b260048036038101906101ad9190610dfe565b610425565b6040516101c092919061102b565b60405180910390f35b6101e360048036038101906101de919061105b565b610550565b6040516101f09190611088565b60405180910390f35b610201610570565b005b61021d6004803603810190610218919061105b565b61082e565b005b6102276108b1565b6040516102349190610e3a565b60405180910390f35b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461031557337f00000000000000000000000000000000000000000000000000000000000000006040517f1cdc5ebb00000000000000000000000000000000000000000000000000000000815260040161030c9291906110a3565b60405180910390fd5b61031f82826108b7565b5050565b61032b6109b1565b6103356000610a2f565b565b6004818154811061034757600080fd5b906000526020600020016000915090505481565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60026020528060005260406000206000915090508060000160009054906101000a900460ff16908060000160019054906101000a900460ff16905082565b6103ca6109b1565b80600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b600060606002600084815260200190815260200160002060000160019054906101000a900460ff1661048c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161048390611129565b60405180910390fd5b6000600260008581526020019081526020016000206040518060600160405290816000820160009054906101000a900460ff161515151581526020016000820160019054906101000a900460ff161515151581526020016001820180548060200260200160405190810160405280929190818152602001828054801561053157602002820191906000526020600020905b81548152602001906001019080831161051d575b5050505050815250509050806000015181604001519250925050915091565b60016020528060005260406000206000915054906101000a900460ff1681565b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16806105fa57506105cb61035b565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b610639576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161063090611195565b60405180910390fd5b6000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635d3b1d30600654600360149054906101000a900467ffffffffffffffff16600760049054906101000a900461ffff16600760009054906101000a900463ffffffff1660016040518663ffffffff1660e01b81526004016106d9959493929190611268565b6020604051808303816000875af11580156106f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061071c91906112d0565b90506040518060600160405280600015158152602001600115158152602001600067ffffffffffffffff81111561075657610755610c5f565b5b6040519080825280602002602001820160405280156107845781602001602082028036833780820191505090505b508152506002600083815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548160ff02191690831515021790555060408201518160010190805190602001906107f7929190610afb565b5090505060048190806001815401808255809150506001900390600052602060002001600090919091909150558060058190555050565b6108366109b1565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036108a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161089c9061136f565b60405180910390fd5b6108ae81610a2f565b50565b60055481565b6002600083815260200190815260200160002060000160019054906101000a900460ff1661091a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161091190611129565b60405180910390fd5b60016002600084815260200190815260200160002060000160006101000a81548160ff02191690831515021790555080600260008481526020019081526020016000206001019080519060200190610973929190610afb565b507ffe2e2d779dba245964d4e3ef9b994be63856fd568bf7d3ca9e224755cb1bd54d82826040516109a592919061138f565b60405180910390a15050565b6109b9610af3565b73ffffffffffffffffffffffffffffffffffffffff166109d761035b565b73ffffffffffffffffffffffffffffffffffffffff1614610a2d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a249061140b565b60405180910390fd5b565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600033905090565b828054828255906000526020600020908101928215610b37579160200282015b82811115610b36578251825591602001919060010190610b1b565b5b509050610b449190610b48565b5090565b5b80821115610b61576000816000905550600101610b49565b5090565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b6000610baa610ba5610ba084610b65565b610b85565b610b65565b9050919050565b6000610bbc82610b8f565b9050919050565b6000610bce82610bb1565b9050919050565b610bde81610bc3565b82525050565b6000602082019050610bf96000830184610bd5565b92915050565b6000604051905090565b600080fd5b600080fd5b6000819050919050565b610c2681610c13565b8114610c3157600080fd5b50565b600081359050610c4381610c1d565b92915050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b610c9782610c4e565b810181811067ffffffffffffffff82111715610cb657610cb5610c5f565b5b80604052505050565b6000610cc9610bff565b9050610cd58282610c8e565b919050565b600067ffffffffffffffff821115610cf557610cf4610c5f565b5b602082029050602081019050919050565b600080fd5b6000610d1e610d1984610cda565b610cbf565b90508083825260208201905060208402830185811115610d4157610d40610d06565b5b835b81811015610d6a5780610d568882610c34565b845260208401935050602081019050610d43565b5050509392505050565b600082601f830112610d8957610d88610c49565b5b8135610d99848260208601610d0b565b91505092915050565b60008060408385031215610db957610db8610c09565b5b6000610dc785828601610c34565b925050602083013567ffffffffffffffff811115610de857610de7610c0e565b5b610df485828601610d74565b9150509250929050565b600060208284031215610e1457610e13610c09565b5b6000610e2284828501610c34565b91505092915050565b610e3481610c13565b82525050565b6000602082019050610e4f6000830184610e2b565b92915050565b6000610e6082610b65565b9050919050565b610e7081610e55565b82525050565b6000602082019050610e8b6000830184610e67565b92915050565b60008115159050919050565b610ea681610e91565b82525050565b6000604082019050610ec16000830185610e9d565b610ece6020830184610e9d565b9392505050565b610ede81610e55565b8114610ee957600080fd5b50565b600081359050610efb81610ed5565b92915050565b610f0a81610e91565b8114610f1557600080fd5b50565b600081359050610f2781610f01565b92915050565b60008060408385031215610f4457610f43610c09565b5b6000610f5285828601610eec565b9250506020610f6385828601610f18565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b610fa281610c13565b82525050565b6000610fb48383610f99565b60208301905092915050565b6000602082019050919050565b6000610fd882610f6d565b610fe28185610f78565b9350610fed83610f89565b8060005b8381101561101e5781516110058882610fa8565b975061101083610fc0565b925050600181019050610ff1565b5085935050505092915050565b60006040820190506110406000830185610e9d565b81810360208301526110528184610fcd565b90509392505050565b60006020828403121561107157611070610c09565b5b600061107f84828501610eec565b91505092915050565b600060208201905061109d6000830184610e9d565b92915050565b60006040820190506110b86000830185610e67565b6110c56020830184610e67565b9392505050565b600082825260208201905092915050565b7f524e473a2072657175657374206e6f7420666f756e6400000000000000000000600082015250565b60006111136016836110cc565b915061111e826110dd565b602082019050919050565b6000602082019050818103600083015261114281611106565b9050919050565b7f524e473a206f6e6c792077686974656c69746564206164647265737365730000600082015250565b600061117f601e836110cc565b915061118a82611149565b602082019050919050565b600060208201905081810360008301526111ae81611172565b9050919050565b6000819050919050565b6111c8816111b5565b82525050565b600067ffffffffffffffff82169050919050565b6111eb816111ce565b82525050565b600061ffff82169050919050565b611208816111f1565b82525050565b600063ffffffff82169050919050565b6112278161120e565b82525050565b6000819050919050565b600061125261124d6112488461122d565b610b85565b61120e565b9050919050565b61126281611237565b82525050565b600060a08201905061127d60008301886111bf565b61128a60208301876111e2565b61129760408301866111ff565b6112a4606083018561121e565b6112b16080830184611259565b9695505050505050565b6000815190506112ca81610c1d565b92915050565b6000602082840312156112e6576112e5610c09565b5b60006112f4848285016112bb565b91505092915050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b60006113596026836110cc565b9150611364826112fd565b604082019050919050565b600060208201905081810360008301526113888161134c565b9050919050565b60006040820190506113a46000830185610e2b565b81810360208301526113b68184610fcd565b90509392505050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b60006113f56020836110cc565b9150611400826113bf565b602082019050919050565b60006020820190508181036000830152611424816113e8565b905091905056fea2646970667358221220f8e243fb678b9f81958bacead5d99aab1c31e3e4f6df27b3558785557ea8c3c364736f6c634300081b00330000000000000000000000007fdbf4fe2dbbdf956c010b3dd83177cb86eb1b1400000000000000000000000000000000000000000000000000000000000000066da22a485fc06c9bce99691a2ff5af57b7fd20b09af4a6572f6a44473d6c151400000000000000000000000000000000000000000000000000000000002625a00000000000000000000000000000000000000000000000000000000000000003
Deployed ByteCode
0x608060405234801561001057600080fd5b50600436106100b45760003560e01c8063b9a45aac11610071578063b9a45aac1461017c578063d8a4676f14610198578063d936547e146101c9578063e0c86289146101f9578063f2fde38b14610203578063fc2a88c31461021f576100b4565b80630a009097146100b95780631fe543e3146100d7578063715018a6146100f35780638796ba8c146100fd5780638da5cb5b1461012d578063a168fa891461014b575b600080fd5b6100c161023d565b6040516100ce9190610be4565b60405180910390f35b6100f160048036038101906100ec9190610da2565b610263565b005b6100fb610323565b005b61011760048036038101906101129190610dfe565b610337565b6040516101249190610e3a565b60405180910390f35b61013561035b565b6040516101429190610e76565b60405180910390f35b61016560048036038101906101609190610dfe565b610384565b604051610173929190610eac565b60405180910390f35b61019660048036038101906101919190610f2d565b6103c2565b005b6101b260048036038101906101ad9190610dfe565b610425565b6040516101c092919061102b565b60405180910390f35b6101e360048036038101906101de919061105b565b610550565b6040516101f09190611088565b60405180910390f35b610201610570565b005b61021d6004803603810190610218919061105b565b61082e565b005b6102276108b1565b6040516102349190610e3a565b60405180910390f35b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b7f0000000000000000000000007fdbf4fe2dbbdf956c010b3dd83177cb86eb1b1473ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461031557337f0000000000000000000000007fdbf4fe2dbbdf956c010b3dd83177cb86eb1b146040517f1cdc5ebb00000000000000000000000000000000000000000000000000000000815260040161030c9291906110a3565b60405180910390fd5b61031f82826108b7565b5050565b61032b6109b1565b6103356000610a2f565b565b6004818154811061034757600080fd5b906000526020600020016000915090505481565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60026020528060005260406000206000915090508060000160009054906101000a900460ff16908060000160019054906101000a900460ff16905082565b6103ca6109b1565b80600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b600060606002600084815260200190815260200160002060000160019054906101000a900460ff1661048c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161048390611129565b60405180910390fd5b6000600260008581526020019081526020016000206040518060600160405290816000820160009054906101000a900460ff161515151581526020016000820160019054906101000a900460ff161515151581526020016001820180548060200260200160405190810160405280929190818152602001828054801561053157602002820191906000526020600020905b81548152602001906001019080831161051d575b5050505050815250509050806000015181604001519250925050915091565b60016020528060005260406000206000915054906101000a900460ff1681565b600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16806105fa57506105cb61035b565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b610639576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161063090611195565b60405180910390fd5b6000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16635d3b1d30600654600360149054906101000a900467ffffffffffffffff16600760049054906101000a900461ffff16600760009054906101000a900463ffffffff1660016040518663ffffffff1660e01b81526004016106d9959493929190611268565b6020604051808303816000875af11580156106f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061071c91906112d0565b90506040518060600160405280600015158152602001600115158152602001600067ffffffffffffffff81111561075657610755610c5f565b5b6040519080825280602002602001820160405280156107845781602001602082028036833780820191505090505b508152506002600083815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548160ff02191690831515021790555060408201518160010190805190602001906107f7929190610afb565b5090505060048190806001815401808255809150506001900390600052602060002001600090919091909150558060058190555050565b6108366109b1565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036108a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161089c9061136f565b60405180910390fd5b6108ae81610a2f565b50565b60055481565b6002600083815260200190815260200160002060000160019054906101000a900460ff1661091a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161091190611129565b60405180910390fd5b60016002600084815260200190815260200160002060000160006101000a81548160ff02191690831515021790555080600260008481526020019081526020016000206001019080519060200190610973929190610afb565b507ffe2e2d779dba245964d4e3ef9b994be63856fd568bf7d3ca9e224755cb1bd54d82826040516109a592919061138f565b60405180910390a15050565b6109b9610af3565b73ffffffffffffffffffffffffffffffffffffffff166109d761035b565b73ffffffffffffffffffffffffffffffffffffffff1614610a2d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a249061140b565b60405180910390fd5b565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b600033905090565b828054828255906000526020600020908101928215610b37579160200282015b82811115610b36578251825591602001919060010190610b1b565b5b509050610b449190610b48565b5090565b5b80821115610b61576000816000905550600101610b49565b5090565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b6000610baa610ba5610ba084610b65565b610b85565b610b65565b9050919050565b6000610bbc82610b8f565b9050919050565b6000610bce82610bb1565b9050919050565b610bde81610bc3565b82525050565b6000602082019050610bf96000830184610bd5565b92915050565b6000604051905090565b600080fd5b600080fd5b6000819050919050565b610c2681610c13565b8114610c3157600080fd5b50565b600081359050610c4381610c1d565b92915050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b610c9782610c4e565b810181811067ffffffffffffffff82111715610cb657610cb5610c5f565b5b80604052505050565b6000610cc9610bff565b9050610cd58282610c8e565b919050565b600067ffffffffffffffff821115610cf557610cf4610c5f565b5b602082029050602081019050919050565b600080fd5b6000610d1e610d1984610cda565b610cbf565b90508083825260208201905060208402830185811115610d4157610d40610d06565b5b835b81811015610d6a5780610d568882610c34565b845260208401935050602081019050610d43565b5050509392505050565b600082601f830112610d8957610d88610c49565b5b8135610d99848260208601610d0b565b91505092915050565b60008060408385031215610db957610db8610c09565b5b6000610dc785828601610c34565b925050602083013567ffffffffffffffff811115610de857610de7610c0e565b5b610df485828601610d74565b9150509250929050565b600060208284031215610e1457610e13610c09565b5b6000610e2284828501610c34565b91505092915050565b610e3481610c13565b82525050565b6000602082019050610e4f6000830184610e2b565b92915050565b6000610e6082610b65565b9050919050565b610e7081610e55565b82525050565b6000602082019050610e8b6000830184610e67565b92915050565b60008115159050919050565b610ea681610e91565b82525050565b6000604082019050610ec16000830185610e9d565b610ece6020830184610e9d565b9392505050565b610ede81610e55565b8114610ee957600080fd5b50565b600081359050610efb81610ed5565b92915050565b610f0a81610e91565b8114610f1557600080fd5b50565b600081359050610f2781610f01565b92915050565b60008060408385031215610f4457610f43610c09565b5b6000610f5285828601610eec565b9250506020610f6385828601610f18565b9150509250929050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b610fa281610c13565b82525050565b6000610fb48383610f99565b60208301905092915050565b6000602082019050919050565b6000610fd882610f6d565b610fe28185610f78565b9350610fed83610f89565b8060005b8381101561101e5781516110058882610fa8565b975061101083610fc0565b925050600181019050610ff1565b5085935050505092915050565b60006040820190506110406000830185610e9d565b81810360208301526110528184610fcd565b90509392505050565b60006020828403121561107157611070610c09565b5b600061107f84828501610eec565b91505092915050565b600060208201905061109d6000830184610e9d565b92915050565b60006040820190506110b86000830185610e67565b6110c56020830184610e67565b9392505050565b600082825260208201905092915050565b7f524e473a2072657175657374206e6f7420666f756e6400000000000000000000600082015250565b60006111136016836110cc565b915061111e826110dd565b602082019050919050565b6000602082019050818103600083015261114281611106565b9050919050565b7f524e473a206f6e6c792077686974656c69746564206164647265737365730000600082015250565b600061117f601e836110cc565b915061118a82611149565b602082019050919050565b600060208201905081810360008301526111ae81611172565b9050919050565b6000819050919050565b6111c8816111b5565b82525050565b600067ffffffffffffffff82169050919050565b6111eb816111ce565b82525050565b600061ffff82169050919050565b611208816111f1565b82525050565b600063ffffffff82169050919050565b6112278161120e565b82525050565b6000819050919050565b600061125261124d6112488461122d565b610b85565b61120e565b9050919050565b61126281611237565b82525050565b600060a08201905061127d60008301886111bf565b61128a60208301876111e2565b61129760408301866111ff565b6112a4606083018561121e565b6112b16080830184611259565b9695505050505050565b6000815190506112ca81610c1d565b92915050565b6000602082840312156112e6576112e5610c09565b5b60006112f4848285016112bb565b91505092915050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b60006113596026836110cc565b9150611364826112fd565b604082019050919050565b600060208201905081810360008301526113888161134c565b9050919050565b60006040820190506113a46000830185610e2b565b81810360208301526113b68184610fcd565b90509392505050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b60006113f56020836110cc565b9150611400826113bf565b602082019050919050565b60006020820190508181036000830152611424816113e8565b905091905056fea2646970667358221220f8e243fb678b9f81958bacead5d99aab1c31e3e4f6df27b3558785557ea8c3c364736f6c634300081b0033