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 helper function to compute start draw reward #7

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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
77 changes: 44 additions & 33 deletions src/DrawManager.sol
@@ -1,6 +1,8 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import "forge-std/console2.sol";

import { PrizePool } from "pt-v5-prize-pool/PrizePool.sol";
import { IERC20 } from "openzeppelin/token/ERC20/IERC20.sol";
import { SafeERC20 } from "openzeppelin/token/ERC20/utils/SafeERC20.sol";
Expand Down Expand Up @@ -332,38 +334,6 @@ contract DrawManager {
return _lastStartDrawAuction;
}

/// ================= Internal =================

/// @notice Checks if the auction has expired.
/// @param startedAt The time at which the auction started
/// @return True if the auction has expired, false otherwise
function _hasAuctionExpired(uint256 startedAt) internal view returns (bool) {
return uint48(block.timestamp - startedAt) > auctionDuration;
}

/// @notice Allocates the reward to the recipient.
/// @param _recipient The recipient of the reward
/// @param _amount The amount of the reward
function _reward(address _recipient, uint256 _amount) internal {
if (_amount > 0) {
prizePool.allocateRewardFromReserve(_recipient, SafeCast.toUint96(_amount));
}
}

/// @notice Computes the rewards for the start and finish draw auctions.
/// @param _drawId The draw id to compute rewards for
/// @param _startDrawOccurredAt The time at which the start rng request occurred. Must be in the past.
/// @return rewards The computed rewards for the start and finish draw auctions
/// @return remainingReserve The remaining reserve after the rewards have been allocated
function _computeRewards(uint24 _drawId, uint256 _startDrawOccurredAt) internal view returns (uint256[] memory rewards, uint256 remainingReserve) {
uint totalReserve = prizePool.reserve() + prizePool.pendingReserveContributions();
uint48 closesAt = prizePool.drawClosesAt(_drawId);
uint48 startDrawElapsedTime = _elapsedTimeSinceDrawClosed(_startDrawOccurredAt, closesAt);
uint48 finishDrawElapsedTime = uint48(block.timestamp - _startDrawOccurredAt);

return computeRewards(startDrawElapsedTime, finishDrawElapsedTime, totalReserve);
}

/// @notice Computes the start draw and finish draw rewards.
/// @param _startDrawElapsedTime The elapsed time between draw close and startDraw()
/// @param _finishDrawElapsedTime The elapsed time between startDraw() and finishDraw()
Expand All @@ -384,6 +354,15 @@ contract DrawManager {
remainingReserve = _totalReserve - totalRewards;
}

/// @notice Computes the start draw reward.
/// @param _startDrawElapsedTime The elapsed time between draw close and startDraw()
/// @param _totalReserve The total reserve available to allocate rewards from
/// @return reward The computed reward for start draw
function computeStartDrawReward(uint48 _startDrawElapsedTime, uint256 _totalReserve) public view returns (uint256) {
(uint256[] memory rewards,) = computeRewards(_startDrawElapsedTime, 0, _totalReserve);
return rewards[0];
}

/// @notice Computes the reward fraction for the start draw auction.
/// @param _elapsedTime The elapsed time since the draw closed in seconds
/// @return The computed reward fraction for the start draw auction
Expand All @@ -408,9 +387,41 @@ contract DrawManager {
);
}

/// ================= Internal =================

/// @notice Checks if the auction has expired.
/// @param startedAt The time at which the auction started
/// @return True if the auction has expired, false otherwise
function _hasAuctionExpired(uint256 startedAt) internal view returns (bool) {
return uint48(block.timestamp - startedAt) > auctionDuration;
}

/// @notice Allocates the reward to the recipient.
/// @param _recipient The recipient of the reward
/// @param _amount The amount of the reward
function _reward(address _recipient, uint256 _amount) internal {
if (_amount > 0) {
prizePool.allocateRewardFromReserve(_recipient, SafeCast.toUint96(_amount));
}
}

/// @notice Computes the rewards for the start and finish draw auctions.
/// @param _drawId The draw id to compute rewards for
/// @param _startDrawOccurredAt The time at which the start rng request occurred. Must be in the past.
/// @return rewards The computed rewards for the start and finish draw auctions
/// @return remainingReserve The remaining reserve after the rewards have been allocated
function _computeRewards(uint24 _drawId, uint256 _startDrawOccurredAt) internal view returns (uint256[] memory rewards, uint256 remainingReserve) {
uint totalReserve = prizePool.reserve() + prizePool.pendingReserveContributions();
uint48 closesAt = prizePool.drawClosesAt(_drawId);
uint48 startDrawElapsedTime = _elapsedTimeSinceDrawClosed(_startDrawOccurredAt, closesAt);
uint48 finishDrawElapsedTime = uint48(block.timestamp - _startDrawOccurredAt);

return computeRewards(startDrawElapsedTime, finishDrawElapsedTime, totalReserve);
}

/// @notice Calculates the elapsed time for the current RNG auction.
/// @return The elapsed time since the start of the current RNG auction in seconds.
function _elapsedTimeSinceDrawClosed(uint256 _timestamp, uint256 _drawClosedAt) public pure returns (uint48) {
function _elapsedTimeSinceDrawClosed(uint256 _timestamp, uint256 _drawClosedAt) internal pure returns (uint48) {
return uint48(_drawClosedAt < _timestamp ? _timestamp - _drawClosedAt : 0);
}

Expand Down
14 changes: 14 additions & 0 deletions test/DrawManager.t.sol
Expand Up @@ -302,6 +302,10 @@ contract DrawManagerTest is Test {
drawManager.finishDraw(address(0));
}

function testComputeStartDrawRewardFraction() public {
assertEq(drawManager.computeStartDrawRewardFraction(auctionTargetTime).unwrap(), 0.1e18);
}

function testComputeRewards() public {
UD2x18[] memory rewardFractions = new UD2x18[](2);
rewardFractions[0] = UD2x18.wrap(0.5e18);
Expand All @@ -311,6 +315,16 @@ contract DrawManagerTest is Test {
assertEq(rewards[1], 20e18, "second reward");
}

function testComputeStartDrawReward_atZero() public {
// tiny amount at zero
assertEq(drawManager.computeStartDrawReward(0, 100e18), 280);
}

function testComputeStartDrawReward_atTarget() public {
// tiny amount at zero
assertEq(drawManager.computeStartDrawReward(auctionTargetTime, 5e18), 0.5e18);
}

function startFirstDraw() public {
vm.warp(1 days);
mockReserve(1e18, 0);
Expand Down