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

Gen 1145 create a prizepoolfactory #90

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions src/PrizePoolFactory.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

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");
}
}
Loading