CREATE2 callback validation; init code storage contracts
This commit is contained in:
@@ -1,91 +1,95 @@
|
||||
// SPDX-License-Identifier: UNLICENSED
|
||||
pragma solidity ^0.8.30;
|
||||
|
||||
import "./PartyPoolMintImpl.sol";
|
||||
import "./PartyPoolSwapImpl.sol";
|
||||
import {IPartyPool} from "./IPartyPool.sol";
|
||||
import {IPartyPoolDeployer} from "./IPartyPoolDeployer.sol";
|
||||
import {PartyPool} from "./PartyPool.sol";
|
||||
import {PartyPoolBalancedPair} from "./PartyPoolBalancedPair.sol";
|
||||
|
||||
// This pattern is needed because the PartyPlanner constructs two different types of pools (regular and balanced-pair)
|
||||
// but doesn't have room to store the initialization code of both contracts. Therefore, we delegate pool construction.
|
||||
|
||||
interface IPartyPoolDeployer {
|
||||
function deploy(
|
||||
address owner_,
|
||||
string memory name_,
|
||||
string memory symbol_,
|
||||
IERC20[] memory tokens_,
|
||||
int128 kappa_,
|
||||
uint256[] memory fees_,
|
||||
uint256 flashFeePpm_,
|
||||
uint256 protocolFeePpm_,
|
||||
address protocolFeeAddress_,
|
||||
NativeWrapper wrapper_,
|
||||
PartyPoolSwapImpl swapImpl_,
|
||||
PartyPoolMintImpl mintImpl_
|
||||
) external returns (IPartyPool pool);
|
||||
// Storage contracts that only hold the init code
|
||||
contract PartyPoolInitCode {
|
||||
constructor() {
|
||||
bytes memory code = type(PartyPool).creationCode;
|
||||
assembly {
|
||||
return(add(code, 0x20), mload(code))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
contract PartyPoolBalancedPairInitCode {
|
||||
constructor() {
|
||||
bytes memory code = type(PartyPoolBalancedPair).creationCode;
|
||||
assembly {
|
||||
return(add(code, 0x20), mload(code))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// @notice Unified deployer that loads init code from external storage contracts
|
||||
/// @dev This pattern avoids storing large init code in the deployer itself, reducing contract size.
|
||||
/// Holds storage addresses for both regular and balanced pair pools, with separate nonce counters.
|
||||
contract PartyPoolDeployer is IPartyPoolDeployer {
|
||||
function deploy(
|
||||
address owner_,
|
||||
string memory name_,
|
||||
string memory symbol_,
|
||||
IERC20[] memory tokens_,
|
||||
int128 kappa_,
|
||||
uint256[] memory fees_,
|
||||
uint256 flashFeePpm_,
|
||||
uint256 protocolFeePpm_,
|
||||
address protocolFeeAddress_,
|
||||
NativeWrapper wrapper_,
|
||||
PartyPoolSwapImpl swapImpl_,
|
||||
PartyPoolMintImpl mintImpl_
|
||||
) external returns (IPartyPool) {
|
||||
return new PartyPool(
|
||||
owner_,
|
||||
name_,
|
||||
symbol_,
|
||||
tokens_,
|
||||
kappa_,
|
||||
fees_,
|
||||
flashFeePpm_,
|
||||
protocolFeePpm_,
|
||||
protocolFeeAddress_,
|
||||
wrapper_,
|
||||
swapImpl_,
|
||||
mintImpl_
|
||||
);
|
||||
}
|
||||
}
|
||||
address private immutable POOL_INIT_CODE_STORAGE;
|
||||
address private immutable BALANCED_PAIR_INIT_CODE_STORAGE;
|
||||
|
||||
contract PartyPoolBalancedPairDeployer is IPartyPoolDeployer {
|
||||
function deploy(
|
||||
address owner_,
|
||||
string memory name_,
|
||||
string memory symbol_,
|
||||
IERC20[] memory tokens_,
|
||||
int128 kappa_,
|
||||
uint256[] memory fees_,
|
||||
uint256 flashFeePpm_,
|
||||
uint256 protocolFeePpm_,
|
||||
address protocolFeeAddress_,
|
||||
NativeWrapper wrapper_,
|
||||
PartyPoolSwapImpl swapImpl_,
|
||||
PartyPoolMintImpl mintImpl_
|
||||
) external returns (IPartyPool) {
|
||||
return new PartyPoolBalancedPair(
|
||||
owner_,
|
||||
name_,
|
||||
symbol_,
|
||||
tokens_,
|
||||
kappa_,
|
||||
fees_,
|
||||
flashFeePpm_,
|
||||
protocolFeePpm_,
|
||||
protocolFeeAddress_,
|
||||
wrapper_,
|
||||
swapImpl_,
|
||||
mintImpl_
|
||||
);
|
||||
uint256 private _poolNonce;
|
||||
uint256 private _balancedPairNonce;
|
||||
DeployParams private _params;
|
||||
|
||||
constructor(PartyPoolInitCode poolInitCodeStorage, PartyPoolBalancedPairInitCode balancedPairInitCodeStorage) {
|
||||
require(address(poolInitCodeStorage) != address(0), "Deployer: zero pool storage address");
|
||||
require(address(balancedPairInitCodeStorage) != address(0), "Deployer: zero balanced pair storage address");
|
||||
POOL_INIT_CODE_STORAGE = address(poolInitCodeStorage);
|
||||
BALANCED_PAIR_INIT_CODE_STORAGE = address(balancedPairInitCodeStorage);
|
||||
}
|
||||
|
||||
function params() external view returns (DeployParams memory) {
|
||||
return _params;
|
||||
}
|
||||
|
||||
/// @notice Deploy a regular PartyPool
|
||||
function _deploy(DeployParams memory params_) internal returns (IPartyPool pool) {
|
||||
return _doDeploy(params_, POOL_INIT_CODE_STORAGE, _poolNonce++);
|
||||
}
|
||||
|
||||
/// @notice Deploy a balanced pair PartyPool
|
||||
function _deployBalancedPair(DeployParams memory params_) internal returns (IPartyPool pool) {
|
||||
return _doDeploy(params_, BALANCED_PAIR_INIT_CODE_STORAGE, _balancedPairNonce++);
|
||||
}
|
||||
|
||||
/// @notice Internal deployment implementation shared by both pool types
|
||||
function _doDeploy(
|
||||
DeployParams memory params_,
|
||||
address initCodeStorage,
|
||||
uint256 nonce
|
||||
) internal returns (IPartyPool pool) {
|
||||
bytes32 salt = bytes32(nonce);
|
||||
_params = params_;
|
||||
_params.nonce = salt;
|
||||
|
||||
// Load init code from storage contract and deploy with CREATE2
|
||||
bytes memory initCode = _getInitCode(initCodeStorage);
|
||||
address poolAddress;
|
||||
assembly {
|
||||
poolAddress := create2(0, add(initCode, 0x20), mload(initCode), salt)
|
||||
if iszero(poolAddress) {
|
||||
revert(0, 0)
|
||||
}
|
||||
}
|
||||
|
||||
pool = IPartyPool(poolAddress);
|
||||
}
|
||||
|
||||
/// @notice Load init code from the specified storage contract using EXTCODECOPY
|
||||
function _getInitCode(address storageContract) internal view returns (bytes memory) {
|
||||
uint256 size;
|
||||
assembly {
|
||||
size := extcodesize(storageContract)
|
||||
}
|
||||
bytes memory code = new bytes(size);
|
||||
assembly {
|
||||
extcodecopy(storageContract, add(code, 0x20), 0, size)
|
||||
}
|
||||
return code;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user