Skip to content

Commit

Permalink
Merge 22ff7c5 into cf4bb35
Browse files Browse the repository at this point in the history
  • Loading branch information
kamescg authored Oct 6, 2021
2 parents cf4bb35 + 22ff7c5 commit a5f5001
Show file tree
Hide file tree
Showing 12 changed files with 179 additions and 118 deletions.
14 changes: 7 additions & 7 deletions contracts/DrawHistory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ import "./libraries/DrawRingBufferLib.sol";
/**
* @title PoolTogether V4 DrawHistory
* @author PoolTogether Inc Team
* @notice The DrawHistory keeps a historical record of Draws created/pushed by DrawBeacon(s).
Once a DrawBeacon (on mainnet) completes a RNG request, a new Draw will be added
to the DrawHistory draws ring buffer. A DrawHistory will store a limited number
of Draws before beginning to overwrite (managed via the cardinality) previous Draws.
All mainnet DrawHistory(s) are updated directly from a DrawBeacon, but non-mainnet
DrawHistory(s) (Matic, Optimism, Arbitrum, etc...) will receive a cross-chain message,
duplicating the mainnet Draw configuration - enabling a prize savings liquidity network.
* @notice The DrawHistory provides historical lookups of Draws via a circular ring buffer.
Historical Draws can be accessed on-chain using a drawId to calculate ring buffer storage slot.
The Draw settings can be created by manager/owner and existing Draws can only be updated the owner.
Once a starting Draw has been added to the ring buffer, all following draws must have a sequential Draw ID.
@dev A DrawHistory store a limited number of Draws before beginning to overwrite (managed via the cardinality) previous Draws.
@dev All mainnet DrawHistory(s) are updated directly from a DrawBeacon, but non-mainnet DrawHistory(s) (Matic, Optimism, Arbitrum, etc...)
will receive a cross-chain message, duplicating the mainnet Draw configuration - enabling a prize savings liquidity network.
*/
contract DrawHistory is IDrawHistory, Manageable {
using DrawRingBufferLib for DrawRingBufferLib.Buffer;
Expand Down
58 changes: 26 additions & 32 deletions contracts/DrawPrize.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,20 @@ import "./interfaces/IDrawCalculator.sol";
import "./interfaces/IDrawBeacon.sol";

/**
* @title PoolTogether V4 DrawPrize
* @author PoolTogether Inc Team
* @notice The DrawPrize distributes claimable draw prizes to users via a pull model.
Managing the regularly captured PrizePool interest, a DrawPrize is the
entrypoint for users to submit Draw.drawId(s) and winning pick indices.
Communicating with a DrawCalculator, the DrawPrize will determine the maximum
prize payout and transfer those tokens directly to a user address.
* @title PoolTogether V4 DrawPrize
* @author PoolTogether Inc Team
* @notice The DrawPrize contract holds Tickets (captured interest) and distributes tickets to users with winning draw claims.
DrawPrize uses an external IDrawCalculator to validate a users draw claim, before awarding payouts. To prevent users
from reclaiming prizes, a payout history for each draw claim is mapped to user accounts. Reclaiming a draw can occur
if an "optimal" prize was not included in previous claim pick indices and the new claims updated payout is greater then
the previous draw prize claim payout.
*/
contract DrawPrize is IDrawPrize, Ownable {
using SafeERC20 for IERC20;

/* ============ Global Variables ============ */

/// @notice The Draw Calculator to use
/// @notice DrawCalculator address
IDrawCalculator internal drawCalculator;

/// @notice Token address
Expand All @@ -37,8 +37,8 @@ contract DrawPrize is IDrawPrize, Ownable {

/**
* @notice Initialize DrawPrize smart contract.
* @param _owner Address of the DrawPrize owner
* @param _token Token address
* @param _owner Owner address
* @param _token Token address
* @param _drawCalculator DrawCalculator address
*/
constructor(
Expand Down Expand Up @@ -87,6 +87,22 @@ contract DrawPrize is IDrawPrize, Ownable {
return totalPayout;
}

/// @inheritdoc IDrawPrize
function withdrawERC20(
IERC20 _erc20Token,
address _to,
uint256 _amount
) external override onlyOwner returns (bool) {
require(_to != address(0), "DrawPrize/recipient-not-zero-address");
require(address(_erc20Token) != address(0), "DrawPrize/ERC20-not-zero-address");

_erc20Token.safeTransfer(_to, _amount);

emit ERC20Withdrawn(_erc20Token, _to, _amount);

return true;
}

/// @inheritdoc IDrawPrize
function getDrawCalculator() external view override returns (IDrawCalculator) {
return drawCalculator;
Expand Down Expand Up @@ -156,26 +172,4 @@ contract DrawPrize is IDrawPrize, Ownable {
token.safeTransfer(_to, _amount);
}

/**
* @notice Transfer ERC20 tokens out of this contract.
* @dev This function is only callable by the owner.
* @param _erc20Token ERC20 token to transfer.
* @param _to Recipient of the tokens.
* @param _amount Amount of tokens to transfer.
* @return true if operation is successful.
*/
function withdrawERC20(
IERC20 _erc20Token,
address _to,
uint256 _amount
) external override onlyOwner returns (bool) {
require(_to != address(0), "DrawPrize/recipient-not-zero-address");
require(address(_erc20Token) != address(0), "DrawPrize/ERC20-not-zero-address");

_erc20Token.safeTransfer(_to, _amount);

emit ERC20Withdrawn(_erc20Token, _to, _amount);

return true;
}
}
8 changes: 5 additions & 3 deletions contracts/PrizeDistributionHistory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ import "./interfaces/IPrizeDistributionHistory.sol";
/**
* @title PoolTogether V4 PrizeDistributionHistory
* @author PoolTogether Inc Team
* @notice The PrizeDistributionHistory stores historic PrizeDistribution for each drawId.
Storage of the PrizeDistributions is handled by a ring buffer with a max cardinality
of 256 or roughly 5 years of history with a weekly draw cadence.
* @notice The PrizeDistributionHistory contract provides historical lookups of PrizeDistribution struct parameters (linked with a Draw ID) via a
circular ring buffer. Historical PrizeDistribution parameters can be accessed on-chain using a drawId to calculate
ring buffer storage slot. The PrizeDistribution parameters can be created by manager/owner and existing PrizeDistribution
parameters can only be updated the owner. When adding a new PrizeDistribution basic sanity checks will be used to
validate the incoming parameters.
*/
contract PrizeDistributionHistory is IPrizeDistributionHistory, Manageable {
using DrawRingBufferLib for DrawRingBufferLib.Buffer;
Expand Down
10 changes: 7 additions & 3 deletions contracts/PrizeFlush.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ import "./interfaces/IPrizeFlush.sol";
* @title PoolTogether V4 PrizeFlush
* @notice The PrizeFlush is a helper library to facilitate interest distribution.
* @author PoolTogether Inc Team
* @notice The PrizeFlush contract helps capture interest from the PrizePool and move collected funds
to a designated PrizeDistributor contract. When deployed the destination, resereve and strategy
addresses are set and used as static parameters during every "flush" execution. The parameters can be
reset by the Owner if neccesary.
*/
contract PrizeFlush is IPrizeFlush, Manageable {
/**
Expand Down Expand Up @@ -48,7 +52,6 @@ contract PrizeFlush is IPrizeFlush, Manageable {
* @param _destination Destination address.
* @param _strategy Strategy address.
* @param _reserve Reserve address.
*
*/
constructor(
address _owner,
Expand Down Expand Up @@ -103,14 +106,15 @@ contract PrizeFlush is IPrizeFlush, Manageable {

/// @inheritdoc IPrizeFlush
function flush() external override onlyManagerOrOwner returns (bool) {
// Captures interest from PrizePool and distributes funds using a PrizeSplitStrategy
strategy.distribute();

// After captured interest transferred to Strategy.PrizeSplits[]: [Reserve, Other]
// transfer the Reserve balance directly to the DrawPrize (destination) address.
// After funds are distributed using PrizeSplitStrategy we EXPECT funds to be located in the Reserve.
IReserve _reserve = reserve;
IERC20 _token = _reserve.getToken();
uint256 _amount = _token.balanceOf(address(_reserve));

// IF the tokens were succesfully moved to the Reserve, now move the to the destination (PrizeDistributor) address.
if (_amount > 0) {
// Create checkpoint and transfers new total balance to DrawPrize
address _destination = destination;
Expand Down
13 changes: 10 additions & 3 deletions contracts/Reserve.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,16 @@ import "./interfaces/IReserve.sol";
import "./libraries/ObservationLib.sol";

/**
* @title PoolTogether V4 Reserve
* @author PoolTogether Inc Team
* @notice The Reserve migrates allotments of token distributions.
* @title PoolTogether V4 Reserve
* @author PoolTogether Inc Team
* @notice The Reserve contract provides historical lookups of a token balance increase during a target timerange.
As the Reserve contract transfers OUT tokens, the withdraw accumulator is increased. When tokens are
transfered IN new checkpoint *can* be created if checkpoint() is called after transfering tokens.
By using the reserve and withdraw accumulators to create a new checkpoint, any contract or account
can lookup the balance increase of the reserve for a target timerange.
* @dev By calculating the total held tokens in a speicific time range, contracts that require knowledge
of captured interest during a draw period, can easily call into the Reserve and determininstially
determine the newly aqcuired tokens for that time range.
*/
contract Reserve is IReserve, Manageable {
using SafeERC20 for IERC20;
Expand Down
43 changes: 27 additions & 16 deletions contracts/interfaces/IControlledToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,40 @@ pragma solidity 0.8.6;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

/// @title Controlled ERC20 Token
/// @notice ERC20 Tokens with a controller for minting & burning
/** @title IControlledToken
* @author PoolTogether Inc Team
* @notice ERC20 Tokens with a controller for minting & burning.
*/
interface IControlledToken is IERC20 {
/// @notice Interface to the contract responsible for controlling mint/burn

/**
@notice Interface to the contract responsible for controlling mint/burn
*/
function controller() external view returns (address);

/// @notice Allows the controller to mint tokens for a user account
/// @dev May be overridden to provide more granular control over minting
/// @param user Address of the receiver of the minted tokens
/// @param amount Amount of tokens to mint
/**
* @notice Allows the controller to mint tokens for a user account
* @dev May be overridden to provide more granular control over minting
* @param user Address of the receiver of the minted tokens
* @param amount Amount of tokens to mint
*/
function controllerMint(address user, uint256 amount) external;

/// @notice Allows the controller to burn tokens from a user account
/// @dev May be overridden to provide more granular control over burning
/// @param user Address of the holder account to burn tokens from
/// @param amount Amount of tokens to burn
/**
* @notice Allows the controller to burn tokens from a user account
* @dev May be overridden to provide more granular control over burning
* @param user Address of the holder account to burn tokens from
* @param amount Amount of tokens to burn
*/
function controllerBurn(address user, uint256 amount) external;

/// @notice Allows an operator via the controller to burn tokens on behalf of a user account
/// @dev May be overridden to provide more granular control over operator-burning
/// @param operator Address of the operator performing the burn action via the controller contract
/// @param user Address of the holder account to burn tokens from
/// @param amount Amount of tokens to burn
/**
* @notice Allows an operator via the controller to burn tokens on behalf of a user account
* @dev May be overridden to provide more granular control over operator-burning
* @param operator Address of the operator performing the burn action via the controller contract
* @param user Address of the holder account to burn tokens from
* @param amount Amount of tokens to burn
*/
function controllerBurnFrom(
address operator,
address user,
Expand Down
4 changes: 4 additions & 0 deletions contracts/interfaces/IDrawBeacon.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ pragma solidity 0.8.6;
import "@pooltogether/pooltogether-rng-contracts/contracts/RNGInterface.sol";
import "./IDrawHistory.sol";

/** @title IDrawBeacon
* @author PoolTogether Inc Team
* @notice The DrawBeacon interface.
*/
interface IDrawBeacon {

/// @notice Draw struct created every draw
Expand Down
2 changes: 1 addition & 1 deletion contracts/interfaces/IDrawCalculator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import "../PrizeDistributionHistory.sol";
import "../DrawPrize.sol";

/**
* @title PoolTogether V4 DrawCalculator
* @title PoolTogether V4 IDrawCalculator
* @author PoolTogether Inc Team
* @notice The DrawCalculator interface.
*/
Expand Down
12 changes: 8 additions & 4 deletions contracts/interfaces/IDrawHistory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ pragma solidity 0.8.6;

import "../interfaces/IDrawBeacon.sol";

/** @title IDrawHistory
* @author PoolTogether Inc Team
* @notice The DrawHistory interface.
*/
interface IDrawHistory {
/**
* @notice Emit when a new draw has been created.
Expand All @@ -22,8 +26,8 @@ interface IDrawHistory {

/**
* @notice Read multiple Draws from the draws ring buffer.
* @dev Read multiple Draws using each Draw.drawId to calculate position in the draws ring buffer.
* @param drawIds Array of Draw.drawIds
* @dev Read multiple Draws using each drawId to calculate position in the draws ring buffer.
* @param drawIds Array of drawIds
* @return IDrawBeacon.Draw[]
*/
function getDraws(uint32[] calldata drawIds) external view returns (IDrawBeacon.Draw[] memory);
Expand All @@ -38,14 +42,14 @@ interface IDrawHistory {
function getDrawCount() external view returns (uint32);

/**
* @notice Read newest Draw from the draws ring buffer.
* @notice Read newest Draw from draws ring buffer.
* @dev Uses the nextDrawIndex to calculate the most recently added Draw.
* @return IDrawBeacon.Draw
*/
function getNewestDraw() external view returns (IDrawBeacon.Draw memory);

/**
* @notice Read oldest Draw from the draws ring buffer.
* @notice Read oldest Draw from draws ring buffer.
* @dev Finds the oldest Draw by comparing and/or diffing totalDraws with the cardinality.
* @return IDrawBeacon.Draw
*/
Expand Down
Loading

0 comments on commit a5f5001

Please sign in to comment.