From 6b760dff61d095ce54a9c175f6f5cbdaf7d8b99b Mon Sep 17 00:00:00 2001 From: Orland0x <37511817+Orland0x@users.noreply.github.com> Date: Mon, 16 Oct 2023 10:45:50 -0400 Subject: [PATCH] chore: replaced old deployer scripts with new one (#243) * chore: replaced old deployer scripts with new one * chore: deployer test base * chore: added merkle whitelist to deployer script * chore: use test.json for test deployer script runs * chore: added merkle whitelist to readme blueprint * chore: updated gitignore * chore: set deployer address in deployer test * chore: empty deployments dir * chore: renamed deployments/.gitkeep -> deployments/.keep * chore: updated .env.example * chore: add deployment instructions to readme * chore: typos * chore: formatting * chore: deployer script fixes * chore: updated readme --------- Co-authored-by: Orlando --- .env.example | 6 +- .gitignore | 2 + README.md | 28 ++- deployments/.keep | 0 foundry.toml | 2 +- script/Deployer.s.sol | 275 ++++++++++++++++++++++++++++++ script/ModulesDeployment.s.sol | 45 ----- script/PopulateVanillaSpace.s.sol | 72 -------- script/SpaceSetup.s.sol | 80 --------- test/Deployer.t.sol | 38 +++++ 10 files changed, 346 insertions(+), 202 deletions(-) create mode 100644 deployments/.keep create mode 100644 script/Deployer.s.sol delete mode 100644 script/ModulesDeployment.s.sol delete mode 100644 script/PopulateVanillaSpace.s.sol delete mode 100644 script/SpaceSetup.s.sol create mode 100644 test/Deployer.t.sol diff --git a/.env.example b/.env.example index 11e0fefd..4077496e 100644 --- a/.env.example +++ b/.env.example @@ -1,4 +1,4 @@ -PRIVATE_KEY= -GOERLI_RPC_URL= +DEPLOYER_ADDRESS= +RPC_URL= ETHERSCAN_API_KEY= -OWNER= \ No newline at end of file +NETWORK= \ No newline at end of file diff --git a/.gitignore b/.gitignore index 53635689..04f4a258 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,5 @@ node_modules # broadcasts /broadcast/ lcov.info + +/deployments/test.json diff --git a/README.md b/README.md index 3ccd0b9a..f5d54fe7 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,8 @@ src ├─ voting-strategies │ ├─ CompVotingStrategy.sol - "Strategy that uses delegated balances of Comp tokens as voting power" │ ├─ OZVotesVotingStrategy.sol - "Strategy that uses delegated balances of OZ Votes tokens as voting power" -│ ├─ WhitelistVotingStrategy.sol — "Strategy that gives predetermined voting power for members in a whitelist, otherwise zero" +│ ├─ WhitelistVotingStrategy.sol — "Strategy that gives predetermined voting power for members in a whitelist. Whitelist is stored in a bytes array On-Chain." +│ ├─ MerkleWhitelistVotingStrategy.sol — "Strategy that gives predetermined voting power for members in a whitelist. Whitelist is stored in a Merkle tree Off-Chain, with only the root being stored On-Chain." │ └─ VanillaVotingStrategy.sol — "Vanilla Strategy" ├─ execution-strategies │ ├─ timelocks @@ -77,3 +78,28 @@ Get a test coverage report: ```sh $ forge coverage ``` + +### Deployment + +To deploy the protocol to an EVM chain, first set the following environment variables: + +```sh +# The address of the account that the protocol will be deployed from. +DEPLOYER_ADDRESS= +# The name of the chain you want to deploy on. The addresses of the deployed contracts will be stored at /deployments/network.json +NETWORK= +# An RPC URL for the chain. +RPC_URL= +# An API key for a block explorer on the chain (Optional). +ETHERSCAN_API_KEY= +``` + +Following this, a [Foundry Script](https://book.getfoundry.sh/tutorials/solidity-scripting) can be run to deploy the +entire protocol. Example usage to deploy from a Ledger Hardware Wallet and verify on a block explorer: + +```sh +forge script script/Deployer.s.sol:Deployer --rpc-url $RPC_URL --optimize --broadcast --verify -vvvv --ledger --sender $DEPLOYER_ADDRESS --hd-paths "m/44'/60'/4'/0/0" +``` + +The script uses the [Singleton Factory](https://eips.ethereum.org/EIPS/eip-2470) for the deployments which ensures that +the addresses of the contracts are the same on all chains (so long as the chain is fully EVM equivalent). diff --git a/deployments/.keep b/deployments/.keep new file mode 100644 index 00000000..e69de29b diff --git a/foundry.toml b/foundry.toml index 4be464f8..802c89b3 100644 --- a/foundry.toml +++ b/foundry.toml @@ -14,7 +14,7 @@ src = "src" test = "test" via_ir = true ffi = true -fs_permissions = [{ access = "read-write", path = ".forge-snapshots/"}] +fs_permissions = [{ access = "read-write", path = ".forge-snapshots/"}, { access = "read-write", path = "./deployments/"}] [profile.ci] fuzz = { runs = 1_000 } diff --git a/script/Deployer.s.sol b/script/Deployer.s.sol new file mode 100644 index 00000000..5ec5f04b --- /dev/null +++ b/script/Deployer.s.sol @@ -0,0 +1,275 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.18; + +import { Script } from "forge-std/Script.sol"; +import { stdJson } from "forge-std/StdJson.sol"; + +import { ProxyFactory } from "../src/ProxyFactory.sol"; +import { Space } from "../src/Space.sol"; +import { Strategy, InitializeCalldata } from "../src/types.sol"; + +import { VanillaExecutionStrategy } from "../src/execution-strategies/VanillaExecutionStrategy.sol"; +import { AvatarExecutionStrategy } from "../src/execution-strategies/AvatarExecutionStrategy.sol"; +import { TimelockExecutionStrategy } from "../src/execution-strategies/timelocks/TimelockExecutionStrategy.sol"; +import { + OptimisticTimelockExecutionStrategy +} from "../src/execution-strategies/timelocks/OptimisticTimelockExecutionStrategy.sol"; +import { + CompTimelockCompatibleExecutionStrategy +} from "../src/execution-strategies/timelocks/CompTimelockCompatibleExecutionStrategy.sol"; +import { + OptimisticCompTimelockCompatibleExecutionStrategy +} from "../src/execution-strategies/timelocks/OptimisticCompTimelockCompatibleExecutionStrategy.sol"; + +import { VanillaAuthenticator } from "../src/authenticators/VanillaAuthenticator.sol"; +import { EthSigAuthenticator } from "../src/authenticators/EthSigAuthenticator.sol"; +import { EthTxAuthenticator } from "../src/authenticators/EthTxAuthenticator.sol"; + +import { VanillaVotingStrategy } from "../src/voting-strategies/VanillaVotingStrategy.sol"; +import { CompVotingStrategy } from "../src/voting-strategies/CompVotingStrategy.sol"; +import { OZVotesVotingStrategy } from "../src/voting-strategies/OZVotesVotingStrategy.sol"; +import { WhitelistVotingStrategy } from "../src/voting-strategies/WhitelistVotingStrategy.sol"; +import { MerkleWhitelistVotingStrategy } from "../src/voting-strategies/MerkleWhitelistVotingStrategy.sol"; + +import { + VanillaProposalValidationStrategy +} from "../src/proposal-validation-strategies/VanillaProposalValidationStrategy.sol"; +import { + PropositionPowerProposalValidationStrategy +} from "../src/proposal-validation-strategies/PropositionPowerProposalValidationStrategy.sol"; +import { + ActiveProposalsLimiterProposalValidationStrategy +} from "../src/proposal-validation-strategies/ActiveProposalsLimiterProposalValidationStrategy.sol"; +import { + PropositionPowerAndActiveProposalsLimiterValidationStrategy +} from "../src/proposal-validation-strategies/PropositionPowerAndActiveProposalsLimiterValidationStrategy.sol"; + +interface SingletonFactory { + function deploy(bytes memory _initCode, bytes32 salt) external returns (address payable); +} + +/// @notice Script to deploy the Snapshot-X contracts +contract Deployer is Script { + error SpaceInitializationFailed(); + + SingletonFactory internal singletonFactory = SingletonFactory(0xce0042B868300000d44A59004Da54A005ffdcf9f); + address internal deployer; + string internal deployments; + string internal deploymentsPath; + + string internal name = "snapshot-x"; + string internal version = "1.0.0"; + + using stdJson for string; + + // Nonce used in the CREATE2 salts computation + uint256 internal saltNonce = 0; + + function run() public { + deployer = vm.envAddress("DEPLOYER_ADDRESS"); + + string memory network = vm.envString("NETWORK"); + + deploymentsPath = string.concat(string.concat("./deployments/", network), ".json"); + + vm.startBroadcast(deployer); + + // ------- EXECUTION STRATEGIES ------- + + (address avatarExecutionStrategy, ) = noRedeploy( + deployer, + abi.encodePacked( + type(AvatarExecutionStrategy).creationCode, + abi.encode(address(0x1), address(0x1), new address[](0), 0) + ), + saltNonce + ); + + deployments.serialize("AvatarExecutionStrategyImplementation", avatarExecutionStrategy); + + (address timelockExecutionStrategy, ) = noRedeploy( + deployer, + abi.encodePacked(type(TimelockExecutionStrategy).creationCode), + saltNonce + ); + + deployments.serialize("TimelockExecutionStrategyImplementation", timelockExecutionStrategy); + + (address optimisticTimelockExecutionStrategy, ) = noRedeploy( + deployer, + abi.encodePacked(type(OptimisticTimelockExecutionStrategy).creationCode), + saltNonce + ); + + deployments.serialize("OptimisticTimelockExecutionStrategyImplementation", optimisticTimelockExecutionStrategy); + + (address compTimelockCompatibleExecutionStrategy, ) = noRedeploy( + deployer, + abi.encodePacked( + type(CompTimelockCompatibleExecutionStrategy).creationCode, + abi.encode(address(0x1), address(0x1), new address[](0), 0, 0) + ), + saltNonce + ); + + deployments.serialize( + "CompTimelockCompatibleExecutionStrategyImplementation", + compTimelockCompatibleExecutionStrategy + ); + + (address optimisticCompTimelockCompatibleExecutionStrategy, ) = noRedeploy( + deployer, + abi.encodePacked( + type(OptimisticCompTimelockCompatibleExecutionStrategy).creationCode, + abi.encode(address(0x1), address(0x1), new address[](0), 0, 0) + ), + saltNonce + ); + + deployments.serialize( + "OptimisticCompTimelockCompatibleExecutionStrategyImplementation", + optimisticCompTimelockCompatibleExecutionStrategy + ); + + // ------- AUTHENTICATORS ------- + + (address vanillaAuthenticator, ) = noRedeploy(deployer, type(VanillaAuthenticator).creationCode, saltNonce); + deployments.serialize("VanillaAuthenticator", vanillaAuthenticator); + + (address ethTxAuthenticator, ) = noRedeploy(deployer, type(EthTxAuthenticator).creationCode, saltNonce); + deployments.serialize("EthTxAuthenticator", ethTxAuthenticator); + + (address ethSigAuthenticator, ) = noRedeploy( + deployer, + abi.encodePacked(type(EthSigAuthenticator).creationCode, abi.encode(name, version)), + saltNonce + ); + deployments.serialize("EthSigAuthenticator", ethSigAuthenticator); + + // ------- VOTING STRATEGIES ------- + + (address vanillaVotingStrategy, ) = noRedeploy(deployer, type(VanillaVotingStrategy).creationCode, saltNonce); + deployments.serialize("VanillaVotingStrategy", vanillaVotingStrategy); + + (address whitelistVotingStrategy, ) = noRedeploy( + deployer, + type(WhitelistVotingStrategy).creationCode, + saltNonce + ); + deployments.serialize("WhitelistVotingStrategy", whitelistVotingStrategy); + + (address compVotingStrategy, ) = noRedeploy(deployer, type(CompVotingStrategy).creationCode, saltNonce); + deployments.serialize("CompVotingStrategy", compVotingStrategy); + + (address ozVotesVotingStrategy, ) = noRedeploy(deployer, type(OZVotesVotingStrategy).creationCode, saltNonce); + deployments.serialize("OZVotesVotingStrategy", ozVotesVotingStrategy); + + (address merkleWhitelistVotingStrategy, ) = noRedeploy( + deployer, + type(MerkleWhitelistVotingStrategy).creationCode, + saltNonce + ); + deployments.serialize("MerkleWhitelistVotingStrategy", merkleWhitelistVotingStrategy); + + // ------- PROPOSAL VALIDATION STRATEGIES ------- + + (address vanillaProposalValidationStrategy, ) = noRedeploy( + deployer, + type(VanillaProposalValidationStrategy).creationCode, + saltNonce + ); + deployments.serialize("VanillaProposalValidationStrategy", vanillaProposalValidationStrategy); + + (address propositionPowerProposalValidationStrategy, ) = noRedeploy( + deployer, + type(PropositionPowerProposalValidationStrategy).creationCode, + saltNonce + ); + deployments.serialize("PropositionPowerProposalValidationStrategy", propositionPowerProposalValidationStrategy); + + (address activeProposalsLimiterProposalValidationStrategy, ) = noRedeploy( + deployer, + type(ActiveProposalsLimiterProposalValidationStrategy).creationCode, + saltNonce + ); + + deployments.serialize( + "ActiveProposalsLimiterProposalValidationStrategy", + activeProposalsLimiterProposalValidationStrategy + ); + + (address propositionPowerAndActiveProposalsLimiterValidationStrategy, ) = noRedeploy( + deployer, + type(PropositionPowerAndActiveProposalsLimiterValidationStrategy).creationCode, + saltNonce + ); + + deployments.serialize( + "PropositionPowerAndActiveProposalsLimiterValidationStrategy", + propositionPowerAndActiveProposalsLimiterValidationStrategy + ); + + // ------- PROXY FACTORY ------- + + (address proxyFactory, ) = noRedeploy(deployer, type(ProxyFactory).creationCode, saltNonce); + deployments.serialize("ProxyFactory", proxyFactory); + + // ------- SPACE ------- + + (address space, ) = noRedeploy(deployer, type(Space).creationCode, saltNonce); + + // If the master space is not initialized, initialize it + if (Space(space).owner() == address(0x0)) { + // Initializer for the master space, to render it unusable + Strategy[] memory dummyStrategyArray = new Strategy[](1); + dummyStrategyArray[0] = Strategy(address(0x1), new bytes(0)); + string[] memory dummyStringArray = new string[](1); + dummyStringArray[0] = ""; + address[] memory dummyAddressArray = new address[](1); + dummyAddressArray[0] = address(0x1); + Space(space).initialize( + InitializeCalldata( + address(0x1), + 1, + 1, + 1, + Strategy(address(0x1), new bytes(0)), + "", + "", + "", + dummyStrategyArray, + dummyStringArray, + dummyAddressArray + ) + ); + } + (address addr, ) = Space(space).proposalValidationStrategy(); + if (Space(space).owner() != address(0x1) || addr != address(0x1)) { + // Initialization of the master space was frontrun + revert SpaceInitializationFailed(); + } + + deployments = deployments.serialize("SpaceImplementation", space); + + deployments.write(deploymentsPath); + + vm.stopBroadcast(); + } + + // Deploys contract if it doesn't exist, otherwise returns the create2 address + function noRedeploy( + address _deployer, + bytes memory _initCode, + uint256 _saltNonce + ) internal returns (address, bool) { + bytes32 salt = keccak256(abi.encodePacked(_deployer, _saltNonce)); + address addy = computeCreate2Address(salt, keccak256(_initCode), address(singletonFactory)); + if (addy.code.length == 0) { + address _addy = singletonFactory.deploy(_initCode, salt); + assert(_addy == addy); + return (addy, true); + } else { + return (addy, false); + } + } +} diff --git a/script/ModulesDeployment.s.sol b/script/ModulesDeployment.s.sol deleted file mode 100644 index bb87e029..00000000 --- a/script/ModulesDeployment.s.sol +++ /dev/null @@ -1,45 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.18; - -import { Script } from "forge-std/Script.sol"; -import { Space } from "../src/Space.sol"; -import { VanillaAuthenticator } from "../src/authenticators/VanillaAuthenticator.sol"; -import { VanillaVotingStrategy } from "../src/voting-strategies/VanillaVotingStrategy.sol"; -import { VanillaExecutionStrategy } from "../src/execution-strategies/VanillaExecutionStrategy.sol"; -import { - PropositionPowerProposalValidationStrategy -} from "../src/proposal-validation-strategies/PropositionPowerProposalValidationStrategy.sol"; -import { EthSigAuthenticator } from "../src/authenticators/EthSigAuthenticator.sol"; -import { EthTxAuthenticator } from "../src/authenticators/EthTxAuthenticator.sol"; -import { CompVotingStrategy } from "../src/voting-strategies/CompVotingStrategy.sol"; -import { WhitelistVotingStrategy } from "../src/voting-strategies/WhitelistVotingStrategy.sol"; -import { ProxyFactory } from "../src/ProxyFactory.sol"; - -contract ModulesDeployment is Script { - VanillaVotingStrategy public vanillaVotingStrategy; - CompVotingStrategy public compVotingStrategy; - WhitelistVotingStrategy public whitelistVotingStrategy; - VanillaAuthenticator public vanillaAuthenticator; - PropositionPowerProposalValidationStrategy public propositionPowerProposalValidationStrategy; - EthSigAuthenticator public ethSigAuthenticator; - EthTxAuthenticator public ethTxAuthenticator; - VanillaExecutionStrategy public vanillaExecutionStrategy; - ProxyFactory public spaceFactory; - - function run() public { - uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); - vm.startBroadcast(deployerPrivateKey); - vanillaVotingStrategy = new VanillaVotingStrategy(); - compVotingStrategy = new CompVotingStrategy(); - whitelistVotingStrategy = new WhitelistVotingStrategy(); - vanillaAuthenticator = new VanillaAuthenticator(); - ethSigAuthenticator = new EthSigAuthenticator("snapshot-x", "0.1.0"); - ethTxAuthenticator = new EthTxAuthenticator(); - // TODO: set quorum prior to this deploy (or remove) - address deployerAddr = vm.addr(deployerPrivateKey); - vanillaExecutionStrategy = new VanillaExecutionStrategy(deployerAddr, 1); - propositionPowerProposalValidationStrategy = new PropositionPowerProposalValidationStrategy(); - spaceFactory = new ProxyFactory(); - vm.stopBroadcast(); - } -} diff --git a/script/PopulateVanillaSpace.s.sol b/script/PopulateVanillaSpace.s.sol deleted file mode 100644 index ce8e0185..00000000 --- a/script/PopulateVanillaSpace.s.sol +++ /dev/null @@ -1,72 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.18; - -import { Script } from "forge-std/Script.sol"; -import { Space } from "../src/Space.sol"; -import { VanillaAuthenticator } from "../src/authenticators/VanillaAuthenticator.sol"; -import { VanillaVotingStrategy } from "../src/voting-strategies/VanillaVotingStrategy.sol"; -import { VanillaExecutionStrategy } from "../src/execution-strategies/VanillaExecutionStrategy.sol"; -import { Choice, IndexedStrategy, Strategy } from "../src/types.sol"; - -contract PopulateVanillaSpace is Script { - bytes4 internal constant PROPOSE_SELECTOR = bytes4(keccak256("propose(address,string,(address,bytes),bytes)")); - bytes4 internal constant VOTE_SELECTOR = bytes4(keccak256("vote(address,uint256,uint8,(uint8,bytes)[],string)")); - - Space internal space; - VanillaVotingStrategy internal vanillaVotingStrategy; - VanillaAuthenticator internal vanillaAuthenticator; - VanillaExecutionStrategy internal vanillaExecutionStrategy; - - string public proposalMetadataURI = "SOC Test Proposal"; - Strategy public executionStrategy; - IndexedStrategy[] public userVotingStrategies; - - string internal voteMetadataURI = ""; - - function run() public { - space = Space(0x95DC6f73301356c9909921e21b735601C42fc1a8); - vanillaAuthenticator = VanillaAuthenticator(0xc4fb316710643f7FfBB566e5586862076198DAdB); - vanillaExecutionStrategy = VanillaExecutionStrategy(0x81519C29621Ba131ea398c15B17391F53e8B9A94); - - executionStrategy = Strategy(address(vanillaExecutionStrategy), new bytes(0)); - userVotingStrategies.push(IndexedStrategy(0, new bytes(0))); - - uint256 proposalId = _createProposal( - address(this), - proposalMetadataURI, - executionStrategy, - userVotingStrategies - ); - - _vote(address(this), proposalId, Choice.For, userVotingStrategies, voteMetadataURI); - } - - function _createProposal( - address _author, - string memory _metadataURI, - Strategy memory _executionStrategy, - IndexedStrategy[] memory _userVotingStrategies - ) internal returns (uint256) { - vanillaAuthenticator.authenticate( - address(space), - PROPOSE_SELECTOR, - abi.encode(_author, _metadataURI, _executionStrategy, _userVotingStrategies) - ); - - return space.nextProposalId() - 1; - } - - function _vote( - address _author, - uint256 _proposalId, - Choice _choice, - IndexedStrategy[] memory _userVotingStrategies, - string memory _voteMetadataURI - ) internal { - vanillaAuthenticator.authenticate( - address(space), - VOTE_SELECTOR, - abi.encode(_author, _proposalId, _choice, _userVotingStrategies, _voteMetadataURI) - ); - } -} diff --git a/script/SpaceSetup.s.sol b/script/SpaceSetup.s.sol deleted file mode 100644 index 75b53519..00000000 --- a/script/SpaceSetup.s.sol +++ /dev/null @@ -1,80 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.18; - -import { Script } from "forge-std/Script.sol"; -import { ProxyFactory } from "../src/ProxyFactory.sol"; -import { Space } from "../src/Space.sol"; -import { VanillaAuthenticator } from "../src/authenticators/VanillaAuthenticator.sol"; -import { VanillaVotingStrategy } from "../src/voting-strategies/VanillaVotingStrategy.sol"; -import { VanillaExecutionStrategy } from "../src/execution-strategies/VanillaExecutionStrategy.sol"; -import { Strategy } from "../src/types.sol"; - -// solhint-disable-next-line max-states-count -contract SpaceSetup is Script { - Space public space; - address internal masterSpace = address(0x1234); - ProxyFactory public spaceFactory = ProxyFactory(0xcae03d02f6840D865ccDD6668f1C2FDCA47F2240); - address public vanillaVotingStrategy = address(0x395eD61716b48DC904140b515e9F682E33330154); - address public compVotingStrategy = address(0xbBD17346378F76c1c94032594b57C93c24857B19); - address public whitelistVotingStrategy = address(0xC89a0C93Af823F794F96F7b2B63Fc2a1f1AE9427); - address public vanillaAuthenticator = address(0x86bfa0726CBA0FeBEeE457F04b705AB74B54D01c); - address public ethSigAuthenticator = address(0x328c6F186639f1981Dc25eD4517E8Ed2aDd85569); - address public ethTxAuthenticator = address(0x37315Ce75920B653f0f13734c709e199876455C9); - address public vanillaExecutionStrategy = address(0xb1001Fdf62C020761039A750b27e73C512fDaa5E); - address public votingPowerProposalValidationContract = address(42); // TODO: update - Strategy public votingPowerProposalValidationStrategy; - address public owner = address(0x2842c82E20ab600F443646e1BC8550B44a513D82); - uint32 public votingDelay; - uint32 public minVotingDuration; - uint32 public maxVotingDuration; - uint256 public proposalThreshold; - uint32 public quorum; - string internal metadataURI = "SX Test Space"; - - function run() public { - Strategy[] memory votingStrategies = new Strategy[](2); - bytes[] memory votingStrategyMetadata = new bytes[](2); - votingStrategies[0] = Strategy(vanillaVotingStrategy, new bytes(0)); - votingStrategyMetadata[0] = new bytes(0); - address uni = address(0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984); // Goerli UNI token - votingStrategies[1] = Strategy(compVotingStrategy, abi.encode(uni)); - votingStrategyMetadata[1] = new bytes(18); // UNI token decimals - - address[] memory authenticators = new address[](3); - authenticators[0] = vanillaAuthenticator; - authenticators[1] = ethSigAuthenticator; - authenticators[2] = ethTxAuthenticator; - Strategy[] memory executionStrategies = new Strategy[](1); - quorum = 1; - executionStrategies[0] = Strategy(vanillaExecutionStrategy, new bytes(quorum)); - votingDelay = 0; - minVotingDuration = 0; - maxVotingDuration = 1000; - proposalThreshold = 1; - votingPowerProposalValidationStrategy = Strategy( - votingPowerProposalValidationContract, - abi.encode(proposalThreshold, votingStrategies) - ); - uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); - vm.startBroadcast(deployerPrivateKey); - spaceFactory.deployProxy( - masterSpace, - abi.encodeWithSelector( - Space.initialize.selector, - owner, - votingDelay, - minVotingDuration, - maxVotingDuration, - votingPowerProposalValidationStrategy, - metadataURI, - votingStrategies, - votingStrategyMetadata, - authenticators, - executionStrategies - ), - 0 - ); - - vm.stopBroadcast(); - } -} diff --git a/test/Deployer.t.sol b/test/Deployer.t.sol new file mode 100644 index 00000000..b3bf6ab4 --- /dev/null +++ b/test/Deployer.t.sol @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.18; + +import { Test } from "forge-std/Test.sol"; +import { Deployer } from "../script/Deployer.s.sol"; + +contract DeployerTest is Test { + Deployer deployer; + + bytes internal constant singletonFactoryBytecode = + hex"6080604052348015600f57600080fd5b506004361060285760" + hex"003560e01c80634af63f0214602d575b600080fd5b60cf6004" + hex"8036036040811015604157600080fd5b810190602081018135" + hex"640100000000811115605b57600080fd5b8201836020820111" + hex"15606c57600080fd5b80359060200191846001830284011164" + hex"010000000083111715608d57600080fd5b91908080601f0160" + hex"20809104026020016040519081016040528093929190818152" + hex"60200183838082843760009201919091525092955050913592" + hex"5060eb915050565b604080516001600160a01b039092168252" + hex"519081900360200190f35b6000818351602085016000f59392" + hex"50505056fea26469706673582212206b44f8a82cb6b156bfcc" + hex"3dc6aadd6df4eefd204bc928a4397fd15dacf6d5320564736f" + hex"6c63430006020033"; + + function setUp() public { + vm.setEnv("NETWORK", "test"); + vm.setEnv("DEPLOYER_ADDRESS", vm.toString(address(this))); + + // Setting the bytecode at the singleton address of the singleton factory. + vm.etch(address(0xce0042B868300000d44A59004Da54A005ffdcf9f), singletonFactoryBytecode); + + deployer = new Deployer(); + } + + function testDeployer() public { + deployer.run(); + } +}