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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added ability to donate to the prizes #92

Merged
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
36 changes: 34 additions & 2 deletions src/PrizePool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,9 @@ contract PrizePool is TieredLiquidityDistributor, Ownable {
/// @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;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing natspec

Also would be nice to know why this address was chosen.


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

Expand Down Expand Up @@ -343,7 +346,7 @@ contract PrizePool is TieredLiquidityDistributor, Ownable {
/// @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 @@ -355,6 +358,13 @@ contract PrizePool is TieredLiquidityDistributor, Ownable {
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 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing natspec

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 @@ -588,6 +598,22 @@ contract PrizePool is TieredLiquidityDistributor, Ownable {
);
}

/// @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 @@ -954,12 +980,18 @@ contract PrizePool is TieredLiquidityDistributor, Ownable {
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 @@ -971,7 +1003,7 @@ contract PrizePool is TieredLiquidityDistributor, Ownable {
_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 @@ -377,6 +377,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 @@ -426,6 +446,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 @@ -477,6 +502,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 @@ -96,6 +96,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
Loading