Skip to content

Commit

Permalink
Merge pull request #70 from GenerationSoftware/gen-700-prevent-reserv…
Browse files Browse the repository at this point in the history
…e-from-changing-after-draw-auctions-start

revert claims made while open draw is closing
  • Loading branch information
trmid authored Sep 25, 2023
2 parents 17ad8cc + 6c9b2be commit 2785fcc
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 3 deletions.
9 changes: 9 additions & 0 deletions src/PrizePool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@ error PrizeIsZero();
/// @notice Emitted when someone tries to claim a prize, but sets the fee recipient address to the zero address.
error FeeRecipientZeroAddress();

/// @notice Emitted when a claim is attempted after the claiming period has expired.
error ClaimPeriodExpired();

/**
* @notice Constructor Parameters
* @param prizeToken The token to use for prizes
Expand Down Expand Up @@ -426,6 +429,12 @@ contract PrizePool is TieredLiquidityDistributor, Ownable {
uint96 _fee,
address _feeRecipient
) external returns (uint256) {
/// @dev Claims cannot occur after the draw auctions have begun for the open draw since a claim might dip into
/// the reserve and cause auction results to be inaccurate. By limiting the claim period to 1 period after the
/// draw ends, we provide a predictable environment for draw auctions to operate in.
if (block.timestamp >= _openDrawEndsAt()) {
revert ClaimPeriodExpired();
}
if (_feeRecipient == address(0) && _fee > 0) {
revert FeeRecipientZeroAddress();
}
Expand Down
50 changes: 47 additions & 3 deletions test/PrizePool.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { TwabController } from "pt-v5-twab-controller/TwabController.sol";

import { TierCalculationLib } from "../src/libraries/TierCalculationLib.sol";
import { MAXIMUM_NUMBER_OF_TIERS, MINIMUM_NUMBER_OF_TIERS } from "../src/abstract/TieredLiquidityDistributor.sol";
import { PrizePool, PrizeIsZero, ConstructorParams, InsufficientRewardsError, DidNotWin, FeeTooLarge, SmoothingGTEOne, ContributionGTDeltaBalance, InsufficientReserve, RandomNumberIsZero, DrawNotFinished, InvalidPrizeIndex, NoClosedDraw, InvalidTier, DrawManagerIsZeroAddress, CallerNotDrawManager, NotDeployer, FeeRecipientZeroAddress, FirstDrawStartsInPast, IncompatibleTwabPeriodLength, IncompatibleTwabPeriodOffset } from "../src/PrizePool.sol";
import { PrizePool, PrizeIsZero, ConstructorParams, InsufficientRewardsError, DidNotWin, FeeTooLarge, SmoothingGTEOne, ContributionGTDeltaBalance, InsufficientReserve, RandomNumberIsZero, DrawNotFinished, InvalidPrizeIndex, NoClosedDraw, InvalidTier, DrawManagerIsZeroAddress, CallerNotDrawManager, NotDeployer, FeeRecipientZeroAddress, FirstDrawStartsInPast, IncompatibleTwabPeriodLength, IncompatibleTwabPeriodOffset, ClaimPeriodExpired } from "../src/PrizePool.sol";
import { ERC20Mintable } from "./mocks/ERC20Mintable.sol";

contract PrizePoolTest is Test {
Expand Down Expand Up @@ -855,6 +855,40 @@ contract PrizePoolTest is Test {
prizePool.claimPrize(winner, 1, 0, winner, 0, address(this));
}

function testClaimPrize_ClaimPeriodExpired() public {
contribute(100e18);
closeDraw(winningRandomNumber);
address winner = makeAddr("winner");
mockTwab(address(this), winner, 1);
uint periodStart = prizePool.openDrawStartedAt();

// warp to end of open draw (end of claim period)
vm.warp(periodStart + drawPeriodSeconds);
vm.expectRevert(abi.encodeWithSelector(ClaimPeriodExpired.selector));
prizePool.claimPrize(winner, 1, 0, winner, 0, address(this));

// warp to end of open draw (end of claim period) + 1 sec
vm.warp(periodStart + drawPeriodSeconds + 1);
vm.expectRevert(abi.encodeWithSelector(ClaimPeriodExpired.selector));
prizePool.claimPrize(winner, 1, 0, winner, 0, address(this));

// warp to right before end of open draw (end of claim period)
vm.warp(periodStart + drawPeriodSeconds - 1);
vm.expectEmit();
emit ClaimedPrize(
address(this),
winner,
winner,
1,
1,
0,
uint152(prizePool.getTierPrizeSize(1)),
0,
address(this)
);
prizePool.claimPrize(winner, 1, 0, winner, 0, address(this));
}

function testClaimPrize_single() public {
contribute(100e18);
closeDraw(winningRandomNumber);
Expand Down Expand Up @@ -997,7 +1031,7 @@ contract PrizePoolTest is Test {
function testClaimPrize_claimFeesAccountedFor() public {
contribute(100e18);
closeDraw(winningRandomNumber);

address winner = makeAddr("winner");
address recipient = makeAddr("recipient");
mockTwab(address(this), winner, 1);
Expand All @@ -1008,7 +1042,17 @@ contract PrizePoolTest is Test {
assertApproxEqAbs(prizeAmount, (10e18 * TIER_SHARES) / (4 * prizePool.getTotalShares()), 100);

vm.expectEmit();
emit ClaimedPrize(address(this), winner, recipient, 1, 1, 0, uint152(prize), fee, address(this));
emit ClaimedPrize(
address(this),
winner,
recipient,
1,
1,
0,
uint152(prize),
fee,
address(this)
);
assertEq(prizePool.claimPrize(winner, 1, 0, recipient, fee, address(this)), prizeAmount);
assertEq(prizeToken.balanceOf(recipient), prize, "recipient balance is good");
assertEq(prizePool.claimCount(), 1);
Expand Down

0 comments on commit 2785fcc

Please sign in to comment.