diff --git a/src/rollup/RollupCreator.sol b/src/rollup/RollupCreator.sol index 73ede3a..a95bdd8 100644 --- a/src/rollup/RollupCreator.sol +++ b/src/rollup/RollupCreator.sol @@ -40,12 +40,21 @@ contract RollupCreator is Ownable { address nativeToken; bool deployFactoriesToL2; uint256 maxFeePerGasForRetryables; - //// @dev The address of the batch poster, not used when set to zero address address[] batchPosters; address batchPosterManager; address eigenDARollupManager; } + modifier onlyUnfrozen() { + require(!deploymentFrozen, "Deployment no longer permitted from this RollupCreator"); + _; + } + + modifier onlyOnce() { + require(!templatesSet, "Templates already set"); + _; + } + BridgeCreator public bridgeCreator; IOneStepProofEntry public osp; IChallengeManager public challengeManagerTemplate; @@ -58,6 +67,9 @@ contract RollupCreator is Ownable { DeployHelper public l2FactoriesDeployer; + bool public templatesSet; + bool public deploymentFrozen; + constructor() Ownable() {} // creator receives back excess fees (for deploying L2 factories) so it can refund the caller @@ -73,7 +85,7 @@ contract RollupCreator is Ownable { address _validatorUtils, address _validatorWalletCreator, DeployHelper _l2FactoriesDeployer - ) external onlyOwner { + ) external onlyOwner onlyOnce { bridgeCreator = _bridgeCreator; osp = _osp; challengeManagerTemplate = _challengeManagerLogic; @@ -83,6 +95,8 @@ contract RollupCreator is Ownable { validatorUtils = _validatorUtils; validatorWalletCreator = _validatorWalletCreator; l2FactoriesDeployer = _l2FactoriesDeployer; + + templatesSet = true; emit TemplatesUpdated(); } @@ -93,11 +107,11 @@ contract RollupCreator is Ownable { * @dev - UpgradeExecutor should be the owner of proxyAdmin which manages bridge contracts * @dev - config.rollupOwner should have executor role on upgradeExecutor * @dev - Bridge should have a single inbox and outbox - * @dev - Validators and batch poster should be set if provided + * @dev - Validators, batch posters and batch poster manager should be set if provided * @param deployParams The parameters for the rollup deployment. It consists of: * - config The configuration for the rollup - * - batchPoster The address of the batch poster, not used when set to zero address * - validators The list of validator addresses, not used when set to empty list + * - maxDataSize Max size of the calldata that can be posted * - nativeToken Address of the custom fee token used by rollup. If rollup is ETH-based address(0) should be provided * - deployFactoriesToL2 Whether to deploy L2 factories using retryable tickets. If true, retryables need to be paid for in native currency. * Deploying factories via retryable tickets at rollup creation time is the most reliable method to do it since it @@ -105,12 +119,15 @@ contract RollupCreator is Ownable { * anyone can try to deploy factories and potentially burn the nonce 0 (ie. due to gas price spike when doing direct * L2 TX). That would mean we permanently lost capability to deploy deterministic factory at expected address. * - maxFeePerGasForRetryables price bid for L2 execution. - * - dataHashReader The address of the data hash reader used to read blob hashes + * - batchPosters The list of batch poster addresses, not used when set to empty list + * - batchPosterManager The address which has the ability to rotate batch poster keys + * - eigenDARollupManager The address of the EigenDABlobVerifier contract * @return The address of the newly created rollup */ function createRollup(RollupDeploymentParams memory deployParams) public payable + onlyUnfrozen returns (address) { { @@ -197,7 +214,7 @@ contract RollupCreator is Ownable { bridgeContracts.sequencerInbox.setBatchPosterManager(deployParams.batchPosterManager); } - // Setting EigenDARollupManager + // Setting EigenDAServiceManager and EigenDARollupManager bridgeContracts.sequencerInbox.setEigenDARollupManager(deployParams.eigenDARollupManager); // Call setValidator on the newly created rollup contract just if validator set is not empty @@ -236,6 +253,10 @@ contract RollupCreator is Ownable { return address(rollup); } + function freezeDeployment() external onlyOwner { + deploymentFrozen = true; + } + function _deployUpgradeExecutor(address rollupOwner, ProxyAdmin proxyAdmin) internal returns (address) @@ -335,4 +356,4 @@ contract RollupCreator is Ownable { } return scaledAmount; } -} +} \ No newline at end of file diff --git a/test/foundry/RollupCreator.t.sol b/test/foundry/RollupCreator.t.sol index 6c81527..da80505 100644 --- a/test/foundry/RollupCreator.t.sol +++ b/test/foundry/RollupCreator.t.sol @@ -28,6 +28,8 @@ contract RollupCreatorTest is Test { IRollupUser public rollupUser; DeployHelper public deployHelper; IReader4844 dummyReader4844 = IReader4844(address(137)); + IEigenDAServiceManager dummyEigenDAServiceManager = IEigenDAServiceManager(address(138)); + IRollupManager rollupManager = IRollupManager(address(139)); // 1 gwei uint256 public constant MAX_FEE_PER_GAS = 1_000_000_000; @@ -124,7 +126,9 @@ contract RollupCreatorTest is Test { address[] memory validators = new address[](2); validators[0] = makeAddr("validator1"); validators[1] = makeAddr("validator2"); - address eigenDARollupManager = makeAddr("eigenda rollup manager"); + + address eigenDASvcManager = makeAddr("eigenDASvcManager"); + address eigenDARollupManager = makeAddr("rollupManager"); RollupCreator.RollupDeploymentParams memory deployParams = RollupCreator .RollupDeploymentParams({ @@ -138,6 +142,7 @@ contract RollupCreatorTest is Test { batchPosterManager: batchPosterManager, eigenDARollupManager: eigenDARollupManager }); + address rollupAddress = rollupCreator.createRollup{value: factoryDeploymentFunds}( deployParams ); @@ -169,11 +174,6 @@ contract RollupCreatorTest is Test { batchPosterManager, "Invalid batch poster manager" ); - assertEq( - address(rollup.sequencerInbox().eigenDARollupManager()), - eigenDARollupManager, - "Invalid eigenda rollup manager" - ); // check proxy admin for non-rollup contracts address proxyAdminExpectedAddress = computeCreateAddress(address(rollupCreator), 1); @@ -287,8 +287,7 @@ contract RollupCreatorTest is Test { address[] memory validators = new address[](2); validators[0] = makeAddr("validator1"); validators[1] = makeAddr("validator2"); - - address eigenDARollupManager = makeAddr("eigendaRollupManager"); + address eigenDARollupManager = makeAddr("rollupManager"); RollupCreator.RollupDeploymentParams memory deployParams = RollupCreator .RollupDeploymentParams({ @@ -408,6 +407,103 @@ contract RollupCreatorTest is Test { ); } + function test_freezeDeployment() public { + vm.startPrank(deployer); + + rollupCreator.freezeDeployment(); + assertTrue(rollupCreator.deploymentFrozen(), "rollupCreator not frozen"); + + ISequencerInbox.MaxTimeVariation memory timeVars = ISequencerInbox.MaxTimeVariation( + ((60 * 60 * 24) / 15), + 12, + 60 * 60 * 24, + 60 * 60 + ); + Config memory config = Config({ + confirmPeriodBlocks: 20, + extraChallengeTimeBlocks: 200, + stakeToken: address(0), + baseStake: 1000, + wasmModuleRoot: keccak256("wasm"), + owner: rollupOwner, + loserStakeEscrow: address(200), + chainId: 1337, + chainConfig: "abc", + genesisBlockNum: 15_000_000, + sequencerInboxMaxTimeVariation: timeVars + }); + + // prepare funds + uint256 factoryDeploymentFunds = 1 ether; + vm.deal(deployer, factoryDeploymentFunds); + + /// deploy rollup + address[] memory batchPosters = new address[](1); + batchPosters[0] = makeAddr("batch poster 1"); + address batchPosterManager = makeAddr("batch poster manager"); + address[] memory validators = new address[](2); + validators[0] = makeAddr("validator1"); + validators[1] = makeAddr("validator2"); + + address eigenDARollupManager = makeAddr("rollupManager"); + + RollupCreator.RollupDeploymentParams memory deployParams = RollupCreator + .RollupDeploymentParams({ + config: config, + batchPosters: batchPosters, + validators: validators, + maxDataSize: MAX_DATA_SIZE, + nativeToken: address(0), + deployFactoriesToL2: true, + maxFeePerGasForRetryables: MAX_FEE_PER_GAS, + batchPosterManager: batchPosterManager, + eigenDARollupManager: eigenDARollupManager + }); + + vm.expectRevert("Deployment no longer permitted from this RollupCreator"); + rollupCreator.createRollup{value: factoryDeploymentFunds}( + deployParams + ); + + vm.stopPrank(); + } + + function test_setTemplates_onlyOnce() public { + vm.startPrank(deployer); + + BridgeCreator bridgeCreator = new BridgeCreator(ethBasedTemplates, erc20BasedTemplates); + + IUpgradeExecutor upgradeExecutorLogic = new UpgradeExecutorMock(); + + ( + IOneStepProofEntry ospEntry, + IChallengeManager challengeManager, + IRollupAdmin _rollupAdmin, + IRollupUser _rollupUser + ) = _prepareRollupDeployment(); + + rollupAdmin = _rollupAdmin; + rollupUser = _rollupUser; + + ValidatorUtils validatorUtils = new ValidatorUtils(); + ValidatorWalletCreator validatorWalletCreator = new ValidatorWalletCreator(); + + vm.expectRevert("Templates already set"); + rollupCreator.setTemplates( + bridgeCreator, + ospEntry, + challengeManager, + _rollupAdmin, + _rollupUser, + upgradeExecutorLogic, + address(validatorUtils), + address(validatorWalletCreator), + deployHelper + ); + + vm.stopPrank(); + } + function test_upgrade() public { vm.startPrank(deployer); @@ -443,7 +539,7 @@ contract RollupCreatorTest is Test { address[] memory validators = new address[](2); validators[0] = makeAddr("validator1"); validators[1] = makeAddr("validator2"); - address eigenDARollupManager = makeAddr("eigenda rollup manager"); + address eigenDARollupManager = makeAddr("rollupManager"); RollupCreator.RollupDeploymentParams memory deployParams = RollupCreator .RollupDeploymentParams({ @@ -547,4 +643,4 @@ contract ProxyUpgradeAction { contract Dummy { function dummy() public {} -} +} \ No newline at end of file