Skip to content

Commit

Permalink
Merge 2b07c47 into 8906897
Browse files Browse the repository at this point in the history
  • Loading branch information
kamescg committed Oct 6, 2021
2 parents 8906897 + 2b07c47 commit 771d8bc
Show file tree
Hide file tree
Showing 12 changed files with 192 additions and 126 deletions.
14 changes: 7 additions & 7 deletions contracts/DrawHistory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,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
44 changes: 19 additions & 25 deletions contracts/DrawPrize.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ contract DrawPrize is IDrawPrize, Ownable {

/* ============ 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 @@ -11,9 +11,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
20 changes: 12 additions & 8 deletions contracts/PrizeFlush.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,14 @@ import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "./interfaces/IPrizeFlush.sol";

/**
* @title PoolTogether V4 PrizeFlush
* @author PoolTogether Inc Team
* @notice The PrizeFlush is a helper library to facilate interest distribution.
* @title PoolTogether V4 PrizeFlush
* @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.
* @dev Ultimately the PrizeFlush contract minimizes the amount of time tokens spend in the Reserve contract by executing
a predictable token transfer "order of operations" which includes a critical checkpoint in the Reserve ring buffer.
*/
contract PrizeFlush is IPrizeFlush, Manageable {
/// @notice Static destination for captured interest
Expand Down Expand Up @@ -39,12 +44,11 @@ contract PrizeFlush is IPrizeFlush, Manageable {
/* ============ Constructor ============ */

/**
* @notice Set owner, reserve and strategy when deployed.
* @notice Set owner, destination, reserve and strategy when deployed.
* @param _owner address
* @param _destination address
* @param _strategy IStrategy
* @param _reserve IReserve
*
*/
constructor(
address _owner,
Expand All @@ -56,7 +60,6 @@ contract PrizeFlush is IPrizeFlush, Manageable {
strategy = _strategy;
reserve = _reserve;

// Emit Deploy State
emit Deployed(_destination, _reserve, _strategy);
}

Expand Down Expand Up @@ -109,14 +112,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
6 changes: 5 additions & 1 deletion contracts/interfaces/IDrawBeacon.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ import "@pooltogether/pooltogether-rng-contracts/contracts/RNGInterface.sol";
import "./IDrawHistory.sol";
import "../libraries/DrawLib.sol";

/** @title IDrawBeacon
* @author PoolTogether Inc Team
* @notice The DrawBeacon interface.
*/
interface IDrawBeacon {
/**
* @notice Emit when a new DrawHistory has been set.
Expand All @@ -15,7 +19,7 @@ interface IDrawBeacon {

/**
* @notice Emit when a draw has opened.
* @param operator User address responsible for opening draw
* @param operator User address responsible for opening draw
* @param startedAt Start timestamp
*/
event BeaconPeriodStarted(address indexed operator, uint64 indexed startedAt);
Expand Down
2 changes: 1 addition & 1 deletion contracts/interfaces/IDrawCalculator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import "../DrawPrize.sol";
import "../libraries/DrawLib.sol";

/**
* @title PoolTogether V4 DrawCalculator
* @title PoolTogether V4 IDrawCalculator
* @author PoolTogether Inc Team
* @notice The DrawCalculator interface.
*/
Expand Down
26 changes: 15 additions & 11 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 "../libraries/DrawLib.sol";

/** @title IDrawHistory
* @author PoolTogether Inc Team
* @notice The DrawHistory interface.
*/
interface IDrawHistory {
/**
* @notice Emit when a new draw has been created.
Expand All @@ -13,17 +17,17 @@ interface IDrawHistory {
event DrawSet(uint32 indexed drawId, DrawLib.Draw draw);

/**
* @notice Read a Draw from the draws ring buffer.
* @dev Read a Draw using the Draw.drawId to calculate position in the draws ring buffer.
* @param drawId Draw.drawId
* @notice Read a Draw from draws ring buffer.
* @dev Read a Draw using the drawId to calculate position in draws ring buffer.
* @param drawId drawId
* @return DrawLib.Draw
*/
function getDraw(uint32 drawId) external view returns (DrawLib.Draw memory);

/**
* @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
* @notice Read multiple Draws from draws ring buffer.
* @dev Read multiple Draws using each drawId to calculate position in draws ring buffer.
* @param drawIds Array of drawIds
* @return DrawLib.Draw[]
*/
function getDraws(uint32[] calldata drawIds) external view returns (DrawLib.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 DrawLib.Draw
*/
function getNewestDraw() external view returns (DrawLib.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 DrawLib.Draw
*/
Expand All @@ -54,16 +58,16 @@ interface IDrawHistory {
/**
* @notice Push Draw onto draws ring buffer history.
* @dev Push new draw onto draws history via authorized manager or owner.
* @param draw DrawLib.Draw
* @return Draw.drawId
* @param draw DrawLib.Draw
* @return drawId
*/
function pushDraw(DrawLib.Draw calldata draw) external returns (uint32);

/**
* @notice Set existing Draw in draws ring buffer with new parameters.
* @dev Updating a Draw should be used sparingly and only in the event an incorrect Draw parameter has been stored.
* @param newDraw DrawLib.Draw
* @return Draw.drawId
* @return drawId
*/
function setDraw(DrawLib.Draw calldata newDraw) external returns (uint32);
}
Loading

0 comments on commit 771d8bc

Please sign in to comment.