// 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;
}
}
// SPDX-License-Identifier: MIT
pragma solidity 0.8.16;
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@chainlink/contracts/src/v0.8/vrf/VRFConsumerBaseV2.sol";
import "@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol";
contract NobodyReserve is Ownable, ReentrancyGuard, VRFConsumerBaseV2 {
uint256 public reservePrice = 0.19527 ether;
// 1706792400 -> 2024-02-01 21:00:00 UTC+8
uint256 public priorityTime = 1706792400;
// reserver raffle weight before priorityTime
uint256 public constant PRIORITY_WEIGHT = 9527;
// reserver raffle weight after priorityTime
uint256 public constant NORMAL_WEIGHT = 1000;
bool public isWhitelistReserveActive = false;
bool public isPublicReserveActive = false;
bool public isRefundActive = false;
address private immutable _VRFCoordinator;
uint64 private _VRFSubscriptionId;
uint256[] private _randomWords;
uint256 public totalReserved;
uint256 private _totalWeight;
uint256 private _priorityCount;
address[] private _publicReservers;
// Don't tell me about using merkel tree to save gas
// In order to prohibit whitelist addresses from participating in the public reserve,
// all whitelist addresses need to be on-chain
mapping(address => bool) public whitelist;
mapping(address => bool) public reserved;
mapping(address => bool) public raffleWon;
mapping(address => bool) public refunded;
// ============ Events ============
event WhitelistReserved(address indexed reserver);
event PublicReserved(address indexed reserver);
event RandomWordsRequested(uint256 requestId);
event RandomWordsFulfilled(uint256 requestId, uint256[] randomWords);
event RaffleWon(address indexed reserver);
event Refunded(address indexed reserver);
// ============ Error ============
error OnlyEOA();
error RserveNotActive();
error InvalidAddress();
error InvalidValue();
error AlreadyReserved();
error InvalidRaffle();
error RefundNotActive();
error NotRefundable();
error AlreadyRefund();
error InsufficientBalance();
error TransferFailed();
// ============ Modifier ============
modifier onlyEOA() {
if (msg.sender != tx.origin) revert OnlyEOA();
_;
}
// ============ Constructor ============
constructor(address VRFCoordinator_, uint64 VRFSubscriptionId_) VRFConsumerBaseV2(VRFCoordinator_) {
_VRFCoordinator = VRFCoordinator_;
_VRFSubscriptionId = VRFSubscriptionId_;
}
function setReservePrice(uint256 _reservePrice) external onlyOwner {
reservePrice = _reservePrice;
}
function setPriorityTime(uint256 _priorityTime) external onlyOwner {
priorityTime = _priorityTime;
}
function setIsWhitelistReserveActive(bool _isWhitelistReserveActive) external onlyOwner {
isWhitelistReserveActive = _isWhitelistReserveActive;
}
function setIsPublicReserveActive(bool _isPublicReserveActive) external onlyOwner {
isPublicReserveActive = _isPublicReserveActive;
}
function setIsRefundActive(bool _isRefundActive) external onlyOwner {
isRefundActive = _isRefundActive;
}
function setVRFSubscriptionId(uint64 VRFSubscriptionId_) external onlyOwner {
_VRFSubscriptionId = VRFSubscriptionId_;
}
function setWhitelist(address[] calldata addresses, bool status) external onlyOwner {
for (uint256 i = 0; i < addresses.length; i++) {
whitelist[addresses[i]] = status;
}
}
function withdraw(uint256 amount) external onlyOwner {
if (amount == 0) {
amount = address(this).balance;
}
_sendValue(payable(owner()), amount);
}
function requestRaffleRandomWords(
bytes32 keyHash,
uint16 requestConfirmations,
uint32 callbackGasLimit,
uint32 numWords
) external onlyOwner {
uint256 requestId = VRFCoordinatorV2Interface(_VRFCoordinator).requestRandomWords(
keyHash,
_VRFSubscriptionId,
requestConfirmations,
callbackGasLimit,
numWords
);
emit RandomWordsRequested(requestId);
}
function executeRaffle(uint256 raffleRound, uint256 raffleCount) external onlyOwner {
if (raffleRound > _randomWords.length) revert InvalidRaffle();
if (raffleCount > _publicReservers.length) revert InvalidRaffle();
uint256 raffleIndex = raffleRound - 1;
uint256 randomWord = _randomWords[raffleIndex];
uint256 priorityTotalWeight = _priorityCount * PRIORITY_WEIGHT;
while (raffleCount > 0) {
uint256 index;
uint256 randomWeight = uint256(keccak256(abi.encodePacked(randomWord))) % _totalWeight;
if (randomWeight <= priorityTotalWeight) {
index = randomWeight / PRIORITY_WEIGHT;
} else {
index = _priorityCount + (randomWeight - priorityTotalWeight) / NORMAL_WEIGHT;
}
address winner = _publicReservers[index];
// select the next reserver as the winner if the current reserver has won
while (raffleWon[winner]) {
index = index < _publicReservers.length - 1 ? index + 1 : 0;
winner = _publicReservers[index];
}
// set reserver as winner
raffleWon[winner] = true;
unchecked {
randomWord++;
}
raffleCount--;
emit RaffleWon(winner);
}
}
function whitelistReserve() external payable onlyEOA nonReentrant {
if (!isWhitelistReserveActive) revert RserveNotActive();
if (!whitelist[msg.sender]) revert InvalidAddress();
if (reserved[msg.sender]) revert AlreadyReserved();
if (msg.value != reservePrice) revert InvalidValue();
reserved[msg.sender] = true;
totalReserved++;
emit WhitelistReserved(msg.sender);
}
function publicReserve() external payable onlyEOA nonReentrant {
if (!isPublicReserveActive) revert RserveNotActive();
// whitelist address is not allowed to participate in the public reserve
if (whitelist[msg.sender]) revert InvalidAddress();
if (reserved[msg.sender]) revert AlreadyReserved();
if (msg.value != reservePrice) revert InvalidValue();
reserved[msg.sender] = true;
totalReserved++;
_publicReservers.push(msg.sender);
if (block.timestamp < priorityTime) {
_totalWeight += PRIORITY_WEIGHT;
_priorityCount++;
} else {
_totalWeight += NORMAL_WEIGHT;
}
emit PublicReserved(msg.sender);
}
function refund() external onlyEOA nonReentrant {
if (!isRefundActive) revert RefundNotActive();
if (!reserved[msg.sender]) revert NotRefundable();
// whitelist address is not allowed to refund
// only address participate in the public reserve could refund
if (whitelist[msg.sender]) revert NotRefundable();
// raffle winner is not allowed to refund
if (raffleWon[msg.sender]) revert NotRefundable();
if (refunded[msg.sender]) revert AlreadyRefund();
refunded[msg.sender] = true;
_sendValue(payable(msg.sender), reservePrice);
emit Refunded(msg.sender);
}
function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal override {
_randomWords = randomWords;
emit RandomWordsFulfilled(requestId, randomWords);
}
function _sendValue(address payable recipient, uint256 amount) private {
if (address(this).balance < amount) revert InsufficientBalance();
(bool success, ) = recipient.call{value: amount}("");
if (!success) revert TransferFailed();
}
}
// 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);
}
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)
pragma solidity ^0.8.0;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be _NOT_ENTERED
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
/**
* @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
* `nonReentrant` function in the call stack.
*/
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == _ENTERED;
}
}
// 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 VRFCoordinator
* @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 _vrfCoordinator, address _link)
* @dev VRFConsumerBase(_vrfCoordinator) 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 VRFCoordinatorInterface
* @dev subscription management functions).
* @dev Call requestRandomWords(keyHash, subId, minimumRequestConfirmations,
* @dev callbackGasLimit, numWords),
* @dev see (VRFCoordinatorInterface for a description of the arguments).
*
* @dev Once the VRFCoordinator 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 OnlyCoordinatorCanFulfill(address have, address want);
address private immutable vrfCoordinator;
/**
* @param _vrfCoordinator address of VRFCoordinator contract
*/
constructor(address _vrfCoordinator) {
vrfCoordinator = _vrfCoordinator;
}
/**
* @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
*/
function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal virtual;
// rawFulfillRandomness is called by VRFCoordinator 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 != vrfCoordinator) {
revert OnlyCoordinatorCanFulfill(msg.sender, vrfCoordinator);
}
fulfillRandomWords(requestId, randomWords);
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface VRFCoordinatorV2Interface {
/**
* @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 VRFCoordinator 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(COORDINATOR),
* @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 (uint96 balance, uint64 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);
}
{
"compilationTarget": {
"contracts/NobodyReserve.sol": "NobodyReserve"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"VRFCoordinator_","type":"address"},{"internalType":"uint64","name":"VRFSubscriptionId_","type":"uint64"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyRefund","type":"error"},{"inputs":[],"name":"AlreadyReserved","type":"error"},{"inputs":[],"name":"InsufficientBalance","type":"error"},{"inputs":[],"name":"InvalidAddress","type":"error"},{"inputs":[],"name":"InvalidRaffle","type":"error"},{"inputs":[],"name":"InvalidValue","type":"error"},{"inputs":[],"name":"NotRefundable","type":"error"},{"inputs":[{"internalType":"address","name":"have","type":"address"},{"internalType":"address","name":"want","type":"address"}],"name":"OnlyCoordinatorCanFulfill","type":"error"},{"inputs":[],"name":"OnlyEOA","type":"error"},{"inputs":[],"name":"RefundNotActive","type":"error"},{"inputs":[],"name":"RserveNotActive","type":"error"},{"inputs":[],"name":"TransferFailed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"reserver","type":"address"}],"name":"PublicReserved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"reserver","type":"address"}],"name":"RaffleWon","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"requestId","type":"uint256"},{"indexed":false,"internalType":"uint256[]","name":"randomWords","type":"uint256[]"}],"name":"RandomWordsFulfilled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"requestId","type":"uint256"}],"name":"RandomWordsRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"reserver","type":"address"}],"name":"Refunded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"reserver","type":"address"}],"name":"WhitelistReserved","type":"event"},{"inputs":[],"name":"NORMAL_WEIGHT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PRIORITY_WEIGHT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"raffleRound","type":"uint256"},{"internalType":"uint256","name":"raffleCount","type":"uint256"}],"name":"executeRaffle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isPublicReserveActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isRefundActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isWhitelistReserveActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priorityTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"publicReserve","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"raffleWon","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"requestId","type":"uint256"},{"internalType":"uint256[]","name":"randomWords","type":"uint256[]"}],"name":"rawFulfillRandomWords","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"refund","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"refunded","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"keyHash","type":"bytes32"},{"internalType":"uint16","name":"requestConfirmations","type":"uint16"},{"internalType":"uint32","name":"callbackGasLimit","type":"uint32"},{"internalType":"uint32","name":"numWords","type":"uint32"}],"name":"requestRaffleRandomWords","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"reservePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"reserved","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"_isPublicReserveActive","type":"bool"}],"name":"setIsPublicReserveActive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_isRefundActive","type":"bool"}],"name":"setIsRefundActive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_isWhitelistReserveActive","type":"bool"}],"name":"setIsWhitelistReserveActive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_priorityTime","type":"uint256"}],"name":"setPriorityTime","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_reservePrice","type":"uint256"}],"name":"setReservePrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"VRFSubscriptionId_","type":"uint64"}],"name":"setVRFSubscriptionId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"addresses","type":"address[]"},{"internalType":"bool","name":"status","type":"bool"}],"name":"setWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalReserved","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"whitelist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"whitelistReserve","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]