Skip to content

Commit

Permalink
Added PrizePoolFactory
Browse files Browse the repository at this point in the history
  • Loading branch information
asselstine committed Feb 14, 2024
1 parent 882296e commit d45719e
Show file tree
Hide file tree
Showing 2 changed files with 155 additions and 0 deletions.
83 changes: 83 additions & 0 deletions src/PrizePoolFactory.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import { IERC20, IERC4626 } from "openzeppelin/token/ERC20/extensions/ERC4626.sol";

import { PrizePool, ConstructorParams } from "./PrizePool.sol";

/**
* @title PoolTogether V5 Prize PrizePool Factory
* @author PoolTogether Inc. & G9 Software Inc.
* @notice Factory contract for deploying new Prize Pool contracts
*/
contract PrizePoolFactory {
/* ============ Events ============ */

/**
* @notice Emitted when a new PrizePool has been deployed by this factory.
* @param prizePool The prizePool that was deployed
*/
event NewPrizePool(
PrizePool indexed prizePool
);

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

/// @notice List of all prizePools deployed by this factory.
PrizePool[] public allPrizePools;

/// @notice Mapping to verify if a PrizePool has been deployed via this factory.
mapping(address prizePool => bool deployedByFactory) public deployedPrizePools;

/// @notice Mapping to store deployer nonces for CREATE2
mapping(address deployer => uint256 nonce) public deployerNonces;

/* ============ External Functions ============ */

/**
* @notice Deploy a new prizePool
* @dev `claimer` can be set to address zero if none is available yet.
* @param _params Params struct for the Prize Pool configuration
* @return PrizePool The newly deployed PrizePool
*/
function deployPrizePool(
ConstructorParams memory _params
) external returns (PrizePool) {
PrizePool _prizePool = new PrizePool{
salt: keccak256(abi.encode(msg.sender, deployerNonces[msg.sender]++))
}(
_params
);

allPrizePools.push(_prizePool);
deployedPrizePools[address(_prizePool)] = true;

emit NewPrizePool(
_prizePool
);

return _prizePool;
}

function computePrizePoolAddress(
ConstructorParams memory _params
) external view returns (address) {
return address(uint160(uint(keccak256(abi.encodePacked(
bytes1(0xff),
address(this),
keccak256(abi.encode(msg.sender, deployerNonces[msg.sender])),
keccak256(abi.encodePacked(
type(PrizePool).creationCode,
abi.encode(_params)
))
)))));
}

/**
* @notice Total number of prizePools deployed by this factory.
* @return uint256 Number of prizePools deployed by this factory.
*/
function totalPrizePools() external view returns (uint256) {
return allPrizePools.length;
}
}
72 changes: 72 additions & 0 deletions test/PrizePoolFactory.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import "forge-std/console2.sol";

import "forge-std/Test.sol";

import { ERC20 } from "openzeppelin/token/ERC20/ERC20.sol";
import { IERC20 } from "openzeppelin/token/ERC20/IERC20.sol";
import { UD34x4, fromUD34x4 } from "../src/libraries/UD34x4.sol";
import { TwabController } from "pt-v5-twab-controller/TwabController.sol";

import { TierCalculationLib } from "../src/libraries/TierCalculationLib.sol";
import { MAXIMUM_NUMBER_OF_TIERS, MINIMUM_NUMBER_OF_TIERS } from "../src/abstract/TieredLiquidityDistributor.sol";
import {
PrizePool,
PrizePoolFactory,
ConstructorParams
} from "../src/PrizePoolFactory.sol";
import { ERC20Mintable } from "./mocks/ERC20Mintable.sol";

contract PrizePoolFactoryTest is Test {

event NewPrizePool(
PrizePool indexed prizePool
);

PrizePoolFactory prizePoolFactory;

ERC20Mintable prizeToken;
TwabController twabController;
uint48 drawPeriodSeconds = 1 days;
uint48 firstDrawOpensAt = 100 days;
uint24 grandPrizePeriodDraws = 10;
uint8 numberOfTiers = 3;
uint8 tierShares = 100;
uint8 reserveShares = 70;
uint24 drawTimeout = 10;

function setUp() public {
vm.warp(firstDrawOpensAt);
prizePoolFactory = new PrizePoolFactory();
prizeToken = new ERC20Mintable("PoolTogether POOL token", "POOL");
twabController = new TwabController(uint32(drawPeriodSeconds), uint32(firstDrawOpensAt - 1 days));
}

function testDeployPrizePool() public {
// Deploy a new prizePool
// `claimer` can be set to address zero if none is available yet.
// Params struct for the Prize Pool configuration
// Returns the newly deployed PrizePool
ConstructorParams memory params = ConstructorParams({
prizeToken: prizeToken,
twabController: twabController,
drawPeriodSeconds: drawPeriodSeconds,
firstDrawOpensAt: firstDrawOpensAt,
grandPrizePeriodDraws: grandPrizePeriodDraws,
numberOfTiers: numberOfTiers,
tierShares: tierShares,
reserveShares: reserveShares,
drawTimeout: drawTimeout
});
address prizePoolAddress = prizePoolFactory.computePrizePoolAddress(params);
vm.expectEmit();
emit NewPrizePool(PrizePool(prizePoolAddress));
PrizePool _prizePool = prizePoolFactory.deployPrizePool(params);
assertEq(address(_prizePool), prizePoolAddress);
assertEq(prizePoolFactory.totalPrizePools(), 1, "correct num of prize pools");
assertEq(prizePoolFactory.deployedPrizePools(prizePoolAddress), true, "correct prize pool deployed");
assertEq(prizePoolFactory.deployerNonces(address(this)), 1, "nonce was increased");
}
}

0 comments on commit d45719e

Please sign in to comment.