Skip to content

Commit

Permalink
fix(constructor): check params first
Browse files Browse the repository at this point in the history
  • Loading branch information
PierrickGT committed Sep 7, 2023
1 parent 9cc9664 commit be60b32
Show file tree
Hide file tree
Showing 12 changed files with 171 additions and 189 deletions.
2 changes: 1 addition & 1 deletion .solhint.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"plugins": ["prettier"],
"rules": {
"avoid-low-level-calls": "off",
"compiler-version": ["error", "0.8.17"],
"compiler-version": ["error", "0.8.19"],
"func-visibility": "off",
"no-empty-blocks": "off",
"no-inline-assembly": "off"
Expand Down
33 changes: 13 additions & 20 deletions src/PrizePool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,7 @@ import { TwabController } from "pt-v5-twab-controller/TwabController.sol";

import { UD34x4 } from "./libraries/UD34x4.sol";
import { DrawAccumulatorLib, Observation } from "./libraries/DrawAccumulatorLib.sol";
import {
TieredLiquidityDistributor,
Tier,
MAXIMUM_NUMBER_OF_TIERS,
MINIMUM_NUMBER_OF_TIERS
} from "./abstract/TieredLiquidityDistributor.sol";
import { TieredLiquidityDistributor, Tier, MAXIMUM_NUMBER_OF_TIERS, MINIMUM_NUMBER_OF_TIERS } from "./abstract/TieredLiquidityDistributor.sol";
import { TierCalculationLib } from "./libraries/TierCalculationLib.sol";

/// @notice Emitted when the prize pool is constructed with a draw start that is in the past
Expand Down Expand Up @@ -277,18 +272,12 @@ contract PrizePool is TieredLiquidityDistributor, Ownable {
revert FirstDrawStartsInPast();
}

prizeToken = params.prizeToken;
twabController = params.twabController;
smoothing = params.smoothing;
drawPeriodSeconds = params.drawPeriodSeconds;
_lastClosedDrawStartedAt = params.firstDrawStartsAt;
firstDrawStartsAt = params.firstDrawStartsAt;

uint48 twabPeriodOffset = params.twabController.PERIOD_OFFSET();
uint48 twabPeriodLength = params.twabController.PERIOD_LENGTH();

if (params.drawPeriodSeconds < twabPeriodLength ||
params.drawPeriodSeconds % twabPeriodLength != 0
if (
params.drawPeriodSeconds < twabPeriodLength ||
params.drawPeriodSeconds % twabPeriodLength != 0
) {
revert IncompatibleTwabPeriodLength();
}
Expand All @@ -297,6 +286,12 @@ contract PrizePool is TieredLiquidityDistributor, Ownable {
revert IncompatibleTwabPeriodOffset();
}

prizeToken = params.prizeToken;
twabController = params.twabController;
smoothing = params.smoothing;
drawPeriodSeconds = params.drawPeriodSeconds;
_lastClosedDrawStartedAt = params.firstDrawStartsAt;
firstDrawStartsAt = params.firstDrawStartsAt;
}

/* ============ Modifiers ============ */
Expand Down Expand Up @@ -727,12 +722,10 @@ contract PrizePool is TieredLiquidityDistributor, Ownable {
_checkValidTier(_tier, _numberOfTiers);
endTimestamp = _lastClosedDrawStartedAt + drawPeriodSeconds;
SD59x18 tierOdds = _tierOdds(_tier, _numberOfTiers);
uint256 durationInSeconds = TierCalculationLib.estimatePrizeFrequencyInDraws(tierOdds) * drawPeriodSeconds;
uint256 durationInSeconds = TierCalculationLib.estimatePrizeFrequencyInDraws(tierOdds) *
drawPeriodSeconds;

startTimestamp = uint64(
endTimestamp -
durationInSeconds
);
startTimestamp = uint64(endTimestamp - durationInSeconds);
}

/**
Expand Down
47 changes: 28 additions & 19 deletions src/abstract/TieredLiquidityDistributor.sol
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ uint8 constant MAXIMUM_NUMBER_OF_TIERS = 10;
/// @author PoolTogether Inc.
/// @notice A contract that distributes liquidity according to PoolTogether V5 distribution rules.
contract TieredLiquidityDistributor {

/* ============ Events ============ */

/// @notice Emitted when the reserve is consumed due to insufficient prize liquidity.
Expand Down Expand Up @@ -109,7 +108,7 @@ contract TieredLiquidityDistributor {
uint32 internal immutable ESTIMATED_PRIZES_PER_DRAW_FOR_10_TIERS;

/// @notice The Tier liquidity data.
mapping (uint8 => Tier) internal _tiers;
mapping(uint8 => Tier) internal _tiers;

/// @notice The frequency of the grand prize
uint24 public immutable grandPrizePeriodDraws;
Expand Down Expand Up @@ -138,7 +137,12 @@ contract TieredLiquidityDistributor {
* @param _tierShares The number of shares to allocate to each tier
* @param _reserveShares The number of shares to allocate to the reserve.
*/
constructor(uint8 _numberOfTiers, uint8 _tierShares, uint8 _reserveShares, uint24 _grandPrizePeriodDraws) {
constructor(
uint8 _numberOfTiers,
uint8 _tierShares,
uint8 _reserveShares,
uint24 _grandPrizePeriodDraws
) {
if (_numberOfTiers < MINIMUM_NUMBER_OF_TIERS) {
revert NumberOfTiersLessThanMinimum(_numberOfTiers);
}
Expand Down Expand Up @@ -212,7 +216,6 @@ contract TieredLiquidityDistributor {
ESTIMATED_PRIZES_PER_DRAW_FOR_8_TIERS = _sumTierPrizeCounts(8);
ESTIMATED_PRIZES_PER_DRAW_FOR_9_TIERS = _sumTierPrizeCounts(9);
ESTIMATED_PRIZES_PER_DRAW_FOR_10_TIERS = _sumTierPrizeCounts(10);

}

/// @notice Adjusts the number of tiers and distributes new liquidity.
Expand Down Expand Up @@ -253,7 +256,12 @@ contract TieredLiquidityDistributor {
_tiers[i] = Tier({
drawId: closedDrawId,
prizeTokenPerShare: _prizeTokenPerShare,
prizeSize: _computePrizeSize(i, _nextNumberOfTiers, _prizeTokenPerShareUD60x18, newPrizeTokenPerShare)
prizeSize: _computePrizeSize(
i,
_nextNumberOfTiers,
_prizeTokenPerShareUD60x18,
newPrizeTokenPerShare
)
});
}

Expand Down Expand Up @@ -308,17 +316,16 @@ contract TieredLiquidityDistributor {

uint256 totalNewLiquidity = _prizeTokenLiquidity + reclaimedLiquidity;
uint256 nextTotalShares = _getTotalShares(_nextNumberOfTiers);
UD60x18 deltaPrizeTokensPerShare = (convert(totalNewLiquidity).div(convert(nextTotalShares))).floor();
UD60x18 deltaPrizeTokensPerShare = (convert(totalNewLiquidity).div(convert(nextTotalShares)))
.floor();

newPrizeTokenPerShare = _currentPrizeTokenPerShare.add(deltaPrizeTokensPerShare);

newReserve = SafeCast.toUint96(
// reserve portion of new liquidity
convert(deltaPrizeTokensPerShare.mul(convert(reserveShares))) +
// remainder left over from shares
(
totalNewLiquidity - convert(deltaPrizeTokensPerShare.mul(convert(nextTotalShares)))
)
// remainder left over from shares
(totalNewLiquidity - convert(deltaPrizeTokensPerShare.mul(convert(nextTotalShares))))
);
}

Expand Down Expand Up @@ -372,10 +379,7 @@ contract TieredLiquidityDistributor {
/// @param _numberOfTiers The number of tiers to calculate the total shares for
/// @return The total shares
function _getTotalShares(uint8 _numberOfTiers) internal view returns (uint256) {
return
uint256(_numberOfTiers) *
uint256(tierShares) +
uint256(reserveShares);
return uint256(_numberOfTiers) * uint256(tierShares) + uint256(reserveShares);
}

/// @notice Consumes liquidity from the given tier.
Expand Down Expand Up @@ -439,7 +443,9 @@ contract TieredLiquidityDistributor {
bool canExpand = _numberOfTiers < MAXIMUM_NUMBER_OF_TIERS;
if (canExpand && _isCanaryTier(_tier, _numberOfTiers)) {
// make canary prizes smaller to account for reduction in shares for next number of tiers
prizeSize = (prizeSize * _getTotalShares(_numberOfTiers)) / _getTotalShares(_numberOfTiers + 1);
prizeSize =
(prizeSize * _getTotalShares(_numberOfTiers)) /
_getTotalShares(_numberOfTiers + 1);
}
}
if (prizeSize > type(uint104).max) {
Expand Down Expand Up @@ -575,7 +581,9 @@ contract TieredLiquidityDistributor {
/// @notice Estimates the prize count for the given tier.
/// @param numTiers The number of prize tiers
/// @return The estimated total number of prizes
function _estimatePrizeCountPerDrawUsingNumberOfTiers(uint8 numTiers) internal view returns (uint32) {
function _estimatePrizeCountPerDrawUsingNumberOfTiers(
uint8 numTiers
) internal view returns (uint32) {
if (numTiers == 3) {
return ESTIMATED_PRIZES_PER_DRAW_FOR_3_TIERS;
} else if (numTiers == 4) {
Expand All @@ -600,7 +608,9 @@ contract TieredLiquidityDistributor {
/// @dev Can return lower than the minimum, so that minimum can be detected
/// @param _prizeCount The number of prizes that were claimed
/// @return The estimated tier
function _estimateNumberOfTiersUsingPrizeCountPerDraw(uint32 _prizeCount) internal view returns (uint8) {
function _estimateNumberOfTiersUsingPrizeCountPerDraw(
uint32 _prizeCount
) internal view returns (uint8) {
// the prize count is slightly more than 4x for each higher tier. i.e. 16, 66, 270, 1108, etc
// by doubling the measured count, we create a safe margin for error.
uint32 _adjustedPrizeCount = _prizeCount * 2;
Expand Down Expand Up @@ -642,8 +652,7 @@ contract TieredLiquidityDistributor {
do {
prizeCount += TierCalculationLib.tierPrizeCountPerDraw(i, _tierOdds(i, _numTiers));
i++;
}
while (i < _numTiers);
} while (i < _numTiers);
return prizeCount;
}

Expand Down
2 changes: 1 addition & 1 deletion src/libraries/DrawAccumulatorLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ library DrawAccumulatorLib {
struct Accumulator {
RingBufferInfo ringBufferInfo;
uint24[366] drawRingBuffer;
mapping (uint256 => Observation) observations;
mapping(uint256 => Observation) observations;
}

/// @notice A pair of uint24s.
Expand Down
38 changes: 15 additions & 23 deletions src/libraries/TierCalculationLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,10 @@ library TierCalculationLib {
uint8 _numberOfTiers,
uint24 _grandPrizePeriod
) internal pure returns (SD59x18) {
return sd(1).div(
sd(int24(_grandPrizePeriod))
).pow(
sd(
int8(_tier) - (int8(_numberOfTiers) - 1)
).div(
sd((-1 * int8(_numberOfTiers) + 1))
)
);
return
sd(1).div(sd(int24(_grandPrizePeriod))).pow(
sd(int8(_tier) - (int8(_numberOfTiers) - 1)).div(sd((-1 * int8(_numberOfTiers) + 1)))
);
}

/// @notice Estimates the number of draws between a tier occurring.
Expand Down Expand Up @@ -73,7 +68,10 @@ library TierCalculationLib {
- Portion of prize that was contributed by the vault
*/
// first constrain the random number to be within the vault total supply
uint256 constrainedRandomNumber = UniformRandomNumber.uniform(_userSpecificRandomNumber, _vaultTwabTotalSupply);
uint256 constrainedRandomNumber = UniformRandomNumber.uniform(
_userSpecificRandomNumber,
_vaultTwabTotalSupply
);
uint256 winningZone = calculateWinningZone(_userTwab, _vaultContributionFraction, _tierOdds);

return constrainedRandomNumber < winningZone;
Expand All @@ -95,7 +93,10 @@ library TierCalculationLib {
uint32 _prizeIndex,
uint256 _winningRandomNumber
) internal pure returns (uint256) {
return uint256(keccak256(abi.encode(_drawId, _vault, _user, _tier, _prizeIndex, _winningRandomNumber)));
return
uint256(
keccak256(abi.encode(_drawId, _vault, _user, _tier, _prizeIndex, _winningRandomNumber))
);
}

/// @notice Calculates the winning zone for a user. If their pseudo-random number falls within this zone, they win the tier.
Expand All @@ -109,24 +110,15 @@ library TierCalculationLib {
SD59x18 _tierOdds
) internal pure returns (uint256) {
return
uint256(
convert(convert(int256(_userTwab)).mul(_tierOdds).mul(_vaultContributionFraction))
);
uint256(convert(convert(int256(_userTwab)).mul(_tierOdds).mul(_vaultContributionFraction)));
}

/// @notice Computes the estimated number of prizes per draw for a given tier and tier odds.
/// @param _tier The tier
/// @param _odds The odds of the tier occurring for the draw
/// @return The estimated number of prizes per draw for the given tier and tier odds
function tierPrizeCountPerDraw(
uint8 _tier,
SD59x18 _odds
) internal pure returns (uint32) {
return uint32(
uint256(
unwrap(sd(int256(prizeCount(_tier))).mul(_odds))
)
);
function tierPrizeCountPerDraw(uint8 _tier, SD59x18 _odds) internal pure returns (uint32) {
return uint32(uint256(unwrap(sd(int256(prizeCount(_tier))).mul(_odds))));
}

/// @notice Checks whether a tier is a valid tier
Expand Down
Loading

0 comments on commit be60b32

Please sign in to comment.