Skip to content

Commit

Permalink
Merge pull request #92 from GenerationSoftware/gen-1081-add-ability-t…
Browse files Browse the repository at this point in the history
…o-contribute-prizes-to-prize-pool

Added ability to donate to the prizes
  • Loading branch information
asselstine authored Feb 19, 2024
2 parents 550d1d1 + 53efe95 commit f23f668
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 2 deletions.
36 changes: 34 additions & 2 deletions src/PrizePool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,9 @@ contract PrizePool is TieredLiquidityDistributor {
/// @notice Records the last shutdown withdrawal for an account
mapping(address vault => mapping(address user => uint24 drawId)) internal _lastShutdownWithdrawal;

/// @notice The special value for the donator address. Contributions from this address are excluded from the total odds. F2EE because it's free money!
address public constant DONATOR = 0x000000000000000000000000000000000000F2EE;

/// @notice The token that is being contributed and awarded as prizes.
IERC20 public immutable prizeToken;

Expand Down Expand Up @@ -333,7 +336,7 @@ contract PrizePool is TieredLiquidityDistributor {
/// @param _prizeVault The address of the vault to contribute to
/// @param _amount The amount of prize tokens to contribute
/// @return The amount of available prize tokens prior to the contribution.
function contributePrizeTokens(address _prizeVault, uint256 _amount) external returns (uint256) {
function contributePrizeTokens(address _prizeVault, uint256 _amount) public returns (uint256) {
uint256 _deltaBalance = prizeToken.balanceOf(address(this)) - accountedBalance();
if (_deltaBalance < _amount) {
revert ContributionGTDeltaBalance(_amount, _deltaBalance);
Expand All @@ -345,6 +348,13 @@ contract PrizePool is TieredLiquidityDistributor {
return _deltaBalance;
}

/// @notice Allows a user to donate prize tokens to the prize pool.
/// @param _amount The amount of tokens to donate. The amount should already be approved for transfer.
function donatePrizeTokens(uint256 _amount) external {
prizeToken.transferFrom(msg.sender, address(this), _amount);
contributePrizeTokens(DONATOR, _amount);
}

/// @notice Allows the Manager to allocate a reward from the reserve to a recipient.
/// @param _to The address to allocate the rewards to
/// @param _amount The amount of tokens for the reward
Expand Down Expand Up @@ -578,6 +588,22 @@ contract PrizePool is TieredLiquidityDistributor {
);
}

/// @notice Returns the total prize tokens donated to the prize pool
/// @param _startDrawIdInclusive Start draw id inclusive
/// @param _endDrawIdInclusive End draw id inclusive
/// @return The total prize tokens donated to the prize pool
function getDonatedBetween(
uint24 _startDrawIdInclusive,
uint24 _endDrawIdInclusive
) external view returns (uint256) {
return
DrawAccumulatorLib.getDisbursedBetween(
_vaultAccumulator[DONATOR],
_startDrawIdInclusive,
_endDrawIdInclusive
);
}

/// @notice Computes the expected duration prize accrual for a tier.
/// @param _tier The tier to check
/// @return The number of draws
Expand Down Expand Up @@ -944,12 +970,18 @@ contract PrizePool is TieredLiquidityDistributor {
uint24 _startDrawIdInclusive,
uint24 _endDrawIdInclusive
) public view returns (SD59x18) {
if (_vault == DONATOR) {
return sd(0);
}

uint256 totalContributed = DrawAccumulatorLib.getDisbursedBetween(
_totalAccumulator,
_startDrawIdInclusive,
_endDrawIdInclusive
);

uint256 totalDonated = DrawAccumulatorLib.getDisbursedBetween(_vaultAccumulator[DONATOR], _startDrawIdInclusive, _endDrawIdInclusive);

// vaultContributed / totalContributed
return
totalContributed != 0
Expand All @@ -961,7 +993,7 @@ contract PrizePool is TieredLiquidityDistributor {
_endDrawIdInclusive
)
)
).div(sd(SafeCast.toInt256(totalContributed)))
).div(sd(SafeCast.toInt256(totalContributed - totalDonated)))
: sd(0);
}

Expand Down
42 changes: 42 additions & 0 deletions test/PrizePool.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,26 @@ contract PrizePoolTest is Test {
prizePool.contributePrizeTokens(address(this), 100);
}

function testDonatePrizeTokens() public {
prizeToken.mint(address(this), 100);
prizeToken.approve(address(prizePool), 100);
prizePool.donatePrizeTokens(100);
assertEq(prizeToken.balanceOf(address(prizePool)), 100);
assertEq(prizePool.getTotalContributedBetween(1, 1), 100);
assertEq(prizePool.getDonatedBetween(1,1), 100);
}

function testDonatePrizeTokens_twice() public {
prizeToken.mint(address(this), 100);
prizeToken.approve(address(prizePool), 100);
prizePool.donatePrizeTokens(50);
awardDraw(winningRandomNumber);
prizePool.donatePrizeTokens(50);
assertEq(prizeToken.balanceOf(address(prizePool)), 100);
assertEq(prizePool.getTotalContributedBetween(1, 2), 100);
assertEq(prizePool.getDonatedBetween(1, 2), 100);
}

function testAccountedBalance_withdrawnReserve() public {
contribute(100e18);
awardDraw(1);
Expand Down Expand Up @@ -425,6 +445,11 @@ contract PrizePoolTest is Test {
assertEq(prizePool.accountedBalance(), 100e18 - prize - prize2, "accounted balance");
}

function testGetVaultPortion_fromDonator() public {
contribute(100e18, prizePool.DONATOR()); // available draw 1
assertEq(SD59x18.unwrap(prizePool.getVaultPortion(prizePool.DONATOR(), 1, 1)), 0);
}

function testGetVaultPortion_WhenEmpty() public {
assertEq(SD59x18.unwrap(prizePool.getVaultPortion(address(this), 0, 0)), 0);
}
Expand Down Expand Up @@ -476,6 +501,23 @@ contract PrizePoolTest is Test {
assertEq(SD59x18.unwrap(prizePool.getVaultPortion(address(this), 0, 2)), 1e18);
}

function testGetVaultPortion_ignoresDonations() public {
// contribute to vault1
prizeToken.mint(address(prizePool), 100);
prizePool.contributePrizeTokens(address(vault), 100);

// contribute to vault2
prizeToken.mint(address(prizePool), 100);
prizePool.contributePrizeTokens(address(vault2), 100);

prizeToken.mint(address(this), 100);
prizeToken.approve(address(prizePool), 100);
prizePool.donatePrizeTokens(100);

assertEq(prizePool.getVaultPortion(address(vault), 1, 1).unwrap(), 0.5e18);
assertEq(prizePool.getVaultPortion(address(vault2), 1, 1).unwrap(), 0.5e18);
}

function testGetOpenDrawId() public {
uint256 openDrawId = prizePool.getOpenDrawId();
assertEq(openDrawId, 1);
Expand Down
11 changes: 11 additions & 0 deletions test/invariants/helpers/PrizePoolFuzzHarness.sol
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,17 @@ contract PrizePoolFuzzHarness is CommonBase, StdCheats, StdUtils, CurrentTimeCon
prizePool.contributePrizeTokens(_actor(actorSeed), _amount);
}

function donatePrizeTokens(uint88 _amount, uint256 actorSeed) public increaseCurrentTime(_timeIncrease()) prankActor(actorSeed) {
// console2.log("contributePrizeTokens");
address actor = _actor(actorSeed);
token.mint(address(actor), _amount);
vm.startPrank(actor);
token.approve(address(prizePool), _amount);
contributed += _amount;
prizePool.donatePrizeTokens(_amount);
vm.stopPrank();
}

function contributeReserve(uint88 _amount, uint256 actorSeed) public increaseCurrentTime(_timeIncrease()) prankActor(actorSeed) {
if (prizePool.isShutdown()) {
return;
Expand Down

0 comments on commit f23f668

Please sign in to comment.