🤑Multiple Winners
The Multiple Winners prize strategy periodically selects a predefined number of winners and awards to them an equal share of the prizes available in the Prize Pool.
Initialization
A Multiple Winners prize strategy is initialized with:
Prize Period Start: the timestamp at which the prize period should start
Prize Period Seconds: the duration of time between prizes
PrizePool Address: the address of the prize pool that implements the pool functionality such as deposit and withdraw
Ticket: The interface to use to select winners
Sponsorship: The token that represents sponsorship
Random Number Generator: used to generate random numbers for winner selection
Number of Winners: the number of winners in a prize period. This can be later changed by the owner calling set number of winners.
Strategy Settings
Set Number of Winners
The number of winners in a prize period can be set by calling:
function setNumberOfWinners(uint256 count)
external onlyOwner requireAwardNotInProgress
Requires that the Award process is not in progress
count
must be greater than 0
View Number of Winners
The number of winners setting can be viewed by calling:
function numberOfWinners() external view returns (uint256
Set Split External ERC-20 Awards
The SplitExternalErc20Awards
flag can be set by calling:
function setSplitExternalErc20Awards(bool _splitExternalErc20Awards)
external onlyOwner requireAwardNotInProgress
This controls how externally added ERC-20's are distributed. Setting to true
results in the ERC-20's paid out uniformly (similar to the main prize), while false
does not pay out external ERC-20's for that award.
Set Random Number Generation Service
The Random Number Generation Service can be set when the award process has not started by the Prize Pool owner by calling:
function setRngService(RNGInterface rngService)
external onlyOwner requireAwardNotInProgress
Set Random Number Generator Request Timeout
The RNG request timeout parameter can be set (in seconds) when the award process has not started by the Prize Pool owner by calling:
function setRngRequestTimeout(uint32 _rngRequestTimeout)
external onlyOwner requireAwardNotInProgress {
Prize Period Information
View if the Prize Period is Over
To check if the prize period is finished call:
function isPrizePeriodOver() external view returns (bool)
Returns true
if the prize period is over, false
otherwise.
View when the Prize Period Finishes
To check the unix time when the prize period ends call:
function prizePeriodEndAt() external view returns (uint256)
View Estimate of Number of Blocks to Prize Block
To estimate the remaining blocks until the prize given a number of seconds per block call estimateRemainingBlocksToPrize
with secondPerBlockMantissa
set to 15 seconds for Ethereum mainnet:
function estimateRemainingBlocksToPrize(uint256 secondsPerBlockMantissa) public
view returns (uint256)
View Prize Period Remaining Time (in seconds)
To get the number of seconds remaining until the prize can be awarded call:
function prizePeriodRemainingSeconds() external view returns (uint256)
View Next Prize Period Start Time
To get the Unix timestamp of when the next prize period will start call calculateNextPrizePeriodStartTime
with currentTime
set to the current Unix time:
function calculateNextPrizePeriodStartTime(uint256 currentTime)
external view returns (uint256)
Award Process
At the end of the prize period, anyone can begin the award process. This happens in two main stages - startAward
and completeAward
. startAward
triggers the configured Random Number Generator request, which will take some blocks. completeAward
can then be called, which selects the winners using the RNG result and pushes the tokens out to the winners.
Start Award
The award process can be started by calling startAward
. This function starts the award process by starting the configured random number request. The prize period must have ended. The RNG-Request-Fee is expected to be held within this contract before calling this function.
function startAward() external requireCanStartAward
Upon completion this function fires the following event:
event PrizePoolAwardStarted(
address indexed operator,
address indexed prizePool,
uint32 indexed rngRequestId,
uint32 rngLockBlock
);
Complete Award
The award process can be finished by calling completeAward
. The random number must have been requested and now available (is can be checked by calling isRngCompleted()
).
function completeAward() external requireCanCompleteAward
This function fires two events upon completion:
event PrizePoolAwarded(
address indexed operator,
uint256 randomNumber
);
Since Prize Pools are continuously rolling the next prize period is now open:
event PrizePoolOpened(
address indexed operator,
uint256 indexed prizePeriodStartedAt
);
Cancel Award
This function can be called by anyone to unlock the tickets if the RNG has timed out:
function cancelAward() public
This function will fire the event:
event PrizePoolAwardCancelled(
address indexed operator,
address indexed prizePool,
uint32 indexed rngRequestId,
uint32 rngLockBlock
);
Listeners
A prize strategy can have both a token listener and a periodic prize strategy listener in order execute code for certain callbacks (event hooks).
Set Token Listener
The token listener can be set by the prize pool owner when the award process is not in progress by calling setTokenListener
with the address of the new tokenList
:
function setTokenListener(TokenListenerInterface _tokenListener)
external onlyOwner requireAwardNotInProgress
Set Periodic Prize Strategy Listener
The periodic prize strategy listener can be set by the prize pool owner when the award process is not in progress by calling setPeriodicPrizeStrategyListener
with the address of the new PeriodicPrizeStrategyListener
:
function setPeriodicPrizeStrategyListener(PeriodicPrizeStrategyListenerInterface _periodicPrizeStrategyListener)
external onlyOwner requireAwardNotInProgress
This function will ensure the Listener Interface is implementing using ERC-165 introspection, and upon completion fire the following event:
event PeriodicPrizeStrategyListenerSet(
PeriodicPrizeStrategyListenerInterface indexed periodicPrizeStrategyListener
);
External ERC20 and ERC721 Awards
External awards can be added to the pool. This is particularly useful in the case of the stake pool. Although still possible for either the token listener or the owner to manually add or remove ERC-20's and ERC-721's, it is recommended to add a single LootBox per prize period and direct the external awards to this LootBox address.
The pool owner or the token listener can add/remove ERC721's by calling:
function addExternalErc721Award(IERC721Upgradeable _externalErc721,
uint256[] calldata _tokenIds)
external onlyOwnerOrListener requireAwardNotInProgress
function removeExternalErc721Award(
IERC721Upgradeable _externalErc721,
IERC721Upgradeable _prevExternalErc721)
external onlyOwner requireAwardNotInProgress
The pool owner or the token listener can add/remove ERC20's by calling:
function addExternalErc20Awards(IERC20Upgradeable[] calldata _externalErc20s)
external onlyOwnerOrListener requireAwardNotInProgress
function removeExternalErc20Award(
IERC20Upgradeable _externalErc20,
IERC20Upgradeable _prevExternalErc20)
external onlyOwner requireAwardNotInProgress
Corresponding events are fired for each ERC type added or removed:
event ExternalErc721AwardAdded(
IERC721Upgradeable indexed externalErc721,
uint256[] tokenIds
);
event ExternalErc20AwardAdded(
IERC20Upgradeable indexed externalErc20
);
event ExternalErc721AwardRemoved(
IERC721Upgradeable indexed externalErc721Award
);
event ExternalErc20AwardRemoved(
IERC20Upgradeable indexed externalErc20Award
);
Last updated
Was this helpful?