Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(tests): add DrawCalculatorV3 and PrizeConfigHistory unit tests #265

Merged
merged 3 commits into from
May 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 45 additions & 40 deletions contracts/DrawCalculatorV3.sol
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ contract DrawCalculatorV3 is IDrawCalculatorV3, Manageable {

/// @notice DrawBuffer address
IDrawBuffer public immutable drawBuffer;


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

/// @notice The tiers array length
Expand All @@ -44,20 +45,23 @@ 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,
Expand All @@ -66,13 +70,14 @@ contract DrawCalculatorV3 is IDrawCalculatorV3, Manageable {
) 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 ============ */
Expand All @@ -92,7 +97,6 @@ contract DrawCalculatorV3 is IDrawCalculatorV3, Manageable {

return _calculatePrizesAwardable(
_ticket,
prizeConfigHistory,
_user,
_userRandomNumber,
_drawIds,
Expand All @@ -103,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 @@ -113,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 @@ -141,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 @@ -158,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 @@ -170,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 @@ -193,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 @@ -221,15 +227,15 @@ 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.
* @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
* @param _endTimestamp Timestamp at which the prize ends
* @param _poolStakeCeiling Globally configured pool stake ceiling
* @param _bitRange Number of bits allocated to each division
* @param _cardinality Number of sub-divisions of a random number
* @return Number of picks a user gets for a Draw
* @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
* @param _endTimestamp Timestamp at which the prize ends
* @param _poolStakeCeiling Globally configured pool stake ceiling
* @param _bitRange Number of bits allocated to each division
* @param _cardinality Number of sub-divisions of a random number
* @return Number of picks a user gets for a Draw
*/
function _calculateUserPicks(
ITicket _ticket,
Expand All @@ -242,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 @@ -310,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 @@ -325,7 +330,7 @@ contract DrawCalculatorV3 is IDrawCalculatorV3, Manageable {
uint64[] memory _picks,
IPrizeConfigHistory.PrizeConfig memory _prizeConfig
) internal pure returns (uint256 prize, uint256[] memory prizeCounts) {
// Create bitmasks for the PrizeDistribution
// 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 @@ -337,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,11 +404,11 @@ 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
* @return The position within the prize tier array (0 = top prize, 1 = runner-up prize, etc)
* @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 PrizeConfig
* @return The position within the prize tier array (0 = top prize, 1 = runner-up prize, etc)
*/
function _calculateTierIndex(
uint256 _randomNumberThisPick,
Expand Down Expand Up @@ -434,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 @@ -456,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 @@ -477,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
9 changes: 4 additions & 5 deletions contracts/PrizeConfigHistory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -147,17 +147,16 @@ contract PrizeConfigHistory is IPrizeConfigHistory, Manageable {
* @param _prizeConfig New PrizeConfig struct to push onto history array
*/
function _push(PrizeConfig memory _prizeConfig) internal {
uint32 _historyLength = uint32(history.length);
uint256 _historyLength = history.length;

if (_historyLength > 0) {
// TODO: Check if cheaper in gas to only cast to uint32 below
uint32 _id = history[_historyLength - 1];
uint256 _id = history[uint32(_historyLength - 1)];

require(_prizeConfig.drawId > _id, "PrizeConfHistory/nonsequentialId");
require(_prizeConfig.drawId > uint32(_id), "PrizeConfHistory/nonsequentialId");
}

history.push(_prizeConfig.drawId);
prizeConfigs[_historyLength] = _prizeConfig;
prizeConfigs[uint32(_historyLength)] = _prizeConfig;

emit PrizeConfigPushed(_prizeConfig.drawId, _prizeConfig);
}
Expand Down
8 changes: 6 additions & 2 deletions contracts/interfaces/IDrawCalculatorV3.sol
Original file line number Diff line number Diff line change
Expand Up @@ -32,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 @@ -55,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
Loading