diff --git a/README.md b/README.md index 0f07377f..b2abf092 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,6 @@ https://docs.pooltogether.com - [DrawCalculator](/contracts/DrawCalculator.sol) - [DrawHistory](/contracts/DrawHistory.sol) - [DrawPrize](/contracts/DrawPrize.sol) -- [PrizeFlush](/contracts/PrizeFlush.sol) - [PrizeSplitStrategy](/contracts/PrizeSplitStrategy.sol) - [Reserve](/contracts/Reserve.sol) diff --git a/contracts/PrizeFlush.sol b/contracts/PrizeFlush.sol deleted file mode 100644 index cc5ef4c5..00000000 --- a/contracts/PrizeFlush.sol +++ /dev/null @@ -1,158 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 - -pragma solidity 0.8.6; - -import "@pooltogether/owner-manager-contracts/contracts/Manageable.sol"; -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; - -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 { - /** - * @notice Destination address for captured interest. - * @dev Should be set to the DrawPrize address. - */ - address internal destination; - - /// @notice Reserve address. - IReserve internal reserve; - - /// @notice Strategy address. - IStrategy internal strategy; - - /* ============ Events ============ */ - - /** - * @notice Emitted when contract has been deployed. - * @param destination Destination address. - * @param reserve Strategy address. - * @param strategy Reserve address. - * - */ - event Deployed( - address indexed destination, - IReserve indexed reserve, - IStrategy indexed strategy - ); - - /* ============ Constructor ============ */ - - /** - * @notice Deploy Prize Flush. - * @param _owner Prize Flush owner address. - * @param _destination Destination address. - * @param _strategy Strategy address. - * @param _reserve Reserve address. - */ - constructor( - address _owner, - address _destination, - IStrategy _strategy, - IReserve _reserve - ) Ownable(_owner) { - _setDestination(_destination); - _setReserve(_reserve); - _setStrategy(_strategy); - - emit Deployed(_destination, _reserve, _strategy); - } - - /* ============ External Functions ============ */ - - /// @inheritdoc IPrizeFlush - function getDestination() external view override returns (address) { - return destination; - } - - /// @inheritdoc IPrizeFlush - function getReserve() external view override returns (IReserve) { - return reserve; - } - - /// @inheritdoc IPrizeFlush - function getStrategy() external view override returns (IStrategy) { - return strategy; - } - - /// @inheritdoc IPrizeFlush - function setDestination(address _destination) external override onlyOwner returns (address) { - _setDestination(_destination); - emit DestinationSet(_destination); - return _destination; - } - - /// @inheritdoc IPrizeFlush - function setReserve(IReserve _reserve) external override onlyOwner returns (IReserve) { - _setReserve(_reserve); - emit ReserveSet(_reserve); - return _reserve; - } - - /// @inheritdoc IPrizeFlush - function setStrategy(IStrategy _strategy) external override onlyOwner returns (IStrategy) { - _setStrategy(_strategy); - emit StrategySet(_strategy); - return _strategy; - } - - /// @inheritdoc IPrizeFlush - function flush() external override onlyManagerOrOwner returns (bool) { - // Captures interest from PrizePool and distributes funds using a PrizeSplitStrategy - strategy.distribute(); - - // 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) { - address _destination = destination; - _reserve.withdrawTo(_destination, _amount); - emit Flushed(_destination, _amount); - } - - return true; - } - - /* ============ Internal Functions ============ */ - - /** - * @notice Set global destination variable. - * @dev `_destination` cannot be the zero address. - * @param _destination Destination address. - */ - function _setDestination(address _destination) internal { - require(_destination != address(0), "Flush/destination-not-zero-address"); - destination = _destination; - } - - /** - * @notice Set global reserve variable. - * @dev `_reserve` cannot be the zero address. - * @param _reserve Reserve address. - */ - function _setReserve(IReserve _reserve) internal { - require(address(_reserve) != address(0), "Flush/reserve-not-zero-address"); - reserve = _reserve; - } - - /** - * @notice Set global strategy variable. - * @dev `_strategy` cannot be the zero address. - * @param _strategy Strategy address. - */ - function _setStrategy(IStrategy _strategy) internal { - require(address(_strategy) != address(0), "Flush/strategy-not-zero-address"); - strategy = _strategy; - } -} diff --git a/contracts/interfaces/IPrizeFlush.sol b/contracts/interfaces/IPrizeFlush.sol deleted file mode 100644 index 70a60f96..00000000 --- a/contracts/interfaces/IPrizeFlush.sol +++ /dev/null @@ -1,86 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 - -pragma solidity 0.8.6; - -import "./IReserve.sol"; -import "./IStrategy.sol"; - -interface IPrizeFlush { - - /** - * @notice Emit when flush is executed. - * @param recipient Receiver of flushed tokens - * @param amount Amount of flushed tokens - */ - event Flushed(address indexed recipient, uint256 amount); - - /** - * @notice Emit when destination is set. - * @param destination Destination address - */ - event DestinationSet(address indexed destination); - - /** - * @notice Emit when strategy is set. - * @param strategy Strategy address - */ - event StrategySet(IStrategy indexed strategy); - - /** - * @notice Emit when destination is set. - * @param reserve Reserve address - */ - event ReserveSet(IReserve indexed reserve); - - /* ============ External Functions ============ */ - - /** - * @notice Read global destination variable. - * @return Destination address. - */ - function getDestination() external view returns (address); - - /** - * @notice Read global reserve variable. - * @return Reserve address. - */ - function getReserve() external view returns (IReserve); - - /** - * @notice Read global strategy variable. - * @return Strategy address. - */ - function getStrategy() external view returns (IStrategy); - - /** - * @notice Set global destination variable. - * @dev Only the owner can set the destination. - * @param _destination Destination address. - * @return Destination address. - */ - function setDestination(address _destination) external returns (address); - - /** - * @notice Set global reserve variable. - * @dev Only the owner can set the reserve. - * @param _reserve Reserve address. - * @return Reserve address. - */ - function setReserve(IReserve _reserve) external returns (IReserve); - - /** - * @notice Set global strategy variable. - * @dev Only the owner can set the strategy. - * @param _strategy Strategy address. - * @return Strategy address. - */ - function setStrategy(IStrategy _strategy) external returns (IStrategy); - - /** - * @notice Migrate interest from PrizePool to DrawPrize in a single transaction. - * @dev Captures interest, checkpoint data and transfers tokens to final destination. - * @dev Only callable by the owner or manager. - * @return True when operation is successful. - */ - function flush() external returns (bool); -} diff --git a/test/PrizeFlush.test.ts b/test/PrizeFlush.test.ts deleted file mode 100644 index 22aac9ee..00000000 --- a/test/PrizeFlush.test.ts +++ /dev/null @@ -1,123 +0,0 @@ -import { expect } from 'chai'; -import { ethers, artifacts } from 'hardhat'; -import { Contract, ContractFactory } from 'ethers'; -import { Signer } from '@ethersproject/abstract-signer'; -import { deployMockContract, MockContract } from 'ethereum-waffle'; -import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'; -const { getSigners } = ethers; -const { parseEther: toWei } = ethers.utils; - -describe('PrizeFlush', () => { - let wallet1: SignerWithAddress; - let wallet2: SignerWithAddress; - let wallet3: SignerWithAddress; - - // Contracts - let prizeFlush: Contract; - let reserve: Contract; - let ticket: Contract; - let strategy: MockContract; - let prizeFlushFactory: ContractFactory; - let reserveFactory: ContractFactory; - let erc20MintableFactory: ContractFactory; - let prizeSplitStrategyFactory: ContractFactory; - - let DESTINATION: any; - - before(async () => { - [wallet1, wallet2, wallet3] = await getSigners(); - DESTINATION = wallet3.address; - erc20MintableFactory = await ethers.getContractFactory('ERC20Mintable'); - prizeFlushFactory = await ethers.getContractFactory('PrizeFlush'); - reserveFactory = await ethers.getContractFactory('ReserveHarness'); - prizeSplitStrategyFactory = await ethers.getContractFactory('PrizeSplitStrategy'); - - let PrizeSplitStrategy = await artifacts.readArtifact('PrizeSplitStrategy'); - strategy = await deployMockContract(wallet1 as Signer, PrizeSplitStrategy.abi); - }); - - beforeEach(async () => { - ticket = await erc20MintableFactory.deploy('Ticket', 'TICK'); - reserve = await reserveFactory.deploy(wallet1.address, ticket.address); - - prizeFlush = await prizeFlushFactory.deploy( - wallet1.address, - DESTINATION, - strategy.address, - reserve.address, - ); - - await reserve.setManager(prizeFlush.address); - }); - - describe('Getters', () => { - it('should get the destination address', async () => { - expect(await prizeFlush.getDestination()).to.equal(DESTINATION); - }); - - it('should get the strategy address', async () => { - expect(await prizeFlush.getStrategy()).to.equal(strategy.address); - }); - - it('should get the reserve address', async () => { - expect(await prizeFlush.getReserve()).to.equal(reserve.address); - }); - }); - - describe('Setters', () => { - it('should fail to set the destination address', async () => { - await expect( - prizeFlush.connect(wallet3).setDestination(wallet3.address), - ).to.revertedWith('Ownable/caller-not-owner'); - }); - - it('should set the destination address', async () => { - await expect(prizeFlush.setDestination(wallet3.address)).to.emit( - prizeFlush, - 'DestinationSet', - ); - }); - - it('should fail to set the strategy address', async () => { - await expect(prizeFlush.connect(wallet3).setStrategy(wallet3.address)).to.revertedWith( - 'Ownable/caller-not-owner', - ); - }); - - it('should set the strategy address', async () => { - await expect(prizeFlush.setStrategy(wallet3.address)).to.emit( - prizeFlush, - 'StrategySet', - ); - }); - - it('should fail to set the reserve address', async () => { - await expect(prizeFlush.connect(wallet3).setReserve(wallet3.address)).to.revertedWith( - 'Ownable/caller-not-owner', - ); - }); - - it('should set the reserve address', async () => { - await strategy.mock.distribute.returns(toWei('0')); - await expect(prizeFlush.setReserve(wallet3.address)).to.emit(prizeFlush, 'ReserveSet'); - }); - }); - - describe('Core', () => { - describe('flush()', () => { - it('should fail to call withdrawTo if zero balance on reserve', async () => { - await strategy.mock.distribute.returns(toWei('0')); - await expect(prizeFlush.flush()).to.not.emit(prizeFlush, 'Flushed'); - }); - - it('should succeed to call withdrawTo prizes if positive balance on reserve.', async () => { - await strategy.mock.distribute.returns(toWei('100')); - await ticket.mint(reserve.address, toWei('100')); - - await expect(prizeFlush.flush()) - .to.emit(prizeFlush, 'Flushed') - .and.to.emit(reserve, 'Withdrawn'); - }); - }); - }); -});