Skip to main content

YOLO Contract Overview

The YoloV2 smart contract enables permissionless hosting of yolo rounds on YOLO Games.

The YOLO game operates on a set of smart contracts designed to provide a transparent, fair, and decentralized game experience. These are YoloV2, the main game contract, and PriceOracle a secondary component used to retrieve the TWAP price in ETH from Uniswap V3 pools for ERC-20s.

The contract is designed to handle deposits of a variety of asset types (ETH, ERC-721, ERC-20). The contract owner can add and remove allowed assets, therefore not all asset types will necessarily be available at any given time, and only selected contracts for each type will be allowed as deposits. The players can then withdraw, claim or rollover their deposits if they won or a round was cancelled.

The likelihood of a participant winning is equivalent to the share of the total pot they deposited. Each deposit value is calculated, and each participant is allocated a number of entry spots proportional to the value deposited. The YOLO contract relies on a few external oracles: Gelato VRF for fair randomness, Reservoir for ERC-721 pricing data and Uniswap for ERC-20s pricing data.

NOTE: All NFTs in a collection will be valued at the floor price of the collection; rarity is not accounted for.

Here we provide an extract of the YOLO contract interface. You can find the full contracts and interfaces by checking out the deployed contracts.

For a more detailed overview see the YOLO Technical Overview

Deployed Contracts

Here are all the YOLO-related contracts used by YOLO Games.

ContractsBlast MainnetBlast Sepolia
YoloV20x0000000000E14E87e5c80A8A90817308fFF715d30x7a8E6D6c6d6BeC39f5aA3D28373916c8e5c02098
PriceOracle0x9C9D8C8ee91f21004A40c4664D49CC1b9DFa69f90x139bF195099B17137B84f5ba812C218b4CE628ea
TransferManager*0x00000000007fe8d7666bb0da2a5d13f72b8dabab0xFD1DcA440E83FF9A1AED83e0f2D4b3EE85Cc2d44

* The TransferManager contract is the same across all YOLO Games products.

Table of Contents

This page includes the following sections.

Enums

The contract includes enums to classify deposit's token type and round's status.

/**
* @notice A round's status
* @param None The round does not exist
* @param Open The round is open for deposits
* @param Drawing The round is being drawn
* @param Drawn The round has been drawn
* @param Cancelled The round has been cancelled
*/
enum RoundStatus {
None,
Open,
Drawing,
Drawn,
Cancelled
}

/**
* @dev Giving TokenType a namespace to avoid name conflicts with TransferManager.
*/
enum YoloV2__TokenType {
ETH,
ERC20,
ERC721
}

Sturcts

The contract includes various structs for the constructor calldata, deposit calldata, Reservoir oracle floor price, a round, a deposit, a randomness request and withdrawal calldata.

/**
* @param owner The owner of the contract.
* @param operator The operator of the contract.
* @param roundDuration The duration of each round.
* @param valuePerEntry The value of each entry in ETH.
* @param protocolFeeRecipient The protocol fee recipient.
* @param protocolFeeBp The protocol fee basis points.
* @param discountedProtocolFeeBp The discounted protocol fee basis points.
* @param keyHash Gelato VRF key hash
* @param subscriptionId Gelato VRF subscription ID
* @param vrfCoordinator Gelato VRF coordinator address
* @param reservoirOracle Reservoir off-chain oracle address
* @param erc20Oracle ERC20 on-chain oracle address
* @param transferManager Transfer manager
* @param signatureValidityPeriod The validity period of a Reservoir signature.
* @param minimumRequestConfirmations The minimum number of confirmation blocks on VRF requests before oracles respond.
*/
struct ConstructorCalldata {
address owner;
address operator;
uint40 maximumNumberOfParticipantsPerRound;
uint40 roundDuration;
uint96 valuePerEntry;
address protocolFeeRecipient;
uint16 protocolFeeBp;
uint16 discountedProtocolFeeBp;
bytes32 keyHash;
uint64 subscriptionId;
address vrfCoordinator;
address reservoirOracle;
address transferManager;
address erc20Oracle;
address weth;
uint40 signatureValidityPeriod;
uint16 minimumRequestConfirmations;
}

/**
* @param id The id of the response.
* @param payload The payload of the response.
* @param timestamp The timestamp of the response.
* @param signature The signature of the response.
*/
struct ReservoirOracleFloorPrice {
bytes32 id;
bytes payload;
uint256 timestamp;
bytes signature;
}

/**
* @param tokenType The type of the token.
* @param tokenAddress The address of the token.
* @param tokenIdsOrAmounts The ids (ERC-721) or amounts (ERC-20) of the tokens.
* @param minimumEntries The minimum entries to receive if it's an ERC-20 deposit. Unused for ERC-721 deposits.
* @param reservoirOracleFloorPrice The Reservoir oracle floor price. Required for ERC-721 deposits.
*/
struct DepositCalldata {
YoloV2__TokenType tokenType;
address tokenAddress;
uint256[] tokenIdsOrAmounts;
uint256 minimumEntries;
ReservoirOracleFloorPrice reservoirOracleFloorPrice;
}

/**
* @notice A round
* @dev The storage layout of a round is as follows:
* |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
* | empty (72 bits) | numberOfParticipants (40) bits) | drawnAt (40 bits) | cutoffTime (40 bits) | protcoolFeeBp (16 bits) | maximumNumberOfParticipants (40 bits) | status (8 bits) |
* |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
* | valuePerEntry (96 bits) | winner (160 bits) |
* |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
* | protocolFeeOwed (256 bits) |
* |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
* | deposits length (256 bits) |
* |----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
*
* @param status The status of the round.
* @param maximumNumberOfParticipants The maximum number of participants.
* @param protocolFeeBp The protocol fee basis points.
* @param cutoffTime The cutoff time of the round.
* @param drawnAt The time the round was drawn.
* @param numberOfParticipants The current number of participants.
* @param winner The winner of the round.
* @param valuePerEntry The value of each entry in ETH.
* @param protocolFeeOwed The protocol fee owed in ETH.
* @param deposits The deposits in the round.
*/
struct Round {
RoundStatus status;
uint40 maximumNumberOfParticipants;
uint16 protocolFeeBp;
uint40 cutoffTime;
uint40 drawnAt;
uint40 numberOfParticipants;
address winner;
uint96 valuePerEntry;
uint256 protocolFeeOwed;
Deposit[] deposits;
}

/**
* @notice A deposit in a round.
* @dev The storage layout of a deposit is as follows:
* |-------------------------------------------------------------------------------------------|
* | empty (88 bits) | tokenAddress (160 bits) | tokenType (8 bits) |
* |-------------------------------------------------------------------------------------------|
* | tokenId (256 bits) |
* |-------------------------------------------------------------------------------------------|
* | tokenAmount (256 bits) |
* |-------------------------------------------------------------------------------------------|
* | empty (48 bits) | currentEntryIndex (40 bits) | withdrawn (8 bits) | depositor (160 bits) |
* |-------------------------------------------------------------------------------------------|
*
* @param tokenType The type of the token.
* @param tokenAddress The address of the token.
* @param tokenId The id of the token.
* @param tokenAmount The amount of the token.
* @param depositor The depositor of the token.
* @param withdrawn Whether the token has been withdrawn.
* @param currentEntryIndex The current entry index.
*/
struct Deposit {
YoloV2__TokenType tokenType;
address tokenAddress;
uint256 tokenId;
uint256 tokenAmount;
address depositor;
bool withdrawn;
uint40 currentEntryIndex;
}

/**
* @param exists Whether the request exists.
* @param roundId The id of the round.
* @param randomWord The random words returned by Chainlink VRF.
* If randomWord == 0, then the request is still pending.
*/
struct RandomnessRequest {
bool exists;
uint40 roundId;
uint256 randomWord;
}

/**
* @param roundId The id of the round.
* @param depositIndices The indices of the deposits to be claimed.
*/
struct WithdrawalCalldata {
uint256 roundId;
uint256[] depositIndices;
}

/**
* @notice This is used to accumulate the amount of tokens to be transferred.
* @param tokenAddress The address of the token.
* @param amount The amount of tokens accumulated.
*/
struct TransferAccumulator {
address tokenAddress;
uint256 amount;
}

Events

Events are emitted for various actions, such as depositing, withdrawing a deposit, updating the round status, claiming prizes, sending a randomness request etc.

/**
* @dev Events emitted during a round.
*/
event Deposited(address depositor, uint256 roundId, uint256 entriesCount);
event MultipleRoundsDeposited(address depositor, uint256 startingRoundId, uint256[] amounts, uint256[] entriesCounts);
event RandomnessRequested(uint256 roundId, uint256 requestId);
event Rollover(address depositor, WithdrawalCalldata[] withdrawalCalldata, uint256 enteredRoundId, uint256 entriesCount);
event RoundsCancelled(uint256 startingRoundId, uint256 numberOfRounds);

/**
* @dev Events emitted when the player withdraws.
*/
event DepositsWithdrawn(address depositor, WithdrawalCalldata[] withdrawalCalldata);
event PrizesClaimed(address winner, WithdrawalCalldata[] withdrawalCalldata);
event ProtocolFeePayment(uint256 amount, address token);

/**
* @dev Events emitted when the contract state is updated.
*/
event DiscountedProtocolFeeBpUpdated(uint16 discountedProtocolFeeBp);
event ERC20OracleUpdated(address erc20Oracle);
event MaximumNumberOfParticipantsPerRoundUpdated(uint40 maximumNumberOfParticipantsPerRound);
event OutflowAllowedUpdated(bool isAllowed);
event ProtocolFeeBpUpdated(uint16 protocolFeeBp);
event ProtocolFeeRecipientUpdated(address protocolFeeRecipient);
event ReservoirOracleUpdated(address reservoirOracle);
event RoundDurationUpdated(uint40 roundDuration);
event RoundStatusUpdated(uint256 roundId, RoundStatus status);
event SignatureValidityPeriodUpdated(uint40 signatureValidityPeriod);
event TokensStatusUpdated(address[] tokens, YoloV2__TokenType tokenType, bool isAllowed);
event ValuePerEntryUpdated(uint256 valuePerEntry);

Functions

The contract includes various functions for interacting with the YOLO game, such as depositing into the current round (deposit), rolling over previous deposits (rolloverETH), deposit into multiple rounds starting from the current one (depositETHIntoMultipleRounds), drawing the winners (drawWinner), claiming the prizes (claimPrizes), cancelling a round if less than two addresses deposited (cancel) and withdrawing the deposit if cancelled (withdrawDeposits).

/**
* @notice This function cancels an expired round that does not have at least 2 participants.
*/
function cancel() external;

/**
* @notice This function cancels multiple rounds (current and future) without any validations (can be any state).
* Only callable by the contract owner.
* @param numberOfRounds Number of rounds to cancel.
*/
function cancel(uint256 numberOfRounds) external;

/**
* @notice Cancels a round after randomness request if the randomness request
* does not arrive after 25 hours. Chainlink VRF stops trying after 24 hours.
* Giving an extra hour should prevent any frontrun attempts.
*/
function cancelAfterRandomnessRequest() external;

/**
* @notice This function allows the winner of a round to withdraw the prizes.
* @param withdrawalCalldata The rounds and the indices for the rounds for the prizes to claim.
* @param payWithLOOKS Whether to pay for the protocol fee with LOOKS.
*/
function claimPrizes(WithdrawalCalldata[] calldata withdrawalCalldata, bool payWithLOOKS) external payable;

/**
* @notice This function calculates the ETH payment required to claim the prizes for multiple rounds.
* @param withdrawalCalldata The rounds and the indices for the rounds for the prizes to claim.
* @param payWithLOOKS Whether to pay for the protocol fee with LOOKS.
* @return protocolFeeOwed The protocol fee owed in ETH or LOOKS.
*/
function getClaimPrizesPaymentRequired(
WithdrawalCalldata[] calldata withdrawalCalldata,
bool payWithLOOKS
) external view returns (uint256 protocolFeeOwed);

/**
* @notice This function is used by the frontend to estimate the minimumEntries to be set for ERC-20 deposits.
* @dev This function does 0 validations. It is the responsibility of the caller to ensure that the deposit is valid and the round is enterable.
* @param roundId The round ID.
* @param singleDeposit The ERC-20 deposit.
* @return entriesCount The estimated number of entries for the deposit amount.
*/
function estimatedERC20DepositEntriesCount(
uint256 roundId,
DepositCalldata calldata singleDeposit
) external view returns (uint256 entriesCount);

/**
* @notice This function allows withdrawal of deposits from a round if the round is cancelled
* @param withdrawalCalldata The rounds and the indices for the rounds for the prizes to claim.
*/
function withdrawDeposits(WithdrawalCalldata[] calldata withdrawalCalldata) external;

/**
* @notice This function allows players to deposit into a round.
* @param roundId The open round ID.
* @param deposits The ERC-20/ERC-721 deposits to be made.
*/
function deposit(uint256 roundId, DepositCalldata[] calldata deposits) external payable;

/**
* @notice This function allows a player to deposit into multiple rounds at once. ETH only.
* @param startingRoundId The starting round ID to deposit into. Round status must be Open.
* @param amounts The amount of ETH to deposit into each round.
*/
function depositETHIntoMultipleRounds(uint256 startingRoundId, uint256[] calldata amounts) external payable;

/**
* @notice This function draws a round.
*/
function drawWinner() external;

/**
* @notice This function returns the given round's data.
* @param roundId The round ID.
* @return status The status of the round.
* @return maximumNumberOfParticipants The round's maximum number of participants.
* @return roundProtocolFeeBp The round's protocol fee in basis points.
* @return cutoffTime The round's cutoff time.
* @return drawnAt The time the round was drawn.
* @return numberOfParticipants The round's current number of participants.
* @return winner The round's winner.
* @return roundValuePerEntry The round's value per entry.
* @return protocolFeeOwed The round's protocol fee owed in ETH.
* @return deposits The round's deposits.
*/
function getRound(
uint256 roundId
)
external
view
returns (
IYoloV2.RoundStatus status,
uint40 maximumNumberOfParticipants,
uint16 roundProtocolFeeBp,
uint40 cutoffTime,
uint40 drawnAt,
uint40 numberOfParticipants,
address winner,
uint96 roundValuePerEntry,
uint256 protocolFeeOwed,
Deposit[] memory deposits
);

/**
* @notice This function allows a player to rollover prizes or deposits from a cancelled round to the current round.
* @param roundId The round ID to rollover ETH into.
* @param withdrawalCalldata The rounds and the indices for the rounds for the prizes to claim.
* @param payWithLOOKS Whether to pay for the protocol fee with LOOKS.
*/
function rolloverETH(uint256 roundId, WithdrawalCalldata[] calldata withdrawalCalldata, bool payWithLOOKS) external;

/**
* @notice This function allows the owner to pause/unpause the contract.
*/
function togglePaused() external;

/**
* @notice This function allows the owner to allow/forbid token outflow.
*/
function toggleOutflowAllowed() external;

/**
* @notice This function allows the owner to update token statuses (ERC-20 and ERC-721).
* @param tokens Token addresses
* @param tokenType Token type
* @param isAllowed Whether the tokens should be allowed in the yolos
* @dev Only callable by owner.
*/
function updateTokensStatus(address[] calldata tokens, YoloV2__TokenType tokenType, bool isAllowed) external;

/**
* @notice This function allows the owner to update the duration of each round.
* @param _roundDuration The duration of each round.
*/
function updateRoundDuration(uint40 _roundDuration) external;

/**
* @notice This function allows the owner to update the signature validity period.
* @param _signatureValidityPeriod The signature validity period.
*/
function updateSignatureValidityPeriod(uint40 _signatureValidityPeriod) external;

/**
* @notice This function allows the owner to update the value of each entry in ETH.
* @param _valuePerEntry The value of each entry in ETH.
*/
function updateValuePerEntry(uint96 _valuePerEntry) external;

/**
* @notice This function allows the owner to update the discounted protocol fee in basis points if paid in LOOKS.
* @param discountedProtocolFeeBp The discounted protocol fee in basis points.
*/
function updateDiscountedProtocolFeeBp(uint16 discountedProtocolFeeBp) external;

/**
* @notice This function allows the owner to update the protocol fee in basis points.
* @param protocolFeeBp The protocol fee in basis points.
*/
function updateProtocolFeeBp(uint16 protocolFeeBp) external;

/**
* @notice This function allows the owner to update the protocol fee recipient.
* @param protocolFeeRecipient The protocol fee recipient.
*/
function updateProtocolFeeRecipient(address protocolFeeRecipient) external;

/**
* @notice This function allows the owner to update Reservoir oracle's address.
* @param reservoirOracle Reservoir oracle address.
*/
function updateReservoirOracle(address reservoirOracle) external;

/**
* @notice This function allows the owner to update the maximum number of participants per round.
* @param _maximumNumberOfParticipantsPerRound The maximum number of participants per round.
*/
function updateMaximumNumberOfParticipantsPerRound(uint40 _maximumNumberOfParticipantsPerRound) external;

/**
* @notice This function allows the owner to update ERC20 oracle's address.
* @param erc20Oracle ERC20 oracle address.
*/
function updateERC20Oracle(address erc20Oracle) external;

/**
* @notice This function allows the owner to set the LOOKS token address. Only callable once.
* @param looks LOOKS token address.
*/
function setLOOKS(address looks) external;