Skip to content

Commit

Permalink
feat(tests): add DrawCalculatorV3 unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
PierrickGT committed May 16, 2022
1 parent 8e70edb commit 4615b03
Show file tree
Hide file tree
Showing 5 changed files with 1,557 additions and 32 deletions.
64 changes: 36 additions & 28 deletions contracts/DrawCalculatorV3.sol
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ contract DrawCalculatorV3 is IDrawCalculatorV3, Manageable {
/// @notice DrawBuffer address
IDrawBuffer public immutable drawBuffer;

/// @notice PrizeConfigHistory address
IPrizeConfigHistory public immutable prizeConfigHistory;

/// @notice The tiers array length
uint8 public constant TIERS_LENGTH = 16;

Expand All @@ -42,41 +45,46 @@ contract DrawCalculatorV3 is IDrawCalculatorV3, Manageable {
* @notice Emitted when the contract is initialized
* @param gaugeController Address of the GaugeController
* @param drawBuffer Address of the DrawBuffer
* @param prizeConfigHistory Address of the PrizeConfigHistory
*/
event Deployed(
IGaugeController indexed gaugeController,
IDrawBuffer indexed drawBuffer
IDrawBuffer indexed drawBuffer,
IPrizeConfigHistory indexed prizeConfigHistory
);

/* ============ Constructor ============ */

/**
* @notice DrawCalculator constructor
* @param _gaugeController Address of the GaugeController
* @param _drawBuffer Address of the draw buffer to push draws to
* @param _drawBuffer Address of the DrawBuffer to push draws to
* @param _prizeConfigHistory Address of the PrizeConfigHistory
* @param _owner Address of the owner
*/
constructor(
IGaugeController _gaugeController,
IDrawBuffer _drawBuffer,
IPrizeConfigHistory _prizeConfigHistory,
address _owner
) Ownable(_owner) {
require(address(_gaugeController) != address(0), "DrawCalc/GC-not-zero-address");
require(address(_drawBuffer) != address(0), "DrawCalc/DB-not-zero-address");
require(address(_prizeConfigHistory) != address(0), "DrawCalc/PCH-not-zero-address");
require(_owner != address(0), "DrawCalc/owner-not-zero-address");

gaugeController = _gaugeController;
drawBuffer = _drawBuffer;
prizeConfigHistory = _prizeConfigHistory;

emit Deployed(_gaugeController, _drawBuffer);
emit Deployed(_gaugeController, _drawBuffer, _prizeConfigHistory);
}

/* ============ External Functions ============ */

/// @inheritdoc IDrawCalculatorV3
function calculate(
ITicket _ticket,
IPrizeConfigHistory _prizeConfigHistory,
address _user,
uint32[] calldata _drawIds,
bytes calldata _pickIndicesForDraws
Expand All @@ -89,7 +97,6 @@ contract DrawCalculatorV3 is IDrawCalculatorV3, Manageable {

return _calculatePrizesAwardable(
_ticket,
_prizeConfigHistory,
_user,
_userRandomNumber,
_drawIds,
Expand All @@ -100,7 +107,6 @@ contract DrawCalculatorV3 is IDrawCalculatorV3, Manageable {
/// @inheritdoc IDrawCalculatorV3
function calculateUserPicks(
ITicket _ticket,
IPrizeConfigHistory _prizeConfigHistory,
address _user,
uint32[] calldata _drawIds
) external view override returns (uint64[] memory picks) {
Expand All @@ -110,7 +116,7 @@ contract DrawCalculatorV3 is IDrawCalculatorV3, Manageable {

for (uint32 _drawIndex = 0; _drawIndex < _drawsLength; _drawIndex++) {
IDrawBeacon.Draw memory _draw = _draws[_drawIndex];
IPrizeConfigHistory.PrizeConfig memory _prizeConfig = _prizeConfigHistory.getPrizeConfig(_draw.drawId);
IPrizeConfigHistory.PrizeConfig memory _prizeConfig = prizeConfigHistory.getPrizeConfig(_draw.drawId);

_requireDrawUnexpired(_draw, _prizeConfig);

Expand Down Expand Up @@ -138,6 +144,11 @@ contract DrawCalculatorV3 is IDrawCalculatorV3, Manageable {
return gaugeController;
}

/// @inheritdoc IDrawCalculatorV3
function getPrizeConfigHistory() external override view returns (IPrizeConfigHistory) {
return prizeConfigHistory;
}

/// @inheritdoc IDrawCalculatorV3
function getTotalPicks(
ITicket _ticket,
Expand All @@ -155,7 +166,7 @@ contract DrawCalculatorV3 is IDrawCalculatorV3, Manageable {
/**
* @notice Ensure that the draw is not expired.
* @param _draw Draw
* @param _prizeConfig Prize tier
* @param _prizeConfig PrizeConfig
*/
function _requireDrawUnexpired(
IDrawBeacon.Draw memory _draw,
Expand All @@ -167,15 +178,13 @@ contract DrawCalculatorV3 is IDrawCalculatorV3, Manageable {
/**
* @notice Calculates the prizes awardable for each DrawIds passed.
* @param _ticket Address of the ticket to calculate awardable prizes for
* @param _prizeConfigHistory Address of the prizeConfigHistory associated with the ticket
* @param _user Address of the user for which to calculate awardable prizes for
* @param _userRandomNumber Random number of the user to consider over draws
* @param _drawIds Array of DrawIds for which to calculate awardable prizes for
* @param _pickIndicesForDraws Pick indices for each Draw
*/
function _calculatePrizesAwardable(
ITicket _ticket,
IPrizeConfigHistory _prizeConfigHistory,
address _user,
bytes32 _userRandomNumber,
uint32[] memory _drawIds,
Expand All @@ -190,7 +199,7 @@ contract DrawCalculatorV3 is IDrawCalculatorV3, Manageable {
// Calculate prizes awardable for each Draw passed
for (uint32 _drawIndex = 0; _drawIndex < _draws.length; _drawIndex++) {
IDrawBeacon.Draw memory _draw = _draws[_drawIndex];
IPrizeConfigHistory.PrizeConfig memory _prizeConfig = _prizeConfigHistory.getPrizeConfig(_draw.drawId);
IPrizeConfigHistory.PrizeConfig memory _prizeConfig = prizeConfigHistory.getPrizeConfig(_draw.drawId);

_requireDrawUnexpired(_draw, _prizeConfig);

Expand Down Expand Up @@ -218,7 +227,7 @@ contract DrawCalculatorV3 is IDrawCalculatorV3, Manageable {
}

/**
* @notice Calculates the number of picks a user gets for a Draw, considering the normalized user balance and the PrizeDistribution.
* @notice Calculates the number of picks a user gets for a Draw, considering the normalized user balance and the PrizeConfig.
* @dev Divided by 1e18 since the normalized user balance is stored as a fixed point 18 number.
* @param _ticket Address of the ticket to get total picks for
* @param _startTimestamp Timestamp at which the prize starts
Expand All @@ -239,7 +248,6 @@ contract DrawCalculatorV3 is IDrawCalculatorV3, Manageable {
) internal view returns (uint64) {
uint256 _numberOfPicks = _getTotalPicks(_ticket, _startTimestamp, _endTimestamp, _poolStakeCeiling, _bitRange, _cardinality);
uint256 _normalizedBalance = _getNormalizedBalanceAt(_ticket, _user, _startTimestamp, _endTimestamp);

return uint64((_normalizedBalance * _numberOfPicks) / 1 ether);
}

Expand Down Expand Up @@ -307,12 +315,12 @@ contract DrawCalculatorV3 is IDrawCalculatorV3, Manageable {
}

/**
* @notice Calculates the prize amount for a PrizeDistribution over given picks
* @param _winningRandomNumber Draw's winningRandomNumber
* @param _totalUserPicks number of picks the user gets for the Draw
* @param _userRandomNumber users randomNumber for that draw
* @param _picks users picks for that draw
* @param _prizeConfig PrizeConfig for that draw
* @notice Calculates the prize amount for a PrizeConfig over given picks
* @param _winningRandomNumber Draw's winningRandomNumber
* @param _totalUserPicks Number of picks the user gets for the Draw
* @param _userRandomNumber User randomNumber for that draw
* @param _picks User picks for that draw
* @param _prizeConfig PrizeConfig for that draw
* @return prize (if any), prizeCounts (if any)
*/
function _calculate(
Expand All @@ -321,8 +329,8 @@ contract DrawCalculatorV3 is IDrawCalculatorV3, Manageable {
bytes32 _userRandomNumber,
uint64[] memory _picks,
IPrizeConfigHistory.PrizeConfig memory _prizeConfig
) internal pure returns (uint256 prize, uint256[] memory prizeCounts) {
// Create bitmasks for the PrizeDistribution
) internal view returns (uint256 prize, uint256[] memory prizeCounts) {
// Create bitmasks for the PrizeConfig
uint256[] memory masks = _createBitMasks(_prizeConfig.matchCardinality, _prizeConfig.bitRangeSize);
uint32 picksLength = uint32(_picks.length);
uint256[] memory _prizeCounts = new uint256[](_prizeConfig.tiers.length);
Expand All @@ -334,7 +342,7 @@ contract DrawCalculatorV3 is IDrawCalculatorV3, Manageable {
"DrawCalc/exceeds-max-user-picks"
);

// for each pick, find number of matching numbers and calculate prize distributions index
// for each pick, find number of matching numbers and calculate prize configs index
for (uint32 index = 0; index < picksLength; index++) {
require(_picks[index] < _totalUserPicks, "DrawCalc/insufficient-user-picks");

Expand Down Expand Up @@ -399,7 +407,7 @@ contract DrawCalculatorV3 is IDrawCalculatorV3, Manageable {
* @notice Calculates the tier index given the random numbers and masks
* @param _randomNumberThisPick User random number for this Pick
* @param _winningRandomNumber The winning number for this draw
* @param _masks The pre-calculated bitmasks for the prizeDistributions
* @param _masks The pre-calculated bitmasks for the PrizeConfig
* @return The position within the prize tier array (0 = top prize, 1 = runner-up prize, etc)
*/
function _calculateTierIndex(
Expand Down Expand Up @@ -431,7 +439,7 @@ contract DrawCalculatorV3 is IDrawCalculatorV3, Manageable {
}

/**
* @notice Creates an array of bitmasks equal to the PrizeDistribution.matchCardinality length
* @notice Creates an array of bitmasks equal to the PrizeConfig.matchCardinality length
* @param _matchCardinality Match cardinality for Draw
* @param _bitRangeSize Bit range size for Draw
* @return Array of bitmasks
Expand All @@ -453,8 +461,8 @@ contract DrawCalculatorV3 is IDrawCalculatorV3, Manageable {
}

/**
* @notice Calculates the expected prize fraction per PrizeDistributions and distributionIndex
* @param _prizeFraction Prize fraction for this PrizeDistribution
* @notice Calculates the expected prize fraction per PrizeConfig and prize tiers index
* @param _prizeFraction Prize fraction for this PrizeConfig
* @param _bitRangeSize Bit range size for Draw
* @param _prizeConfigIndex Index of the prize tiers array to calculate
* @return returns the fraction of the total prize (fixed point 9 number)
Expand All @@ -474,9 +482,9 @@ contract DrawCalculatorV3 is IDrawCalculatorV3, Manageable {
}

/**
* @notice Calculates the number of prizes for a given prizeDistributionIndex
* @notice Calculates the number of prizes for a given PrizeConfigIndex
* @param _bitRangeSize Bit range size for Draw
* @param _prizeConfigIndex Index of the prize config array to calculate
* @param _prizeConfigIndex Index of the PrizeConfig array to calculate
* @return returns the fraction of the total prize (base 1e18)
*/
function _numberOfPrizesForIndex(uint8 _bitRangeSize, uint256 _prizeConfigIndex)
Expand Down
10 changes: 6 additions & 4 deletions contracts/interfaces/IDrawCalculatorV3.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ interface IDrawCalculatorV3 {
/**
* @notice Calculates the awardable prizes for a user for Multiple Draws. Typically called by a PrizeDistributor.
* @param ticket Address of the ticket to calculate awardable prizes for
* @param prizeConfigHistory Address of the prizeConfigHistory associated with the ticket
* @param user Address of the user for which to calculate awardable prizes for
* @param drawIds Array of DrawIds for which to calculate awardable prizes for
* @param data ABI encoded pick indices for all Draws. Expected to be winning picks. Pick indices must be less than the totalUserPicks.
Expand All @@ -25,7 +24,6 @@ interface IDrawCalculatorV3 {
*/
function calculate(
ITicket ticket,
IPrizeConfigHistory prizeConfigHistory,
address user,
uint32[] calldata drawIds,
bytes calldata data
Expand All @@ -34,13 +32,11 @@ interface IDrawCalculatorV3 {
/**
* @notice Calculates picks for a user for Multiple Draws.
* @param ticket Address of the ticket to calculate picks for
* @param prizeConfigHistory Address of the prizeConfigHistory associated with the ticket
* @param user Address of the user for which to calculate picks for
* @param drawIds Array of DrawIds for which to calculate picks for
*/
function calculateUserPicks(
ITicket ticket,
IPrizeConfigHistory prizeConfigHistory,
address user,
uint32[] calldata drawIds
) external view returns (uint64[] memory);
Expand All @@ -57,6 +53,12 @@ interface IDrawCalculatorV3 {
*/
function getGaugeController() external view returns (IGaugeController);

/**
* @notice Returns PrizeConfigHistory address.
* @return The PrizeConfigHistory address
*/
function getPrizeConfigHistory() external view returns (IPrizeConfigHistory);

/**
* @notice Returns the total number of picks for a prize pool / ticket.
* @param ticket Address of the ticket to get total picks for
Expand Down
46 changes: 46 additions & 0 deletions contracts/test/DrawCalculatorV3Harness.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// SPDX-License-Identifier: GPL-3.0

pragma solidity 0.8.6;

import "../DrawCalculatorV3.sol";

contract DrawCalculatorV3Harness is DrawCalculatorV3 {
constructor(
IGaugeController _gaugeController,
IDrawBuffer _drawBuffer,
IPrizeConfigHistory _prizeConfigHistory,
address _owner
) DrawCalculatorV3(_gaugeController, _drawBuffer, _prizeConfigHistory, _owner) {}

function calculateTierIndex(
uint256 _randomNumberThisPick,
uint256 _winningRandomNumber,
uint256[] memory _masks
) public pure returns (uint256) {
return _calculateTierIndex(_randomNumberThisPick, _winningRandomNumber, _masks);
}

function createBitMasks(uint8 _matchCardinality, uint8 _bitRangeSize)
public
pure
returns (uint256[] memory)
{
return _createBitMasks(_matchCardinality, _bitRangeSize);
}

function calculatePrizeTierFraction(
uint256 _prizeFraction,
uint8 _bitRangeSize,
uint256 _prizeConfigIndex
) external pure returns (uint256) {
return _calculatePrizeTierFraction(_prizeFraction, _bitRangeSize, _prizeConfigIndex);
}

function numberOfPrizesForIndex(uint8 _bitRangeSize, uint256 _prizeConfigIndex)
external
pure
returns (uint256)
{
return _numberOfPrizesForIndex(_bitRangeSize, _prizeConfigIndex);
}
}

0 comments on commit 4615b03

Please sign in to comment.