feat (contracts): ComplexPool deployment script (#99)

Co-authored-by: moebius <0xmoebius@protonmail.com>
Co-authored-by: moebius <132487952+0xmoebius@users.noreply.github.com>
This commit is contained in:
attemka
2025-07-31 20:48:17 +04:00
committed by GitHub
parent 50058bc9d6
commit e95ad5eeae
5 changed files with 130 additions and 9 deletions

View File

@@ -1,5 +1,5 @@
ETHEREUM_MAINNET_RPC=
ETHEREUM_SEPOLIA_RPC
ETHEREUM_SEPOLIA_RPC=
GNOSIS_RPC=
GNOSIS_CHIADO_RPC=
@@ -11,3 +11,5 @@ OWNER_ADDRESS=
POSTMAN_ADDRESS=
ENTRYPOINT_ADDRESS=
WITHDRAWAL_VERIFIER_ADDRESS=
RAGEQUIT_VERIFIER_ADDRESS=

View File

@@ -0,0 +1 @@
src/contracts/verifiers/*

View File

@@ -10,6 +10,8 @@
"build": "forge build",
"build:optimized": "FOUNDRY_PROFILE=optimized forge build",
"coverage": "forge coverage --report summary --report lcov --match-path 'test/unit/*'",
"deploy:complexpool:mainnet": "bash -c 'source .env && forge script script/DeployComplexPool.s.sol:DeployComplexPool --verify --account DEPLOYER --rpc-url $ETHEREUM_MAINNET_RPC --sender $DEPLOYER_ADDRESS --slow -vv $0'",
"deploy:complexpool:sepolia": "bash -c 'source .env && forge script script/DeployComplexPool.s.sol:DeployComplexPool --verify --account DEPLOYER --rpc-url $ETHEREUM_SEPOLIA_RPC --sender $DEPLOYER_ADDRESS --slow -vv $0'",
"deploy:protocol:chiado": "bash -c 'source .env && forge script script/Deploy.s.sol:GnosisChiado --verify --account DEPLOYER --rpc-url $GNOSIS_CHIADO_RPC --sender $DEPLOYER_ADDRESS --slow -vv $0'",
"deploy:protocol:gnosis": "bash -c 'source .env && forge script script/Deploy.s.sol:Gnosis --verify --account DEPLOYER --rpc-url $GNOSIS_RPC --sender $DEPLOYER_ADDRESS --slow -vv $0'",
"deploy:protocol:mainnet": "bash -c 'source .env && forge script script/Deploy.s.sol:EthereumMainnet --verify --account DEPLOYER --rpc-url $ETHEREUM_MAINNET_RPC --sender $DEPLOYER_ADDRESS --slow -vv $0'",

View File

@@ -0,0 +1,119 @@
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.28;
import {IERC20} from '@oz/token/ERC20/ERC20.sol';
import {ERC20} from '@oz/token/ERC20/ERC20.sol';
import {Script} from 'forge-std/Script.sol';
import {console} from 'forge-std/console.sol';
import {Constants} from 'contracts/lib/Constants.sol';
import {DeployLib} from 'contracts/lib/DeployLib.sol';
import {IPrivacyPool} from 'interfaces/IPrivacyPool.sol';
import {ICreateX} from 'interfaces/external/ICreateX.sol';
import {Entrypoint} from 'contracts/Entrypoint.sol';
import {PrivacyPoolComplex} from 'contracts/implementations/PrivacyPoolComplex.sol';
/*///////////////////////////////////////////////////////////////
COMPLEX POOL DEPLOYMENT
//////////////////////////////////////////////////////////////*/
/**
* @notice Script to deploy a Privacy Pool Complex.
*/
contract DeployComplexPool is Script {
error InvalidERC20Address();
error InvalidSymbol();
error ConfirmationMismatch();
// @notice Deployed Entrypoint from environment
Entrypoint public entrypoint;
// @notice Deployed Groth16 Withdrawal Verifier from environment
address public withdrawalVerifier;
// @notice Deployed Groth16 Ragequit Verifier from environment
address public ragequitVerifier;
// @notice Deployer address
address public deployer;
// @notice CreateX Singleton
ICreateX public constant CreateX = ICreateX(0xba5Ed099633D3B313e4D5F7bdc1305d3c28ba5Ed);
// @notice User-provided ERC20 details
address public erc20Address;
string public erc20Symbol;
function setUp() public virtual {
// Read addresses from environment
entrypoint = Entrypoint(payable(vm.envAddress('ENTRYPOINT_ADDRESS')));
withdrawalVerifier = vm.envAddress('WITHDRAWAL_VERIFIER_ADDRESS');
ragequitVerifier = vm.envAddress('RAGEQUIT_VERIFIER_ADDRESS');
deployer = vm.envAddress('DEPLOYER_ADDRESS');
// Prompt user for ERC20 details
_promptForERC20Details();
// Display configuration and ask for confirmation
_displayConfigurationAndConfirm();
}
function _promptForERC20Details() private {
// Prompt for ERC20 address
string memory _addressInput = vm.prompt('Enter ERC20 token address:');
erc20Address = vm.parseAddress(_addressInput);
if (erc20Address == address(0)) {
revert InvalidERC20Address();
}
// Prompt for ERC20 symbol
string memory _symbolInput = vm.prompt('Enter ERC20 token symbol:');
if (bytes(_symbolInput).length == 0) {
revert InvalidSymbol();
}
erc20Symbol = _symbolInput;
}
function _displayConfigurationAndConfirm() private {
string memory _confirmation = vm.prompt(
string.concat(
'Deploy ERC20 Privacy Pool for ', erc20Symbol, ' on chain ', vm.toString(block.chainid), '? (yes/no):'
)
);
if (keccak256(bytes(_confirmation)) != keccak256(bytes('yes'))) {
revert ConfirmationMismatch();
}
}
function run() public virtual {
vm.startBroadcast(deployer);
// Deploy the Privacy Pool Complex
address pool = _deployComplexPool();
console.log('Pool:', pool);
console.log('Symbol:', erc20Symbol);
console.log('Chain:', block.chainid);
vm.stopBroadcast();
}
function _deployComplexPool() private returns (address) {
// Encode constructor args
bytes memory _constructorArgs = abi.encode(address(entrypoint), withdrawalVerifier, ragequitVerifier, erc20Address);
// Generate salt for this specific token
bytes11 _tokenSalt = bytes11(keccak256(abi.encodePacked(DeployLib.COMPLEX_POOL_SALT, erc20Symbol)));
// Deploy pool with Create2
address _pool = CreateX.deployCreate2(
DeployLib.salt(deployer, _tokenSalt), abi.encodePacked(type(PrivacyPoolComplex).creationCode, _constructorArgs)
);
return _pool;
}
}

View File

@@ -1,14 +1,11 @@
{
"rules": {
"style-guide-casing": [
"warn",
{
"ignorePublicFunctions":true,
"ignoreExternalFunctions":true,
"ignoreContracts":true
}
],
"style-guide-casing": "off",
"no-unused-vars": "off",
"no-global-import": "off",
"private-vars-leading-underscore": "off",
"state-visibility": "off",
"compiler-version": "off",
"max-states-count": "off",
"ordering": "off",
"one-contract-per-file": "off"