-
Notifications
You must be signed in to change notification settings - Fork 32
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
882296e
commit d45719e
Showing
2 changed files
with
155 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"); | ||
} | ||
} |