From e625b43aa54c8e7206797577b1d4141d70912499 Mon Sep 17 00:00:00 2001 From: Edmund Edgar Date: Wed, 20 Mar 2024 05:25:21 +0000 Subject: [PATCH 01/16] Break initialization out into an internal function, remove the duplication from executeFork, replace with AddressPair with a struct per fork. --- contracts/ForkingManager.sol | 208 ++++++++++------------- contracts/interfaces/IForkingManager.sol | 19 +-- 2 files changed, 98 insertions(+), 129 deletions(-) diff --git a/contracts/ForkingManager.sol b/contracts/ForkingManager.sol index 36fdbf17..6c6bbdce 100644 --- a/contracts/ForkingManager.sol +++ b/contracts/ForkingManager.sol @@ -100,41 +100,32 @@ contract ForkingManager is IForkingManager, ForkableStructure { executionTimeForProposal = (block.timestamp + forkPreparationTime); } - /** - * @dev function that executes a fork proposal - */ - function executeFork() external onlyBeforeForking { - if ( - executionTimeForProposal == 0 || - // solhint-disable-next-line not-rely-on-time - executionTimeForProposal > block.timestamp - ) { - revert NotYetReadyToFork(); - } - - // Create the children of each contract - NewInstances memory newInstances; - ( - newInstances.forkingManager.one, - newInstances.forkingManager.two - ) = _createChildren(); - (newInstances.bridge.one, newInstances.bridge.two) = IForkableBridge( - bridge - ).createChildren(); - (newInstances.zkEVM.one, newInstances.zkEVM.two) = IForkableZkEVM(zkEVM) - .createChildren(); - ( - newInstances.forkonomicToken.one, - newInstances.forkonomicToken.two - ) = IForkonomicToken(forkonomicToken).createChildren(); - ( - newInstances.globalExitRoot.one, - newInstances.globalExitRoot.two - ) = IForkableGlobalExitRoot(globalExitRoot).createChildren(); + function _prepareInitilizePackedParameters( + uint64 _newChainId + ) internal returns (IPolygonZkEVM.InitializePackedParameters memory) { + return + IPolygonZkEVM.InitializePackedParameters({ + admin: IPolygonZkEVM(zkEVM).admin(), + trustedSequencer: IPolygonZkEVM(zkEVM).trustedSequencer(), + pendingStateTimeout: IPolygonZkEVM(zkEVM).pendingStateTimeout(), + trustedAggregator: IPolygonZkEVM(zkEVM).trustedAggregator(), + trustedAggregatorTimeout: IPolygonZkEVM(zkEVM) + .trustedAggregatorTimeout(), + chainID: _newChainId, + forkID: IPolygonZkEVM(zkEVM).forkID(), + lastVerifiedBatch: IPolygonZkEVM(zkEVM).lastVerifiedBatch() + }); + } + function _initializeChild( + uint64 _chainId, + NewInstance memory _newInstance + ) internal { // Initialize the zkEVM contracts IPolygonZkEVM.InitializePackedParameters - memory initializePackedParameters; + memory initializePackedParameters = _prepareInitilizePackedParameters( + _chainId + ); { // retrieve some information from the zkEVM contract @@ -145,87 +136,41 @@ contract ForkingManager is IForkingManager, ForkableStructure { string memory trustedSequencerURL = IPolygonZkEVM(zkEVM) .trustedSequencerURL(); string memory networkName = IPolygonZkEVM(zkEVM).networkName(); - initializePackedParameters = IPolygonZkEVM - .InitializePackedParameters({ - admin: IPolygonZkEVM(zkEVM).admin(), - trustedSequencer: IPolygonZkEVM(zkEVM).trustedSequencer(), - pendingStateTimeout: IPolygonZkEVM(zkEVM) - .pendingStateTimeout(), - trustedAggregator: IPolygonZkEVM(zkEVM).trustedAggregator(), - trustedAggregatorTimeout: IPolygonZkEVM(zkEVM) - .trustedAggregatorTimeout(), - chainID: reservedChainIdForFork1, - forkID: IPolygonZkEVM(zkEVM).forkID(), - lastVerifiedBatch: IPolygonZkEVM(zkEVM).lastVerifiedBatch() - }); - IForkableZkEVM(newInstances.zkEVM.one).initialize( - newInstances.forkingManager.one, - zkEVM, - initializePackedParameters, - genesisRoot, - trustedSequencerURL, - networkName, - "0.1.0", // hardcoded as the version is not stored in the zkEVM contract, only emitted as event - IPolygonZkEVMGlobalExitRoot(newInstances.globalExitRoot.one), - IERC20Upgradeable(newInstances.forkonomicToken.one), - IForkableZkEVM(zkEVM).rollupVerifier(), - IPolygonZkEVMBridge(newInstances.bridge.one) - ); - initializePackedParameters.chainID = reservedChainIdForFork2; - IForkableZkEVM(newInstances.zkEVM.two).initialize( - newInstances.forkingManager.two, + IForkableZkEVM(_newInstance.zkEVM).initialize( + _newInstance.forkingManager, zkEVM, initializePackedParameters, genesisRoot, trustedSequencerURL, networkName, "0.1.0", // hardcoded as the version is not stored in the zkEVM contract, only emitted as event - IPolygonZkEVMGlobalExitRoot(newInstances.globalExitRoot.two), - IERC20Upgradeable(newInstances.forkonomicToken.two), + IPolygonZkEVMGlobalExitRoot(_newInstance.globalExitRoot), + IERC20Upgradeable(_newInstance.forkonomicToken), IForkableZkEVM(zkEVM).rollupVerifier(), - IPolygonZkEVMBridge(newInstances.bridge.two) + IPolygonZkEVMBridge(_newInstance.bridge) ); } // Initialize the tokens - IForkonomicToken(newInstances.forkonomicToken.one).initialize( - newInstances.forkingManager.one, + IForkonomicToken(_newInstance.forkonomicToken).initialize( + _newInstance.forkingManager, forkonomicToken, address(this), string.concat(IERC20Metadata(forkonomicToken).name(), "0"), IERC20Metadata(forkonomicToken).symbol() ); - IForkonomicToken(newInstances.forkonomicToken.two).initialize( - newInstances.forkingManager.two, - forkonomicToken, - address(this), - string.concat(IERC20Metadata(forkonomicToken).name(), "1"), - IERC20Metadata(forkonomicToken).symbol() - ); bytes32[DEPOSIT_CONTRACT_TREE_DEPTH] memory depositBranch = IForkableBridge(bridge).getBranch(); //Initialize the bridge contracts - IForkableBridge(newInstances.bridge.one).initialize( - newInstances.forkingManager.one, + IForkableBridge(_newInstance.bridge).initialize( + _newInstance.forkingManager, bridge, 0, // network identifiers will always be 0 on mainnet and 1 on L2 - IBasePolygonZkEVMGlobalExitRoot(newInstances.globalExitRoot.one), - address(newInstances.zkEVM.one), - address(newInstances.forkonomicToken.one), - false, - IForkableBridge(bridge).getHardAssetManager(), - IForkableBridge(bridge).getLastUpdatedDepositCount(), - depositBranch - ); - IForkableBridge(newInstances.bridge.two).initialize( - newInstances.forkingManager.two, - bridge, - 0, - IBasePolygonZkEVMGlobalExitRoot(newInstances.globalExitRoot.two), - address(newInstances.zkEVM.two), - address(newInstances.forkonomicToken.two), + IBasePolygonZkEVMGlobalExitRoot(_newInstance.globalExitRoot), + address(_newInstance.zkEVM), + address(_newInstance.forkonomicToken), false, IForkableBridge(bridge).getHardAssetManager(), IForkableBridge(bridge).getLastUpdatedDepositCount(), @@ -233,43 +178,74 @@ contract ForkingManager is IForkingManager, ForkableStructure { ); //Initialize the forking manager contracts - IForkingManager(newInstances.forkingManager.one).initialize( - newInstances.zkEVM.one, - newInstances.bridge.one, - newInstances.forkonomicToken.one, + IForkingManager(_newInstance.forkingManager).initialize( + _newInstance.zkEVM, + _newInstance.bridge, + _newInstance.forkonomicToken, address(this), - newInstances.globalExitRoot.one, - arbitrationFee, - chainIdManager, - forkPreparationTime - ); - IForkingManager(newInstances.forkingManager.two).initialize( - newInstances.zkEVM.two, - newInstances.bridge.two, - newInstances.forkonomicToken.two, - address(this), - newInstances.globalExitRoot.two, + _newInstance.globalExitRoot, arbitrationFee, chainIdManager, forkPreparationTime ); //Initialize the global exit root contracts - IForkableGlobalExitRoot(newInstances.globalExitRoot.one).initialize( - newInstances.forkingManager.one, + IForkableGlobalExitRoot(_newInstance.globalExitRoot).initialize( + _newInstance.forkingManager, globalExitRoot, - newInstances.zkEVM.one, - newInstances.bridge.one, + _newInstance.zkEVM, + _newInstance.bridge, IForkableGlobalExitRoot(globalExitRoot).lastMainnetExitRoot(), IForkableGlobalExitRoot(globalExitRoot).lastRollupExitRoot() ); - IForkableGlobalExitRoot(newInstances.globalExitRoot.two).initialize( - newInstances.forkingManager.two, - globalExitRoot, - newInstances.zkEVM.two, - newInstances.bridge.two, - IForkableGlobalExitRoot(globalExitRoot).lastMainnetExitRoot(), - IForkableGlobalExitRoot(globalExitRoot).lastRollupExitRoot() + } + + /** + * @dev function that executes a fork proposal + */ + function executeFork() external onlyBeforeForking { + if ( + executionTimeForProposal == 0 || + // solhint-disable-next-line not-rely-on-time + executionTimeForProposal > block.timestamp + ) { + revert NotYetReadyToFork(); + } + + (address forkingManager1, address forkingManager2) = _createChildren(); + + (address bridge1, address bridge2) = IForkableBridge(bridge) + .createChildren(); + + (address zkEVM1, address zkEVM2) = IForkableZkEVM(zkEVM) + .createChildren(); + + (address forkonomicToken1, address forkonomicToken2) = IForkonomicToken( + forkonomicToken + ).createChildren(); + + ( + address globalExitRoot1, + address globalExitRoot2 + ) = IForkableGlobalExitRoot(globalExitRoot).createChildren(); + + NewInstance memory child1 = NewInstance( + zkEVM1, + bridge1, + forkonomicToken1, + globalExitRoot1, + forkingManager1 + ); + + NewInstance memory child2 = NewInstance( + zkEVM2, + bridge2, + forkonomicToken2, + globalExitRoot2, + forkingManager2 ); + + _initializeChild(reservedChainIdForFork1, child1); + _initializeChild(reservedChainIdForFork2, child2); } } diff --git a/contracts/interfaces/IForkingManager.sol b/contracts/interfaces/IForkingManager.sol index fb69f8de..13b3d43a 100644 --- a/contracts/interfaces/IForkingManager.sol +++ b/contracts/interfaces/IForkingManager.sol @@ -48,19 +48,12 @@ interface IForkingManager is IForkableStructure { function isForkingExecuted() external returns (bool); - // Struct that holds an address pair used to store the new child contracts - struct AddressPair { - address one; - address two; - } - - // Struct containing the addresses of the new instances - struct NewInstances { - AddressPair forkingManager; - AddressPair bridge; - AddressPair zkEVM; - AddressPair forkonomicToken; - AddressPair globalExitRoot; + struct NewInstance { + address zkEVM; + address bridge; + address forkonomicToken; + address globalExitRoot; + address forkingManager; } /** From 447a3ee89b8c16b6e7a61fbb1f8a65c578d717f7 Mon Sep 17 00:00:00 2001 From: Edmund Edgar Date: Wed, 20 Mar 2024 22:10:23 +0000 Subject: [PATCH 02/16] Make a function in the ForkingManager implementation contract to spawn the original genesis deploy. (Haven't changed the deployment script yet). --- contracts/ForkingManager.sol | 201 ++++++++++++++++++++++++++++------- test/ForkingManager.t.sol | 135 ++++++++--------------- 2 files changed, 206 insertions(+), 130 deletions(-) diff --git a/contracts/ForkingManager.sol b/contracts/ForkingManager.sol index 6c6bbdce..f63905d7 100644 --- a/contracts/ForkingManager.sol +++ b/contracts/ForkingManager.sol @@ -5,6 +5,7 @@ import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import {IPolygonZkEVM} from "@RealityETH/zkevm-contracts/contracts/interfaces/IPolygonZkEVM.sol"; +import {IVerifierRollup} from "@RealityETH/zkevm-contracts/contracts/interfaces/IVerifierRollup.sol"; import {IPolygonZkEVMGlobalExitRoot} from "@RealityETH/zkevm-contracts/contracts/interfaces/IPolygonZkEVMGlobalExitRoot.sol"; import {IERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol"; import {IBasePolygonZkEVMGlobalExitRoot} from "@RealityETH/zkevm-contracts/contracts/inheritedMainContracts/PolygonZkEVMBridge.sol"; @@ -16,8 +17,31 @@ import {IForkingManager} from "./interfaces/IForkingManager.sol"; import {IForkonomicToken} from "./interfaces/IForkonomicToken.sol"; import {IForkableGlobalExitRoot} from "./interfaces/IForkableGlobalExitRoot.sol"; import {ChainIdManager} from "./ChainIdManager.sol"; +import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; contract ForkingManager is IForkingManager, ForkableStructure { + struct DeploymentConfig { + bytes32 genesisRoot; + string trustedSequencerURL; + string networkName; + string version; + IVerifierRollup rollupVerifier; + address minter; + string tokenName; + string tokenSymbol; + uint256 arbitrationFee; + address chainIdManager; + uint256 forkPreparationTime; + address hardAssetManager; + uint32 lastUpdatedDepositCount; // starts at 0 + bytes32 lastMainnetExitRoot; + bytes32 lastRollupExitRoot; + address parentGlobalExitRoot; + address parentZkEVM; + address parentForkonomicToken; + address parentBridge; + } + using SafeERC20 for IERC20; // The depth of the deposit contract tree @@ -66,6 +90,58 @@ contract ForkingManager is IForkingManager, ForkableStructure { ForkableStructure.initialize(address(this), _parentContract); } + // This can be called against the initial ForkingManager implementation to spawn a ForkingManager instance and all the other contracts involved + function spawnInstance( + address _admin, + address _zkEVMImplementation, + address _bridgeImplementation, + address _forkonomicTokenImplementation, + address _globalExitRootImplementation, + uint64 _genesisChainId, + DeploymentConfig memory _deploymentConfig, + IPolygonZkEVM.InitializePackedParameters + memory _initializePackedParameters + ) external returns (address) { + NewInstance memory instance = NewInstance( + address( + new TransparentUpgradeableProxy( + _zkEVMImplementation, + _admin, + "" + ) + ), + address( + new TransparentUpgradeableProxy( + _bridgeImplementation, + _admin, + "" + ) + ), + address( + new TransparentUpgradeableProxy( + _forkonomicTokenImplementation, + _admin, + "" + ) + ), + address( + new TransparentUpgradeableProxy( + _globalExitRootImplementation, + _admin, + "" + ) + ), + address(new TransparentUpgradeableProxy(address(this), _admin, "")) + ); + _initializeStack( + _genesisChainId, + instance, + _deploymentConfig, + _initializePackedParameters + ); + return instance.forkingManager; + } + function isForkingInitiated() external view returns (bool) { return (executionTimeForProposal > 0); } @@ -100,7 +176,7 @@ contract ForkingManager is IForkingManager, ForkableStructure { executionTimeForProposal = (block.timestamp + forkPreparationTime); } - function _prepareInitilizePackedParameters( + function _prepareInitializePackedParameters( uint64 _newChainId ) internal returns (IPolygonZkEVM.InitializePackedParameters memory) { return @@ -117,36 +193,26 @@ contract ForkingManager is IForkingManager, ForkableStructure { }); } - function _initializeChild( + function _initializeStack( uint64 _chainId, - NewInstance memory _newInstance - ) internal { - // Initialize the zkEVM contracts + NewInstance memory _newInstance, + DeploymentConfig memory _deploymentConfig, IPolygonZkEVM.InitializePackedParameters - memory initializePackedParameters = _prepareInitilizePackedParameters( - _chainId - ); - + memory initializePackedParameters + ) internal { { - // retrieve some information from the zkEVM contract - bytes32 genesisRoot = IPolygonZkEVM(zkEVM).batchNumToStateRoot( - IPolygonZkEVM(zkEVM).lastVerifiedBatch() - ); - // the following variables could be used to save gas, but it requires via-ir in the compiler settings - string memory trustedSequencerURL = IPolygonZkEVM(zkEVM) - .trustedSequencerURL(); - string memory networkName = IPolygonZkEVM(zkEVM).networkName(); + string memory networkName = _deploymentConfig.networkName; IForkableZkEVM(_newInstance.zkEVM).initialize( _newInstance.forkingManager, - zkEVM, + _deploymentConfig.parentZkEVM, initializePackedParameters, - genesisRoot, - trustedSequencerURL, - networkName, - "0.1.0", // hardcoded as the version is not stored in the zkEVM contract, only emitted as event + _deploymentConfig.genesisRoot, + _deploymentConfig.trustedSequencerURL, + _deploymentConfig.networkName, + _deploymentConfig.version, IPolygonZkEVMGlobalExitRoot(_newInstance.globalExitRoot), IERC20Upgradeable(_newInstance.forkonomicToken), - IForkableZkEVM(zkEVM).rollupVerifier(), + _deploymentConfig.rollupVerifier, IPolygonZkEVMBridge(_newInstance.bridge) ); } @@ -154,26 +220,28 @@ contract ForkingManager is IForkingManager, ForkableStructure { // Initialize the tokens IForkonomicToken(_newInstance.forkonomicToken).initialize( _newInstance.forkingManager, - forkonomicToken, - address(this), - string.concat(IERC20Metadata(forkonomicToken).name(), "0"), - IERC20Metadata(forkonomicToken).symbol() + _deploymentConfig.parentForkonomicToken, + _deploymentConfig.minter, // TODO should this just be the parent token? + _deploymentConfig.tokenName, + _deploymentConfig.tokenSymbol ); - bytes32[DEPOSIT_CONTRACT_TREE_DEPTH] - memory depositBranch = IForkableBridge(bridge).getBranch(); + bytes32[DEPOSIT_CONTRACT_TREE_DEPTH] memory depositBranch; + if (address(bridge) != address(0)) { + depositBranch = IForkableBridge(bridge).getBranch(); + } //Initialize the bridge contracts IForkableBridge(_newInstance.bridge).initialize( _newInstance.forkingManager, - bridge, + _deploymentConfig.parentBridge, 0, // network identifiers will always be 0 on mainnet and 1 on L2 IBasePolygonZkEVMGlobalExitRoot(_newInstance.globalExitRoot), address(_newInstance.zkEVM), address(_newInstance.forkonomicToken), false, - IForkableBridge(bridge).getHardAssetManager(), - IForkableBridge(bridge).getLastUpdatedDepositCount(), + _deploymentConfig.hardAssetManager, + _deploymentConfig.lastUpdatedDepositCount, depositBranch ); @@ -182,24 +250,63 @@ contract ForkingManager is IForkingManager, ForkableStructure { _newInstance.zkEVM, _newInstance.bridge, _newInstance.forkonomicToken, - address(this), + address(this), // TODO check this _newInstance.globalExitRoot, - arbitrationFee, - chainIdManager, - forkPreparationTime + _deploymentConfig.arbitrationFee, + _deploymentConfig.chainIdManager, + _deploymentConfig.forkPreparationTime ); //Initialize the global exit root contracts IForkableGlobalExitRoot(_newInstance.globalExitRoot).initialize( _newInstance.forkingManager, - globalExitRoot, + _deploymentConfig.parentGlobalExitRoot, _newInstance.zkEVM, _newInstance.bridge, - IForkableGlobalExitRoot(globalExitRoot).lastMainnetExitRoot(), - IForkableGlobalExitRoot(globalExitRoot).lastRollupExitRoot() + _deploymentConfig.lastMainnetExitRoot, + _deploymentConfig.lastRollupExitRoot ); } + /** + * @dev Clones the current deployment ready to configure a child in a fork + */ + function _cloneDeploymentConfig() + internal + returns (DeploymentConfig memory) + { + return + DeploymentConfig({ + genesisRoot: IPolygonZkEVM(zkEVM).batchNumToStateRoot( + IPolygonZkEVM(zkEVM).lastVerifiedBatch() + ), + trustedSequencerURL: IPolygonZkEVM(zkEVM).trustedSequencerURL(), + networkName: IPolygonZkEVM(zkEVM).networkName(), + version: "0.0.1", // hardcoded as the version is not stored in the zkEVM contract, only emitted as event + rollupVerifier: IForkableZkEVM(zkEVM).rollupVerifier(), + minter: address(0), // We only mint against genesis + tokenName: string.concat( + IERC20Metadata(forkonomicToken).name(), + "0" + ), + tokenSymbol: IERC20Metadata(forkonomicToken).symbol(), + arbitrationFee: arbitrationFee, + chainIdManager: chainIdManager, + forkPreparationTime: forkPreparationTime, + hardAssetManager: IForkableBridge(bridge).getHardAssetManager(), + lastUpdatedDepositCount: IForkableBridge(bridge) + .getLastUpdatedDepositCount(), + lastMainnetExitRoot: IForkableGlobalExitRoot(globalExitRoot) + .lastMainnetExitRoot(), + lastRollupExitRoot: IForkableGlobalExitRoot(globalExitRoot) + .lastRollupExitRoot(), + parentGlobalExitRoot: globalExitRoot, + parentZkEVM: zkEVM, + parentForkonomicToken: forkonomicToken, + parentBridge: bridge + }); + } + /** * @dev function that executes a fork proposal */ @@ -245,7 +352,19 @@ contract ForkingManager is IForkingManager, ForkableStructure { forkingManager2 ); - _initializeChild(reservedChainIdForFork1, child1); - _initializeChild(reservedChainIdForFork2, child2); + DeploymentConfig memory deploymentConfig = _cloneDeploymentConfig(); + + _initializeStack( + reservedChainIdForFork1, + child1, + deploymentConfig, + _prepareInitializePackedParameters(reservedChainIdForFork1) + ); + _initializeStack( + reservedChainIdForFork2, + child2, + deploymentConfig, + _prepareInitializePackedParameters(reservedChainIdForFork2) + ); } } diff --git a/test/ForkingManager.t.sol b/test/ForkingManager.t.sol index e3b942f6..21ee5b48 100644 --- a/test/ForkingManager.t.sol +++ b/test/ForkingManager.t.sol @@ -88,70 +88,16 @@ contract ForkingManagerTest is Test { event Transfer(address indexed from, address indexed to, uint256 tokenId); function setUp() public { - bridgeImplementation = address(new ForkableBridge()); - bridge = ForkableBridge( - address( - new TransparentUpgradeableProxy(bridgeImplementation, admin, "") - ) - ); forkmanagerImplementation = address(new ForkingManager()); - forkmanager = ForkingManager( - address( - new TransparentUpgradeableProxy( - forkmanagerImplementation, - admin, - "" - ) - ) - ); - zkevmImplementation = address(new ForkableZkEVM()); - zkevm = ForkableZkEVM( - address( - new TransparentUpgradeableProxy(zkevmImplementation, admin, "") - ) - ); + bridgeImplementation = address(new ForkableBridge()); forkonomicTokenImplementation = address(new ForkonomicToken()); - forkonomicToken = ForkonomicToken( - address( - new TransparentUpgradeableProxy( - forkonomicTokenImplementation, - admin, - "" - ) - ) - ); + zkevmImplementation = address(new ForkableZkEVM()); globalExitRootImplementation = address(new ForkableGlobalExitRoot()); - globalExitRoot = ForkableGlobalExitRoot( - address( - new TransparentUpgradeableProxy( - globalExitRootImplementation, - admin, - "" - ) - ) - ); + ChainIdManager chainIdManager = new ChainIdManager(initialChainId); chainIdManagerAddress = address(chainIdManager); - globalExitRoot.initialize( - address(forkmanager), - address(0x0), - address(zkevm), - address(bridge), - bytes32(0), - bytes32(0) - ); - bridge.initialize( - address(forkmanager), - address(0x0), - networkID, - globalExitRoot, - address(zkevm), - address(forkonomicToken), - false, - hardAssetManger, - 0, - depositTree - ); + + uint64 chainId = chainIdManager.getNextUsableChainId(); IPolygonZkEVM.InitializePackedParameters memory initializePackedParameters = IPolygonZkEVM @@ -161,40 +107,51 @@ contract ForkingManagerTest is Test { pendingStateTimeout: pendingStateTimeout, trustedAggregator: trustedAggregator, trustedAggregatorTimeout: trustedAggregatorTimeout, - chainID: chainIdManager.getNextUsableChainId(), + chainID: chainId, forkID: forkID, lastVerifiedBatch: 0 }); - zkevm.initialize( - address(forkmanager), - address(0x0), - initializePackedParameters, - genesisRoot, - "trustedSequencerURL", - "test network", - "0.0.1", - globalExitRoot, - IERC20Upgradeable(address(forkonomicToken)), - rollupVerifierMock, - IPolygonZkEVMBridge(address(bridge)) - ); - forkmanager.initialize( - address(zkevm), - address(bridge), - address(forkonomicToken), - address(0x0), - address(globalExitRoot), - arbitrationFee, - chainIdManagerAddress, - forkPreparationTime - ); - forkonomicToken.initialize( - address(forkmanager), - address(0x0), - address(this), - "Fork", - "FORK" + + ForkingManager.DeploymentConfig memory deploymentConfig = ForkingManager + .DeploymentConfig({ + genesisRoot: genesisRoot, + trustedSequencerURL: "trustedSequencerURL", + networkName: "my network", + version: "0.0.1", + rollupVerifier: IVerifierRollup(rollupVerifierMock), + minter: address(this), + tokenName: "Fork", + tokenSymbol: "FORK", + arbitrationFee: arbitrationFee, + chainIdManager: chainIdManagerAddress, + forkPreparationTime: forkPreparationTime, + hardAssetManager: hardAssetManger, + lastUpdatedDepositCount: 0, + lastMainnetExitRoot: bytes32(0), + lastRollupExitRoot: bytes32(0), + parentGlobalExitRoot: address(0), + parentZkEVM: address(0), + parentForkonomicToken: address(0), + parentBridge: address(0) + }); + + forkmanager = ForkingManager( + ForkingManager(forkmanagerImplementation).spawnInstance( + admin, + zkevmImplementation, + bridgeImplementation, + forkonomicTokenImplementation, + globalExitRootImplementation, + chainId, + deploymentConfig, + initializePackedParameters + ) ); + + bridge = ForkableBridge(forkmanager.bridge()); + zkevm = ForkableZkEVM(forkmanager.zkEVM()); + forkonomicToken = ForkonomicToken(forkmanager.forkonomicToken()); + globalExitRoot = ForkableGlobalExitRoot(forkmanager.globalExitRoot()); } function testForkingStatusFunctions() public { From 3cace673c36ddc6566d23c2ccc2a65db0b648eb1 Mon Sep 17 00:00:00 2001 From: Edmund Edgar Date: Wed, 20 Mar 2024 22:36:36 +0000 Subject: [PATCH 03/16] linting, remove unused chainid params which are already in intializePackedParameters --- contracts/ForkingManager.sol | 8 +------- test/ForkingManager.t.sol | 4 ---- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/contracts/ForkingManager.sol b/contracts/ForkingManager.sol index f63905d7..2251efc3 100644 --- a/contracts/ForkingManager.sol +++ b/contracts/ForkingManager.sol @@ -97,7 +97,6 @@ contract ForkingManager is IForkingManager, ForkableStructure { address _bridgeImplementation, address _forkonomicTokenImplementation, address _globalExitRootImplementation, - uint64 _genesisChainId, DeploymentConfig memory _deploymentConfig, IPolygonZkEVM.InitializePackedParameters memory _initializePackedParameters @@ -134,7 +133,6 @@ contract ForkingManager is IForkingManager, ForkableStructure { address(new TransparentUpgradeableProxy(address(this), _admin, "")) ); _initializeStack( - _genesisChainId, instance, _deploymentConfig, _initializePackedParameters @@ -178,7 +176,7 @@ contract ForkingManager is IForkingManager, ForkableStructure { function _prepareInitializePackedParameters( uint64 _newChainId - ) internal returns (IPolygonZkEVM.InitializePackedParameters memory) { + ) internal view returns (IPolygonZkEVM.InitializePackedParameters memory) { return IPolygonZkEVM.InitializePackedParameters({ admin: IPolygonZkEVM(zkEVM).admin(), @@ -194,14 +192,12 @@ contract ForkingManager is IForkingManager, ForkableStructure { } function _initializeStack( - uint64 _chainId, NewInstance memory _newInstance, DeploymentConfig memory _deploymentConfig, IPolygonZkEVM.InitializePackedParameters memory initializePackedParameters ) internal { { - string memory networkName = _deploymentConfig.networkName; IForkableZkEVM(_newInstance.zkEVM).initialize( _newInstance.forkingManager, _deploymentConfig.parentZkEVM, @@ -355,13 +351,11 @@ contract ForkingManager is IForkingManager, ForkableStructure { DeploymentConfig memory deploymentConfig = _cloneDeploymentConfig(); _initializeStack( - reservedChainIdForFork1, child1, deploymentConfig, _prepareInitializePackedParameters(reservedChainIdForFork1) ); _initializeStack( - reservedChainIdForFork2, child2, deploymentConfig, _prepareInitializePackedParameters(reservedChainIdForFork2) diff --git a/test/ForkingManager.t.sol b/test/ForkingManager.t.sol index 21ee5b48..2daf9560 100644 --- a/test/ForkingManager.t.sol +++ b/test/ForkingManager.t.sol @@ -13,10 +13,7 @@ import {IForkableStructure} from "../contracts/interfaces/IForkableStructure.sol import {IPolygonZkEVMGlobalExitRoot} from "@RealityETH/zkevm-contracts/contracts/interfaces/IPolygonZkEVMGlobalExitRoot.sol"; import {IForkingManager} from "../contracts/interfaces/IForkingManager.sol"; import {IVerifierRollup} from "@RealityETH/zkevm-contracts/contracts/interfaces/IVerifierRollup.sol"; -import {IPolygonZkEVMBridge} from "@RealityETH/zkevm-contracts/contracts/interfaces/IPolygonZkEVMBridge.sol"; -import {IERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/interfaces/IERC20Upgradeable.sol"; import {IPolygonZkEVM} from "@RealityETH/zkevm-contracts/contracts/interfaces/IPolygonZkEVM.sol"; -import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; import {ChainIdManager} from "../contracts/ChainIdManager.sol"; import {ForkableZkEVM} from "../contracts/ForkableZkEVM.sol"; import {Util} from "./utils/Util.sol"; @@ -142,7 +139,6 @@ contract ForkingManagerTest is Test { bridgeImplementation, forkonomicTokenImplementation, globalExitRootImplementation, - chainId, deploymentConfig, initializePackedParameters ) From dfc6771f5c6fc7c3368164db0f71d12ab844d6f5 Mon Sep 17 00:00:00 2001 From: Edmund Edgar Date: Wed, 20 Mar 2024 22:46:13 +0000 Subject: [PATCH 04/16] Put DeploymentConfig struct definition in interface, use an address for the rollup verifier for consistency --- contracts/ForkingManager.sol | 29 ++++-------------------- contracts/interfaces/IForkingManager.sol | 22 ++++++++++++++++++ test/ForkingManager.t.sol | 4 ++-- 3 files changed, 28 insertions(+), 27 deletions(-) diff --git a/contracts/ForkingManager.sol b/contracts/ForkingManager.sol index 2251efc3..7d9cfcc1 100644 --- a/contracts/ForkingManager.sol +++ b/contracts/ForkingManager.sol @@ -20,27 +20,6 @@ import {ChainIdManager} from "./ChainIdManager.sol"; import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; contract ForkingManager is IForkingManager, ForkableStructure { - struct DeploymentConfig { - bytes32 genesisRoot; - string trustedSequencerURL; - string networkName; - string version; - IVerifierRollup rollupVerifier; - address minter; - string tokenName; - string tokenSymbol; - uint256 arbitrationFee; - address chainIdManager; - uint256 forkPreparationTime; - address hardAssetManager; - uint32 lastUpdatedDepositCount; // starts at 0 - bytes32 lastMainnetExitRoot; - bytes32 lastRollupExitRoot; - address parentGlobalExitRoot; - address parentZkEVM; - address parentForkonomicToken; - address parentBridge; - } using SafeERC20 for IERC20; @@ -97,7 +76,7 @@ contract ForkingManager is IForkingManager, ForkableStructure { address _bridgeImplementation, address _forkonomicTokenImplementation, address _globalExitRootImplementation, - DeploymentConfig memory _deploymentConfig, + IForkingManager.DeploymentConfig memory _deploymentConfig, IPolygonZkEVM.InitializePackedParameters memory _initializePackedParameters ) external returns (address) { @@ -193,7 +172,7 @@ contract ForkingManager is IForkingManager, ForkableStructure { function _initializeStack( NewInstance memory _newInstance, - DeploymentConfig memory _deploymentConfig, + IForkingManager.DeploymentConfig memory _deploymentConfig, IPolygonZkEVM.InitializePackedParameters memory initializePackedParameters ) internal { @@ -208,7 +187,7 @@ contract ForkingManager is IForkingManager, ForkableStructure { _deploymentConfig.version, IPolygonZkEVMGlobalExitRoot(_newInstance.globalExitRoot), IERC20Upgradeable(_newInstance.forkonomicToken), - _deploymentConfig.rollupVerifier, + IVerifierRollup(_deploymentConfig.rollupVerifier), IPolygonZkEVMBridge(_newInstance.bridge) ); } @@ -279,7 +258,7 @@ contract ForkingManager is IForkingManager, ForkableStructure { trustedSequencerURL: IPolygonZkEVM(zkEVM).trustedSequencerURL(), networkName: IPolygonZkEVM(zkEVM).networkName(), version: "0.0.1", // hardcoded as the version is not stored in the zkEVM contract, only emitted as event - rollupVerifier: IForkableZkEVM(zkEVM).rollupVerifier(), + rollupVerifier: address(IForkableZkEVM(zkEVM).rollupVerifier()), minter: address(0), // We only mint against genesis tokenName: string.concat( IERC20Metadata(forkonomicToken).name(), diff --git a/contracts/interfaces/IForkingManager.sol b/contracts/interfaces/IForkingManager.sol index 13b3d43a..a438471f 100644 --- a/contracts/interfaces/IForkingManager.sol +++ b/contracts/interfaces/IForkingManager.sol @@ -28,6 +28,28 @@ interface IForkingManager is IForkableStructure { uint64 forkID; } + struct DeploymentConfig { + bytes32 genesisRoot; + string trustedSequencerURL; + string networkName; + string version; + address rollupVerifier; + address minter; + string tokenName; + string tokenSymbol; + uint256 arbitrationFee; + address chainIdManager; + uint256 forkPreparationTime; + address hardAssetManager; + uint32 lastUpdatedDepositCount; // starts at 0 + bytes32 lastMainnetExitRoot; + bytes32 lastRollupExitRoot; + address parentGlobalExitRoot; + address parentZkEVM; + address parentForkonomicToken; + address parentBridge; + } + function zkEVM() external returns (address); function bridge() external returns (address); diff --git a/test/ForkingManager.t.sol b/test/ForkingManager.t.sol index 2daf9560..04e7ebe5 100644 --- a/test/ForkingManager.t.sol +++ b/test/ForkingManager.t.sol @@ -109,13 +109,13 @@ contract ForkingManagerTest is Test { lastVerifiedBatch: 0 }); - ForkingManager.DeploymentConfig memory deploymentConfig = ForkingManager + IForkingManager.DeploymentConfig memory deploymentConfig = IForkingManager .DeploymentConfig({ genesisRoot: genesisRoot, trustedSequencerURL: "trustedSequencerURL", networkName: "my network", version: "0.0.1", - rollupVerifier: IVerifierRollup(rollupVerifierMock), + rollupVerifier: address(rollupVerifierMock), minter: address(this), tokenName: "Fork", tokenSymbol: "FORK", From e275204ed73cb8daad9d4fa6f1f3b3c34e071d7c Mon Sep 17 00:00:00 2001 From: Edmund Edgar Date: Wed, 20 Mar 2024 22:49:39 +0000 Subject: [PATCH 05/16] linting --- contracts/ForkingManager.sol | 1 - test/ForkingManager.t.sol | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/contracts/ForkingManager.sol b/contracts/ForkingManager.sol index 7d9cfcc1..6e32321a 100644 --- a/contracts/ForkingManager.sol +++ b/contracts/ForkingManager.sol @@ -20,7 +20,6 @@ import {ChainIdManager} from "./ChainIdManager.sol"; import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; contract ForkingManager is IForkingManager, ForkableStructure { - using SafeERC20 for IERC20; // The depth of the deposit contract tree diff --git a/test/ForkingManager.t.sol b/test/ForkingManager.t.sol index 04e7ebe5..f1900207 100644 --- a/test/ForkingManager.t.sol +++ b/test/ForkingManager.t.sol @@ -109,8 +109,8 @@ contract ForkingManagerTest is Test { lastVerifiedBatch: 0 }); - IForkingManager.DeploymentConfig memory deploymentConfig = IForkingManager - .DeploymentConfig({ + IForkingManager.DeploymentConfig + memory deploymentConfig = IForkingManager.DeploymentConfig({ genesisRoot: genesisRoot, trustedSequencerURL: "trustedSequencerURL", networkName: "my network", From 70a31bdeeba74a28ad71b5f6e9b74398aa2c2d23 Mon Sep 17 00:00:00 2001 From: Edmund Edgar Date: Fri, 22 Mar 2024 04:18:55 +0000 Subject: [PATCH 06/16] Initial deployment needs the proxy for the token not just the implementation, as its address is used when making zkevm params --- contracts/ForkingManager.sol | 10 ++-------- test/ForkingManager.t.sol | 9 ++++++++- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/contracts/ForkingManager.sol b/contracts/ForkingManager.sol index 6e32321a..2a281dff 100644 --- a/contracts/ForkingManager.sol +++ b/contracts/ForkingManager.sol @@ -70,10 +70,10 @@ contract ForkingManager is IForkingManager, ForkableStructure { // This can be called against the initial ForkingManager implementation to spawn a ForkingManager instance and all the other contracts involved function spawnInstance( + address _forkonomicToken, // This should be deployed but not initialized as its address is needed to create genesis.json address _admin, address _zkEVMImplementation, address _bridgeImplementation, - address _forkonomicTokenImplementation, address _globalExitRootImplementation, IForkingManager.DeploymentConfig memory _deploymentConfig, IPolygonZkEVM.InitializePackedParameters @@ -94,13 +94,7 @@ contract ForkingManager is IForkingManager, ForkableStructure { "" ) ), - address( - new TransparentUpgradeableProxy( - _forkonomicTokenImplementation, - _admin, - "" - ) - ), + _forkonomicToken, address( new TransparentUpgradeableProxy( _globalExitRootImplementation, diff --git a/test/ForkingManager.t.sol b/test/ForkingManager.t.sol index f1900207..57bccf5c 100644 --- a/test/ForkingManager.t.sol +++ b/test/ForkingManager.t.sol @@ -17,6 +17,7 @@ import {IPolygonZkEVM} from "@RealityETH/zkevm-contracts/contracts/interfaces/IP import {ChainIdManager} from "../contracts/ChainIdManager.sol"; import {ForkableZkEVM} from "../contracts/ForkableZkEVM.sol"; import {Util} from "./utils/Util.sol"; +import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; contract ForkingManagerTest is Test { ForkableBridge public bridge; @@ -134,10 +135,16 @@ contract ForkingManagerTest is Test { forkmanager = ForkingManager( ForkingManager(forkmanagerImplementation).spawnInstance( + address( + new TransparentUpgradeableProxy( + forkonomicTokenImplementation, + admin, + "" + ) + ), admin, zkevmImplementation, bridgeImplementation, - forkonomicTokenImplementation, globalExitRootImplementation, deploymentConfig, initializePackedParameters From 41e13ca0510cc697ab507ecd51894abba4e4593b Mon Sep 17 00:00:00 2001 From: Edmund Edgar Date: Tue, 26 Mar 2024 01:08:21 +0000 Subject: [PATCH 07/16] Revert "Initial deployment needs the proxy for the token not just the implementation, as its address is used when making zkevm params" This reverts commit 70a31bdeeba74a28ad71b5f6e9b74398aa2c2d23. --- contracts/ForkingManager.sol | 10 ++++++++-- test/ForkingManager.t.sol | 9 +-------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/contracts/ForkingManager.sol b/contracts/ForkingManager.sol index 2a281dff..6e32321a 100644 --- a/contracts/ForkingManager.sol +++ b/contracts/ForkingManager.sol @@ -70,10 +70,10 @@ contract ForkingManager is IForkingManager, ForkableStructure { // This can be called against the initial ForkingManager implementation to spawn a ForkingManager instance and all the other contracts involved function spawnInstance( - address _forkonomicToken, // This should be deployed but not initialized as its address is needed to create genesis.json address _admin, address _zkEVMImplementation, address _bridgeImplementation, + address _forkonomicTokenImplementation, address _globalExitRootImplementation, IForkingManager.DeploymentConfig memory _deploymentConfig, IPolygonZkEVM.InitializePackedParameters @@ -94,7 +94,13 @@ contract ForkingManager is IForkingManager, ForkableStructure { "" ) ), - _forkonomicToken, + address( + new TransparentUpgradeableProxy( + _forkonomicTokenImplementation, + _admin, + "" + ) + ), address( new TransparentUpgradeableProxy( _globalExitRootImplementation, diff --git a/test/ForkingManager.t.sol b/test/ForkingManager.t.sol index 57bccf5c..f1900207 100644 --- a/test/ForkingManager.t.sol +++ b/test/ForkingManager.t.sol @@ -17,7 +17,6 @@ import {IPolygonZkEVM} from "@RealityETH/zkevm-contracts/contracts/interfaces/IP import {ChainIdManager} from "../contracts/ChainIdManager.sol"; import {ForkableZkEVM} from "../contracts/ForkableZkEVM.sol"; import {Util} from "./utils/Util.sol"; -import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; contract ForkingManagerTest is Test { ForkableBridge public bridge; @@ -135,16 +134,10 @@ contract ForkingManagerTest is Test { forkmanager = ForkingManager( ForkingManager(forkmanagerImplementation).spawnInstance( - address( - new TransparentUpgradeableProxy( - forkonomicTokenImplementation, - admin, - "" - ) - ), admin, zkevmImplementation, bridgeImplementation, + forkonomicTokenImplementation, globalExitRootImplementation, deploymentConfig, initializePackedParameters From 4cf5b769c4249b9ad03f0a5841e865caa1cbfc07 Mon Sep 17 00:00:00 2001 From: Edmund Edgar Date: Wed, 27 Mar 2024 03:14:41 +0000 Subject: [PATCH 08/16] Use create2 for the spawnInstance deploys as it's easier than counting nonces --- contracts/ForkingManager.sol | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/contracts/ForkingManager.sol b/contracts/ForkingManager.sol index 6e32321a..7f32e99f 100644 --- a/contracts/ForkingManager.sol +++ b/contracts/ForkingManager.sol @@ -79,36 +79,38 @@ contract ForkingManager is IForkingManager, ForkableStructure { IPolygonZkEVM.InitializePackedParameters memory _initializePackedParameters ) external returns (address) { + // Genesis deployment is salted by hash of sender + bytes32 salt = keccak256(abi.encodePacked(msg.sender)); NewInstance memory instance = NewInstance( address( - new TransparentUpgradeableProxy( + new TransparentUpgradeableProxy{salt:salt}( _zkEVMImplementation, _admin, "" ) ), address( - new TransparentUpgradeableProxy( + new TransparentUpgradeableProxy{salt:salt}( _bridgeImplementation, _admin, "" ) ), address( - new TransparentUpgradeableProxy( + new TransparentUpgradeableProxy{salt:salt}( _forkonomicTokenImplementation, _admin, "" ) ), address( - new TransparentUpgradeableProxy( + new TransparentUpgradeableProxy{salt:salt}( _globalExitRootImplementation, _admin, "" ) ), - address(new TransparentUpgradeableProxy(address(this), _admin, "")) + address(new TransparentUpgradeableProxy{salt:salt}(address(this), _admin, "")) ); _initializeStack( instance, From 8e430748f9534ed08de3c24dea2e864f04b761ac Mon Sep 17 00:00:00 2001 From: Edmund Edgar Date: Wed, 27 Mar 2024 03:40:41 +0000 Subject: [PATCH 09/16] Do most deploys in initial step, make sure everything is deterministic, deploy with spawnInstance --- src/deployment/1_deployforkableToken.js | 208 +++---- src/deployment/2_creategenesis.js | 25 +- src/deployment/3_deployContracts.js | 746 ++++-------------------- src/deployment/common.js | 57 +- 4 files changed, 285 insertions(+), 751 deletions(-) diff --git a/src/deployment/1_deployforkableToken.js b/src/deployment/1_deployforkableToken.js index 05132576..299758a2 100644 --- a/src/deployment/1_deployforkableToken.js +++ b/src/deployment/1_deployforkableToken.js @@ -1,3 +1,5 @@ +// This deploys the keyless deployer, then uses it deploy implementations with create2 + /* eslint-disable no-await-in-loop, no-use-before-define, no-lonely-if, import/no-dynamic-require, global-require */ /* eslint-disable no-console, no-inner-declarations, no-undef, import/no-unresolved, no-restricted-syntax */ const path = require('path'); @@ -10,146 +12,120 @@ const { deployPolygonZkEVMDeployer } = require('./helpers/deployment-helpers'); const { create2Deployment } = require('./helpers/deployment-helpers'); const deployParameters = require('./deploy_parameters.json'); +const generatedPath = path.join(__dirname, './deploy_generated.json'); + const pathDeployParameters = path.join(__dirname, './deploy_parameters.json'); +const commonDeployment = require('./common'); +const common = require('../common/common'); + async function main() { - const attemptsDeployProxy = 5; - // Load provider - let currentProvider = ethers.provider; - if (process.env.HARDHAT_NETWORK === 'localhost') { - currentProvider = new ethers.providers.JsonRpcProvider('https://127.0.0.1:8454'); - } else { - if (deployParameters.multiplierGas || deployParameters.maxFeePerGas) { - if (process.env.HARDHAT_NETWORK !== 'hardhat') { - currentProvider = new ethers.providers.JsonRpcProvider(`https://${process.env.HARDHAT_NETWORK}.infura.io/v3/${process.env.INFURA_PROJECT_ID}`); - if (deployParameters.maxPriorityFeePerGas && deployParameters.maxFeePerGas) { - console.log(`Hardcoded gas used: MaxPriority${deployParameters.maxPriorityFeePerGas} gwei, MaxFee${deployParameters.maxFeePerGas} gwei`); - const FEE_DATA = { - maxFeePerGas: ethers.utils.parseUnits(deployParameters.maxFeePerGas, 'gwei'), - maxPriorityFeePerGas: ethers.utils.parseUnits(deployParameters.maxPriorityFeePerGas, 'gwei'), - }; - currentProvider.getFeeData = async () => FEE_DATA; - } else { - console.log('Multiplier gas used: ', deployParameters.multiplierGas); - async function overrideFeeData() { - const feedata = await ethers.provider.getFeeData(); - return { - maxFeePerGas: feedata.maxFeePerGas.mul(deployParameters.multiplierGas).div(1000), - maxPriorityFeePerGas: feedata.maxPriorityFeePerGas.mul(deployParameters.multiplierGas).div(1000), - }; - } - currentProvider.getFeeData = overrideFeeData; - } - } - } - } - // Load deployer - let deployer; - if (deployParameters.deployerPvtKey) { - deployer = new ethers.Wallet(deployParameters.deployerPvtKey, currentProvider); - } else if (process.env.HARDHAT_NETWORK === 'localhost') { - [deployer] = (await ethers.getSigners()); - } else if (process.env.MNEMONIC) { - deployer = ethers.Wallet.fromMnemonic(process.env.MNEMONIC, 'm/44\'/60\'/0\'/0/0').connect(currentProvider); - } else { - [deployer] = (await ethers.getSigners()); + + // Hardhat needs a special gas override to avoid errors about the block gas limit. + // Sepolia doesn't seem to care. + const overrideGasLimit = (process.env.HARDHAT_NETWORK == 'hardhat') ? ethers.BigNumber.from(6500000) : null; + + // Check if there's an ongoing deployment + let generated = {}; + if (fs.existsSync(generatedPath)) { + generated = require(generatedPath); } + + const currentProvider = await common.loadProvider(deployParameters, process.env); + const deployer = await common.loadDeployer(currentProvider, deployParameters); console.log('Deployer: ', deployer.address); // Load initialZkEVMDeployerOwner - const { + let { + realVerifier, + chainID, + admin, initialZkEVMDeployerOwner, salt, + maticTokenAddressFromConfig } = deployParameters; - if (initialZkEVMDeployerOwner === undefined || initialZkEVMDeployerOwner === '') { - throw new Error('Missing parameter: initialZkEVMDeployerOwner'); + if (!initialZkEVMDeployerOwner) { + initialZkEVMDeployerOwner = deployer.address; + console.log('initialZkEVMDeployerOwner not set, using deployer,', initialZkEVMDeployerOwner); } // Deploy PolygonZkEVMDeployer if is not deployed already using keyless deployment const [zkEVMDeployerContract, keylessDeployer] = await deployPolygonZkEVMDeployer(initialZkEVMDeployerOwner, deployer); if (keylessDeployer === ethers.constants.AddressZero) { - console.log('#######################\n'); - console.log('polygonZkEVMDeployer already deployed on: ', zkEVMDeployerContract.address); + console.log('PolygonZkEVMDeployer was already deployed on: ', zkEVMDeployerContract.address); } else { - console.log('#######################\n'); - console.log('polygonZkEVMDeployer deployed on: ', zkEVMDeployerContract.address); + console.log('PolygonZkEVMDeployer deployed on: ', zkEVMDeployerContract.address); } expect(deployer.address).to.be.equal(await zkEVMDeployerContract.owner()); - const proxyAdminFactory = await ethers.getContractFactory('ProxyAdmin', deployer); - const deployTransactionAdmin = (proxyAdminFactory.getDeployTransaction()).data; - const dataCallAdmin = proxyAdminFactory.interface.encodeFunctionData('transferOwnership', [deployer.address]); - const [proxyAdminAddress, isProxyAdminDeployed] = await create2Deployment( - zkEVMDeployerContract, - salt, - deployTransactionAdmin, - dataCallAdmin, - deployer, - ); - - if (isProxyAdminDeployed) { - console.log('#######################\n'); - console.log('proxyAdmin deployed on: ', proxyAdminAddress); - } else { - console.log('#######################\n'); - console.log('proxyAdmin already deployed on: ', proxyAdminAddress); + const createChildrenImplementationContract = await commonDeployment.loadOngoingOrDeployCreate2(zkEVMDeployerContract, salt, deployer, 'CreateChildren', 'createChildren', [], generated, generatedPath, overrideGasLimit, null, true); + + const bridgeAssetOperationImplementationContract = await commonDeployment.loadOngoingOrDeployCreate2(zkEVMDeployerContract, salt, deployer, 'BridgeAssetOperations', 'bridgeAssetOperations', [], generated, generatedPath); + + const bridgeLibs = { + CreateChildren: createChildrenImplementationContract.address, + BridgeAssetOperations: bridgeAssetOperationImplementationContract.address } - // Deploy implementation PolygonZkEVMBridge - const createChildrenLib = await ethers.getContractFactory('CreateChildren', deployer); - const createChildrenLibDeployTransaction = (createChildrenLib.getDeployTransaction()).data; - const overrideGasLimit = ethers.BigNumber.from(6500000); - const [createChildrenImplementationAddress] = await create2Deployment( - zkEVMDeployerContract, - salt, - createChildrenLibDeployTransaction, - null, - deployer, - overrideGasLimit, - ); - - console.log('#######################\n'); - console.log('createChildrenImplementation deployed on: ', createChildrenImplementationAddress); - - const forkonomicTokenFactory = await ethers.getContractFactory('ForkonomicToken', { - signer: deployer, - libraries: { CreateChildren: createChildrenImplementationAddress }, - }); - for (let i = 0; i < attemptsDeployProxy; i++) { - try { - forkonomicTokenProxy = await upgrades.deployProxy(forkonomicTokenFactory, [], { - initializer: false, - libraries: { - CreateChildren: createChildrenImplementationAddress, - }, - constructorArgs: [], - unsafeAllowLinkedLibraries: true, - }); - break; - } catch (error) { - console.log(`attempt ${i}`); - console.log('upgrades.deployProxy of forkonomicToken ', error.message); - } - - // reach limits of attempts - if (i + 1 === attemptsDeployProxy) { - throw new Error('forkonomicToken contract has not been deployed'); - } + // TODO I wanted to use create2 for this but it runs into some block size limitation with hardhat + //const bridgeImplementationContract = await commonDeployment.loadOngoingOrDeployCreate2(zkEVMDeployerContract, salt, deployer, 'ForkableBridge', 'forkableBridge', [], generated, generatedPath, null, bridgeLibs); + const forkableBridgeImplementationContract = await commonDeployment.loadOngoingOrDeployCreate2(zkEVMDeployerContract, salt, deployer, 'ForkableBridge', 'forkableBridge', [], generated, generatedPath, overrideGasLimit, bridgeLibs); + + const forkableLibs = { + CreateChildren: createChildrenImplementationContract.address } - console.log('#######################\n'); - console.log('forkonomicToken deployed on: ', forkonomicTokenProxy.address); - console.log( - ' Use this forkonomic token instead of the matic token in the next steps.', - ); - - // append the new address to the deploy_parameters.json file as the maticTokenAddress, even though we use it as native token - deployParameters.proxyAdminAddress = proxyAdminAddress; - deployParameters.maticTokenAddress = forkonomicTokenProxy.address; - deployParameters.createChildrenImplementationAddress = createChildrenImplementationAddress; - deployParameters.zkEVMDeployerAddress = zkEVMDeployerContract.address; - fs.writeFileSync(pathDeployParameters, JSON.stringify(deployParameters, null, 1)); + + const forkonomicTokenImplementationContract = await commonDeployment.loadOngoingOrDeployCreate2(zkEVMDeployerContract, salt, deployer, 'ForkonomicToken', 'forkonomicToken', [], generated, generatedPath, null, forkableLibs); + + const chainIdManagerContract = await commonDeployment.loadOngoingOrDeployCreate2(zkEVMDeployerContract, salt, deployer, 'ChainIdManager', 'chainIdManager', [chainID], generated, generatedPath); + + const verifierPath = realVerifier ? '@RealityETH/zkevm-contracts/contracts/verifiers/FflonkVerifier.sol:FflonkVerifier' : '@RealityETH/zkevm-contracts/contracts/mocks/VerifierRollupHelperMock.sol:VerifierRollupHelperMock'; + const verifierContract = await commonDeployment.loadOngoingOrDeployCreate2(zkEVMDeployerContract, salt, deployer, verifierPath, 'verifierContract', [], generated, generatedPath); + + const forkableZkEVMImplmentationContract = await commonDeployment.loadOngoingOrDeployCreate2(zkEVMDeployerContract, salt, deployer, 'ForkableZkEVM', 'forkableZkEVM', [], generated, generatedPath, overrideGasLimit, forkableLibs); + + const forkableGlobalExitRootImplementationContract = await commonDeployment.loadOngoingOrDeployCreate2(zkEVMDeployerContract, salt, deployer, 'ForkableGlobalExitRoot', 'forkableGlobalExitRoot', [], generated, generatedPath, null, forkableLibs); + + const forkingManagerImplementationContract = await commonDeployment.loadOngoingOrDeployCreate2(zkEVMDeployerContract, salt, deployer, 'ForkingManager', 'forkingManager', [], generated, generatedPath, overrideGasLimit, forkableLibs); + + /* + * We use a Proxy Admin to control the contracts instead of an EOA as recommended here: + * https://docs.openzeppelin.com/contracts/4.x/api/proxy#TransparentUpgradeableProxy + * Do not initialize directly the proxy since we want to deploy the same code on L2 and this will alter the bytecode deployed of the proxy + */ + const proxyAdminPath = "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol:ProxyAdmin"; + const proxyAdminFactory = await ethers.getContractFactory(proxyAdminPath, deployer); + const dataCallAdmin = proxyAdminFactory.interface.encodeFunctionData("transferOwnership", [admin]); + const proxyAdminContract = await commonDeployment.loadOngoingOrDeployCreate2(zkEVMDeployerContract, salt, deployer, proxyAdminPath, 'proxyAdmin', [], generated, generatedPath, overrideGasLimit, null, dataCallAdmin); + const proxyAdminAddress = proxyAdminContract.address; + + const instanceSpawner = forkingManagerImplementationContract.address; + + const forkableGlobalExitRoot = await commonDeployment.predictTransparentProxyAddress(instanceSpawner, forkableGlobalExitRootImplementationContract.address, proxyAdminAddress, deployer.address); + const forkableZkEVM = await commonDeployment.predictTransparentProxyAddress(instanceSpawner, forkableZkEVMImplmentationContract.address, proxyAdminAddress, deployer.address); + const forkingManager = await commonDeployment.predictTransparentProxyAddress(instanceSpawner, forkingManagerImplementationContract.address, proxyAdminAddress, deployer.address); + const forkonomicToken = await commonDeployment.predictTransparentProxyAddress(instanceSpawner, forkonomicTokenImplementationContract.address, proxyAdminAddress, deployer.address); + const forkableBridge = await commonDeployment.predictTransparentProxyAddress(instanceSpawner, forkableBridgeImplementationContract.address, proxyAdminAddress, deployer.address); + + console.log('Contract deployments in step 3 will be as follows:'); + console.log('forkableGlobalExitRoot', forkableGlobalExitRoot); + console.log('forkableZkEVM', forkableZkEVM); + console.log('forkingManager', forkingManager) + console.log('forkonomicToken', forkonomicToken); + console.log('forkableBridge', forkableBridge); + + generated['forkableGlobalExitRootPredicted'] = forkableGlobalExitRoot; + generated['forkableZkEVMPredicted'] = forkableZkEVM; + generated['forkingManagerPredicted'] = forkingManager; + generated['forkonomicTokenPredicted'] = forkonomicToken; + generated['forkableBridgePredicted'] = forkableBridge; + + fs.writeFileSync(generatedPath, JSON.stringify(generated, null, 1)); + + return; + } main().catch((e) => { diff --git a/src/deployment/2_creategenesis.js b/src/deployment/2_creategenesis.js index 3ff9757f..9cc0337f 100644 --- a/src/deployment/2_creategenesis.js +++ b/src/deployment/2_creategenesis.js @@ -19,6 +19,9 @@ const { deployPolygonZkEVMDeployer, create2Deployment } = require('./helpers/dep const deployParametersPath = argv.input ? argv.input : './deploy_parameters.json'; const deployParameters = require(deployParametersPath); +const deployGeneratedPath = argv.input ? argv.input : './deploy_generated.json'; +const deployGenerated = require(deployGeneratedPath); + const outPath = argv.out ? argv.out : './genesis.json'; const pathOutputJson = path.join(__dirname, outPath); @@ -38,11 +41,11 @@ async function main() { // deploy parameters const mandatoryDeploymentParameters = [ - 'timelockAddress', - 'minDelayTimelock', + //'timelockAddress', + //'minDelayTimelock', + 'admin', 'salt', 'initialZkEVMDeployerOwner', - 'maticTokenAddress', // This will actually be the gas token address ]; for (const parameterName of mandatoryDeploymentParameters) { @@ -52,14 +55,14 @@ async function main() { } const { - timelockAddress, - minDelayTimelock, + //timelockAddress, + //minDelayTimelock, + admin, salt, initialZkEVMDeployerOwner, - maticTokenAddress, } = deployParameters; - const gasTokenAddress = maticTokenAddress; + const gasTokenAddress = deployGenerated['forkonomicTokenPredicted']; // Load deployer await ethers.provider.send('hardhat_impersonateAccount', [initialZkEVMDeployerOwner]); @@ -180,6 +183,7 @@ async function main() { expect(await upgrades.erc1967.getAdminAddress(polygonZkEVMGlobalExitRootL2.address)).to.be.equal(proxyAdminAddress); expect(await upgrades.erc1967.getAdminAddress(proxyBridgeAddress)).to.be.equal(proxyAdminAddress); + /* const timelockContractFactory = await ethers.getContractFactory('@RealityETH/zkevm-contracts/contracts/PolygonZkEVMTimelock.sol:PolygonZkEVMTimelock', deployer); const timelockContract = await timelockContractFactory.deploy( minDelayTimelock, @@ -189,10 +193,11 @@ async function main() { zkevmAddressL2, ); await timelockContract.deployed(); + */ // Transfer ownership of the proxyAdmin to timelock const proxyAdminInstance = proxyAdminFactory.attach(proxyAdminAddress); - await (await proxyAdminInstance.connect(deployer).transferOwnership(timelockContract.address)).wait(); + await (await proxyAdminInstance.connect(deployer).transferOwnership(admin)).wait(); // Recreate genesis with the current information: const genesis = []; @@ -265,8 +270,10 @@ async function main() { storage: proxyGlobalExitRootL2Info.storage, }); + /* // Timelock const timelockInfo = await getAddressInfo(timelockContract.address); + */ /* * Since roles are used, most storage are writted in peusdoRandom storage slots @@ -275,6 +282,7 @@ async function main() { * bytes32 public constant EXECUTOR_ROLE = keccak256("EXECUTOR_ROLE"); * bytes32 public constant CANCELLER_ROLE = keccak256("CANCELLER_ROLE"); */ + /* const timelockRolesHash = [ ethers.utils.id('TIMELOCK_ADMIN_ROLE'), ethers.utils.id('PROPOSER_ROLE'), @@ -310,6 +318,7 @@ async function main() { bytecode: timelockInfo.bytecode, storage: timelockInfo.storage, }); + */ // Put nonces on deployers diff --git a/src/deployment/3_deployContracts.js b/src/deployment/3_deployContracts.js index 091d9b64..275a472e 100644 --- a/src/deployment/3_deployContracts.js +++ b/src/deployment/3_deployContracts.js @@ -1,3 +1,14 @@ +/* +Deployment loosely based on the upstream 3_deployContracts.ts + +NB Upstream Polygon administers things with a ProxyAdmin controlled by a Timelock. +For simplicity we remove the timelock and have the ProxyAdmin controlled purely by an EOA. +Ultimately we will have our own custom system for controlling L1 upgrades. + +We also remove the deploy_ongoing stuff as the only deployment here is done by create2. +*/ + + /* eslint-disable no-await-in-loop, no-use-before-define, no-lonely-if, import/no-dynamic-require, global-require */ /* eslint-disable no-console, no-inner-declarations, no-undef, import/no-unresolved, no-restricted-syntax */ const path = require('path'); @@ -7,9 +18,11 @@ const { ethers, upgrades } = require('hardhat'); require('dotenv').config({ path: path.resolve(__dirname, '../.env') }); const { create2Deployment } = require('./helpers/deployment-helpers'); +const commonDeployment = require('./common'); +const common = require('../common/common'); const pathOutputJson = path.join(__dirname, './deploy_output.json'); -const pathOngoingDeploymentJson = path.join(__dirname, './deploy_ongoing.json'); +const generated = require('./deploy_generated.json'); const deployParameters = require('./deploy_parameters.json'); const genesis = require('./genesis.json'); @@ -23,22 +36,14 @@ async function main() { throw new Error(`There's upgradability information from previous deployments, it's mandatory to erase them before start a new one, path: ${pathOZUpgradability}`); } - // Check if there's an ongoing deployment - let ongoingDeployment = {}; - if (fs.existsSync(pathOngoingDeploymentJson)) { - ongoingDeployment = require(pathOngoingDeploymentJson); - } - // Constant variables const networkIDMainnet = 0; - const attemptsDeployProxy = 5; /* * Check deploy parameters * Check that every necessary parameter is fullfilled */ const mandatoryDeploymentParameters = [ - 'realVerifier', 'trustedSequencerURL', 'networkName', 'version', @@ -46,27 +51,33 @@ async function main() { 'trustedSequencer', 'chainID', 'admin', + 'minter', 'trustedAggregator', 'trustedAggregatorTimeout', 'pendingStateTimeout', 'forkID', 'zkEVMOwner', - 'timelockAddress', + // 'timelockAddress', 'minDelayTimelock', 'salt', 'zkEVMDeployerAddress', - 'maticTokenAddress', 'createChildrenImplementationAddress', 'hardAssetManagerAddress', 'arbitrationFee', - 'proxyAdminAddress', ]; - - for (const parameterName of mandatoryDeploymentParameters) { - if (deployParameters[parameterName] === undefined || deployParameters[parameterName] === '') { - throw new Error(`Missing parameter: ${parameterName}`); - } - } + common.verifyDeploymentParameters(mandatoryDeploymentParameters, deployParameters); + + const mandatoryImplementationAddresses = [ + 'createChildren', + 'bridgeAssetOperations', + 'forkableBridge', + 'forkonomicToken', + 'chainIdManager', + 'forkableZkEVM', + 'forkableGlobalExitRoot', + 'forkingManager' + ] + common.verifyDeploymentParameters(mandatoryImplementationAddresses, generated); const { realVerifier, @@ -77,67 +88,23 @@ async function main() { trustedSequencer, chainID, admin, + minter, trustedAggregator, trustedAggregatorTimeout, pendingStateTimeout, forkID, zkEVMOwner, - timelockAddress, + // timelockAddress, minDelayTimelock, salt, zkEVMDeployerAddress, - maticTokenAddress, createChildrenImplementationAddress, hardAssetManagerAddress, arbitrationFee, - proxyAdminAddress, } = deployParameters; - const gasTokenAddress = maticTokenAddress; - // Load provider - let currentProvider = ethers.provider; - if (process.env.HARDHAT_NETWORK === 'localhost') { - currentProvider = new ethers.providers.JsonRpcProvider('https://127.0.0.1:8454'); - } else { - if (deployParameters.multiplierGas || deployParameters.maxFeePerGas) { - if (process.env.HARDHAT_NETWORK !== 'hardhat') { - currentProvider = new ethers.providers.JsonRpcProvider(`https://${process.env.HARDHAT_NETWORK}.infura.io/v3/${process.env.INFURA_PROJECT_ID}`); - if (deployParameters.maxPriorityFeePerGas && deployParameters.maxFeePerGas) { - console.log(`Hardcoded gas used: MaxPriority${deployParameters.maxPriorityFeePerGas} gwei, MaxFee${deployParameters.maxFeePerGas} gwei`); - const FEE_DATA = { - maxFeePerGas: ethers.utils.parseUnits(deployParameters.maxFeePerGas, 'gwei'), - maxPriorityFeePerGas: ethers.utils.parseUnits(deployParameters.maxPriorityFeePerGas, 'gwei'), - }; - currentProvider.getFeeData = async () => FEE_DATA; - } else { - console.log('Multiplier gas used: ', deployParameters.multiplierGas); - async function overrideFeeData() { - const feedata = await ethers.provider.getFeeData(); - return { - maxFeePerGas: feedata.maxFeePerGas.mul(deployParameters.multiplierGas).div(1000), - maxPriorityFeePerGas: feedata.maxPriorityFeePerGas.mul(deployParameters.multiplierGas).div(1000), - }; - } - currentProvider.getFeeData = overrideFeeData; - } - } - } - } - - // Load deployer - let deployer; - if (deployParameters.deployerPvtKey) { - deployer = new ethers.Wallet(deployParameters.deployerPvtKey, currentProvider); - console.log('Using pvtKey deployer with address: ', deployer.address); - } else if (process.env.HARDHAT_NETWORK === 'localhost') { - [deployer] = (await ethers.getSigners()); - } else if (process.env.MNEMONIC) { - deployer = ethers.Wallet.fromMnemonic(process.env.MNEMONIC, 'm/44\'/60\'/0\'/0/0').connect(currentProvider); - console.log('Using MNEMONIC deployer with address: ', deployer.address); - } else { - [deployer] = (await ethers.getSigners()); - } - console.log('using deployer: ', deployer.address); + const currentProvider = await common.loadProvider(deployParameters, process.env); + const deployer = await common.loadDeployer(currentProvider, deployParameters); // Load zkEVM deployer const PolgonZKEVMDeployerFactory = await ethers.getContractFactory('@RealityETH/zkevm-contracts/contracts/deployment/PolygonZkEVMDeployer.sol:PolygonZkEVMDeployer', deployer); @@ -149,581 +116,114 @@ async function main() { } expect(deployer.address).to.be.equal(await zkEVMDeployerContract.owner()); - const ChainIdManagerFactory = await ethers.getContractFactory('ChainIdManager', { - signer: deployer, - }); - - if (!ongoingDeployment.chainIdManager) { - chainIdManagerContract = await ChainIdManagerFactory.deploy(1500054); - console.log('#######################\n'); - console.log('chainIdManager deployed to:', chainIdManagerContract.address); - - // save an ongoing deployment - ongoingDeployment.chainIdManager = chainIdManagerContract.address; - fs.writeFileSync(pathOngoingDeploymentJson, JSON.stringify(ongoingDeployment, null, 1)); - } else { - // Expect the precalculate address matches the ongoing deployment - chainIdManagerContract = ChainIdManagerFactory.attach(ongoingDeployment.chainIdManager); - - console.log('#######################\n'); - console.log('chainIdManager already deployed on: ', ongoingDeployment.chainIdManager); - } - - const ForkingManagerFactory = await ethers.getContractFactory('ForkingManager', { - signer: deployer, - libraries: { CreateChildren: createChildrenImplementationAddress }, - unsafeAllowLinkedLibraries: true, - }); - - if (!ongoingDeployment.forkingManager) { - for (let i = 0; i < attemptsDeployProxy; i++) { - try { - forkingManagerContract = await upgrades.deployProxy(ForkingManagerFactory, [], { - initializer: false, - constructorArgs: [], - unsafeAllowLinkedLibraries: true, - }); - break; - } catch (error) { - console.log(`attempt ${i}`); - console.log('upgrades.deployProxy of polygonZkEVMGlobalExitRoot ', error.message); - } - - // reach limits of attempts - if (i + 1 === attemptsDeployProxy) { - throw new Error('polygonZkEVMGlobalExitRoot contract has not been deployed'); - } - } - - console.log('#######################\n'); - console.log('forkingManager deployed to:', forkingManagerContract.address); - - // save an ongoing deployment - ongoingDeployment.forkingManager = forkingManagerContract.address; - fs.writeFileSync(pathOngoingDeploymentJson, JSON.stringify(ongoingDeployment, null, 1)); - } else { - // Expect the precalculate address matches the ongoing deployment - forkingManagerContract = ForkingManagerFactory.attach(ongoingDeployment.forkingManager); - - console.log('#######################\n'); - console.log('forkingManager already deployed on: ', ongoingDeployment.forkingManager); - - // Import OZ manifest the deployed contracts, its enough to import just the proyx, the rest are imported automatically (admin/impl) - await upgrades.forceImport(ongoingDeployment.forkingManager, ForkingManagerFactory, 'transparent'); - } - - let verifierContract; - if (!ongoingDeployment.verifierContract) { - if (realVerifier === true) { - const VerifierRollup = await ethers.getContractFactory('@RealityETH/zkevm-contracts/contracts/verifiers/FflonkVerifier.sol:FflonkVerifier', deployer); - verifierContract = await VerifierRollup.deploy(); - await verifierContract.deployed(); - } else { - const VerifierRollupHelperFactory = await ethers.getContractFactory('@RealityETH/zkevm-contracts/contracts/mocks/VerifierRollupHelperMock.sol:VerifierRollupHelperMock', deployer); - verifierContract = await VerifierRollupHelperFactory.deploy(); - await verifierContract.deployed(); - } - console.log('#######################\n'); - console.log('Verifier deployed to:', verifierContract.address); - - // save an ongoing deployment - ongoingDeployment.verifierContract = verifierContract.address; - fs.writeFileSync(pathOngoingDeploymentJson, JSON.stringify(ongoingDeployment, null, 1)); - } else { - console.log('Verifier already deployed on: ', ongoingDeployment.verifierContract); - const VerifierRollupFactory = await ethers.getContractFactory('@RealityETH/zkevm-contracts/contracts/verifiers/FflonkVerifier.sol:FflonkVerifier', deployer); - verifierContract = VerifierRollupFactory.attach(ongoingDeployment.verifierContract); - } - - /* - * Deploy Bridge - * Deploy admin --> implementation --> proxy - */ - - // Deploy implementation PolygonZkEVMBridge - const overrideGasLimit = ethers.BigNumber.from(5500000); - let bridgeOperationImplementationAddress; - if (!ongoingDeployment.bridgeOperationImplementationAddress) { - const bridgeOperationLib = await ethers.getContractFactory('BridgeAssetOperations', deployer); - const bridgeOperationLibDeployTransaction = (bridgeOperationLib.getDeployTransaction()).data; - [bridgeOperationImplementationAddress] = await create2Deployment( - zkEVMDeployerContract, - salt, - bridgeOperationLibDeployTransaction, - null, - deployer, - overrideGasLimit, - ); - console.log('#######################\n'); - console.log('bridgeOperationImplementationAddress deployed to:', bridgeOperationImplementationAddress); - ongoingDeployment.bridgeOperationImplementationAddress = bridgeOperationImplementationAddress; - fs.writeFileSync(pathOngoingDeploymentJson, JSON.stringify(ongoingDeployment, null, 1)); - } else { - console.log('bridgeOperationImplementation already deployed on: ', ongoingDeployment.bridgeOperationImplementationAddress); - bridgeOperationImplementationAddress = ongoingDeployment.bridgeOperationImplementationAddress; - } - - const polygonZkEVMBridgeFactory = await ethers.getContractFactory('ForkableBridge', { - libraries: { - CreateChildren: createChildrenImplementationAddress, - BridgeAssetOperations: bridgeOperationImplementationAddress, - }, - }, deployer); - - const deployTransactionBridge = (polygonZkEVMBridgeFactory.getDeployTransaction()).data; - const dataCallNull = null; - // Mandatory to override the gasLimit since the estimation with create are mess up D: - const [bridgeImplementationAddress, isBridgeImplDeployed] = await create2Deployment( - zkEVMDeployerContract, - salt, - deployTransactionBridge, - dataCallNull, - deployer, - overrideGasLimit, - ); - - if (isBridgeImplDeployed) { - console.log('#######################\n'); - console.log('bridge impl deployed to:', bridgeImplementationAddress); - } else { - console.log('#######################\n'); - console.log('bridge impl was already deployed to:', bridgeImplementationAddress); - } - - /* - * deploy proxy - * Do not initialize directly the proxy since we want to deploy the same code on L2 and this will alter the bytecode deployed of the proxy - */ - const transparentProxyFactory = await ethers.getContractFactory('@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol:TransparentUpgradeableProxy', deployer); - const initializeEmptyDataProxy = '0x'; - const deployTransactionProxy = (transparentProxyFactory.getDeployTransaction( - bridgeImplementationAddress, - proxyAdminAddress, - initializeEmptyDataProxy, - )).data; - - // Nonce globalExitRoot: currentNonce + 1 (deploy bridge proxy) + 1(impl globalExitRoot) = +2 - const nonceProxyGlobalExitRoot = Number((await ethers.provider.getTransactionCount(deployer.address))) + 2; - - console.log('nonceProxyGlobalExitRoot', nonceProxyGlobalExitRoot); - - // nonceProxyZkevm :Nonce globalExitRoot + 1 (proxy globalExitRoot) + 1 (impl Zkevm)+ initialize global proxy = +3 - const nonceProxyZkevm = nonceProxyGlobalExitRoot + 3; - console.log('nonceProxyZkevm', nonceProxyZkevm); - - let precalculateGLobalExitRootAddress; - let precalculateZkevmAddress; - - // Check if the contract is already deployed - if (ongoingDeployment.polygonZkEVMGlobalExitRoot && ongoingDeployment.polygonZkEVMContract) { - precalculateGLobalExitRootAddress = ongoingDeployment.polygonZkEVMGlobalExitRoot; - precalculateZkevmAddress = ongoingDeployment.polygonZkEVMContract; - } else { - // If both are not deployed, it's better to deploy them both again - delete ongoingDeployment.polygonZkEVMGlobalExitRoot; - delete ongoingDeployment.polygonZkEVMContract; - fs.writeFileSync(pathOngoingDeploymentJson, JSON.stringify(ongoingDeployment, null, 1)); - - // Contracts are not deployed, normal deployment - precalculateGLobalExitRootAddress = ethers.utils.getContractAddress({ from: deployer.address, nonce: nonceProxyGlobalExitRoot }); - precalculateZkevmAddress = ethers.utils.getContractAddress({ from: deployer.address, nonce: nonceProxyZkevm }); - } - - const dataCallProxy = polygonZkEVMBridgeFactory.interface.encodeFunctionData( - 'initialize(address,address,uint32,address,address,address,bool,address,uint32, bytes32[32])', - [ - forkingManagerContract.address, - parentContract, - networkIDMainnet, - precalculateGLobalExitRootAddress, - precalculateZkevmAddress, - maticTokenAddress, - false, - hardAssetManagerAddress, - 0, - Array(32).fill(ethers.constants.HashZero), - ], - ); - const [proxyBridgeAddress, isBridgeProxyDeployed] = await create2Deployment( - zkEVMDeployerContract, - salt, - deployTransactionProxy, - dataCallProxy, - deployer, - ); - const polygonZkEVMBridgeContract = polygonZkEVMBridgeFactory.attach(proxyBridgeAddress); - - if (isBridgeProxyDeployed) { - console.log('#######################\n'); - console.log('PolygonZkEVMBridge deployed to:', polygonZkEVMBridgeContract.address); - } else { - console.log('#######################\n'); - console.log('PolygonZkEVMBridge was already deployed to:', polygonZkEVMBridgeContract.address); - - // If it was already deployed, check that the initialized calldata matches the actual deployment - expect(precalculateGLobalExitRootAddress).to.be.equal(await polygonZkEVMBridgeContract.globalExitRootManager()); - expect(precalculateZkevmAddress).to.be.equal(await polygonZkEVMBridgeContract.polygonZkEVMaddress()); - expect(forkingManagerContract.address).to.be.equal(await polygonZkEVMBridgeContract.forkingManager()); - } - - console.log('\n#######################'); - console.log('##### Checks PolygonZkEVMBridge #####'); - console.log('#######################'); - console.log('PolygonZkEVMGlobalExitRootAddress:', await polygonZkEVMBridgeContract.globalExitRootManager()); - console.log('networkID:', await polygonZkEVMBridgeContract.networkID()); - console.log('zkEVMaddress:', await polygonZkEVMBridgeContract.polygonZkEVMaddress()); - // Import OZ manifest the deployed contracts, its enough to import just the proxy, the rest are imported automatically (admin/impl) - await upgrades.forceImport(proxyBridgeAddress, polygonZkEVMBridgeFactory, 'transparent'); - - /* - *Deployment Global exit root manager - */ - let polygonZkEVMGlobalExitRoot; - const PolygonZkEVMGlobalExitRootFactory = await ethers.getContractFactory('ForkableGlobalExitRoot', { - libraries: { - CreateChildren: createChildrenImplementationAddress, - }, - }, deployer); - if (!ongoingDeployment.polygonZkEVMGlobalExitRoot) { - for (let i = 0; i < attemptsDeployProxy; i++) { - try { - polygonZkEVMGlobalExitRoot = await upgrades.deployProxy(PolygonZkEVMGlobalExitRootFactory, [], { - initializer: false, - libraries: { - CreateChildren: createChildrenImplementationAddress, - }, - proxyAdmin: proxyAdminAddress, - unsafeAllowLinkedLibraries: true, - }); - break; - } catch (error) { - console.log(`attempt ${i}`); - console.log('upgrades.deployProxy of polygonZkEVMGlobalExitRoot ', error.message); - } - - // reach limits of attempts - if (i + 1 === attemptsDeployProxy) { - throw new Error('polygonZkEVMGlobalExitRoot contract has not been deployed'); - } - } - console.log('Actual nonce for globalExitRoot deployment', polygonZkEVMGlobalExitRoot.deployTransaction.nonce); - - try { - const iForkableExitRoot = await ethers.getContractAt('IForkableGlobalExitRoot', polygonZkEVMGlobalExitRoot.address); - await iForkableExitRoot.initialize( - forkingManagerContract.address, - parentContract, - precalculateZkevmAddress, - proxyBridgeAddress, - ethers.constants.HashZero, - ethers.constants.HashZero, - { gasLimit: 5000000 }, // required as native gas limit estimation would return a too low result - ); - } catch (error) { - console.error('polygonZkEVMGlobalExitRoot initialization error', error.message); - } - - expect(precalculateGLobalExitRootAddress).to.be.equal(polygonZkEVMGlobalExitRoot.address); - - console.log('#######################\n'); - console.log('polygonZkEVMGlobalExitRoot deployed to:', polygonZkEVMGlobalExitRoot.address); - - // save an ongoing deployment - ongoingDeployment.polygonZkEVMGlobalExitRoot = polygonZkEVMGlobalExitRoot.address; - fs.writeFileSync(pathOngoingDeploymentJson, JSON.stringify(ongoingDeployment, null, 1)); - } else { - // sanity check - expect(precalculateGLobalExitRootAddress).to.be.equal(polygonZkEVMGlobalExitRoot.address); - // Expect the precalculate address matches the ongoing deployment - polygonZkEVMGlobalExitRoot = PolygonZkEVMGlobalExitRootFactory.attach(ongoingDeployment.polygonZkEVMGlobalExitRoot); - - console.log('#######################\n'); - console.log('polygonZkEVMGlobalExitRoot already deployed on: ', ongoingDeployment.polygonZkEVMGlobalExitRoot); - - // Import OZ manifest the deployed contracts, its enough to import just the proyx, the rest are imported automatically (admin/impl) - await upgrades.forceImport(ongoingDeployment.polygonZkEVMGlobalExitRoot, PolygonZkEVMGlobalExitRootFactory, 'transparent'); - - // Check against current deployment - expect(polygonZkEVMBridgeContract.address).to.be.equal(await polygonZkEVMBridgeContract.bridgeAddress()); - expect(precalculateZkevmAddress).to.be.equal(await polygonZkEVMBridgeContract.rollupAddress()); - } + //await upgrades.forceImport(proxyBridgeAddress, polygonZkEVMBridgeFactory, 'transparent'); // deploy PolygonZkEVMM const genesisRootHex = genesis.root; - console.log('\n#######################'); - console.log('##### Deployment Polygon ZK-EVM #####'); - console.log('#######################'); - console.log('deployer:', deployer.address); - console.log('PolygonZkEVMGlobalExitRootAddress:', polygonZkEVMGlobalExitRoot.address); - console.log('maticTokenAddress:', maticTokenAddress); - console.log('verifierAddress:', verifierContract.address); - console.log('polygonZkEVMBridgeContract:', polygonZkEVMBridgeContract.address); - - console.log('admin:', admin); - console.log('chainID:', chainID); - console.log('trustedSequencer:', trustedSequencer); - console.log('pendingStateTimeout:', pendingStateTimeout); - console.log('trustedAggregator:', trustedAggregator); - console.log('trustedAggregatorTimeout:', trustedAggregatorTimeout); - - console.log('genesisRoot:', genesisRootHex); - console.log('trustedSequencerURL:', trustedSequencerURL); - console.log('networkName:', networkName); - console.log('forkID:', forkID); - - const PolygonZkEVMFactory = await ethers.getContractFactory( - 'ForkableZkEVM', - { - signer: deployer, - libraries: { CreateChildren: createChildrenImplementationAddress }, - }, - ); - - let polygonZkEVMContract; - let deploymentBlockNumber; - if (!ongoingDeployment.polygonZkEVMContract) { - for (let i = 0; i < attemptsDeployProxy; i++) { - try { - polygonZkEVMContract = await upgrades.deployProxy( - PolygonZkEVMFactory, - [], - { - initializer: false, - libraries: { - CreateChildren: createChildrenImplementationAddress, - }, - proxyAdmin: proxyAdminAddress, - unsafeAllowLinkedLibraries: true, - }, - ); - console.log('polygonZkEVMContract nonce', polygonZkEVMContract.deployTransaction.nonce); - break; - } catch (error) { - console.log(`attempt ${i}`); - console.log('upgrades.deployProxy of polygonZkEVMContract ', error.message); - } - - // reach limits of attempts - if (i + 1 === attemptsDeployProxy) { - throw new Error('PolygonZkEVM contract has not been deployed'); - } - } - - try { - const iForkableZkEVM = await ethers.getContractAt('IForkableZkEVM', polygonZkEVMContract.address); - const initializeTx = await iForkableZkEVM.initialize( - forkingManagerContract.address, - parentContract, - [ - admin, - trustedSequencer, - pendingStateTimeout, - trustedAggregator, - trustedAggregatorTimeout, - chainID, - forkID, - 0, - ], - genesisRootHex, - trustedSequencerURL, - networkName, - version, - polygonZkEVMGlobalExitRoot.address, - gasTokenAddress, - verifierContract.address, - polygonZkEVMBridgeContract.address, - { gasLimit: 5000000 }, // required as native gas limit estimation would return a too low result - ); - console.log('initializeTx', initializeTx.hash); - } catch (error) { - console.error('polygonZkEVMContract initialize threw some error', error.message); - } - - expect(precalculateZkevmAddress).to.be.equal(polygonZkEVMContract.address); - - console.log('#######################\n'); - console.log('polygonZkEVMContract deployed to:', polygonZkEVMContract.address); - - // save an ongoing deployment - ongoingDeployment.polygonZkEVMContract = polygonZkEVMContract.address; - fs.writeFileSync(pathOngoingDeploymentJson, JSON.stringify(ongoingDeployment, null, 1)); - - // Transfer ownership of polygonZkEVMContract - if (zkEVMOwner !== deployer.address) { - await (await polygonZkEVMContract.transferOwnership(zkEVMOwner)).wait(); - } - - deploymentBlockNumber = (await polygonZkEVMContract.deployTransaction.wait()).blockNumber; - } else { - // Expect the precalculate address matches de onogin deployment, sanity check - expect(precalculateZkevmAddress).to.be.equal(ongoingDeployment.polygonZkEVMContract); - polygonZkEVMContract = PolygonZkEVMFactory.attach(ongoingDeployment.polygonZkEVMContract); - - console.log('#######################\n'); - console.log('polygonZkEVMContract already deployed on: ', ongoingDeployment.polygonZkEVMContract); + const deploymentConfig = [ + genesisRootHex, + trustedSequencerURL, + networkName, + version, + generated['verifierContract'], + minter, + 'Backstop0', + 'BOP0', + arbitrationFee, + generated['chainIdManager'], + forkPreparationTime, + hardAssetManagerAddress, + 0, + ethers.constants.HashZero, // TODO: Do we need to fill in lastMainnetExitRoot? + ethers.constants.HashZero, // TODO: Do we need to fill in lastRollupExitRoot? + ethers.constants.AddressZero, + ethers.constants.AddressZero, + ethers.constants.AddressZero, + ethers.constants.AddressZero, + ]; - // Import OZ manifest the deployed contracts, its enough to import just the proyx, the rest are imported automatically ( admin/impl) - await upgrades.forceImport(ongoingDeployment.polygonZkEVMContract, PolygonZkEVMFactory, 'transparent'); + const polygonZkEVMParams = [ + admin, + trustedSequencer, + pendingStateTimeout, + trustedAggregator, + trustedAggregatorTimeout, + chainID, + forkID, + 0 + ]; - const zkEVMOwnerContract = await polygonZkEVMContract.owner(); - if (zkEVMOwnerContract === deployer.address) { - // Transfer ownership of polygonZkEVMContract - if (zkEVMOwner !== deployer.address) { - await (await polygonZkEVMContract.transferOwnership(zkEVMOwner)).wait(); - } - } else { - expect(zkEVMOwner).to.be.equal(zkEVMOwnerContract); - } - deploymentBlockNumber = 0; - } - try { - const iForkingManager = await ethers.getContractAt('IForkingManager', forkingManagerContract.address); - await iForkingManager.initialize( - polygonZkEVMContract.address, - polygonZkEVMBridgeContract.address, - gasTokenAddress, - parentContract, - polygonZkEVMGlobalExitRoot.address, - arbitrationFee, - chainIdManagerContract.address, - forkPreparationTime, + // We run spawnInstance against the implementation contract + const forkingManagerFactory = await ethers.getContractFactory('ForkingManager', {'libraries': {'CreateChildren': generated['createChildren']}}); + const forkingManagerImplContract = forkingManagerFactory.attach(generated['forkingManager']); + const signedForkingManagerImplContract = forkingManagerImplContract.connect(deployer); + + deploymentBlockNumber = -1; + const deployedCode = await deployer.provider.getCode(generated['forkableZkEVMPredicted']); + if (deployedCode === '0x') { + const tx = await forkingManagerImplContract.spawnInstance( + generated['proxyAdminAddress'], + generated['forkableZkEVM'], + generated['forkableBridge'], + generated['forkonomicToken'], + generated['forkableGlobalExitRoot'], + deploymentConfig, + polygonZkEVMParams ); - } catch (e) { - console.error(`ForkingManager likely already initialized. Following error was received ${e}`); - } - - const forkonomicTokenContract = await hre.ethers.getContractAt( - 'ForkonomicToken', - gasTokenAddress, - ); - - const minter = deployer.address; - try { - if (await forkonomicTokenContract.forkmanager() === ethers.constants.AddressZero) { - const iForkonomicTokenContract = await ethers.getContractAt('IForkonomicToken', forkonomicTokenContract.address); - await iForkonomicTokenContract.initialize( - forkingManagerContract.address, - parentContract, - minter, - 'Forkonomic Token', - 'FORK', - ); - } - } catch (e) { - console.error('error deploying forkonomic token', e); - } - console.log('\n#######################'); - console.log('##### Checks PolygonZkEVM #####'); - console.log('#######################'); - console.log('PolygonZkEVMGlobalExitRootAddress:', await polygonZkEVMContract.globalExitRootManager()); - console.log('maticTokenAddress:', await polygonZkEVMContract.matic()); - console.log('verifierAddress:', await polygonZkEVMContract.rollupVerifier()); - console.log('polygonZkEVMBridgeContract:', await polygonZkEVMContract.bridgeAddress()); - - console.log('admin:', await polygonZkEVMContract.admin()); - console.log('chainID:', await polygonZkEVMContract.chainID()); - console.log('trustedSequencer:', await polygonZkEVMContract.trustedSequencer()); - console.log('pendingStateTimeout:', await polygonZkEVMContract.pendingStateTimeout()); - console.log('trustedAggregator:', await polygonZkEVMContract.trustedAggregator()); - console.log('trustedAggregatorTimeout:', await polygonZkEVMContract.trustedAggregatorTimeout()); - - console.log('genesiRoot:', await polygonZkEVMContract.batchNumToStateRoot(0)); - console.log('trustedSequencerURL:', await polygonZkEVMContract.trustedSequencerURL()); - console.log('networkName:', await polygonZkEVMContract.networkName()); - console.log('owner:', await polygonZkEVMContract.owner()); - console.log('forkID:', await polygonZkEVMContract.forkID()); - - /* - * Todo: set admin addresses correct from the start. Right now, they are differing, due to the split of the deployment script - * and the deletion of .openzepplin/network.json file mentioned in the readme. - * expect(await upgrades.erc1967.getAdminAddress(proxyBridgeAddress)).to.be.equal(proxyAdminAddress); - * expect(await upgrades.erc1967.getAdminAddress(precalculateZkevmAddress)).to.be.equal(proxyAdminAddress); - * expect(await upgrades.erc1967.getAdminAddress(precalculateGLobalExitRootAddress)).to.be.equal(proxyAdminAddress); - * expect(await upgrades.erc1967.getAdminAddress(gasTokenAddress)).to.be.equal(proxyAdminAddress); - * expect(await upgrades.erc1967.getAdminAddress(forkingManagerContract.address)).to.be.equal(proxyAdminAddress); - */ - - const proxyAdminFactory = await ethers.getContractFactory('ProxyAdmin', deployer); - const proxyAdminInstance = proxyAdminFactory.attach(proxyAdminAddress); - const proxyAdminOwner = await proxyAdminInstance.owner(); - const timelockContractFactory = await ethers.getContractFactory('PolygonZkEVMTimelock', deployer); - let timelockContract; - if (proxyAdminOwner !== deployer.address) { - // Check if there's a timelock deployed there that match the current deployment - timelockContract = timelockContractFactory.attach(proxyAdminOwner); - expect(precalculateZkevmAddress).to.be.equal(await timelockContract.polygonZkEVM()); + console.log('tx', tx); - console.log('#######################\n'); - console.log( - 'Polygon timelockContract already deployed to:', - timelockContract.address, - ); + const receipt = await tx.wait(); + deploymentBlockNumber = receipt.blockNumber; + console.log(receipt.logs); } else { - // deploy timelock - console.log('\n#######################'); - console.log('##### Deployment TimelockContract #####'); - console.log('#######################'); - console.log('minDelayTimelock:', minDelayTimelock); - console.log('timelockAddress:', timelockAddress); - console.log('zkEVMAddress:', polygonZkEVMContract.address); - timelockContract = await timelockContractFactory.deploy( - minDelayTimelock, - [timelockAddress], - [timelockAddress], - timelockAddress, - polygonZkEVMContract.address, - ); - await timelockContract.deployed(); - console.log('#######################\n'); - console.log( - 'Polygon timelockContract deployed to:', - timelockContract.address, - ); - - // Transfer ownership of the proxyAdmin to timelock - await upgrades.admin.transferProxyAdminOwnership(timelockContract.address); + console.log('Already called spawnInstance with this salt. Change the salt and redeploy.'); + console.log('If you are sure the deployment is correct you can instead fill in block number manually.'); } - console.log('\n#######################'); - console.log('##### Checks TimelockContract #####'); - console.log('#######################'); - console.log('minDelayTimelock:', await timelockContract.getMinDelay()); - console.log('polygonZkEVM:', await timelockContract.polygonZkEVM()); + // Check deployment + expect('0x').not.to.be.equal(await deployer.provider.getCode(generated['forkableZkEVMPredicted'])); + expect('0x').not.to.be.equal(await deployer.provider.getCode(generated['forkableBridgePredicted'])); + expect('0x').not.to.be.equal(await deployer.provider.getCode(generated['forkableGlobalExitRootPredicted'])); + expect('0x').not.to.be.equal(await deployer.provider.getCode(generated['forkingManagerPredicted'])); + expect('0x').not.to.be.equal(await deployer.provider.getCode(generated['forkonomicTokenPredicted'])); + + const forkingManagerDeployedContract = forkingManagerFactory.attach(generated['forkingManagerPredicted']); + expect(await forkingManagerDeployedContract.zkEVM()).to.be.equal(generated['forkableZkEVMPredicted']); + expect(await forkingManagerDeployedContract.bridge()).to.be.equal(generated['forkableBridgePredicted']); + expect(await forkingManagerDeployedContract.forkonomicToken()).to.be.equal(generated['forkonomicTokenPredicted']); + expect(await forkingManagerDeployedContract.globalExitRoot()).to.be.equal(generated['forkableGlobalExitRootPredicted']); const outputJson = { - polygonZkEVMAddress: polygonZkEVMContract.address, - polygonZkEVMBridgeAddress: polygonZkEVMBridgeContract.address, - polygonZkEVMGlobalExitRootAddress: polygonZkEVMGlobalExitRoot.address, - forkingManager: forkingManagerContract.address, - maticTokenAddress, - createChildrenImplementationAddress, - bridgeImplementationAddress, - verifierAddress: verifierContract.address, - zkEVMDeployerContract: zkEVMDeployerContract.address, - deployerAddress: deployer.address, - timelockContractAddress: timelockContract.address, - deploymentBlockNumber, - genesisRoot: genesisRootHex, - trustedSequencer, - trustedSequencerURL, - chainID, - networkName, - admin, - trustedAggregator, - proxyAdminAddress, - forkID, - salt, - version, - minter, - bridgeOperationImplementationAddress, + polygonZkEVMAddress: generated['forkableZkEVMPredicted'], + polygonZkEVMBridgeAddress: generated['forkableBridgePredicted'], + polygonZkEVMGlobalExitRootAddress: generated['forkableGlobalExitRootPredicted'], + forkingManager: generated['forkingManagerPredicted'], + maticTokenAddress: generated['forkonomicTokenPredicted'], + createChildrenImplementationAddress: generated['createChildren'], + bridgeImplementationAddress: generated['forkableBridge'], + verifierAddress: generated['verifierContract'], + zkEVMDeployerContract: generated['zkEVMDeployerAddress'], + deployerAddress: deployer.address, + timelockContractAddress: null, + deploymentBlockNumber: deploymentBlockNumber, + genesisRoot: genesisRootHex, + trustedSequencer: trustedSequencer, + trustedSequencerURL: trustedSequencerURL, + chainID: chainID, + networkName: networkName, + admin: admin, + trustedAggregator: trustedAggregator, + proxyAdminAddress: generated['proxyAdminAddress'], + forkID: forkID, + salt: salt, + version: version, + minter: minter }; fs.writeFileSync(pathOutputJson, JSON.stringify(outputJson, null, 1)); - // Remove ongoing deployment - fs.unlinkSync(pathOngoingDeploymentJson); } main().catch((e) => { diff --git a/src/deployment/common.js b/src/deployment/common.js index ad158dbc..a2f03efc 100644 --- a/src/deployment/common.js +++ b/src/deployment/common.js @@ -6,10 +6,13 @@ const { ethers } = require('hardhat'); require('dotenv').config({ path: path.resolve(__dirname, '../.env') }); const pathGenesisJson = path.join(__dirname, './deployment/genesis.json'); +const { create2Deployment } = require('./helpers/deployment-helpers'); -async function loadOngoingOrDeploy(deployer, contractName, ongoingName, args, ongoing, pathOngoing, externallyDeployedAddress) { +async function loadOngoingOrDeploy(deployer, contractName, ongoingName, args, ongoing, pathOngoing, externallyDeployedAddress, libraries, unsafeAllowLinkedLibraries) { const contractFactory = await ethers.getContractFactory(contractName, { signer: deployer, + libraries: libraries, + unsafeAllowLinkedLibraries: unsafeAllowLinkedLibraries }); let existingAddress; @@ -23,7 +26,6 @@ async function loadOngoingOrDeploy(deployer, contractName, ongoingName, args, on if (!existingAddress) { contractInstance = await contractFactory.deploy(...args); await contractInstance.deployed(); - console.log('#######################\n'); console.log(ongoingName, 'deployed to:', contractInstance.address); // save an ongoing deployment @@ -31,13 +33,47 @@ async function loadOngoingOrDeploy(deployer, contractName, ongoingName, args, on fs.writeFileSync(pathOngoing, JSON.stringify(ongoing, null, 1)); } else { contractInstance = contractFactory.attach(existingAddress); - console.log('#######################\n'); console.log(ongoingName, 'already deployed on: ', existingAddress); } return contractInstance; } + +async function loadOngoingOrDeployCreate2(create2Deployer, salt, deployer, contractName, ongoingName, args, ongoing, pathOngoing, overrideGasLimit, libraries, unsafeAllowLinkedLibraries, dataCall) { + + const contractFactory = await ethers.getContractFactory(contractName, { + signer: deployer, + libraries: libraries, + unsafeAllowLinkedLibraries: unsafeAllowLinkedLibraries + }); + + let addr; + if (ongoing[ongoingName]) { + addr = ongoing[ongoingName]; + } + + let contractInstance; + let isAlreadyCreated = false; + if (addr) { + console.log(ongoingName, 'using existing from ongoing deployment', addr); + } else { + const deployTransaction = (contractFactory.getDeployTransaction(...args)).data; + [addr, isNewlyCreated] = await create2Deployment(create2Deployer, salt, deployTransaction, dataCall, deployer, overrideGasLimit); + if (isNewlyCreated) { + console.log(ongoingName, 'deployed with create2', addr); + } else { + console.log(ongoingName, 'detected existing create2 deployment, using that', addr); + } + // save an ongoing deployment + ongoing[ongoingName] = addr; + fs.writeFileSync(pathOngoing, JSON.stringify(ongoing, null, 1)); + } + contractInstance = contractFactory.attach(addr); + + return contractInstance; +} + function genesisAddressForContractName(contractName) { const genesisJSON = require(pathGenesisJson); const genesisEntries = genesisJSON.genesis; @@ -49,6 +85,19 @@ function genesisAddressForContractName(contractName) { throw new Error(`Could not find genesis entry ${contractName}`); } +async function predictTransparentProxyAddress(deployingForkingManagerImplementationAddress, implementationAddress, admin, sender) { + const transparentProxyFactory = await ethers.getContractFactory('@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol:TransparentUpgradeableProxy'); + const initializeEmptyDataProxy = '0x'; + const deployTransactionProxy = (transparentProxyFactory.getDeployTransaction( + implementationAddress, + admin, // proxyAdminAddress, + initializeEmptyDataProxy, + )).data; + const hashInitCode = ethers.utils.solidityKeccak256(['bytes'], [deployTransactionProxy]); + const salt = ethers.utils.solidityKeccak256(['address'], [sender]); + return ethers.utils.getCreate2Address(deployingForkingManagerImplementationAddress, salt, hashInitCode); +} + module.exports = { - verifyDeploymentParameters, loadOngoingOrDeploy, genesisAddressForContractName, + loadOngoingOrDeploy, loadOngoingOrDeployCreate2, genesisAddressForContractName, predictTransparentProxyAddress }; From c1b56ffda85eeaea6b998b646ba5e5b3ce354a00 Mon Sep 17 00:00:00 2001 From: Edmund Edgar Date: Wed, 27 Mar 2024 04:45:13 +0000 Subject: [PATCH 10/16] rename to match their new roles --- .../{1_deployforkableToken.js => 1_deployBase.js} | 0 .../{3_deployContracts.js => 3_spawnInstance.js} | 0 src/deployment/README.md | 10 +++++----- 3 files changed, 5 insertions(+), 5 deletions(-) rename src/deployment/{1_deployforkableToken.js => 1_deployBase.js} (100%) rename src/deployment/{3_deployContracts.js => 3_spawnInstance.js} (100%) diff --git a/src/deployment/1_deployforkableToken.js b/src/deployment/1_deployBase.js similarity index 100% rename from src/deployment/1_deployforkableToken.js rename to src/deployment/1_deployBase.js diff --git a/src/deployment/3_deployContracts.js b/src/deployment/3_spawnInstance.js similarity index 100% rename from src/deployment/3_deployContracts.js rename to src/deployment/3_spawnInstance.js diff --git a/src/deployment/README.md b/src/deployment/README.md index 79d0b127..b4c83ce0 100644 --- a/src/deployment/README.md +++ b/src/deployment/README.md @@ -101,7 +101,7 @@ Start a node by running: npx hardhat node ``` -Prefill deploy_parameters where possible +Prefill deploy_parameters ```sh cd src/deployment @@ -114,7 +114,7 @@ You can just take the first address from the output of `npx hardhat node` Then run: ```sh -yarn hardhat run src/deployment/1_deployforkableToken.js --network localhost +yarn hardhat run src/deployment/1_deployBase.js --network localhost ``` This will fill your forkonomic(= maticTokenAddress) in deploy_parameters. @@ -127,7 +127,7 @@ yarn hardhat run src/deployment/2_creategenesis.js --network hardhat ```sh rm .openzeppelin/$HARDHAT_NETWORK.json -yarn hardhat run src/deployment/3_deployContracts.js --network localhost +yarn hardhat run src/deployment/3_spawnInstance.js --network localhost ``` If precalculated addresses are not correct, its due to false nonces. Make sure to delete the deploy_ongoing.json and restart the process and the nonce situation should clear itself or adopt the nonces. @@ -146,7 +146,7 @@ cp deploy_parameters.json.example deploy_parameters.json run ```sh -yarn hardhat run src/deployment/1_deployforkableToken.js --network sepolia +yarn hardhat run src/deployment/1_deployBase.js --network sepolia ``` This will fill your maticTokenAddress in deploy_parameters. @@ -157,7 +157,7 @@ yarn hardhat run src/deployment/2_creategenesis.js --network hardhat ```sh rm .openzeppelin/$HARDHAT_NETWORK.json -yarn hardhat run src/deployment/3_deployContracts.js --network sepolia +yarn hardhat run src/deployment/3_spawnInstance.js --network sepolia ``` and verify all contracts by: From c6ab43fbe58980d3a37a959dc63d2ba1b45ebe44 Mon Sep 17 00:00:00 2001 From: Edmund Edgar Date: Wed, 27 Mar 2024 06:14:44 +0000 Subject: [PATCH 11/16] Remove the ongoing deployment stuff since everything is create2 anyhow, restructure slightly with a view to making the scripts testable in future --- src/deployment/1_deployBase.js | 81 ++++++++++++------------------- src/deployment/3_spawnInstance.js | 36 ++++++-------- src/deployment/common.js | 24 +++------ 3 files changed, 55 insertions(+), 86 deletions(-) diff --git a/src/deployment/1_deployBase.js b/src/deployment/1_deployBase.js index 299758a2..1b83657b 100644 --- a/src/deployment/1_deployBase.js +++ b/src/deployment/1_deployBase.js @@ -19,17 +19,13 @@ const pathDeployParameters = path.join(__dirname, './deploy_parameters.json'); const commonDeployment = require('./common'); const common = require('../common/common'); -async function main() { +async function doDeployBase() { // Hardhat needs a special gas override to avoid errors about the block gas limit. // Sepolia doesn't seem to care. const overrideGasLimit = (process.env.HARDHAT_NETWORK == 'hardhat') ? ethers.BigNumber.from(6500000) : null; - // Check if there's an ongoing deployment let generated = {}; - if (fs.existsSync(generatedPath)) { - generated = require(generatedPath); - } const currentProvider = await common.loadProvider(deployParameters, process.env); const deployer = await common.loadDeployer(currentProvider, deployParameters); @@ -57,38 +53,33 @@ async function main() { } else { console.log('PolygonZkEVMDeployer deployed on: ', zkEVMDeployerContract.address); } + generated['zkEVMDeployerAddress'] = zkEVMDeployerContract.address; expect(deployer.address).to.be.equal(await zkEVMDeployerContract.owner()); - const createChildrenImplementationContract = await commonDeployment.loadOngoingOrDeployCreate2(zkEVMDeployerContract, salt, deployer, 'CreateChildren', 'createChildren', [], generated, generatedPath, overrideGasLimit, null, true); - - const bridgeAssetOperationImplementationContract = await commonDeployment.loadOngoingOrDeployCreate2(zkEVMDeployerContract, salt, deployer, 'BridgeAssetOperations', 'bridgeAssetOperations', [], generated, generatedPath); + generated['createChildren'] = await commonDeployment.create2Deploy(zkEVMDeployerContract, salt, deployer, 'CreateChildren', [], overrideGasLimit, null, true); + generated['bridgeAssetOperations'] = await commonDeployment.create2Deploy(zkEVMDeployerContract, salt, deployer, 'BridgeAssetOperations', []); const bridgeLibs = { - CreateChildren: createChildrenImplementationContract.address, - BridgeAssetOperations: bridgeAssetOperationImplementationContract.address + CreateChildren: generated['createChildren'], + BridgeAssetOperations: generated['bridgeAssetOperations'] } - // TODO I wanted to use create2 for this but it runs into some block size limitation with hardhat - //const bridgeImplementationContract = await commonDeployment.loadOngoingOrDeployCreate2(zkEVMDeployerContract, salt, deployer, 'ForkableBridge', 'forkableBridge', [], generated, generatedPath, null, bridgeLibs); - const forkableBridgeImplementationContract = await commonDeployment.loadOngoingOrDeployCreate2(zkEVMDeployerContract, salt, deployer, 'ForkableBridge', 'forkableBridge', [], generated, generatedPath, overrideGasLimit, bridgeLibs); + generated['forkableBridge'] = await commonDeployment.create2Deploy(zkEVMDeployerContract, salt, deployer, 'ForkableBridge', [], overrideGasLimit, bridgeLibs); const forkableLibs = { - CreateChildren: createChildrenImplementationContract.address + CreateChildren: generated['createChildren'] } - const forkonomicTokenImplementationContract = await commonDeployment.loadOngoingOrDeployCreate2(zkEVMDeployerContract, salt, deployer, 'ForkonomicToken', 'forkonomicToken', [], generated, generatedPath, null, forkableLibs); - - const chainIdManagerContract = await commonDeployment.loadOngoingOrDeployCreate2(zkEVMDeployerContract, salt, deployer, 'ChainIdManager', 'chainIdManager', [chainID], generated, generatedPath); + generated['forkonomicToken'] = await commonDeployment.create2Deploy(zkEVMDeployerContract, salt, deployer, 'ForkonomicToken', [], overrideGasLimit, forkableLibs); + generated['chainIdManager'] = await commonDeployment.create2Deploy(zkEVMDeployerContract, salt, deployer, 'ChainIdManager', [chainID]); const verifierPath = realVerifier ? '@RealityETH/zkevm-contracts/contracts/verifiers/FflonkVerifier.sol:FflonkVerifier' : '@RealityETH/zkevm-contracts/contracts/mocks/VerifierRollupHelperMock.sol:VerifierRollupHelperMock'; - const verifierContract = await commonDeployment.loadOngoingOrDeployCreate2(zkEVMDeployerContract, salt, deployer, verifierPath, 'verifierContract', [], generated, generatedPath); + generated['verifierContract'] = await commonDeployment.create2Deploy(zkEVMDeployerContract, salt, deployer, verifierPath, []); + generated['forkableZkEVM'] = await commonDeployment.create2Deploy(zkEVMDeployerContract, salt, deployer, 'ForkableZkEVM', [], overrideGasLimit, forkableLibs); + generated['forkableGlobalExitRoot'] = await commonDeployment.create2Deploy(zkEVMDeployerContract, salt, deployer, 'ForkableGlobalExitRoot', [], overrideGasLimit, forkableLibs); - const forkableZkEVMImplmentationContract = await commonDeployment.loadOngoingOrDeployCreate2(zkEVMDeployerContract, salt, deployer, 'ForkableZkEVM', 'forkableZkEVM', [], generated, generatedPath, overrideGasLimit, forkableLibs); - - const forkableGlobalExitRootImplementationContract = await commonDeployment.loadOngoingOrDeployCreate2(zkEVMDeployerContract, salt, deployer, 'ForkableGlobalExitRoot', 'forkableGlobalExitRoot', [], generated, generatedPath, null, forkableLibs); - - const forkingManagerImplementationContract = await commonDeployment.loadOngoingOrDeployCreate2(zkEVMDeployerContract, salt, deployer, 'ForkingManager', 'forkingManager', [], generated, generatedPath, overrideGasLimit, forkableLibs); + generated['forkingManager'] = await commonDeployment.create2Deploy(zkEVMDeployerContract, salt, deployer, 'ForkingManager', [], overrideGasLimit, forkableLibs); /* * We use a Proxy Admin to control the contracts instead of an EOA as recommended here: @@ -98,34 +89,26 @@ async function main() { const proxyAdminPath = "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol:ProxyAdmin"; const proxyAdminFactory = await ethers.getContractFactory(proxyAdminPath, deployer); const dataCallAdmin = proxyAdminFactory.interface.encodeFunctionData("transferOwnership", [admin]); - const proxyAdminContract = await commonDeployment.loadOngoingOrDeployCreate2(zkEVMDeployerContract, salt, deployer, proxyAdminPath, 'proxyAdmin', [], generated, generatedPath, overrideGasLimit, null, dataCallAdmin); - const proxyAdminAddress = proxyAdminContract.address; - - const instanceSpawner = forkingManagerImplementationContract.address; - - const forkableGlobalExitRoot = await commonDeployment.predictTransparentProxyAddress(instanceSpawner, forkableGlobalExitRootImplementationContract.address, proxyAdminAddress, deployer.address); - const forkableZkEVM = await commonDeployment.predictTransparentProxyAddress(instanceSpawner, forkableZkEVMImplmentationContract.address, proxyAdminAddress, deployer.address); - const forkingManager = await commonDeployment.predictTransparentProxyAddress(instanceSpawner, forkingManagerImplementationContract.address, proxyAdminAddress, deployer.address); - const forkonomicToken = await commonDeployment.predictTransparentProxyAddress(instanceSpawner, forkonomicTokenImplementationContract.address, proxyAdminAddress, deployer.address); - const forkableBridge = await commonDeployment.predictTransparentProxyAddress(instanceSpawner, forkableBridgeImplementationContract.address, proxyAdminAddress, deployer.address); - - console.log('Contract deployments in step 3 will be as follows:'); - console.log('forkableGlobalExitRoot', forkableGlobalExitRoot); - console.log('forkableZkEVM', forkableZkEVM); - console.log('forkingManager', forkingManager) - console.log('forkonomicToken', forkonomicToken); - console.log('forkableBridge', forkableBridge); - - generated['forkableGlobalExitRootPredicted'] = forkableGlobalExitRoot; - generated['forkableZkEVMPredicted'] = forkableZkEVM; - generated['forkingManagerPredicted'] = forkingManager; - generated['forkonomicTokenPredicted'] = forkonomicToken; - generated['forkableBridgePredicted'] = forkableBridge; + generated['proxyAdmin'] = await commonDeployment.create2Deploy(zkEVMDeployerContract, salt, deployer, proxyAdminPath, [], overrideGasLimit, null, dataCallAdmin); - fs.writeFileSync(generatedPath, JSON.stringify(generated, null, 1)); - - return; + // We use the forking manager implementation to spawn the instances + // TODO: This might be better as a separate contract sharing relevant parts with ForkingManager +// const forkingManagerFactory = await ethers.getContractFactory('ForkingManager', {signer: deployer, libraries: forkableLibs, unsafeAllowLinkedLibraries: true}); + const spawner = generated['forkingManager']; + generated['forkableGlobalExitRootPredicted'] = await commonDeployment.predictTransparentProxyAddress(spawner, generated['forkableGlobalExitRoot'], generated['proxyAdmin'], deployer.address); + generated['forkableZkEVMPredicted'] = await commonDeployment.predictTransparentProxyAddress(spawner, generated['forkableZkEVM'], generated['proxyAdmin'], deployer.address); + generated['forkingManagerPredicted'] = await commonDeployment.predictTransparentProxyAddress(spawner, generated['forkingManager'], generated['proxyAdmin'], deployer.address); + generated['forkonomicTokenPredicted'] = await commonDeployment.predictTransparentProxyAddress(spawner, generated['forkonomicToken'], generated['proxyAdmin'], deployer.address); + generated['forkableBridgePredicted'] = await commonDeployment.predictTransparentProxyAddress(spawner, generated['forkableBridge'], generated['proxyAdmin'], deployer.address); + + return generated; + +} + +async function main() { + const generated = await doDeployBase(); + fs.writeFileSync(generatedPath, JSON.stringify(generated, null, 1)); } main().catch((e) => { diff --git a/src/deployment/3_spawnInstance.js b/src/deployment/3_spawnInstance.js index 275a472e..81e8c04b 100644 --- a/src/deployment/3_spawnInstance.js +++ b/src/deployment/3_spawnInstance.js @@ -30,7 +30,7 @@ const genesis = require('./genesis.json'); const pathOZUpgradability = path.join(__dirname, `../.openzeppelin/${process.env.HARDHAT_NETWORK}.json`); const parentContract = ethers.constants.AddressZero; -async function main() { +async function doSpawnInstance() { // Check that there's no previous OZ deployment if (fs.existsSync(pathOZUpgradability)) { throw new Error(`There's upgradability information from previous deployments, it's mandatory to erase them before start a new one, path: ${pathOZUpgradability}`); @@ -106,19 +106,6 @@ async function main() { const currentProvider = await common.loadProvider(deployParameters, process.env); const deployer = await common.loadDeployer(currentProvider, deployParameters); - // Load zkEVM deployer - const PolgonZKEVMDeployerFactory = await ethers.getContractFactory('@RealityETH/zkevm-contracts/contracts/deployment/PolygonZkEVMDeployer.sol:PolygonZkEVMDeployer', deployer); - const zkEVMDeployerContract = PolgonZKEVMDeployerFactory.attach(zkEVMDeployerAddress); - - // check deployer is the owner of the deployer - if (await deployer.provider.getCode(zkEVMDeployerContract.address) === '0x') { - throw new Error('zkEVM deployer contract is not deployed at {zkEVMDeployerContract.address}'); - } - expect(deployer.address).to.be.equal(await zkEVMDeployerContract.owner()); - - // Import OZ manifest the deployed contracts, its enough to import just the proxy, the rest are imported automatically (admin/impl) - //await upgrades.forceImport(proxyBridgeAddress, polygonZkEVMBridgeFactory, 'transparent'); - // deploy PolygonZkEVMM const genesisRootHex = genesis.root; @@ -159,12 +146,11 @@ async function main() { const forkingManagerFactory = await ethers.getContractFactory('ForkingManager', {'libraries': {'CreateChildren': generated['createChildren']}}); const forkingManagerImplContract = forkingManagerFactory.attach(generated['forkingManager']); const signedForkingManagerImplContract = forkingManagerImplContract.connect(deployer); - deploymentBlockNumber = -1; const deployedCode = await deployer.provider.getCode(generated['forkableZkEVMPredicted']); if (deployedCode === '0x') { const tx = await forkingManagerImplContract.spawnInstance( - generated['proxyAdminAddress'], + generated['proxyAdmin'], generated['forkableZkEVM'], generated['forkableBridge'], generated['forkonomicToken'], @@ -173,11 +159,13 @@ async function main() { polygonZkEVMParams ); - console.log('tx', tx); - + // console.log('tx', tx); const receipt = await tx.wait(); deploymentBlockNumber = receipt.blockNumber; - console.log(receipt.logs); + + // Receipts should holdlog events from the proxy including our predicted addresses + // console.log(receipt.logs); + } else { console.log('Already called spawnInstance with this salt. Change the salt and redeploy.'); console.log('If you are sure the deployment is correct you can instead fill in block number manually.'); @@ -216,14 +204,20 @@ async function main() { networkName: networkName, admin: admin, trustedAggregator: trustedAggregator, - proxyAdminAddress: generated['proxyAdminAddress'], + proxyAdminAddress: generated['proxyAdmin'], forkID: forkID, salt: salt, version: version, minter: minter }; - fs.writeFileSync(pathOutputJson, JSON.stringify(outputJson, null, 1)); + return outputJson; + +} + +async function main() { + const output = await doSpawnInstance(); + fs.writeFileSync(pathOutputJson, JSON.stringify(output, null, 1)); } main().catch((e) => { diff --git a/src/deployment/common.js b/src/deployment/common.js index a2f03efc..6c8b2d11 100644 --- a/src/deployment/common.js +++ b/src/deployment/common.js @@ -40,8 +40,7 @@ async function loadOngoingOrDeploy(deployer, contractName, ongoingName, args, on } -async function loadOngoingOrDeployCreate2(create2Deployer, salt, deployer, contractName, ongoingName, args, ongoing, pathOngoing, overrideGasLimit, libraries, unsafeAllowLinkedLibraries, dataCall) { - +async function create2Deploy(create2Deployer, salt, deployer, contractName, args, overrideGasLimit, libraries, unsafeAllowLinkedLibraries, dataCall) { const contractFactory = await ethers.getContractFactory(contractName, { signer: deployer, libraries: libraries, @@ -49,29 +48,22 @@ async function loadOngoingOrDeployCreate2(create2Deployer, salt, deployer, contr }); let addr; - if (ongoing[ongoingName]) { - addr = ongoing[ongoingName]; - } - let contractInstance; + const displayName = contractName.replace(/^.*[\\\/]/, ''); + let isAlreadyCreated = false; if (addr) { - console.log(ongoingName, 'using existing from ongoing deployment', addr); + console.log(displayName, 'using existing from ongoing deployment', addr); } else { const deployTransaction = (contractFactory.getDeployTransaction(...args)).data; [addr, isNewlyCreated] = await create2Deployment(create2Deployer, salt, deployTransaction, dataCall, deployer, overrideGasLimit); if (isNewlyCreated) { - console.log(ongoingName, 'deployed with create2', addr); + console.log(displayName, 'deployed with create2', addr); } else { - console.log(ongoingName, 'detected existing create2 deployment, using that', addr); + console.log(displayName, 'detected existing create2 deployment, using that', addr); } - // save an ongoing deployment - ongoing[ongoingName] = addr; - fs.writeFileSync(pathOngoing, JSON.stringify(ongoing, null, 1)); } - contractInstance = contractFactory.attach(addr); - - return contractInstance; + return addr; } function genesisAddressForContractName(contractName) { @@ -99,5 +91,5 @@ async function predictTransparentProxyAddress(deployingForkingManagerImplementat } module.exports = { - loadOngoingOrDeploy, loadOngoingOrDeployCreate2, genesisAddressForContractName, predictTransparentProxyAddress + loadOngoingOrDeploy, create2Deploy, genesisAddressForContractName, predictTransparentProxyAddress }; From 1d66889b0c94d001f73aac7848d0c3f4b34e1412 Mon Sep 17 00:00:00 2001 From: Edmund Edgar Date: Wed, 27 Mar 2024 06:46:20 +0000 Subject: [PATCH 12/16] Remove unused verification, put everything we need to verify in output instead of relying on another file --- src/deployment/3_spawnInstance.js | 3 +-- src/deployment/verifyContracts.js | 5 ++++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/deployment/3_spawnInstance.js b/src/deployment/3_spawnInstance.js index 81e8c04b..51c54603 100644 --- a/src/deployment/3_spawnInstance.js +++ b/src/deployment/3_spawnInstance.js @@ -61,7 +61,6 @@ async function doSpawnInstance() { 'minDelayTimelock', 'salt', 'zkEVMDeployerAddress', - 'createChildrenImplementationAddress', 'hardAssetManagerAddress', 'arbitrationFee', ]; @@ -98,7 +97,6 @@ async function doSpawnInstance() { minDelayTimelock, salt, zkEVMDeployerAddress, - createChildrenImplementationAddress, hardAssetManagerAddress, arbitrationFee, } = deployParameters; @@ -191,6 +189,7 @@ async function doSpawnInstance() { forkingManager: generated['forkingManagerPredicted'], maticTokenAddress: generated['forkonomicTokenPredicted'], createChildrenImplementationAddress: generated['createChildren'], + bridgeOperationImplementationAddress: generated['bridgeAssetOperations'], bridgeImplementationAddress: generated['forkableBridge'], verifierAddress: generated['verifierContract'], zkEVMDeployerContract: generated['zkEVMDeployerAddress'], diff --git a/src/deployment/verifyContracts.js b/src/deployment/verifyContracts.js index 82abcf44..cad5369f 100644 --- a/src/deployment/verifyContracts.js +++ b/src/deployment/verifyContracts.js @@ -50,8 +50,10 @@ async function main() { expect(error.message.toLowerCase().includes('already verified')).to.be.equal(true); } + /* // verify timelock const { minDelayTimelock } = deployParameters; + const { timelockAddress } = deployParameters; try { await hre.run( @@ -70,6 +72,7 @@ async function main() { } catch (error) { expect(error.message.toLowerCase().includes('already verified')).to.be.equal(true); } + */ // verify proxy admin try { @@ -88,7 +91,7 @@ async function main() { await hre.run( 'verify:verify', { - address: deployParameters.createChildrenImplementationAddress, + address: deployOutputParameters.createChildrenImplementationAddress, }, ); } catch (error) { From 22709c2313568295d2eb18ff2214c0259020461b Mon Sep 17 00:00:00 2001 From: Edmund Edgar Date: Thu, 28 Mar 2024 00:14:15 +0000 Subject: [PATCH 13/16] linting --- src/deployment/1_deployBase.js | 68 ++++++++-------- src/deployment/2_creategenesis.js | 112 +++++++++++++------------- src/deployment/3_spawnInstance.js | 125 +++++++++++++++--------------- src/deployment/common.js | 15 ++-- src/deployment/verifyContracts.js | 44 +++++------ 5 files changed, 184 insertions(+), 180 deletions(-) diff --git a/src/deployment/1_deployBase.js b/src/deployment/1_deployBase.js index 1b83657b..503f924f 100644 --- a/src/deployment/1_deployBase.js +++ b/src/deployment/1_deployBase.js @@ -20,12 +20,13 @@ const commonDeployment = require('./common'); const common = require('../common/common'); async function doDeployBase() { - - // Hardhat needs a special gas override to avoid errors about the block gas limit. - // Sepolia doesn't seem to care. + /* + * Hardhat needs a special gas override to avoid errors about the block gas limit. + * Sepolia doesn't seem to care. + */ const overrideGasLimit = (process.env.HARDHAT_NETWORK == 'hardhat') ? ethers.BigNumber.from(6500000) : null; - let generated = {}; + const generated = {}; const currentProvider = await common.loadProvider(deployParameters, process.env); const deployer = await common.loadDeployer(currentProvider, deployParameters); @@ -38,7 +39,7 @@ async function doDeployBase() { admin, initialZkEVMDeployerOwner, salt, - maticTokenAddressFromConfig + maticTokenAddressFromConfig, } = deployParameters; if (!initialZkEVMDeployerOwner) { @@ -53,57 +54,58 @@ async function doDeployBase() { } else { console.log('PolygonZkEVMDeployer deployed on: ', zkEVMDeployerContract.address); } - generated['zkEVMDeployerAddress'] = zkEVMDeployerContract.address; + generated.zkEVMDeployerAddress = zkEVMDeployerContract.address; expect(deployer.address).to.be.equal(await zkEVMDeployerContract.owner()); - generated['createChildren'] = await commonDeployment.create2Deploy(zkEVMDeployerContract, salt, deployer, 'CreateChildren', [], overrideGasLimit, null, true); - generated['bridgeAssetOperations'] = await commonDeployment.create2Deploy(zkEVMDeployerContract, salt, deployer, 'BridgeAssetOperations', []); + generated.createChildren = await commonDeployment.create2Deploy(zkEVMDeployerContract, salt, deployer, 'CreateChildren', [], overrideGasLimit, null, true); + generated.bridgeAssetOperations = await commonDeployment.create2Deploy(zkEVMDeployerContract, salt, deployer, 'BridgeAssetOperations', []); const bridgeLibs = { - CreateChildren: generated['createChildren'], - BridgeAssetOperations: generated['bridgeAssetOperations'] - } + CreateChildren: generated.createChildren, + BridgeAssetOperations: generated.bridgeAssetOperations, + }; - generated['forkableBridge'] = await commonDeployment.create2Deploy(zkEVMDeployerContract, salt, deployer, 'ForkableBridge', [], overrideGasLimit, bridgeLibs); + generated.forkableBridge = await commonDeployment.create2Deploy(zkEVMDeployerContract, salt, deployer, 'ForkableBridge', [], overrideGasLimit, bridgeLibs); const forkableLibs = { - CreateChildren: generated['createChildren'] - } + CreateChildren: generated.createChildren, + }; - generated['forkonomicToken'] = await commonDeployment.create2Deploy(zkEVMDeployerContract, salt, deployer, 'ForkonomicToken', [], overrideGasLimit, forkableLibs); - generated['chainIdManager'] = await commonDeployment.create2Deploy(zkEVMDeployerContract, salt, deployer, 'ChainIdManager', [chainID]); + generated.forkonomicToken = await commonDeployment.create2Deploy(zkEVMDeployerContract, salt, deployer, 'ForkonomicToken', [], overrideGasLimit, forkableLibs); + generated.chainIdManager = await commonDeployment.create2Deploy(zkEVMDeployerContract, salt, deployer, 'ChainIdManager', [chainID]); const verifierPath = realVerifier ? '@RealityETH/zkevm-contracts/contracts/verifiers/FflonkVerifier.sol:FflonkVerifier' : '@RealityETH/zkevm-contracts/contracts/mocks/VerifierRollupHelperMock.sol:VerifierRollupHelperMock'; - generated['verifierContract'] = await commonDeployment.create2Deploy(zkEVMDeployerContract, salt, deployer, verifierPath, []); - generated['forkableZkEVM'] = await commonDeployment.create2Deploy(zkEVMDeployerContract, salt, deployer, 'ForkableZkEVM', [], overrideGasLimit, forkableLibs); - generated['forkableGlobalExitRoot'] = await commonDeployment.create2Deploy(zkEVMDeployerContract, salt, deployer, 'ForkableGlobalExitRoot', [], overrideGasLimit, forkableLibs); + generated.verifierContract = await commonDeployment.create2Deploy(zkEVMDeployerContract, salt, deployer, verifierPath, []); + generated.forkableZkEVM = await commonDeployment.create2Deploy(zkEVMDeployerContract, salt, deployer, 'ForkableZkEVM', [], overrideGasLimit, forkableLibs); + generated.forkableGlobalExitRoot = await commonDeployment.create2Deploy(zkEVMDeployerContract, salt, deployer, 'ForkableGlobalExitRoot', [], overrideGasLimit, forkableLibs); - generated['forkingManager'] = await commonDeployment.create2Deploy(zkEVMDeployerContract, salt, deployer, 'ForkingManager', [], overrideGasLimit, forkableLibs); + generated.forkingManager = await commonDeployment.create2Deploy(zkEVMDeployerContract, salt, deployer, 'ForkingManager', [], overrideGasLimit, forkableLibs); /* * We use a Proxy Admin to control the contracts instead of an EOA as recommended here: * https://docs.openzeppelin.com/contracts/4.x/api/proxy#TransparentUpgradeableProxy * Do not initialize directly the proxy since we want to deploy the same code on L2 and this will alter the bytecode deployed of the proxy */ - const proxyAdminPath = "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol:ProxyAdmin"; + const proxyAdminPath = '@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol:ProxyAdmin'; const proxyAdminFactory = await ethers.getContractFactory(proxyAdminPath, deployer); - const dataCallAdmin = proxyAdminFactory.interface.encodeFunctionData("transferOwnership", [admin]); - generated['proxyAdmin'] = await commonDeployment.create2Deploy(zkEVMDeployerContract, salt, deployer, proxyAdminPath, [], overrideGasLimit, null, dataCallAdmin); + const dataCallAdmin = proxyAdminFactory.interface.encodeFunctionData('transferOwnership', [admin]); + generated.proxyAdmin = await commonDeployment.create2Deploy(zkEVMDeployerContract, salt, deployer, proxyAdminPath, [], overrideGasLimit, null, dataCallAdmin); - // We use the forking manager implementation to spawn the instances - // TODO: This might be better as a separate contract sharing relevant parts with ForkingManager -// const forkingManagerFactory = await ethers.getContractFactory('ForkingManager', {signer: deployer, libraries: forkableLibs, unsafeAllowLinkedLibraries: true}); - const spawner = generated['forkingManager']; + /* + * We use the forking manager implementation to spawn the instances + * TODO: This might be better as a separate contract sharing relevant parts with ForkingManager + * const forkingManagerFactory = await ethers.getContractFactory('ForkingManager', {signer: deployer, libraries: forkableLibs, unsafeAllowLinkedLibraries: true}); + */ + const spawner = generated.forkingManager; - generated['forkableGlobalExitRootPredicted'] = await commonDeployment.predictTransparentProxyAddress(spawner, generated['forkableGlobalExitRoot'], generated['proxyAdmin'], deployer.address); - generated['forkableZkEVMPredicted'] = await commonDeployment.predictTransparentProxyAddress(spawner, generated['forkableZkEVM'], generated['proxyAdmin'], deployer.address); - generated['forkingManagerPredicted'] = await commonDeployment.predictTransparentProxyAddress(spawner, generated['forkingManager'], generated['proxyAdmin'], deployer.address); - generated['forkonomicTokenPredicted'] = await commonDeployment.predictTransparentProxyAddress(spawner, generated['forkonomicToken'], generated['proxyAdmin'], deployer.address); - generated['forkableBridgePredicted'] = await commonDeployment.predictTransparentProxyAddress(spawner, generated['forkableBridge'], generated['proxyAdmin'], deployer.address); + generated.forkableGlobalExitRootPredicted = await commonDeployment.predictTransparentProxyAddress(spawner, generated.forkableGlobalExitRoot, generated.proxyAdmin, deployer.address); + generated.forkableZkEVMPredicted = await commonDeployment.predictTransparentProxyAddress(spawner, generated.forkableZkEVM, generated.proxyAdmin, deployer.address); + generated.forkingManagerPredicted = await commonDeployment.predictTransparentProxyAddress(spawner, generated.forkingManager, generated.proxyAdmin, deployer.address); + generated.forkonomicTokenPredicted = await commonDeployment.predictTransparentProxyAddress(spawner, generated.forkonomicToken, generated.proxyAdmin, deployer.address); + generated.forkableBridgePredicted = await commonDeployment.predictTransparentProxyAddress(spawner, generated.forkableBridge, generated.proxyAdmin, deployer.address); return generated; - } async function main() { diff --git a/src/deployment/2_creategenesis.js b/src/deployment/2_creategenesis.js index 9cc0337f..c6264d47 100644 --- a/src/deployment/2_creategenesis.js +++ b/src/deployment/2_creategenesis.js @@ -41,8 +41,10 @@ async function main() { // deploy parameters const mandatoryDeploymentParameters = [ - //'timelockAddress', - //'minDelayTimelock', + /* + * 'timelockAddress', + * 'minDelayTimelock', + */ 'admin', 'salt', 'initialZkEVMDeployerOwner', @@ -55,14 +57,16 @@ async function main() { } const { - //timelockAddress, - //minDelayTimelock, + /* + * timelockAddress, + * minDelayTimelock, + */ admin, salt, initialZkEVMDeployerOwner, } = deployParameters; - const gasTokenAddress = deployGenerated['forkonomicTokenPredicted']; + const gasTokenAddress = deployGenerated.forkonomicTokenPredicted; // Load deployer await ethers.provider.send('hardhat_impersonateAccount', [initialZkEVMDeployerOwner]); @@ -184,16 +188,16 @@ async function main() { expect(await upgrades.erc1967.getAdminAddress(proxyBridgeAddress)).to.be.equal(proxyAdminAddress); /* - const timelockContractFactory = await ethers.getContractFactory('@RealityETH/zkevm-contracts/contracts/PolygonZkEVMTimelock.sol:PolygonZkEVMTimelock', deployer); - const timelockContract = await timelockContractFactory.deploy( - minDelayTimelock, - [timelockAddress], - [timelockAddress], - timelockAddress, - zkevmAddressL2, - ); - await timelockContract.deployed(); - */ + *const timelockContractFactory = await ethers.getContractFactory('@RealityETH/zkevm-contracts/contracts/PolygonZkEVMTimelock.sol:PolygonZkEVMTimelock', deployer); + *const timelockContract = await timelockContractFactory.deploy( + * minDelayTimelock, + * [timelockAddress], + * [timelockAddress], + * timelockAddress, + * zkevmAddressL2, + *); + *await timelockContract.deployed(); + */ // Transfer ownership of the proxyAdmin to timelock const proxyAdminInstance = proxyAdminFactory.attach(proxyAdminAddress); @@ -271,9 +275,9 @@ async function main() { }); /* - // Timelock - const timelockInfo = await getAddressInfo(timelockContract.address); - */ + * // Timelock + *const timelockInfo = await getAddressInfo(timelockContract.address); + */ /* * Since roles are used, most storage are writted in peusdoRandom storage slots @@ -283,42 +287,42 @@ async function main() { * bytes32 public constant CANCELLER_ROLE = keccak256("CANCELLER_ROLE"); */ /* - const timelockRolesHash = [ - ethers.utils.id('TIMELOCK_ADMIN_ROLE'), - ethers.utils.id('PROPOSER_ROLE'), - ethers.utils.id('EXECUTOR_ROLE'), - ethers.utils.id('CANCELLER_ROLE'), - ]; - - for (let i = 0; i < timelockRolesHash.length; i++) { - const rolesMappingStoragePositionStruct = 0; - const storagePosition = ethers.utils.solidityKeccak256(['uint256', 'uint256'], [timelockRolesHash[i], rolesMappingStoragePositionStruct]); - - // check timelock address manager, and timelock address itself - const addressArray = [timelockAddress, timelockContract.address]; - for (let j = 0; j < addressArray.length; j++) { - const storagePositionRole = ethers.utils.solidityKeccak256(['uint256', 'uint256'], [addressArray[j], storagePosition]); - const valueRole = await ethers.provider.getStorageAt(timelockContract.address, storagePositionRole); - if (valueRole !== '0x0000000000000000000000000000000000000000000000000000000000000000') { - timelockInfo.storage[storagePositionRole] = valueRole; - } - } - const roleAdminSlot = ethers.utils.hexZeroPad((ethers.BigNumber.from(storagePosition).add(1)).toHexString(), 32); - const valueRoleAdminSlot = await ethers.provider.getStorageAt(timelockContract.address, roleAdminSlot); - if (valueRoleAdminSlot !== '0x0000000000000000000000000000000000000000000000000000000000000000') { - timelockInfo.storage[roleAdminSlot] = valueRoleAdminSlot; - } - } - - genesis.push({ - contractName: 'PolygonZkEVMTimelock', - balance: '0', - nonce: timelockInfo.nonce.toString(), - address: timelockContract.address, - bytecode: timelockInfo.bytecode, - storage: timelockInfo.storage, - }); - */ + *const timelockRolesHash = [ + * ethers.utils.id('TIMELOCK_ADMIN_ROLE'), + * ethers.utils.id('PROPOSER_ROLE'), + * ethers.utils.id('EXECUTOR_ROLE'), + * ethers.utils.id('CANCELLER_ROLE'), + *]; + * + *for (let i = 0; i < timelockRolesHash.length; i++) { + * const rolesMappingStoragePositionStruct = 0; + * const storagePosition = ethers.utils.solidityKeccak256(['uint256', 'uint256'], [timelockRolesHash[i], rolesMappingStoragePositionStruct]); + * + * // check timelock address manager, and timelock address itself + * const addressArray = [timelockAddress, timelockContract.address]; + * for (let j = 0; j < addressArray.length; j++) { + * const storagePositionRole = ethers.utils.solidityKeccak256(['uint256', 'uint256'], [addressArray[j], storagePosition]); + * const valueRole = await ethers.provider.getStorageAt(timelockContract.address, storagePositionRole); + * if (valueRole !== '0x0000000000000000000000000000000000000000000000000000000000000000') { + * timelockInfo.storage[storagePositionRole] = valueRole; + * } + * } + * const roleAdminSlot = ethers.utils.hexZeroPad((ethers.BigNumber.from(storagePosition).add(1)).toHexString(), 32); + * const valueRoleAdminSlot = await ethers.provider.getStorageAt(timelockContract.address, roleAdminSlot); + * if (valueRoleAdminSlot !== '0x0000000000000000000000000000000000000000000000000000000000000000') { + * timelockInfo.storage[roleAdminSlot] = valueRoleAdminSlot; + * } + *} + * + *genesis.push({ + * contractName: 'PolygonZkEVMTimelock', + * balance: '0', + * nonce: timelockInfo.nonce.toString(), + * address: timelockContract.address, + * bytecode: timelockInfo.bytecode, + * storage: timelockInfo.storage, + *}); + */ // Put nonces on deployers diff --git a/src/deployment/3_spawnInstance.js b/src/deployment/3_spawnInstance.js index 51c54603..f5cf54b0 100644 --- a/src/deployment/3_spawnInstance.js +++ b/src/deployment/3_spawnInstance.js @@ -1,13 +1,12 @@ /* -Deployment loosely based on the upstream 3_deployContracts.ts - -NB Upstream Polygon administers things with a ProxyAdmin controlled by a Timelock. -For simplicity we remove the timelock and have the ProxyAdmin controlled purely by an EOA. -Ultimately we will have our own custom system for controlling L1 upgrades. - -We also remove the deploy_ongoing stuff as the only deployment here is done by create2. -*/ - + *Deployment loosely based on the upstream 3_deployContracts.ts + * + *NB Upstream Polygon administers things with a ProxyAdmin controlled by a Timelock. + *For simplicity we remove the timelock and have the ProxyAdmin controlled purely by an EOA. + *Ultimately we will have our own custom system for controlling L1 upgrades. + * + *We also remove the deploy_ongoing stuff as the only deployment here is done by create2. + */ /* eslint-disable no-await-in-loop, no-use-before-define, no-lonely-if, import/no-dynamic-require, global-require */ /* eslint-disable no-console, no-inner-declarations, no-undef, import/no-unresolved, no-restricted-syntax */ @@ -74,8 +73,8 @@ async function doSpawnInstance() { 'chainIdManager', 'forkableZkEVM', 'forkableGlobalExitRoot', - 'forkingManager' - ] + 'forkingManager', + ]; common.verifyDeploymentParameters(mandatoryImplementationAddresses, generated); const { @@ -112,12 +111,12 @@ async function doSpawnInstance() { trustedSequencerURL, networkName, version, - generated['verifierContract'], + generated.verifierContract, minter, 'Backstop0', 'BOP0', arbitrationFee, - generated['chainIdManager'], + generated.chainIdManager, forkPreparationTime, hardAssetManagerAddress, 0, @@ -137,81 +136,81 @@ async function doSpawnInstance() { trustedAggregatorTimeout, chainID, forkID, - 0 + 0, ]; // We run spawnInstance against the implementation contract - const forkingManagerFactory = await ethers.getContractFactory('ForkingManager', {'libraries': {'CreateChildren': generated['createChildren']}}); - const forkingManagerImplContract = forkingManagerFactory.attach(generated['forkingManager']); + const forkingManagerFactory = await ethers.getContractFactory('ForkingManager', { libraries: { CreateChildren: generated.createChildren } }); + const forkingManagerImplContract = forkingManagerFactory.attach(generated.forkingManager); const signedForkingManagerImplContract = forkingManagerImplContract.connect(deployer); deploymentBlockNumber = -1; - const deployedCode = await deployer.provider.getCode(generated['forkableZkEVMPredicted']); + const deployedCode = await deployer.provider.getCode(generated.forkableZkEVMPredicted); if (deployedCode === '0x') { const tx = await forkingManagerImplContract.spawnInstance( - generated['proxyAdmin'], - generated['forkableZkEVM'], - generated['forkableBridge'], - generated['forkonomicToken'], - generated['forkableGlobalExitRoot'], + generated.proxyAdmin, + generated.forkableZkEVM, + generated.forkableBridge, + generated.forkonomicToken, + generated.forkableGlobalExitRoot, deploymentConfig, - polygonZkEVMParams + polygonZkEVMParams, ); // console.log('tx', tx); const receipt = await tx.wait(); deploymentBlockNumber = receipt.blockNumber; - // Receipts should holdlog events from the proxy including our predicted addresses - // console.log(receipt.logs); - + /* + * Receipts should holdlog events from the proxy including our predicted addresses + * console.log(receipt.logs); + */ } else { console.log('Already called spawnInstance with this salt. Change the salt and redeploy.'); console.log('If you are sure the deployment is correct you can instead fill in block number manually.'); } // Check deployment - expect('0x').not.to.be.equal(await deployer.provider.getCode(generated['forkableZkEVMPredicted'])); - expect('0x').not.to.be.equal(await deployer.provider.getCode(generated['forkableBridgePredicted'])); - expect('0x').not.to.be.equal(await deployer.provider.getCode(generated['forkableGlobalExitRootPredicted'])); - expect('0x').not.to.be.equal(await deployer.provider.getCode(generated['forkingManagerPredicted'])); - expect('0x').not.to.be.equal(await deployer.provider.getCode(generated['forkonomicTokenPredicted'])); - - const forkingManagerDeployedContract = forkingManagerFactory.attach(generated['forkingManagerPredicted']); - expect(await forkingManagerDeployedContract.zkEVM()).to.be.equal(generated['forkableZkEVMPredicted']); - expect(await forkingManagerDeployedContract.bridge()).to.be.equal(generated['forkableBridgePredicted']); - expect(await forkingManagerDeployedContract.forkonomicToken()).to.be.equal(generated['forkonomicTokenPredicted']); - expect(await forkingManagerDeployedContract.globalExitRoot()).to.be.equal(generated['forkableGlobalExitRootPredicted']); + expect('0x').not.to.be.equal(await deployer.provider.getCode(generated.forkableZkEVMPredicted)); + expect('0x').not.to.be.equal(await deployer.provider.getCode(generated.forkableBridgePredicted)); + expect('0x').not.to.be.equal(await deployer.provider.getCode(generated.forkableGlobalExitRootPredicted)); + expect('0x').not.to.be.equal(await deployer.provider.getCode(generated.forkingManagerPredicted)); + expect('0x').not.to.be.equal(await deployer.provider.getCode(generated.forkonomicTokenPredicted)); + + const forkingManagerDeployedContract = forkingManagerFactory.attach(generated.forkingManagerPredicted); + expect(await forkingManagerDeployedContract.zkEVM()).to.be.equal(generated.forkableZkEVMPredicted); + expect(await forkingManagerDeployedContract.bridge()).to.be.equal(generated.forkableBridgePredicted); + expect(await forkingManagerDeployedContract.forkonomicToken()).to.be.equal(generated.forkonomicTokenPredicted); + expect(await forkingManagerDeployedContract.globalExitRoot()).to.be.equal(generated.forkableGlobalExitRootPredicted); const outputJson = { - polygonZkEVMAddress: generated['forkableZkEVMPredicted'], - polygonZkEVMBridgeAddress: generated['forkableBridgePredicted'], - polygonZkEVMGlobalExitRootAddress: generated['forkableGlobalExitRootPredicted'], - forkingManager: generated['forkingManagerPredicted'], - maticTokenAddress: generated['forkonomicTokenPredicted'], - createChildrenImplementationAddress: generated['createChildren'], - bridgeOperationImplementationAddress: generated['bridgeAssetOperations'], - bridgeImplementationAddress: generated['forkableBridge'], - verifierAddress: generated['verifierContract'], - zkEVMDeployerContract: generated['zkEVMDeployerAddress'], - deployerAddress: deployer.address, - timelockContractAddress: null, - deploymentBlockNumber: deploymentBlockNumber, - genesisRoot: genesisRootHex, - trustedSequencer: trustedSequencer, - trustedSequencerURL: trustedSequencerURL, - chainID: chainID, - networkName: networkName, - admin: admin, - trustedAggregator: trustedAggregator, - proxyAdminAddress: generated['proxyAdmin'], - forkID: forkID, - salt: salt, - version: version, - minter: minter + polygonZkEVMAddress: generated.forkableZkEVMPredicted, + polygonZkEVMBridgeAddress: generated.forkableBridgePredicted, + polygonZkEVMGlobalExitRootAddress: generated.forkableGlobalExitRootPredicted, + forkingManager: generated.forkingManagerPredicted, + maticTokenAddress: generated.forkonomicTokenPredicted, + createChildrenImplementationAddress: generated.createChildren, + bridgeOperationImplementationAddress: generated.bridgeAssetOperations, + bridgeImplementationAddress: generated.forkableBridge, + verifierAddress: generated.verifierContract, + zkEVMDeployerContract: generated.zkEVMDeployerAddress, + deployerAddress: deployer.address, + timelockContractAddress: null, + deploymentBlockNumber, + genesisRoot: genesisRootHex, + trustedSequencer, + trustedSequencerURL, + chainID, + networkName, + admin, + trustedAggregator, + proxyAdminAddress: generated.proxyAdmin, + forkID, + salt, + version, + minter, }; return outputJson; - } async function main() { diff --git a/src/deployment/common.js b/src/deployment/common.js index 6c8b2d11..e9518899 100644 --- a/src/deployment/common.js +++ b/src/deployment/common.js @@ -11,8 +11,8 @@ const { create2Deployment } = require('./helpers/deployment-helpers'); async function loadOngoingOrDeploy(deployer, contractName, ongoingName, args, ongoing, pathOngoing, externallyDeployedAddress, libraries, unsafeAllowLinkedLibraries) { const contractFactory = await ethers.getContractFactory(contractName, { signer: deployer, - libraries: libraries, - unsafeAllowLinkedLibraries: unsafeAllowLinkedLibraries + libraries, + unsafeAllowLinkedLibraries, }); let existingAddress; @@ -39,19 +39,18 @@ async function loadOngoingOrDeploy(deployer, contractName, ongoingName, args, on return contractInstance; } - async function create2Deploy(create2Deployer, salt, deployer, contractName, args, overrideGasLimit, libraries, unsafeAllowLinkedLibraries, dataCall) { const contractFactory = await ethers.getContractFactory(contractName, { signer: deployer, - libraries: libraries, - unsafeAllowLinkedLibraries: unsafeAllowLinkedLibraries + libraries, + unsafeAllowLinkedLibraries, }); let addr; const displayName = contractName.replace(/^.*[\\\/]/, ''); - let isAlreadyCreated = false; + const isAlreadyCreated = false; if (addr) { console.log(displayName, 'using existing from ongoing deployment', addr); } else { @@ -62,7 +61,7 @@ async function create2Deploy(create2Deployer, salt, deployer, contractName, args } else { console.log(displayName, 'detected existing create2 deployment, using that', addr); } - } + } return addr; } @@ -91,5 +90,5 @@ async function predictTransparentProxyAddress(deployingForkingManagerImplementat } module.exports = { - loadOngoingOrDeploy, create2Deploy, genesisAddressForContractName, predictTransparentProxyAddress + loadOngoingOrDeploy, create2Deploy, genesisAddressForContractName, predictTransparentProxyAddress, }; diff --git a/src/deployment/verifyContracts.js b/src/deployment/verifyContracts.js index cad5369f..2829862d 100644 --- a/src/deployment/verifyContracts.js +++ b/src/deployment/verifyContracts.js @@ -51,28 +51,28 @@ async function main() { } /* - // verify timelock - const { minDelayTimelock } = deployParameters; - - const { timelockAddress } = deployParameters; - try { - await hre.run( - 'verify:verify', - { - address: deployOutputParameters.timelockContractAddress, - constructorArguments: [ - minDelayTimelock, - [timelockAddress], - [timelockAddress], - timelockAddress, - deployOutputParameters.polygonZkEVMAddress, - ], - }, - ); - } catch (error) { - expect(error.message.toLowerCase().includes('already verified')).to.be.equal(true); - } - */ + * // verify timelock + *const { minDelayTimelock } = deployParameters; + * + *const { timelockAddress } = deployParameters; + *try { + * await hre.run( + * 'verify:verify', + * { + * address: deployOutputParameters.timelockContractAddress, + * constructorArguments: [ + * minDelayTimelock, + * [timelockAddress], + * [timelockAddress], + * timelockAddress, + * deployOutputParameters.polygonZkEVMAddress, + * ], + * }, + * ); + *} catch (error) { + * expect(error.message.toLowerCase().includes('already verified')).to.be.equal(true); + *} + */ // verify proxy admin try { From 4829dd9a6e62829be0701ca4e56c3a987e07dea8 Mon Sep 17 00:00:00 2001 From: Edmund Edgar Date: Thu, 28 Mar 2024 00:46:49 +0000 Subject: [PATCH 14/16] fix some linting errors --- src/deployment/1_deployBase.js | 46 +++++++++++++++---------------- src/deployment/3_spawnInstance.js | 13 --------- src/deployment/common.js | 7 ++--- src/deployment/verifyContracts.js | 2 -- 4 files changed, 26 insertions(+), 42 deletions(-) diff --git a/src/deployment/1_deployBase.js b/src/deployment/1_deployBase.js index 503f924f..5293e90b 100644 --- a/src/deployment/1_deployBase.js +++ b/src/deployment/1_deployBase.js @@ -9,14 +9,11 @@ require('dotenv').config({ path: path.resolve(__dirname, '../.env') }); const { expect } = require('chai'); const { deployPolygonZkEVMDeployer } = require('./helpers/deployment-helpers'); -const { create2Deployment } = require('./helpers/deployment-helpers'); const deployParameters = require('./deploy_parameters.json'); const generatedPath = path.join(__dirname, './deploy_generated.json'); -const pathDeployParameters = path.join(__dirname, './deploy_parameters.json'); - -const commonDeployment = require('./common'); +const { create2Deploy, predictTransparentProxyAddress } = require('./common'); const common = require('../common/common'); async function doDeployBase() { @@ -24,7 +21,7 @@ async function doDeployBase() { * Hardhat needs a special gas override to avoid errors about the block gas limit. * Sepolia doesn't seem to care. */ - const overrideGasLimit = (process.env.HARDHAT_NETWORK == 'hardhat') ? ethers.BigNumber.from(6500000) : null; + const overrideGasLimit = (process.env.HARDHAT_NETWORK === 'hardhat') ? ethers.BigNumber.from(6500000) : null; const generated = {}; @@ -33,13 +30,15 @@ async function doDeployBase() { console.log('Deployer: ', deployer.address); // Load initialZkEVMDeployerOwner - let { + const { realVerifier, chainID, admin, - initialZkEVMDeployerOwner, salt, - maticTokenAddressFromConfig, + } = deployParameters; + + let { + initialZkEVMDeployerOwner, } = deployParameters; if (!initialZkEVMDeployerOwner) { @@ -58,29 +57,29 @@ async function doDeployBase() { expect(deployer.address).to.be.equal(await zkEVMDeployerContract.owner()); - generated.createChildren = await commonDeployment.create2Deploy(zkEVMDeployerContract, salt, deployer, 'CreateChildren', [], overrideGasLimit, null, true); - generated.bridgeAssetOperations = await commonDeployment.create2Deploy(zkEVMDeployerContract, salt, deployer, 'BridgeAssetOperations', []); + generated.createChildren = await create2Deploy(zkEVMDeployerContract, salt, deployer, 'CreateChildren', [], overrideGasLimit, null, true); + generated.bridgeAssetOperations = await create2Deploy(zkEVMDeployerContract, salt, deployer, 'BridgeAssetOperations', []); const bridgeLibs = { CreateChildren: generated.createChildren, BridgeAssetOperations: generated.bridgeAssetOperations, }; - generated.forkableBridge = await commonDeployment.create2Deploy(zkEVMDeployerContract, salt, deployer, 'ForkableBridge', [], overrideGasLimit, bridgeLibs); + generated.forkableBridge = await create2Deploy(zkEVMDeployerContract, salt, deployer, 'ForkableBridge', [], overrideGasLimit, bridgeLibs); const forkableLibs = { CreateChildren: generated.createChildren, }; - generated.forkonomicToken = await commonDeployment.create2Deploy(zkEVMDeployerContract, salt, deployer, 'ForkonomicToken', [], overrideGasLimit, forkableLibs); - generated.chainIdManager = await commonDeployment.create2Deploy(zkEVMDeployerContract, salt, deployer, 'ChainIdManager', [chainID]); + generated.forkonomicToken = await create2Deploy(zkEVMDeployerContract, salt, deployer, 'ForkonomicToken', [], overrideGasLimit, forkableLibs); + generated.chainIdManager = await create2Deploy(zkEVMDeployerContract, salt, deployer, 'ChainIdManager', [chainID]); const verifierPath = realVerifier ? '@RealityETH/zkevm-contracts/contracts/verifiers/FflonkVerifier.sol:FflonkVerifier' : '@RealityETH/zkevm-contracts/contracts/mocks/VerifierRollupHelperMock.sol:VerifierRollupHelperMock'; - generated.verifierContract = await commonDeployment.create2Deploy(zkEVMDeployerContract, salt, deployer, verifierPath, []); - generated.forkableZkEVM = await commonDeployment.create2Deploy(zkEVMDeployerContract, salt, deployer, 'ForkableZkEVM', [], overrideGasLimit, forkableLibs); - generated.forkableGlobalExitRoot = await commonDeployment.create2Deploy(zkEVMDeployerContract, salt, deployer, 'ForkableGlobalExitRoot', [], overrideGasLimit, forkableLibs); + generated.verifierContract = await create2Deploy(zkEVMDeployerContract, salt, deployer, verifierPath, []); + generated.forkableZkEVM = await create2Deploy(zkEVMDeployerContract, salt, deployer, 'ForkableZkEVM', [], overrideGasLimit, forkableLibs); + generated.forkableGlobalExitRoot = await create2Deploy(zkEVMDeployerContract, salt, deployer, 'ForkableGlobalExitRoot', [], overrideGasLimit, forkableLibs); - generated.forkingManager = await commonDeployment.create2Deploy(zkEVMDeployerContract, salt, deployer, 'ForkingManager', [], overrideGasLimit, forkableLibs); + generated.forkingManager = await create2Deploy(zkEVMDeployerContract, salt, deployer, 'ForkingManager', [], overrideGasLimit, forkableLibs); /* * We use a Proxy Admin to control the contracts instead of an EOA as recommended here: @@ -90,7 +89,8 @@ async function doDeployBase() { const proxyAdminPath = '@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol:ProxyAdmin'; const proxyAdminFactory = await ethers.getContractFactory(proxyAdminPath, deployer); const dataCallAdmin = proxyAdminFactory.interface.encodeFunctionData('transferOwnership', [admin]); - generated.proxyAdmin = await commonDeployment.create2Deploy(zkEVMDeployerContract, salt, deployer, proxyAdminPath, [], overrideGasLimit, null, dataCallAdmin); + const proxyAdmin = await create2Deploy(zkEVMDeployerContract, salt, deployer, proxyAdminPath, [], overrideGasLimit, null, dataCallAdmin); + generated.proxyAdmin = proxyAdmin; /* * We use the forking manager implementation to spawn the instances @@ -99,11 +99,11 @@ async function doDeployBase() { */ const spawner = generated.forkingManager; - generated.forkableGlobalExitRootPredicted = await commonDeployment.predictTransparentProxyAddress(spawner, generated.forkableGlobalExitRoot, generated.proxyAdmin, deployer.address); - generated.forkableZkEVMPredicted = await commonDeployment.predictTransparentProxyAddress(spawner, generated.forkableZkEVM, generated.proxyAdmin, deployer.address); - generated.forkingManagerPredicted = await commonDeployment.predictTransparentProxyAddress(spawner, generated.forkingManager, generated.proxyAdmin, deployer.address); - generated.forkonomicTokenPredicted = await commonDeployment.predictTransparentProxyAddress(spawner, generated.forkonomicToken, generated.proxyAdmin, deployer.address); - generated.forkableBridgePredicted = await commonDeployment.predictTransparentProxyAddress(spawner, generated.forkableBridge, generated.proxyAdmin, deployer.address); + generated.forkableGlobalExitRootPredicted = await predictTransparentProxyAddress(spawner, generated.forkableGlobalExitRoot, proxyAdmin, deployer.address); + generated.forkableZkEVMPredicted = await predictTransparentProxyAddress(spawner, generated.forkableZkEVM, proxyAdmin, deployer.address); + generated.forkingManagerPredicted = await predictTransparentProxyAddress(spawner, generated.forkingManager, proxyAdmin, deployer.address); + generated.forkonomicTokenPredicted = await predictTransparentProxyAddress(spawner, generated.forkonomicToken, proxyAdmin, deployer.address); + generated.forkableBridgePredicted = await predictTransparentProxyAddress(spawner, generated.forkableBridge, proxyAdmin, deployer.address); return generated; } diff --git a/src/deployment/3_spawnInstance.js b/src/deployment/3_spawnInstance.js index f5cf54b0..dc96c293 100644 --- a/src/deployment/3_spawnInstance.js +++ b/src/deployment/3_spawnInstance.js @@ -16,8 +16,6 @@ const { expect } = require('chai'); const { ethers, upgrades } = require('hardhat'); require('dotenv').config({ path: path.resolve(__dirname, '../.env') }); -const { create2Deployment } = require('./helpers/deployment-helpers'); -const commonDeployment = require('./common'); const common = require('../common/common'); const pathOutputJson = path.join(__dirname, './deploy_output.json'); @@ -27,7 +25,6 @@ const deployParameters = require('./deploy_parameters.json'); const genesis = require('./genesis.json'); const pathOZUpgradability = path.join(__dirname, `../.openzeppelin/${process.env.HARDHAT_NETWORK}.json`); -const parentContract = ethers.constants.AddressZero; async function doSpawnInstance() { // Check that there's no previous OZ deployment @@ -35,9 +32,6 @@ async function doSpawnInstance() { throw new Error(`There's upgradability information from previous deployments, it's mandatory to erase them before start a new one, path: ${pathOZUpgradability}`); } - // Constant variables - const networkIDMainnet = 0; - /* * Check deploy parameters * Check that every necessary parameter is fullfilled @@ -59,7 +53,6 @@ async function doSpawnInstance() { // 'timelockAddress', 'minDelayTimelock', 'salt', - 'zkEVMDeployerAddress', 'hardAssetManagerAddress', 'arbitrationFee', ]; @@ -78,7 +71,6 @@ async function doSpawnInstance() { common.verifyDeploymentParameters(mandatoryImplementationAddresses, generated); const { - realVerifier, trustedSequencerURL, networkName, version, @@ -91,11 +83,7 @@ async function doSpawnInstance() { trustedAggregatorTimeout, pendingStateTimeout, forkID, - zkEVMOwner, - // timelockAddress, - minDelayTimelock, salt, - zkEVMDeployerAddress, hardAssetManagerAddress, arbitrationFee, } = deployParameters; @@ -142,7 +130,6 @@ async function doSpawnInstance() { // We run spawnInstance against the implementation contract const forkingManagerFactory = await ethers.getContractFactory('ForkingManager', { libraries: { CreateChildren: generated.createChildren } }); const forkingManagerImplContract = forkingManagerFactory.attach(generated.forkingManager); - const signedForkingManagerImplContract = forkingManagerImplContract.connect(deployer); deploymentBlockNumber = -1; const deployedCode = await deployer.provider.getCode(generated.forkableZkEVMPredicted); if (deployedCode === '0x') { diff --git a/src/deployment/common.js b/src/deployment/common.js index e9518899..dd8aed13 100644 --- a/src/deployment/common.js +++ b/src/deployment/common.js @@ -39,7 +39,7 @@ async function loadOngoingOrDeploy(deployer, contractName, ongoingName, args, on return contractInstance; } -async function create2Deploy(create2Deployer, salt, deployer, contractName, args, overrideGasLimit, libraries, unsafeAllowLinkedLibraries, dataCall) { +async function create2Deploy(create2Deployer, salt, deployer, contractName, args, gasLimit, libraries, unsafeAllowLinkedLibraries, dataCall) { const contractFactory = await ethers.getContractFactory(contractName, { signer: deployer, libraries, @@ -48,14 +48,13 @@ async function create2Deploy(create2Deployer, salt, deployer, contractName, args let addr; - const displayName = contractName.replace(/^.*[\\\/]/, ''); + const displayName = contractName.replace(/^.*[\\/]/, ''); - const isAlreadyCreated = false; if (addr) { console.log(displayName, 'using existing from ongoing deployment', addr); } else { const deployTransaction = (contractFactory.getDeployTransaction(...args)).data; - [addr, isNewlyCreated] = await create2Deployment(create2Deployer, salt, deployTransaction, dataCall, deployer, overrideGasLimit); + [addr, isNewlyCreated] = await create2Deployment(create2Deployer, salt, deployTransaction, dataCall, deployer, gasLimit); if (isNewlyCreated) { console.log(displayName, 'deployed with create2', addr); } else { diff --git a/src/deployment/verifyContracts.js b/src/deployment/verifyContracts.js index 2829862d..0789981c 100644 --- a/src/deployment/verifyContracts.js +++ b/src/deployment/verifyContracts.js @@ -5,9 +5,7 @@ const hre = require('hardhat'); const { expect } = require('chai'); const pathDeployOutputParameters = path.join(__dirname, './deploy_output.json'); -const pathDeployParameters = path.join(__dirname, './deploy_parameters.json'); const deployOutputParameters = require(pathDeployOutputParameters); -const deployParameters = require(pathDeployParameters); async function getImplementationAddress(proxyAddress) { // The specific storage slot for the implementation address as per EIP-1967 From 601837c4bf8ebbd2a033ae82cfd5b56530ca0747 Mon Sep 17 00:00:00 2001 From: Edmund Edgar Date: Fri, 29 Mar 2024 00:23:23 +0000 Subject: [PATCH 15/16] Break out the functionality of the main deployment scripts so it can be called from a test etc --- src/deployment/1_deployBase.js | 101 +--------------- src/deployment/3_spawnInstance.js | 177 +--------------------------- src/deployment/deployBase.js | 106 +++++++++++++++++ src/deployment/spawnInstance.js | 190 ++++++++++++++++++++++++++++++ 4 files changed, 301 insertions(+), 273 deletions(-) create mode 100644 src/deployment/deployBase.js create mode 100644 src/deployment/spawnInstance.js diff --git a/src/deployment/1_deployBase.js b/src/deployment/1_deployBase.js index 5293e90b..38273b6c 100644 --- a/src/deployment/1_deployBase.js +++ b/src/deployment/1_deployBase.js @@ -4,112 +4,15 @@ /* eslint-disable no-console, no-inner-declarations, no-undef, import/no-unresolved, no-restricted-syntax */ const path = require('path'); const fs = require('fs'); -const { ethers, upgrades } = require('hardhat'); require('dotenv').config({ path: path.resolve(__dirname, '../.env') }); -const { expect } = require('chai'); -const { deployPolygonZkEVMDeployer } = require('./helpers/deployment-helpers'); const deployParameters = require('./deploy_parameters.json'); - const generatedPath = path.join(__dirname, './deploy_generated.json'); -const { create2Deploy, predictTransparentProxyAddress } = require('./common'); -const common = require('../common/common'); - -async function doDeployBase() { - /* - * Hardhat needs a special gas override to avoid errors about the block gas limit. - * Sepolia doesn't seem to care. - */ - const overrideGasLimit = (process.env.HARDHAT_NETWORK === 'hardhat') ? ethers.BigNumber.from(6500000) : null; - - const generated = {}; - - const currentProvider = await common.loadProvider(deployParameters, process.env); - const deployer = await common.loadDeployer(currentProvider, deployParameters); - console.log('Deployer: ', deployer.address); - - // Load initialZkEVMDeployerOwner - const { - realVerifier, - chainID, - admin, - salt, - } = deployParameters; - - let { - initialZkEVMDeployerOwner, - } = deployParameters; - - if (!initialZkEVMDeployerOwner) { - initialZkEVMDeployerOwner = deployer.address; - console.log('initialZkEVMDeployerOwner not set, using deployer,', initialZkEVMDeployerOwner); - } - - // Deploy PolygonZkEVMDeployer if is not deployed already using keyless deployment - const [zkEVMDeployerContract, keylessDeployer] = await deployPolygonZkEVMDeployer(initialZkEVMDeployerOwner, deployer); - if (keylessDeployer === ethers.constants.AddressZero) { - console.log('PolygonZkEVMDeployer was already deployed on: ', zkEVMDeployerContract.address); - } else { - console.log('PolygonZkEVMDeployer deployed on: ', zkEVMDeployerContract.address); - } - generated.zkEVMDeployerAddress = zkEVMDeployerContract.address; - - expect(deployer.address).to.be.equal(await zkEVMDeployerContract.owner()); - - generated.createChildren = await create2Deploy(zkEVMDeployerContract, salt, deployer, 'CreateChildren', [], overrideGasLimit, null, true); - generated.bridgeAssetOperations = await create2Deploy(zkEVMDeployerContract, salt, deployer, 'BridgeAssetOperations', []); - - const bridgeLibs = { - CreateChildren: generated.createChildren, - BridgeAssetOperations: generated.bridgeAssetOperations, - }; - - generated.forkableBridge = await create2Deploy(zkEVMDeployerContract, salt, deployer, 'ForkableBridge', [], overrideGasLimit, bridgeLibs); - - const forkableLibs = { - CreateChildren: generated.createChildren, - }; - - generated.forkonomicToken = await create2Deploy(zkEVMDeployerContract, salt, deployer, 'ForkonomicToken', [], overrideGasLimit, forkableLibs); - generated.chainIdManager = await create2Deploy(zkEVMDeployerContract, salt, deployer, 'ChainIdManager', [chainID]); - - const verifierPath = realVerifier ? '@RealityETH/zkevm-contracts/contracts/verifiers/FflonkVerifier.sol:FflonkVerifier' : '@RealityETH/zkevm-contracts/contracts/mocks/VerifierRollupHelperMock.sol:VerifierRollupHelperMock'; - generated.verifierContract = await create2Deploy(zkEVMDeployerContract, salt, deployer, verifierPath, []); - generated.forkableZkEVM = await create2Deploy(zkEVMDeployerContract, salt, deployer, 'ForkableZkEVM', [], overrideGasLimit, forkableLibs); - generated.forkableGlobalExitRoot = await create2Deploy(zkEVMDeployerContract, salt, deployer, 'ForkableGlobalExitRoot', [], overrideGasLimit, forkableLibs); - - generated.forkingManager = await create2Deploy(zkEVMDeployerContract, salt, deployer, 'ForkingManager', [], overrideGasLimit, forkableLibs); - - /* - * We use a Proxy Admin to control the contracts instead of an EOA as recommended here: - * https://docs.openzeppelin.com/contracts/4.x/api/proxy#TransparentUpgradeableProxy - * Do not initialize directly the proxy since we want to deploy the same code on L2 and this will alter the bytecode deployed of the proxy - */ - const proxyAdminPath = '@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol:ProxyAdmin'; - const proxyAdminFactory = await ethers.getContractFactory(proxyAdminPath, deployer); - const dataCallAdmin = proxyAdminFactory.interface.encodeFunctionData('transferOwnership', [admin]); - const proxyAdmin = await create2Deploy(zkEVMDeployerContract, salt, deployer, proxyAdminPath, [], overrideGasLimit, null, dataCallAdmin); - generated.proxyAdmin = proxyAdmin; - - /* - * We use the forking manager implementation to spawn the instances - * TODO: This might be better as a separate contract sharing relevant parts with ForkingManager - * const forkingManagerFactory = await ethers.getContractFactory('ForkingManager', {signer: deployer, libraries: forkableLibs, unsafeAllowLinkedLibraries: true}); - */ - const spawner = generated.forkingManager; - - generated.forkableGlobalExitRootPredicted = await predictTransparentProxyAddress(spawner, generated.forkableGlobalExitRoot, proxyAdmin, deployer.address); - generated.forkableZkEVMPredicted = await predictTransparentProxyAddress(spawner, generated.forkableZkEVM, proxyAdmin, deployer.address); - generated.forkingManagerPredicted = await predictTransparentProxyAddress(spawner, generated.forkingManager, proxyAdmin, deployer.address); - generated.forkonomicTokenPredicted = await predictTransparentProxyAddress(spawner, generated.forkonomicToken, proxyAdmin, deployer.address); - generated.forkableBridgePredicted = await predictTransparentProxyAddress(spawner, generated.forkableBridge, proxyAdmin, deployer.address); - - return generated; -} +const { doDeployBase } = require('./deployBase'); async function main() { - const generated = await doDeployBase(); + const generated = await doDeployBase(deployParameters); fs.writeFileSync(generatedPath, JSON.stringify(generated, null, 1)); } diff --git a/src/deployment/3_spawnInstance.js b/src/deployment/3_spawnInstance.js index dc96c293..532720e7 100644 --- a/src/deployment/3_spawnInstance.js +++ b/src/deployment/3_spawnInstance.js @@ -12,11 +12,9 @@ /* eslint-disable no-console, no-inner-declarations, no-undef, import/no-unresolved, no-restricted-syntax */ const path = require('path'); const fs = require('fs'); -const { expect } = require('chai'); const { ethers, upgrades } = require('hardhat'); require('dotenv').config({ path: path.resolve(__dirname, '../.env') }); - -const common = require('../common/common'); +const { doSpawnInstance} = require('./spawnInstance'); const pathOutputJson = path.join(__dirname, './deploy_output.json'); const generated = require('./deploy_generated.json'); @@ -26,182 +24,13 @@ const genesis = require('./genesis.json'); const pathOZUpgradability = path.join(__dirname, `../.openzeppelin/${process.env.HARDHAT_NETWORK}.json`); -async function doSpawnInstance() { +async function main() { // Check that there's no previous OZ deployment if (fs.existsSync(pathOZUpgradability)) { throw new Error(`There's upgradability information from previous deployments, it's mandatory to erase them before start a new one, path: ${pathOZUpgradability}`); } - /* - * Check deploy parameters - * Check that every necessary parameter is fullfilled - */ - const mandatoryDeploymentParameters = [ - 'trustedSequencerURL', - 'networkName', - 'version', - 'forkPreparationTime', - 'trustedSequencer', - 'chainID', - 'admin', - 'minter', - 'trustedAggregator', - 'trustedAggregatorTimeout', - 'pendingStateTimeout', - 'forkID', - 'zkEVMOwner', - // 'timelockAddress', - 'minDelayTimelock', - 'salt', - 'hardAssetManagerAddress', - 'arbitrationFee', - ]; - common.verifyDeploymentParameters(mandatoryDeploymentParameters, deployParameters); - - const mandatoryImplementationAddresses = [ - 'createChildren', - 'bridgeAssetOperations', - 'forkableBridge', - 'forkonomicToken', - 'chainIdManager', - 'forkableZkEVM', - 'forkableGlobalExitRoot', - 'forkingManager', - ]; - common.verifyDeploymentParameters(mandatoryImplementationAddresses, generated); - - const { - trustedSequencerURL, - networkName, - version, - forkPreparationTime, - trustedSequencer, - chainID, - admin, - minter, - trustedAggregator, - trustedAggregatorTimeout, - pendingStateTimeout, - forkID, - salt, - hardAssetManagerAddress, - arbitrationFee, - } = deployParameters; - - const currentProvider = await common.loadProvider(deployParameters, process.env); - const deployer = await common.loadDeployer(currentProvider, deployParameters); - - // deploy PolygonZkEVMM - const genesisRootHex = genesis.root; - - const deploymentConfig = [ - genesisRootHex, - trustedSequencerURL, - networkName, - version, - generated.verifierContract, - minter, - 'Backstop0', - 'BOP0', - arbitrationFee, - generated.chainIdManager, - forkPreparationTime, - hardAssetManagerAddress, - 0, - ethers.constants.HashZero, // TODO: Do we need to fill in lastMainnetExitRoot? - ethers.constants.HashZero, // TODO: Do we need to fill in lastRollupExitRoot? - ethers.constants.AddressZero, - ethers.constants.AddressZero, - ethers.constants.AddressZero, - ethers.constants.AddressZero, - ]; - - const polygonZkEVMParams = [ - admin, - trustedSequencer, - pendingStateTimeout, - trustedAggregator, - trustedAggregatorTimeout, - chainID, - forkID, - 0, - ]; - - // We run spawnInstance against the implementation contract - const forkingManagerFactory = await ethers.getContractFactory('ForkingManager', { libraries: { CreateChildren: generated.createChildren } }); - const forkingManagerImplContract = forkingManagerFactory.attach(generated.forkingManager); - deploymentBlockNumber = -1; - const deployedCode = await deployer.provider.getCode(generated.forkableZkEVMPredicted); - if (deployedCode === '0x') { - const tx = await forkingManagerImplContract.spawnInstance( - generated.proxyAdmin, - generated.forkableZkEVM, - generated.forkableBridge, - generated.forkonomicToken, - generated.forkableGlobalExitRoot, - deploymentConfig, - polygonZkEVMParams, - ); - - // console.log('tx', tx); - const receipt = await tx.wait(); - deploymentBlockNumber = receipt.blockNumber; - - /* - * Receipts should holdlog events from the proxy including our predicted addresses - * console.log(receipt.logs); - */ - } else { - console.log('Already called spawnInstance with this salt. Change the salt and redeploy.'); - console.log('If you are sure the deployment is correct you can instead fill in block number manually.'); - } - - // Check deployment - expect('0x').not.to.be.equal(await deployer.provider.getCode(generated.forkableZkEVMPredicted)); - expect('0x').not.to.be.equal(await deployer.provider.getCode(generated.forkableBridgePredicted)); - expect('0x').not.to.be.equal(await deployer.provider.getCode(generated.forkableGlobalExitRootPredicted)); - expect('0x').not.to.be.equal(await deployer.provider.getCode(generated.forkingManagerPredicted)); - expect('0x').not.to.be.equal(await deployer.provider.getCode(generated.forkonomicTokenPredicted)); - - const forkingManagerDeployedContract = forkingManagerFactory.attach(generated.forkingManagerPredicted); - expect(await forkingManagerDeployedContract.zkEVM()).to.be.equal(generated.forkableZkEVMPredicted); - expect(await forkingManagerDeployedContract.bridge()).to.be.equal(generated.forkableBridgePredicted); - expect(await forkingManagerDeployedContract.forkonomicToken()).to.be.equal(generated.forkonomicTokenPredicted); - expect(await forkingManagerDeployedContract.globalExitRoot()).to.be.equal(generated.forkableGlobalExitRootPredicted); - - const outputJson = { - polygonZkEVMAddress: generated.forkableZkEVMPredicted, - polygonZkEVMBridgeAddress: generated.forkableBridgePredicted, - polygonZkEVMGlobalExitRootAddress: generated.forkableGlobalExitRootPredicted, - forkingManager: generated.forkingManagerPredicted, - maticTokenAddress: generated.forkonomicTokenPredicted, - createChildrenImplementationAddress: generated.createChildren, - bridgeOperationImplementationAddress: generated.bridgeAssetOperations, - bridgeImplementationAddress: generated.forkableBridge, - verifierAddress: generated.verifierContract, - zkEVMDeployerContract: generated.zkEVMDeployerAddress, - deployerAddress: deployer.address, - timelockContractAddress: null, - deploymentBlockNumber, - genesisRoot: genesisRootHex, - trustedSequencer, - trustedSequencerURL, - chainID, - networkName, - admin, - trustedAggregator, - proxyAdminAddress: generated.proxyAdmin, - forkID, - salt, - version, - minter, - }; - - return outputJson; -} - -async function main() { - const output = await doSpawnInstance(); + const output = await doSpawnInstance(genesis, deployParameters, generated); fs.writeFileSync(pathOutputJson, JSON.stringify(output, null, 1)); } diff --git a/src/deployment/deployBase.js b/src/deployment/deployBase.js new file mode 100644 index 00000000..8bcf98ac --- /dev/null +++ b/src/deployment/deployBase.js @@ -0,0 +1,106 @@ +// This deploys the keyless deployer, then uses it deploy implementations with create2 + +/* eslint-disable no-await-in-loop, no-use-before-define, no-lonely-if, import/no-dynamic-require, global-require */ +/* eslint-disable no-console, no-inner-declarations, no-undef, import/no-unresolved, no-restricted-syntax */ +const { ethers, upgrades } = require('hardhat'); +const { expect } = require('chai'); +const { deployPolygonZkEVMDeployer } = require('./helpers/deployment-helpers'); + +const { create2Deploy, predictTransparentProxyAddress } = require('./common'); +const common = require('../common/common'); + +async function doDeployBase(deployParameters) { + /* + * Hardhat needs a special gas override to avoid errors about the block gas limit. + * Sepolia doesn't seem to care. + */ + const overrideGasLimit = (process.env.HARDHAT_NETWORK === 'hardhat') ? ethers.BigNumber.from(6500000) : null; + + const generated = {}; + + const currentProvider = await common.loadProvider(deployParameters, process.env); + const deployer = await common.loadDeployer(currentProvider, deployParameters); + console.log('Deployer: ', deployer.address); + + // Load initialZkEVMDeployerOwner + const { + realVerifier, + chainID, + admin, + salt, + } = deployParameters; + + let { + initialZkEVMDeployerOwner, + } = deployParameters; + + if (!initialZkEVMDeployerOwner) { + initialZkEVMDeployerOwner = deployer.address; + console.log('initialZkEVMDeployerOwner not set, using deployer,', initialZkEVMDeployerOwner); + } + + // Deploy PolygonZkEVMDeployer if is not deployed already using keyless deployment + const [zkEVMDeployerContract, keylessDeployer] = await deployPolygonZkEVMDeployer(initialZkEVMDeployerOwner, deployer); + if (keylessDeployer === ethers.constants.AddressZero) { + console.log('PolygonZkEVMDeployer was already deployed on: ', zkEVMDeployerContract.address); + } else { + console.log('PolygonZkEVMDeployer deployed on: ', zkEVMDeployerContract.address); + } + generated.zkEVMDeployerAddress = zkEVMDeployerContract.address; + + expect(deployer.address).to.be.equal(await zkEVMDeployerContract.owner()); + + generated.createChildren = await create2Deploy(zkEVMDeployerContract, salt, deployer, 'CreateChildren', [], overrideGasLimit, null, true); + generated.bridgeAssetOperations = await create2Deploy(zkEVMDeployerContract, salt, deployer, 'BridgeAssetOperations', []); + + const bridgeLibs = { + CreateChildren: generated.createChildren, + BridgeAssetOperations: generated.bridgeAssetOperations, + }; + + generated.forkableBridge = await create2Deploy(zkEVMDeployerContract, salt, deployer, 'ForkableBridge', [], overrideGasLimit, bridgeLibs); + + const forkableLibs = { + CreateChildren: generated.createChildren, + }; + + generated.forkonomicToken = await create2Deploy(zkEVMDeployerContract, salt, deployer, 'ForkonomicToken', [], overrideGasLimit, forkableLibs); + generated.chainIdManager = await create2Deploy(zkEVMDeployerContract, salt, deployer, 'ChainIdManager', [chainID]); + + const verifierPath = realVerifier ? '@RealityETH/zkevm-contracts/contracts/verifiers/FflonkVerifier.sol:FflonkVerifier' : '@RealityETH/zkevm-contracts/contracts/mocks/VerifierRollupHelperMock.sol:VerifierRollupHelperMock'; + generated.verifierContract = await create2Deploy(zkEVMDeployerContract, salt, deployer, verifierPath, []); + generated.forkableZkEVM = await create2Deploy(zkEVMDeployerContract, salt, deployer, 'ForkableZkEVM', [], overrideGasLimit, forkableLibs); + generated.forkableGlobalExitRoot = await create2Deploy(zkEVMDeployerContract, salt, deployer, 'ForkableGlobalExitRoot', [], overrideGasLimit, forkableLibs); + + generated.forkingManager = await create2Deploy(zkEVMDeployerContract, salt, deployer, 'ForkingManager', [], overrideGasLimit, forkableLibs); + + /* + * We use a Proxy Admin to control the contracts instead of an EOA as recommended here: + * https://docs.openzeppelin.com/contracts/4.x/api/proxy#TransparentUpgradeableProxy + * Do not initialize directly the proxy since we want to deploy the same code on L2 and this will alter the bytecode deployed of the proxy + */ + const proxyAdminPath = '@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol:ProxyAdmin'; + const proxyAdminFactory = await ethers.getContractFactory(proxyAdminPath, deployer); + const dataCallAdmin = proxyAdminFactory.interface.encodeFunctionData('transferOwnership', [admin]); + const proxyAdmin = await create2Deploy(zkEVMDeployerContract, salt, deployer, proxyAdminPath, [], overrideGasLimit, null, dataCallAdmin); + generated.proxyAdmin = proxyAdmin; + + /* + * We use the forking manager implementation to spawn the instances + * TODO: This might be better as a separate contract sharing relevant parts with ForkingManager + * const forkingManagerFactory = await ethers.getContractFactory('ForkingManager', {signer: deployer, libraries: forkableLibs, unsafeAllowLinkedLibraries: true}); + */ + const spawner = generated.forkingManager; + + generated.forkableGlobalExitRootPredicted = await predictTransparentProxyAddress(spawner, generated.forkableGlobalExitRoot, proxyAdmin, deployer.address); + generated.forkableZkEVMPredicted = await predictTransparentProxyAddress(spawner, generated.forkableZkEVM, proxyAdmin, deployer.address); + generated.forkingManagerPredicted = await predictTransparentProxyAddress(spawner, generated.forkingManager, proxyAdmin, deployer.address); + generated.forkonomicTokenPredicted = await predictTransparentProxyAddress(spawner, generated.forkonomicToken, proxyAdmin, deployer.address); + generated.forkableBridgePredicted = await predictTransparentProxyAddress(spawner, generated.forkableBridge, proxyAdmin, deployer.address); + + return generated; +} + +module.exports = { + doDeployBase +} diff --git a/src/deployment/spawnInstance.js b/src/deployment/spawnInstance.js new file mode 100644 index 00000000..70196e4c --- /dev/null +++ b/src/deployment/spawnInstance.js @@ -0,0 +1,190 @@ +/* + *Deployment loosely based on the upstream 3_deployContracts.ts + * + *NB Upstream Polygon administers things with a ProxyAdmin controlled by a Timelock. + *For simplicity we remove the timelock and have the ProxyAdmin controlled purely by an EOA. + *Ultimately we will have our own custom system for controlling L1 upgrades. + * + *We also remove the deploy_ongoing stuff as the only deployment here is done by create2. + */ + +/* eslint-disable no-await-in-loop, no-use-before-define, no-lonely-if, import/no-dynamic-require, global-require */ +/* eslint-disable no-console, no-inner-declarations, no-undef, import/no-unresolved, no-restricted-syntax */ +const { expect } = require('chai'); +const { ethers, upgrades } = require('hardhat'); + +const common = require('../common/common'); + +async function doSpawnInstance(genesis, deployParameters, generated) { + + /* + * Check deploy parameters + * Check that every necessary parameter is fullfilled + */ + const mandatoryDeploymentParameters = [ + 'trustedSequencerURL', + 'networkName', + 'version', + 'forkPreparationTime', + 'trustedSequencer', + 'chainID', + 'admin', + 'minter', + 'trustedAggregator', + 'trustedAggregatorTimeout', + 'pendingStateTimeout', + 'forkID', + 'zkEVMOwner', + // 'timelockAddress', + 'minDelayTimelock', + 'salt', + 'hardAssetManagerAddress', + 'arbitrationFee', + ]; + common.verifyDeploymentParameters(mandatoryDeploymentParameters, deployParameters); + + const mandatoryImplementationAddresses = [ + 'createChildren', + 'bridgeAssetOperations', + 'forkableBridge', + 'forkonomicToken', + 'chainIdManager', + 'forkableZkEVM', + 'forkableGlobalExitRoot', + 'forkingManager', + ]; + common.verifyDeploymentParameters(mandatoryImplementationAddresses, generated); + + const { + trustedSequencerURL, + networkName, + version, + forkPreparationTime, + trustedSequencer, + chainID, + admin, + minter, + trustedAggregator, + trustedAggregatorTimeout, + pendingStateTimeout, + forkID, + salt, + hardAssetManagerAddress, + arbitrationFee, + } = deployParameters; + + const currentProvider = await common.loadProvider(deployParameters, process.env); + const deployer = await common.loadDeployer(currentProvider, deployParameters); + + // deploy PolygonZkEVMM + const genesisRootHex = genesis.root; + + const deploymentConfig = [ + genesisRootHex, + trustedSequencerURL, + networkName, + version, + generated.verifierContract, + minter, + 'Backstop0', + 'BOP0', + arbitrationFee, + generated.chainIdManager, + forkPreparationTime, + hardAssetManagerAddress, + 0, + ethers.constants.HashZero, // TODO: Do we need to fill in lastMainnetExitRoot? + ethers.constants.HashZero, // TODO: Do we need to fill in lastRollupExitRoot? + ethers.constants.AddressZero, + ethers.constants.AddressZero, + ethers.constants.AddressZero, + ethers.constants.AddressZero, + ]; + + const polygonZkEVMParams = [ + admin, + trustedSequencer, + pendingStateTimeout, + trustedAggregator, + trustedAggregatorTimeout, + chainID, + forkID, + 0, + ]; + + // We run spawnInstance against the implementation contract + const forkingManagerFactory = await ethers.getContractFactory('ForkingManager', { libraries: { CreateChildren: generated.createChildren } }); + const forkingManagerImplContract = forkingManagerFactory.attach(generated.forkingManager); + deploymentBlockNumber = -1; + const deployedCode = await deployer.provider.getCode(generated.forkableZkEVMPredicted); + if (deployedCode === '0x') { + const tx = await forkingManagerImplContract.spawnInstance( + generated.proxyAdmin, + generated.forkableZkEVM, + generated.forkableBridge, + generated.forkonomicToken, + generated.forkableGlobalExitRoot, + deploymentConfig, + polygonZkEVMParams, + ); + + // console.log('tx', tx); + const receipt = await tx.wait(); + deploymentBlockNumber = receipt.blockNumber; + + /* + * Receipts should holdlog events from the proxy including our predicted addresses + * console.log(receipt.logs); + */ + } else { + console.log('Already called spawnInstance with this salt. Change the salt and redeploy.'); + console.log('If you are sure the deployment is correct you can instead fill in block number manually.'); + } + + // Check deployment + expect('0x').not.to.be.equal(await deployer.provider.getCode(generated.forkableZkEVMPredicted)); + expect('0x').not.to.be.equal(await deployer.provider.getCode(generated.forkableBridgePredicted)); + expect('0x').not.to.be.equal(await deployer.provider.getCode(generated.forkableGlobalExitRootPredicted)); + expect('0x').not.to.be.equal(await deployer.provider.getCode(generated.forkingManagerPredicted)); + expect('0x').not.to.be.equal(await deployer.provider.getCode(generated.forkonomicTokenPredicted)); + + const forkingManagerDeployedContract = forkingManagerFactory.attach(generated.forkingManagerPredicted); + expect(await forkingManagerDeployedContract.zkEVM()).to.be.equal(generated.forkableZkEVMPredicted); + expect(await forkingManagerDeployedContract.bridge()).to.be.equal(generated.forkableBridgePredicted); + expect(await forkingManagerDeployedContract.forkonomicToken()).to.be.equal(generated.forkonomicTokenPredicted); + expect(await forkingManagerDeployedContract.globalExitRoot()).to.be.equal(generated.forkableGlobalExitRootPredicted); + + const outputJson = { + polygonZkEVMAddress: generated.forkableZkEVMPredicted, + polygonZkEVMBridgeAddress: generated.forkableBridgePredicted, + polygonZkEVMGlobalExitRootAddress: generated.forkableGlobalExitRootPredicted, + forkingManager: generated.forkingManagerPredicted, + maticTokenAddress: generated.forkonomicTokenPredicted, + createChildrenImplementationAddress: generated.createChildren, + bridgeOperationImplementationAddress: generated.bridgeAssetOperations, + bridgeImplementationAddress: generated.forkableBridge, + verifierAddress: generated.verifierContract, + zkEVMDeployerContract: generated.zkEVMDeployerAddress, + deployerAddress: deployer.address, + timelockContractAddress: null, + deploymentBlockNumber, + genesisRoot: genesisRootHex, + trustedSequencer, + trustedSequencerURL, + chainID, + networkName, + admin, + trustedAggregator, + proxyAdminAddress: generated.proxyAdmin, + forkID, + salt, + version, + minter, + }; + + return outputJson; +} + +module.exports = { + doSpawnInstance +} From 5aeb2d39043d6fc9e074f7541960b320713df0ae Mon Sep 17 00:00:00 2001 From: Edmund Edgar Date: Fri, 29 Mar 2024 05:24:06 +0000 Subject: [PATCH 16/16] made a deployment (only as far as l1 applications) --- ...deploy_application_parameters.example.json | 8 + .../sepolia_1711689773/deploy_generated.json | 18 ++ .../sepolia_1711689773/deploy_output.json | 27 ++ .../deploy_output_l1_applications.json | 4 + .../sepolia_1711689773/deploy_parameters.json | 27 ++ deployments/sepolia_1711689773/genesis.json | 77 ++++++ deployments/sepolia_1711689773/sepolia.json | 249 ++++++++++++++++++ 7 files changed, 410 insertions(+) create mode 100644 deployments/sepolia_1711689773/deploy_application_parameters.example.json create mode 100644 deployments/sepolia_1711689773/deploy_generated.json create mode 100644 deployments/sepolia_1711689773/deploy_output.json create mode 100644 deployments/sepolia_1711689773/deploy_output_l1_applications.json create mode 100644 deployments/sepolia_1711689773/deploy_parameters.json create mode 100644 deployments/sepolia_1711689773/genesis.json create mode 100644 deployments/sepolia_1711689773/sepolia.json diff --git a/deployments/sepolia_1711689773/deploy_application_parameters.example.json b/deployments/sepolia_1711689773/deploy_application_parameters.example.json new file mode 100644 index 00000000..baf1939f --- /dev/null +++ b/deployments/sepolia_1711689773/deploy_application_parameters.example.json @@ -0,0 +1,8 @@ +{ + "adjudicationFrameworkDisputeFee": 123, + "forkArbitratorDisputeFee": 200, + "arbitratorDisputeFee": 12, + "arbitratorOwner": null, + "realityETHAddress": null, + "initialArbitratorAddresses": [] +} diff --git a/deployments/sepolia_1711689773/deploy_generated.json b/deployments/sepolia_1711689773/deploy_generated.json new file mode 100644 index 00000000..1bd34b36 --- /dev/null +++ b/deployments/sepolia_1711689773/deploy_generated.json @@ -0,0 +1,18 @@ +{ + "zkEVMDeployerAddress": "0x4e78730851Ec0d97B3785A1811e02b7e941c2943", + "createChildren": "0x219714200c7f774B152F8Cbb2571E049D4A56430", + "bridgeAssetOperations": "0x23748193fE94B8fdDc06A3f261cB5DB2dB21Dfac", + "forkableBridge": "0x91d8785bBa30E09255eC906F2bDfDf5919109b4f", + "forkonomicToken": "0x584f5e3B1d6f9274b7eeB5512c58ad0525804Ad4", + "chainIdManager": "0x94eF4E5637A07131062E75c397b8083c968a8DFb", + "verifierContract": "0xC8C0ab7485BaaF91698FC7a431801068df43c6c3", + "forkableZkEVM": "0x68Bdff669946bC9b30f0Ceb11c7004a47E41A91D", + "forkableGlobalExitRoot": "0x449Cd8D72cF668fab82E7DB5D856Dca7a8F53a4D", + "forkingManager": "0xB8A6158CF55f02A228C2Ecd6Aec722699297f0a5", + "proxyAdmin": "0x9029C03d935AdC24b3164bD289d5EAC8209afcc0", + "forkableGlobalExitRootPredicted": "0xdB7E1c8396483cBfa3e7D2728CE0c88452A29111", + "forkableZkEVMPredicted": "0xA75F4289b4b78Fd09c6C02b99E94EbE3B307A472", + "forkingManagerPredicted": "0x51F236d3482b3a923ee565259841a54426C5c141", + "forkonomicTokenPredicted": "0xF782C0A4708E9c9Ed84C66f8c4011F137A5E30e5", + "forkableBridgePredicted": "0xEA7ba7a39763ae484F616a9FB7E45beFB48b5D09" +} \ No newline at end of file diff --git a/deployments/sepolia_1711689773/deploy_output.json b/deployments/sepolia_1711689773/deploy_output.json new file mode 100644 index 00000000..ead66af1 --- /dev/null +++ b/deployments/sepolia_1711689773/deploy_output.json @@ -0,0 +1,27 @@ +{ + "polygonZkEVMAddress": "0xA75F4289b4b78Fd09c6C02b99E94EbE3B307A472", + "polygonZkEVMBridgeAddress": "0xEA7ba7a39763ae484F616a9FB7E45beFB48b5D09", + "polygonZkEVMGlobalExitRootAddress": "0xdB7E1c8396483cBfa3e7D2728CE0c88452A29111", + "forkingManager": "0x51F236d3482b3a923ee565259841a54426C5c141", + "maticTokenAddress": "0xF782C0A4708E9c9Ed84C66f8c4011F137A5E30e5", + "createChildrenImplementationAddress": "0x219714200c7f774B152F8Cbb2571E049D4A56430", + "bridgeOperationImplementationAddress": "0x23748193fE94B8fdDc06A3f261cB5DB2dB21Dfac", + "bridgeImplementationAddress": "0x91d8785bBa30E09255eC906F2bDfDf5919109b4f", + "verifierAddress": "0xC8C0ab7485BaaF91698FC7a431801068df43c6c3", + "zkEVMDeployerContract": "0x4e78730851Ec0d97B3785A1811e02b7e941c2943", + "deployerAddress": "0x55ddcD448cE2f52c29965B882279F120ec3506f8", + "timelockContractAddress": null, + "deploymentBlockNumber": 5582884, + "genesisRoot": "0x3a9a6ae2c73fff3ece22e24cc9caf0a6cf94ea0f5b0c350df3697663d0d47d10", + "trustedSequencer": "0x740a98F8f4fAe0986FB3264Fe4aaCf94ac1EE96f", + "trustedSequencerURL": "https://rpc.testnet.backstop.technology", + "chainID": 10101901, + "networkName": "BackstopL2", + "admin": "0x55ddcD448cE2f52c29965B882279F120ec3506f8", + "trustedAggregator": "0x5669C63E3B461cf50696AD0378fE2E66b982D4A7", + "proxyAdminAddress": "0x9029C03d935AdC24b3164bD289d5EAC8209afcc0", + "forkID": 6, + "salt": "0x1000000000000000000000000000000000000000000000000000000000000007", + "version": "0.0.1", + "minter": "0x55ddcD448cE2f52c29965B882279F120ec3506f8" +} \ No newline at end of file diff --git a/deployments/sepolia_1711689773/deploy_output_l1_applications.json b/deployments/sepolia_1711689773/deploy_output_l1_applications.json new file mode 100644 index 00000000..1431c840 --- /dev/null +++ b/deployments/sepolia_1711689773/deploy_output_l1_applications.json @@ -0,0 +1,4 @@ +{ + "l1GlobalChainInfoPublisher": "0xcDAdec0D1C09E8eD7e234cc51B4ECb5eEFD27b24", + "l1GlobalForkRequester": "0xc379D5a3B906F90df53a91e01e37E9A8CD966F0a" +} \ No newline at end of file diff --git a/deployments/sepolia_1711689773/deploy_parameters.json b/deployments/sepolia_1711689773/deploy_parameters.json new file mode 100644 index 00000000..b0a57d87 --- /dev/null +++ b/deployments/sepolia_1711689773/deploy_parameters.json @@ -0,0 +1,27 @@ +{ + "realVerifier": false, + "trustedSequencerURL": "https://rpc.testnet.backstop.technology", + "networkName": "BackstopL2", + "version": "0.0.1", + "forkPreparationTime": 60, + "trustedSequencer": "0x740a98F8f4fAe0986FB3264Fe4aaCf94ac1EE96f", + "chainID": 10101901, + "trustedAggregator": "0x5669C63E3B461cf50696AD0378fE2E66b982D4A7", + "trustedAggregatorTimeout": 604799, + "pendingStateTimeout": 604799, + "forkID": 6, + "admin": "0x55ddcD448cE2f52c29965B882279F120ec3506f8", + "minter": "0x55ddcD448cE2f52c29965B882279F120ec3506f8", + "zkEVMOwner": "0x55ddcD448cE2f52c29965B882279F120ec3506f8", + "minDelayTimelock": 60, + "salt": "0x1000000000000000000000000000000000000000000000000000000000000007", + "deployerPvtKey": "", + "maxFeePerGas": "100", + "maxPriorityFeePerGas": "10", + "multiplierGas": "2", + "hardAssetManagerAddress": "0x55ddcD448cE2f52c29965B882279F120ec3506f8", + "arbitrationFee": "1000000000000000000", + "initialZkEVMDeployerOwner": "0x55ddcD448cE2f52c29965B882279F120ec3506f8", + "proxyAdminAddress": "0x1046398D1B36911C3ff59DE9A8A9Da0850C39b39", + "zkEVMDeployerAddress": "0x4e78730851Ec0d97B3785A1811e02b7e941c2943" +} \ No newline at end of file diff --git a/deployments/sepolia_1711689773/genesis.json b/deployments/sepolia_1711689773/genesis.json new file mode 100644 index 00000000..deb949a5 --- /dev/null +++ b/deployments/sepolia_1711689773/genesis.json @@ -0,0 +1,77 @@ +{ + "root": "0x3a9a6ae2c73fff3ece22e24cc9caf0a6cf94ea0f5b0c350df3697663d0d47d10", + "genesis": [ + { + "contractName": "PolygonZkEVMDeployer", + "balance": "0", + "nonce": "6", + "address": "0x4e78730851Ec0d97B3785A1811e02b7e941c2943", + "bytecode": "0x6080604052600436106100705760003560e01c8063715018a61161004e578063715018a6146100d95780638da5cb5b146100ee578063e11ae6cb1461010c578063f2fde38b1461011f57600080fd5b80632b79805a146100755780634a94d4871461008a5780636d07dbf81461009d575b600080fd5b610088610083366004610765565b61013f565b005b6100886100983660046107f8565b6101a4565b3480156100a957600080fd5b506100bd6100b836600461084f565b6101e6565b6040516001600160a01b03909116815260200160405180910390f35b3480156100e557600080fd5b506100886101f9565b3480156100fa57600080fd5b506000546001600160a01b03166100bd565b61008861011a366004610871565b61020d565b34801561012b57600080fd5b5061008861013a3660046108c1565b610267565b6101476102e5565b600061015485858561033f565b90506101608183610443565b506040516001600160a01b03821681527fba82f25fed02cd2a23d9f5d11c2ef588d22af5437cbf23bfe61d87257c480e4c9060200160405180910390a15050505050565b6101ac6102e5565b6101b7838383610487565b506040517f25adb19089b6a549831a273acdf7908cff8b7ee5f551f8d1d37996cf01c5df5b90600090a1505050565b60006101f283836104b5565b9392505050565b6102016102e5565b61020b60006104c2565b565b6102156102e5565b600061022284848461033f565b6040516001600160a01b03821681529091507fba82f25fed02cd2a23d9f5d11c2ef588d22af5437cbf23bfe61d87257c480e4c9060200160405180910390a150505050565b61026f6102e5565b6001600160a01b0381166102d95760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b6102e2816104c2565b50565b6000546001600160a01b0316331461020b5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016102d0565b6000834710156103915760405162461bcd60e51b815260206004820152601d60248201527f437265617465323a20696e73756666696369656e742062616c616e636500000060448201526064016102d0565b81516000036103e25760405162461bcd60e51b815260206004820181905260248201527f437265617465323a2062797465636f6465206c656e677468206973207a65726f60448201526064016102d0565b8282516020840186f590506001600160a01b0381166101f25760405162461bcd60e51b815260206004820152601960248201527f437265617465323a204661696c6564206f6e206465706c6f790000000000000060448201526064016102d0565b60606101f2838360006040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c6564000081525061051f565b60606104ad8484846040518060600160405280602981526020016109506029913961051f565b949350505050565b60006101f28383306105fa565b600080546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6060824710156105805760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016102d0565b600080866001600160a01b0316858760405161059c9190610900565b60006040518083038185875af1925050503d80600081146105d9576040519150601f19603f3d011682016040523d82523d6000602084013e6105de565b606091505b50915091506105ef87838387610624565b979650505050505050565b6000604051836040820152846020820152828152600b8101905060ff815360559020949350505050565b6060831561069357825160000361068c576001600160a01b0385163b61068c5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102d0565b50816104ad565b6104ad83838151156106a85781518083602001fd5b8060405162461bcd60e51b81526004016102d0919061091c565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126106e957600080fd5b813567ffffffffffffffff80821115610704576107046106c2565b604051601f8301601f19908116603f0116810190828211818310171561072c5761072c6106c2565b8160405283815286602085880101111561074557600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000806000806080858703121561077b57600080fd5b8435935060208501359250604085013567ffffffffffffffff808211156107a157600080fd5b6107ad888389016106d8565b935060608701359150808211156107c357600080fd5b506107d0878288016106d8565b91505092959194509250565b80356001600160a01b03811681146107f357600080fd5b919050565b60008060006060848603121561080d57600080fd5b610816846107dc565b9250602084013567ffffffffffffffff81111561083257600080fd5b61083e868287016106d8565b925050604084013590509250925092565b6000806040838503121561086257600080fd5b50508035926020909101359150565b60008060006060848603121561088657600080fd5b8335925060208401359150604084013567ffffffffffffffff8111156108ab57600080fd5b6108b7868287016106d8565b9150509250925092565b6000602082840312156108d357600080fd5b6101f2826107dc565b60005b838110156108f75781810151838201526020016108df565b50506000910152565b600082516109128184602087016108dc565b9190910192915050565b602081526000825180602084015261093b8160408501602087016108dc565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2063616c6c20776974682076616c7565206661696c6564a264697066735822122098945a959130d6c15cf2906084bee6abd72e08b14d79b892027e34f5d3322d3264736f6c63430008140033", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x00000000000000000000000055ddcd448ce2f52c29965b882279f120ec3506f8" + } + }, + { + "contractName": "ProxyAdmin", + "balance": "0", + "nonce": "1", + "address": "0x9029C03d935AdC24b3164bD289d5EAC8209afcc0", + "bytecode": "0x60806040526004361061007b5760003560e01c80639623609d1161004e5780639623609d1461011157806399a88ec414610124578063f2fde38b14610144578063f3b7dead1461016457600080fd5b8063204e1c7a14610080578063715018a6146100bc5780637eff275e146100d35780638da5cb5b146100f3575b600080fd5b34801561008c57600080fd5b506100a061009b3660046104a6565b610184565b6040516001600160a01b03909116815260200160405180910390f35b3480156100c857600080fd5b506100d1610215565b005b3480156100df57600080fd5b506100d16100ee3660046104ca565b610229565b3480156100ff57600080fd5b506000546001600160a01b03166100a0565b6100d161011f366004610519565b610291565b34801561013057600080fd5b506100d161013f3660046104ca565b610300565b34801561015057600080fd5b506100d161015f3660046104a6565b610336565b34801561017057600080fd5b506100a061017f3660046104a6565b6103b4565b6000806000836001600160a01b03166040516101aa90635c60da1b60e01b815260040190565b600060405180830381855afa9150503d80600081146101e5576040519150601f19603f3d011682016040523d82523d6000602084013e6101ea565b606091505b5091509150816101f957600080fd5b8080602001905181019061020d91906105ef565b949350505050565b61021d6103da565b6102276000610434565b565b6102316103da565b6040516308f2839760e41b81526001600160a01b038281166004830152831690638f283970906024015b600060405180830381600087803b15801561027557600080fd5b505af1158015610289573d6000803e3d6000fd5b505050505050565b6102996103da565b60405163278f794360e11b81526001600160a01b03841690634f1ef2869034906102c9908690869060040161060c565b6000604051808303818588803b1580156102e257600080fd5b505af11580156102f6573d6000803e3d6000fd5b5050505050505050565b6103086103da565b604051631b2ce7f360e11b81526001600160a01b038281166004830152831690633659cfe69060240161025b565b61033e6103da565b6001600160a01b0381166103a85760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b6103b181610434565b50565b6000806000836001600160a01b03166040516101aa906303e1469160e61b815260040190565b6000546001600160a01b031633146102275760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161039f565b600080546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811681146103b157600080fd5b6000602082840312156104b857600080fd5b81356104c381610491565b9392505050565b600080604083850312156104dd57600080fd5b82356104e881610491565b915060208301356104f881610491565b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b60008060006060848603121561052e57600080fd5b833561053981610491565b9250602084013561054981610491565b9150604084013567ffffffffffffffff8082111561056657600080fd5b818601915086601f83011261057a57600080fd5b81358181111561058c5761058c610503565b604051601f8201601f19908116603f011681019083821181831017156105b4576105b4610503565b816040528281528960208487010111156105cd57600080fd5b8260208601602083013760006020848301015280955050505050509250925092565b60006020828403121561060157600080fd5b81516104c381610491565b6001600160a01b038316815260006020604081840152835180604085015260005b818110156106495785810183015185820160600152820161062d565b506000606082860101526060601f19601f83011685010192505050939250505056fea26469706673582212209f8e196929518fdc9b6d59215411fe4fd1b8a3bd80711de126a3a60ccf54c35b64736f6c63430008140033", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x00000000000000000000000055ddcd448ce2f52c29965b882279f120ec3506f8" + } + }, + { + "contractName": "PolygonZkEVMBridge implementation", + "balance": "0", + "nonce": "1", + "address": "0x91d8785bBa30E09255eC906F2bDfDf5919109b4f", + "bytecode": "0x608060405260043610620002a55760003560e01c80637002ce421162000164578063be5831c711620000d6578063e9913e7c1162000095578063f4b0eb6a116200006c578063f4b0eb6a14620008f4578063f83866f4146200091b578063fb570834146200094057600080fd5b8063e9913e7c1462000879578063ea8ef6be146200089c578063ee25560b14620008c357600080fd5b8063be5831c714620007dd578063cd5865791462000803578063d02103ca146200081a578063dbc16976146200083c578063e7403efb146200085457600080fd5b8063955bd57d1162000123578063955bd57d14620007135780639e34070f1462000748578063a4396d69146200076d578063aaa13cc21462000792578063bab161bf14620007b757600080fd5b80637002ce42146200064257806379e2cf97146200067c5780637b44b368146200069457806381b1c17414620006b4578063892076f514620006ee57600080fd5b80632dfdf0b5116200021b5780633ae0504711620001da578063485cc95511620001b1578063485cc955146200059a5780634892e8e814620005bf5780635509e609146200061d57600080fd5b80633ae05047146200053b5780633c351e1014620005535780633e197043146200057557600080fd5b80632dfdf0b514620004485780632f3954c91462000460578063316c859e1462000485578063318aee3d14620004aa57806334ac9cf2146200051957600080fd5b806322e95f2c116200026857806322e95f2c1462000387578063230b9da314620003c5578063240ff37814620003e75780632cffd02e14620003fe5780632d2c9d94146200042357600080fd5b80630d46caee14620002aa57806315064c9614620002d15780631c13c0f414620003025780632072f6c51462000336578063209ee16d146200034e575b600080fd5b348015620002b757600080fd5b50620002cf620002c936600462003779565b62000965565b005b348015620002de57600080fd5b50606854620002ed9060ff1681565b60405190151581526020015b60405180910390f35b3480156200030f57600080fd5b506200032762000321366004620037a8565b62000a95565b604051908152602001620002f9565b3480156200034357600080fd5b50620002cf62000aad565b3480156200035b57600080fd5b506200036662000ae5565b604080516001600160a01b03938416815292909116602083015201620002f9565b3480156200039457600080fd5b50620003ac620003a6366004620037d7565b62000b37565b6040516001600160a01b039091168152602001620002f9565b348015620003d257600080fd5b50606954620003ac906001600160a01b031681565b620002cf620003f83660046200386e565b62000ba2565b3480156200040b57600080fd5b50620002cf6200041d36600462003905565b62000bfa565b3480156200043057600080fd5b50620002cf6200044236600462003905565b62000c5e565b3480156200045557600080fd5b506200032760535481565b3480156200046d57600080fd5b50620002cf6200047f366004620039eb565b62000cb5565b3480156200049257600080fd5b50620002cf620004a436600462003a32565b62000e5a565b348015620004b757600080fd5b50620004f4620004c936600462003abf565b606f6020526000908152604090205463ffffffff81169064010000000090046001600160a01b031682565b6040805163ffffffff90931683526001600160a01b03909116602083015201620002f9565b3480156200052657600080fd5b50607054620003ac906001600160a01b031681565b3480156200054857600080fd5b506200032762000f01565b3480156200056057600080fd5b50606b54620003ac906001600160a01b031681565b3480156200058257600080fd5b50620003276200059436600462003aef565b62000fe7565b348015620005a757600080fd5b50620002cf620005b936600462003b79565b62001079565b348015620005cc57600080fd5b50606a60205260008051602062005e638339815191525460016000527ff585789965ba69220d5ce3dc1b444eb22ff546f2650694fef8fafe9c26560af9546001600160a01b03918216911662000366565b3480156200062a57600080fd5b50620002cf6200063c36600462003bdd565b620010f1565b3480156200064f57600080fd5b50620003ac62000661366004620037a8565b606a602052600090815260409020546001600160a01b031681565b3480156200068957600080fd5b50620002cf6200121d565b348015620006a157600080fd5b506071546001600160a01b0316620003ac565b348015620006c157600080fd5b50620003ac620006d3366004620037a8565b606e602052600090815260409020546001600160a01b031681565b348015620006fb57600080fd5b50620002cf6200070d36600462003cc0565b62001241565b3480156200072057600080fd5b50606c54600160a01b900463ffffffff165b60405163ffffffff9091168152602001620002f9565b3480156200075557600080fd5b50620002ed62000767366004620037a8565b62001377565b3480156200077a57600080fd5b50620002cf6200078c36600462003cfc565b6200144d565b3480156200079f57600080fd5b50620003ac620007b136600462003dda565b620015d6565b348015620007c457600080fd5b50606b546200073290600160a81b900463ffffffff1681565b348015620007ea57600080fd5b50606c546200073290600160a01b900463ffffffff1681565b620002cf6200081436600462003e8e565b62001712565b3480156200082757600080fd5b50606c54620003ac906001600160a01b031681565b3480156200084957600080fd5b50620002cf62001765565b3480156200086157600080fd5b50620002cf6200087336600462003f30565b6200179b565b3480156200088657600080fd5b50606b54620002ed90600160a01b900460ff1681565b348015620008a957600080fd5b50620008b4620018b7565b604051620002f9919062003f6c565b348015620008d057600080fd5b5062000327620008e2366004620037a8565b606d6020526000908152604090205481565b3480156200090157600080fd5b50606854620003ac9061010090046001600160a01b031681565b3480156200092857600080fd5b50620002cf6200093a36600462003fa5565b620018f6565b3480156200094d57600080fd5b50620002ed6200095f36600462003ffb565b620019e8565b60008052606a60205260008051602062005e63833981519152546001600160a01b0316620009a657604051632c17738b60e01b815260040160405180910390fd5b6001600160a01b038281166000818152606f60209081526040808320606a835260008051602062005e638339815191525460019094527ff585789965ba69220d5ce3dc1b444eb22ff546f2650694fef8fafe9c26560af954915163d5f37c5d60e01b81526004810195909552602485018790525463ffffffff8116604486015290911c84166064840152908316608483015290911660a48201527323748193fe94b8fddc06a3f261cb5db2db21dfac9063d5f37c5d9060c40160006040518083038186803b15801562000a7857600080fd5b505af415801562000a8d573d6000803e3d6000fd5b505050505050565b6033816020811062000aa657600080fd5b0154905081565b6070546001600160a01b0316331462000ad95760405163e2e8106b60e01b815260040160405180910390fd5b62000ae362001ad1565b565b606854600090819061010090046001600160a01b0316331462000b1b57604051631c2ba6ab60e31b815260040160405180910390fd5b62000b256200121d565b62000b2f62001b2e565b915091509091565b6040805160e084901b6001600160e01b031916602080830191909152606084901b6bffffffffffffffffffffffff1916602483015282516018818403018152603890920183528151918101919091206000908152606e90915220546001600160a01b03165b92915050565b60008052606a60205260008051602062005e63833981519152546001600160a01b03161562000be45760405163057ecdd960e51b815260040160405180910390fd5b62000bf3858585858562001c10565b5050505050565b60008052606a60205260008051602062005e63833981519152546001600160a01b03161562000c3c5760405163057ecdd960e51b815260040160405180910390fd5b62000c518b8b8b8b8b8b8b8b8b8b8b62001d52565b5050505050505050505050565b60008052606a60205260008051602062005e63833981519152546001600160a01b03161562000ca05760405163057ecdd960e51b815260040160405180910390fd5b62000c518b8b8b8b8b8b8b8b8b8b8b62001f6f565b60008052606a60205260008051602062005e63833981519152546001600160a01b031662000cf657604051632c17738b60e01b815260040160405180910390fd5b6071546001600160a01b0316331462000d225760405163ea8e4eb560e01b815260040160405180910390fd5b60008052606a60205260008051602062005e63833981519152546001600160a01b0382811691161480159062000d8f57506001600052606a6020527ff585789965ba69220d5ce3dc1b444eb22ff546f2650694fef8fafe9c26560af9546001600160a01b03828116911614155b1562000dae57604051631e2a7cbb60e21b815260040160405180910390fd5b606b546001600160a01b039081169084160362000dde5760405163b5959a5b60e01b815260040160405180910390fd5b60405163a9059cbb60e01b81526001600160a01b0382811660048301526024820184905284169063a9059cbb906044016020604051808303816000875af115801562000e2e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000e54919062004048565b50505050565b6069546001600160a01b0316331462000e8657604051633f39cc6b60e21b815260040160405180910390fd5b606b5463ffffffff600160a81b90910481169086160362000eba57604051632a34ecff60e01b815260040160405180910390fd5b62000a8d858785858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508792508a9150620020db9050565b605354600090819081805b602081101562000fde578083901c60011660010362000f6f576033816020811062000f3b5762000f3b62004068565b0154604080516020810192909252810185905260600160405160208183030381529060405280519060200120935062000f9c565b60408051602081018690529081018390526060016040516020818303038152906040528051906020012093505b6040805160208101849052908101839052606001604051602081830303815290604052805190602001209150808062000fd59062004094565b91505062000f0c565b50919392505050565b6040516001600160f81b031960f889901b1660208201526001600160e01b031960e088811b821660218401526bffffffffffffffffffffffff19606089811b821660258601529188901b909216603984015285901b16603d8201526051810183905260718101829052600090609101604051602081830303815290604052805190602001209050979650505050505050565b600054610100900460ff16620010ac5760405162461bcd60e51b8152600401620010a390620040b0565b60405180910390fd5b6068805474ffffffffffffffffffffffffffffffffffffffff0019166101006001600160a01b0394851602179055606980546001600160a01b03191691909216179055565b600054610100900460ff166200111b5760405162461bcd60e51b8152600401620010a390620040b0565b86606b60156101000a81548163ffffffff021916908363ffffffff16021790555085606c60006101000a8154816001600160a01b0302191690836001600160a01b0316021790555084607060006101000a8154816001600160a01b0302191690836001600160a01b0316021790555083606b60006101000a8154816001600160a01b0302191690836001600160a01b0316021790555082606b60146101000a81548160ff02191690831515021790555081606c60146101000a81548163ffffffff021916908363ffffffff1602179055506200120a606c60149054906101000a900463ffffffff168262002396565b62001214620023de565b50505050505050565b605354606c54600160a01b900463ffffffff16101562000ae35762000ae362002412565b60008052606a60205260008051602062005e63833981519152546001600160a01b03166200128257604051632c17738b60e01b815260040160405180910390fd5b60008052606a60205260008051602062005e63833981519152547323748193fe94b8fddc06a3f261cb5db2db21dfac90630596dab190859085906001600160a01b031685620012d357600062001309565b6001600052606a6020527ff585789965ba69220d5ce3dc1b444eb22ff546f2650694fef8fafe9c26560af9546001600160a01b03165b6001600160a01b0389166000908152606f60205260409081902090516001600160e01b031960e088901b16815262001349959493929190600401620040fb565b60006040518083038186803b1580156200136257600080fd5b505af415801562001214573d6000803e3d6000fd5b60008160535410156200138c57506000919050565b600882901c6000908152606d6020526040902054600160ff84161b908116148015620013bb5750600192915050565b6069546001600160a01b0316156200144457606954604051639e34070f60e01b8152600481018590526001600160a01b0390911690639e34070f90602401602060405180830381865afa15801562001417573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200143d919062004048565b9392505050565b50600092915050565b600054610100900460ff16158080156200146e5750600054600160ff909116105b806200148a5750303b1580156200148a575060005460ff166001145b620014fe5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a65640000000000000000000000000000000000006064820152608401620010a3565b6000805460ff19166001179055801562001522576000805461ff0019166101001790555b6200152e8b8b62001079565b620015678989898989888860208060200260405190810160405280929190826020800280828437600092019190915250620010f1915050565b607180546001600160a01b0319166001600160a01b038616179055801562000c51576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498906020015b60405180910390a15050505050505050505050565b6040516001600160e01b031960e089901b1660208201526bffffffffffffffffffffffff19606088901b1660248201526000908190603801604051602081830303815290604052805190602001209050600060ff60f81b3083604051806020016200164190620036dc565b601f1982820381018352601f9091011660408190526200166e908d908d908d908d908d906020016200416e565b60408051601f19818403018152908290526200168e9291602001620041d5565b60405160208183030381529060405280519060200120604051602001620016ec94939291906001600160f81b031994909416845260609290921b6bffffffffffffffffffffffff191660018401526015830152603582015260550190565b60408051808303601f1901815291905280516020909101209a9950505050505050505050565b60008052606a60205260008051602062005e63833981519152546001600160a01b031615620017545760405163057ecdd960e51b815260040160405180910390fd5b6200121487878787878787620024a3565b6070546001600160a01b03163314620017915760405163e2e8106b60e01b815260040160405180910390fd5b62000ae362002871565b60008052606a60205260008051602062005e63833981519152546001600160a01b0316620017dc57604051632c17738b60e01b815260040160405180910390fd5b606b547323748193fe94b8fddc06a3f261cb5db2db21dfac906323f9096e906001600160a01b0316858562001846576001600052606a6020527ff585789965ba69220d5ce3dc1b444eb22ff546f2650694fef8fafe9c26560af9546001600160a01b03166200186a565b60008052606a60205260008051602062005e63833981519152546001600160a01b03165b60405160e085901b6001600160e01b03191681526001600160a01b039384166004820152602481019290925290911660448201528415156064820152831515608482015260a40162001349565b620018c1620036ea565b604080516104008101918290529060339060209082845b815481526020019060010190808311620018d8575050505050905090565b6069546001600160a01b031633146200192257604051633f39cc6b60e21b815260040160405180910390fd5b6040516001600160e01b031960e084901b1660208201526bffffffffffffffffffffffff19606085901b16602482015260009060380160408051808303601f1901815282825280516020918201206000818152606e90925291902054632770a7eb60e21b83526001600160a01b038881166004850152602484018690529193501690639dc29fac90604401600060405180830381600087803b158015620019c857600080fd5b505af1158015620019dd573d6000803e3d6000fd5b505050505050505050565b600084815b602081101562001ac357600163ffffffff8616821c8116900362001a5f5785816020811062001a205762001a2062004068565b60200201358260405160200162001a41929190918252602082015260400190565b60405160208183030381529060405280519060200120915062001aae565b8186826020811062001a755762001a7562004068565b602002013560405160200162001a95929190918252602082015260400190565b6040516020818303038152906040528051906020012091505b8062001aba8162004094565b915050620019ed565b50821490505b949350505050565b60685460ff161562001af657604051630bc011ff60e21b815260040160405180910390fd5b6068805460ff191660011790556040517f2261efe5aef6fedc1fd1550b25facc9181745623049c7901287030b9ad1a549790600090a1565b60008073219714200c7f774b152f8cbb2571e049d4a5643063209ee16d6040518163ffffffff1660e01b81526004016040805180830381865af415801562001b7a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001ba0919062004208565b606a60205260008051602062005e6383398151915280546001600160a01b038085166001600160a01b03199283161790925560016000527ff585789965ba69220d5ce3dc1b444eb22ff546f2650694fef8fafe9c26560af980549284169290911691909117905590939092509050565b60685460ff161562001c3557604051630bc011ff60e21b815260040160405180910390fd5b341562001c555760405163798ee6f160e01b815260040160405180910390fd5b606b5463ffffffff868116600160a81b90920416148062001c7d5750600263ffffffff861610155b1562001c9c576040516302caf51760e11b815260040160405180910390fd5b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b6001606b60159054906101000a900463ffffffff1633888834888860535460405162001cf2999897969594939291906200423c565b60405180910390a162001d4162001d3b6001606b60159054906101000a900463ffffffff1633898934898960405162001d2d929190620042aa565b604051809103902062000fe7565b620028ca565b821562000bf35762000bf362002412565b60685460ff161562001d7757604051630bc011ff60e21b815260040160405180910390fd5b62001d8e8b8b8b8b8b8b8b8b8b8b8b6000620029c3565b6001600160a01b03861615801562001daf5750606b54600160a01b900460ff165b1562001e4f57604080516000808252602082019092526001600160a01b03861690859060405162001de19190620042ba565b60006040518083038185875af1925050503d806000811462001e20576040519150601f19603f3d011682016040523d82523d6000602084013e62001e25565b606091505b505090508062001e4857604051630ce8f45160e31b815260040160405180910390fd5b5062001f0e565b6001600160a01b03861615801562001e715750606b54600160a01b900460ff16155b1562001e9657606b5462001e90906001600160a01b0316858562002b3e565b62001f0e565b606b5463ffffffff600160a81b90910481169088160362001ec75762001e906001600160a01b038716858562002b3e565b62001f0e878784848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a9250899150620020db9050565b6040805163ffffffff808d168252891660208201526001600160a01b03808916928201929092529085166060820152608081018490527f25308c93ceeed162da955b3f7ce3e3f93606579e40fb92029faa9efe275459839060a001620015c1565b60685460ff161562001f9457604051630bc011ff60e21b815260040160405180910390fd5b62001fab8b8b8b8b8b8b8b8b8b8b8b6001620029c3565b6000846001600160a01b031684888a868660405160240162001fd19493929190620042d8565b60408051601f198184030181529181526020820180516001600160e01b0316630c035af960e11b17905251620020089190620042ba565b60006040518083038185875af1925050503d806000811462002047576040519150601f19603f3d011682016040523d82523d6000602084013e6200204c565b606091505b50509050806200206f576040516337e391c360e01b815260040160405180910390fd5b6040805163ffffffff8d811682528a1660208201526001600160a01b0389811682840152871660608201526080810186905290517f25308c93ceeed162da955b3f7ce3e3f93606579e40fb92029faa9efe275459839181900360a00190a1505050505050505050505050565b6040516001600160e01b031960e087901b1660208201526bffffffffffffffffffffffff19606086901b16602482015260009060380160408051601f1981840301815291815281516020928301206000818152606e9093529120549091506001600160a01b031680620023365760008060008780602001905181019062002163919062004391565b9250925092506000858484846040516200217d90620036dc565b6200218b9392919062004435565b8190604051809103906000f5905080158015620021ac573d6000803e3d6000fd5b506040516340c10f1960e01b81526001600160a01b038a81166004830152602482018a9052919250908216906340c10f1990604401600060405180830381600087803b158015620021fc57600080fd5b505af115801562002211573d6000803e3d6000fd5b5050505080606e600088815260200190815260200160002060006101000a8154816001600160a01b0302191690836001600160a01b0316021790555060405180604001604052808c63ffffffff1681526020018b6001600160a01b0316815250606f6000836001600160a01b03166001600160a01b0316815260200190815260200160002060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a8154816001600160a01b0302191690836001600160a01b031602179055509050507f490e59a1701b938786ac72570a1efeac994a3dbe96e2e883e19e902ace6e6a398b8b838c60405162002324949392919062004472565b60405180910390a15050505062001214565b6040516340c10f1960e01b81526001600160a01b038581166004830152602482018590528216906340c10f1990604401600060405180830381600087803b1580156200238157600080fd5b505af115801562000c51573d6000803e3d6000fd5b600054610100900460ff16620023c05760405162461bcd60e51b8152600401620010a390620040b0565b63ffffffff8216605355620023d9603382602062003709565b505050565b600054610100900460ff16620024085760405162461bcd60e51b8152600401620010a390620040b0565b62000ae362002ba3565b605354606c805463ffffffff909216600160a01b0263ffffffff60a01b19831681179091556001600160a01b039081169116176333d6247d6200245462000f01565b6040518263ffffffff1660e01b81526004016200247391815260200190565b600060405180830381600087803b1580156200248e57600080fd5b505af115801562000e54573d6000803e3d6000fd5b60685460ff1615620024c857604051630bc011ff60e21b815260040160405180910390fd5b620024d262002bd3565b606b5463ffffffff888116600160a81b909204161480620024fa5750600263ffffffff881610155b1562002519576040516302caf51760e11b815260040160405180910390fd5b6000806060876001600160a01b038816158015620025405750606b54600160a01b900460ff165b156200257157883414620025675760405163b89240f560e01b815260040160405180910390fd5b60009250620027eb565b3415620025915760405163798ee6f160e01b815260040160405180910390fd5b6001600160a01b038089166000908152606f602090815260409182902082518084019093525463ffffffff81168352640100000000900490921691810182905290156200264e57604051632770a7eb60e21b8152336004820152602481018b90526001600160a01b038a1690639dc29fac90604401600060405180830381600087803b1580156200262157600080fd5b505af115801562002636573d6000803e3d6000fd5b505050508060200151945080600001519350620027e9565b8515620026635762002663898b898962002c2e565b6040516370a0823160e01b81523060048201526000906001600160a01b038b16906370a0823190602401602060405180830381865afa158015620026ab573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620026d19190620044ac565b9050620026ea6001600160a01b038b1633308e62002f90565b6040516370a0823160e01b81523060048201526000906001600160a01b038c16906370a0823190602401602060405180830381865afa15801562002732573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620027589190620044ac565b9050620027668282620044c6565b606b549094506001600160a01b03908116908c16036200278a57600096506200278e565b8a96505b606b54600160a81b900463ffffffff169550620027ab8b62002fca565b620027b68c62003091565b620027c18d6200314f565b604051602001620027d59392919062004435565b604051602081830303815290604052945050505b505b7f501781209a1f8899323b96b4ef08b168df93e0a90c673d1e4cce39366cb62f9b600084868e8e86886053546040516200282d989796959493929190620044dc565b60405180910390a16200285262001d3b600085878f8f87898051906020012062000fe7565b861562002863576200286362002412565b505050506200121460018055565b60685460ff166200289557604051635386698160e01b815260040160405180910390fd5b6068805460ff191690556040517f1e5e34eea33501aecf2ebec9fe0e884a40804275ea7fe10b2ba084c8374308b390600090a1565b806001620028db6020600262004645565b620028e79190620044c6565b6053541062002909576040516377ae67b360e11b815260040160405180910390fd5b60006053600081546200291c9062004094565b9182905550905060005b6020811015620029b8578082901c6001166001036200295e57826033826020811062002956576200295662004068565b015550505050565b6033816020811062002974576200297462004068565b015460408051602081019290925281018490526060016040516020818303038152906040528051906020012092508080620029af9062004094565b91505062002926565b50620023d962004653565b620029d48b63ffffffff1662003210565b606c546040805160208082018e90528183018d9052825180830384018152606083019384905280519101206312bd9b1960e11b90925260648101919091526000916001600160a01b03169063257b3632906084016020604051808303816000875af115801562002a48573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002a6e9190620044ac565b90508060000362002a9157604051622f6fad60e01b815260040160405180910390fd5b606b5463ffffffff888116600160a81b909204161462002ac4576040516302caf51760e11b815260040160405180910390fd5b606b54600090600160a81b900463ffffffff1662002ae457508962002ae7565b508a5b62002b1062002b07848c8c8c8c8c8c8c60405162001d2d929190620042aa565b8f8f84620019e8565b62002b2e576040516338105f3b60e21b815260040160405180910390fd5b5050505050505050505050505050565b6040516001600160a01b038316602482015260448101829052620023d990849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152620032bf565b600054610100900460ff1662002bcd5760405162461bcd60e51b8152600401620010a390620040b0565b60018055565b60026001540362002c275760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401620010a3565b6002600155565b600062002c3f600482848662004669565b62002c4a9162004695565b9050632afa533160e01b6001600160e01b031982160162002deb57600080808080808062002c7c896004818d62004669565b81019062002c8b9190620046c6565b9650965096509650965096509650336001600160a01b0316876001600160a01b03161462002ccc5760405163912ecce760e01b815260040160405180910390fd5b6001600160a01b038616301462002cf65760405163750643af60e01b815260040160405180910390fd5b8a851462002d17576040516303fffc4b60e01b815260040160405180910390fd5b604080516001600160a01b0389811660248301528881166044830152606482018890526084820187905260ff861660a483015260c4820185905260e48083018590528351808403909101815261010490920183526020820180516001600160e01b031663d505accf60e01b1790529151918e169162002d979190620042ba565b6000604051808303816000865af19150503d806000811462002dd6576040519150601f19603f3d011682016040523d82523d6000602084013e62002ddb565b606091505b5050505050505050505062000bf3565b6001600160e01b031981166323f2ebc360e21b1462002e1d57604051637141605d60e11b815260040160405180910390fd5b60008080808080808062002e358a6004818e62004669565b81019062002e44919062004721565b97509750975097509750975097509750336001600160a01b0316886001600160a01b03161462002e875760405163912ecce760e01b815260040160405180910390fd5b6001600160a01b038716301462002eb15760405163750643af60e01b815260040160405180910390fd5b604080516001600160a01b038a811660248301528981166044830152606482018990526084820188905286151560a483015260ff861660c483015260e482018590526101048083018590528351808403909101815261012490920183526020820180516001600160e01b03166323f2ebc360e21b1790529151918f169162002f3a9190620042ba565b6000604051808303816000865af19150503d806000811462002f79576040519150601f19603f3d011682016040523d82523d6000602084013e62002f7e565b606091505b50505050505050505050505050505050565b6040516001600160a01b038085166024830152831660448201526064810182905262000e549085906323b872dd60e01b9060840162002b6b565b60408051600481526024810182526020810180516001600160e01b03166306fdde0360e01b179052905160609160009182916001600160a01b03861691620030139190620042ba565b600060405180830381855afa9150503d806000811462003050576040519150601f19603f3d011682016040523d82523d6000602084013e62003055565b606091505b5091509150816200308657604051806040016040528060078152602001664e4f5f4e414d4560c81b81525062001ac9565b62001ac9816200339b565b60408051600481526024810182526020810180516001600160e01b03166395d89b4160e01b179052905160609160009182916001600160a01b03861691620030da9190620042ba565b600060405180830381855afa9150503d806000811462003117576040519150601f19603f3d011682016040523d82523d6000602084013e6200311c565b606091505b5091509150816200308657604051806040016040528060098152602001681393d7d4d6535093d360ba1b81525062001ac9565b60408051600481526024810182526020810180516001600160e01b031663313ce56760e01b1790529051600091829182916001600160a01b03861691620031979190620042ba565b600060405180830381855afa9150503d8060008114620031d4576040519150601f19603f3d011682016040523d82523d6000602084013e620031d9565b606091505b5091509150818015620031ed575080516020145b620031fa57601262001ac9565b8080602001905181019062001ac99190620047ad565b6069546001600160a01b031615620032b157606954604051639e34070f60e01b8152600481018390526001600160a01b0390911690639e34070f90602401602060405180830381865afa1580156200326c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062003292919062004048565b15620032b157604051630c8d9eab60e31b815260040160405180910390fd5b620032bc816200355d565b50565b600062003316826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316620035a99092919063ffffffff16565b90508051600014806200333a5750808060200190518101906200333a919062004048565b620023d95760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401620010a3565b60606040825110620033bd578180602001905181019062000b9c9190620047cd565b81516020036200352a5760005b602081108015620033fd5750828181518110620033eb57620033eb62004068565b01602001516001600160f81b03191615155b156200341857806200340f8162004094565b915050620033ca565b80600003620034515750506040805180820190915260128152714e4f545f56414c49445f454e434f44494e4760701b6020820152919050565b60008167ffffffffffffffff8111156200346f576200346f62003b9a565b6040519080825280601f01601f1916602001820160405280156200349a576020820181803683370190505b50905060005b828110156200352257848181518110620034be57620034be62004068565b602001015160f81c60f81b828281518110620034de57620034de62004068565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080620035198162004094565b915050620034a0565b509392505050565b50506040805180820190915260128152714e4f545f56414c49445f454e434f44494e4760701b602082015290565b919050565b600881901c6000818152606d602052604081208054600160ff861690811b9182189283905592909190818316900362000bf357604051630c8d9eab60e31b815260040160405180910390fd5b606062001ac9848460008585600080866001600160a01b03168587604051620035d39190620042ba565b60006040518083038185875af1925050503d806000811462003612576040519150601f19603f3d011682016040523d82523d6000602084013e62003617565b606091505b50915091506200362a8783838762003635565b979650505050505050565b60608315620036a9578251600003620036a1576001600160a01b0385163b620036a15760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401620010a3565b508162001ac9565b62001ac98383815115620036c05781518083602001fd5b8060405162461bcd60e51b8152600401620010a3919062004806565b611647806200481c83390190565b6040518061040001604052806020906020820280368337509192915050565b82602081019282156200373a579160200282015b828111156200373a5782518255916020019190600101906200371d565b50620037489291506200374c565b5090565b5b808211156200374857600081556001016200374d565b6001600160a01b0381168114620032bc57600080fd5b600080604083850312156200378d57600080fd5b82356200379a8162003763565b946020939093013593505050565b600060208284031215620037bb57600080fd5b5035919050565b803563ffffffff811681146200355857600080fd5b60008060408385031215620037eb57600080fd5b620037f683620037c2565b91506020830135620038088162003763565b809150509250929050565b8015158114620032bc57600080fd5b60008083601f8401126200383557600080fd5b50813567ffffffffffffffff8111156200384e57600080fd5b6020830191508360208285010111156200386757600080fd5b9250929050565b6000806000806000608086880312156200388757600080fd5b6200389286620037c2565b94506020860135620038a48162003763565b93506040860135620038b68162003813565b9250606086013567ffffffffffffffff811115620038d357600080fd5b620038e18882890162003822565b969995985093965092949392505050565b80610400810183101562000b9c57600080fd5b60008060008060008060008060008060006105208c8e0312156200392857600080fd5b620039348d8d620038f2565b9a50620039456104008d01620037c2565b99506104208c013598506104408c01359750620039666104608d01620037c2565b96506104808c0135620039798162003763565b95506200398a6104a08d01620037c2565b94506104c08c01356200399d8162003763565b93506104e08c013592506105008c013567ffffffffffffffff811115620039c357600080fd5b620039d18e828f0162003822565b915080935050809150509295989b509295989b9093969950565b60008060006060848603121562003a0157600080fd5b833562003a0e8162003763565b925060208401359150604084013562003a278162003763565b809150509250925092565b60008060008060008060a0878903121562003a4c57600080fd5b863562003a598162003763565b955062003a6960208801620037c2565b945060408701359350606087013567ffffffffffffffff81111562003a8d57600080fd5b62003a9b89828a0162003822565b909450925050608087013562003ab18162003763565b809150509295509295509295565b60006020828403121562003ad257600080fd5b81356200143d8162003763565b60ff81168114620032bc57600080fd5b600080600080600080600060e0888a03121562003b0b57600080fd5b873562003b188162003adf565b965062003b2860208901620037c2565b9550604088013562003b3a8162003763565b945062003b4a60608901620037c2565b9350608088013562003b5c8162003763565b9699959850939692959460a0840135945060c09093013592915050565b6000806040838503121562003b8d57600080fd5b8235620037f68162003763565b634e487b7160e01b600052604160045260246000fd5b604051610400810167ffffffffffffffff8111828210171562003bd75762003bd762003b9a565b60405290565b60008060008060008060006104c080898b03121562003bfb57600080fd5b62003c0689620037c2565b97506020808a013562003c198162003763565b975060408a013562003c2b8162003763565b965060608a013562003c3d8162003763565b955060808a013562003c4f8162003813565b945062003c5f60a08b01620037c2565b93508a60df8b011262003c7157600080fd5b62003c7b62003bb0565b918a0191808c84111562003c8e57600080fd5b60c08c015b8481101562003cac578035835291830191830162003c93565b508094505050505092959891949750929550565b60008060006060848603121562003cd657600080fd5b833562003ce38162003763565b925060208401359150604084013562003a278162003813565b6000806000806000806000806000806105208b8d03121562003d1d57600080fd5b8a3562003d2a8162003763565b995060208b013562003d3c8162003763565b985062003d4c60408c01620037c2565b975060608b013562003d5e8162003763565b965060808b013562003d708162003763565b955060a08b013562003d828162003763565b945060c08b013562003d948162003813565b935060e08b013562003da68162003763565b925062003db76101008c01620037c2565b915062003dc98c6101208d01620038f2565b90509295989b9194979a5092959850565b600080600080600080600060a0888a03121562003df657600080fd5b62003e0188620037c2565b9650602088013562003e138162003763565b9550604088013567ffffffffffffffff8082111562003e3157600080fd5b62003e3f8b838c0162003822565b909750955060608a013591508082111562003e5957600080fd5b5062003e688a828b0162003822565b909450925050608088013562003e7e8162003adf565b8091505092959891949750929550565b600080600080600080600060c0888a03121562003eaa57600080fd5b62003eb588620037c2565b9650602088013562003ec78162003763565b955060408801359450606088013562003ee08162003763565b9350608088013562003ef28162003813565b925060a088013567ffffffffffffffff81111562003f0f57600080fd5b62003f1d8a828b0162003822565b989b979a50959850939692959293505050565b60008060006060848603121562003f4657600080fd5b83359250602084013562003f5a8162003813565b9150604084013562003a278162003813565b6104008101818360005b602080821062003f87575062003f9c565b82518452928301929091019060010162003f76565b50505092915050565b6000806000806080858703121562003fbc57600080fd5b843562003fc98162003763565b9350602085013562003fdb8162003763565b925062003feb60408601620037c2565b9396929550929360600135925050565b60008060008061046085870312156200401357600080fd5b84359350620040268660208701620038f2565b9250620040376104208601620037c2565b939692955092936104400135925050565b6000602082840312156200405b57600080fd5b81516200143d8162003813565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060018201620040a957620040a96200407e565b5060010190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b6001600160a01b038681168252602080830187905285821660408401528482166060840152835463ffffffff81166080850152901c1660a082015260c081015b9695505050505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6060815260006200418460608301878962004145565b82810360208401526200419981868862004145565b91505060ff831660408301529695505050505050565b60005b83811015620041cc578181015183820152602001620041b2565b50506000910152565b60008351620041e9818460208801620041af565b835190830190620041ff818360208801620041af565b01949350505050565b600080604083850312156200421c57600080fd5b8251620042298162003763565b6020840151909250620038088162003763565b600061010060ff8c16835263ffffffff808c1660208501526001600160a01b03808c166040860152818b166060860152808a166080860152508760a08501528160c085015262004290828501878962004145565b925080851660e085015250509a9950505050505050505050565b8183823760009101908152919050565b60008251620042ce818460208701620041af565b9190910192915050565b6001600160a01b038516815263ffffffff841660208201526060604082015260006200413b60608301848662004145565b600082601f8301126200431b57600080fd5b815167ffffffffffffffff8082111562004339576200433962003b9a565b604051601f8301601f19908116603f0116810190828211818310171562004364576200436462003b9a565b816040528381528660208588010111156200437e57600080fd5b6200413b846020830160208901620041af565b600080600060608486031215620043a757600080fd5b835167ffffffffffffffff80821115620043c057600080fd5b620043ce8783880162004309565b94506020860151915080821115620043e557600080fd5b50620043f48682870162004309565b925050604084015162003a278162003adf565b6000815180845262004421816020860160208601620041af565b601f01601f19169290920160200192915050565b6060815260006200444a606083018662004407565b82810360208401526200445e818662004407565b91505060ff83166040830152949350505050565b63ffffffff8516815260006001600160a01b038086166020840152808516604084015250608060608301526200413b608083018462004407565b600060208284031215620044bf57600080fd5b5051919050565b8181038181111562000b9c5762000b9c6200407e565b600061010060ff8b16835263ffffffff808b1660208501526001600160a01b03808b166040860152818a1660608601528089166080860152508660a08501528160c08501526200452f8285018762004407565b925080851660e085015250509998505050505050505050565b600181815b80851115620045895781600019048211156200456d576200456d6200407e565b808516156200457b57918102915b93841c93908002906200454d565b509250929050565b600082620045a25750600162000b9c565b81620045b15750600062000b9c565b8160018114620045ca5760028114620045d557620045f5565b600191505062000b9c565b60ff841115620045e957620045e96200407e565b50506001821b62000b9c565b5060208310610133831016604e8410600b84101617156200461a575081810a62000b9c565b62004626838362004548565b80600019048211156200463d576200463d6200407e565b029392505050565b60006200143d838362004591565b634e487b7160e01b600052600160045260246000fd5b600080858511156200467a57600080fd5b838611156200468857600080fd5b5050820193919092039150565b6001600160e01b03198135818116916004851015620046be5780818660040360031b1b83161692505b505092915050565b600080600080600080600060e0888a031215620046e257600080fd5b8735620046ef8162003763565b96506020880135620047018162003763565b95506040880135945060608801359350608088013562003b5c8162003adf565b600080600080600080600080610100898b0312156200473f57600080fd5b88356200474c8162003763565b975060208901356200475e8162003763565b9650604089013595506060890135945060808901356200477e8162003813565b935060a0890135620047908162003adf565b979a969950949793969295929450505060c08201359160e0013590565b600060208284031215620047c057600080fd5b81516200143d8162003adf565b600060208284031215620047e057600080fd5b815167ffffffffffffffff811115620047f857600080fd5b62001ac98482850162004309565b6020815260006200143d60208301846200440756fe6101006040523480156200001257600080fd5b50604051620016473803806200164783398101604081905262000035916200028d565b82826003620000458382620003a1565b506004620000548282620003a1565b50503360c0525060ff811660e052466080819052620000739062000080565b60a052506200046d915050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f620000ad6200012e565b805160209182012060408051808201825260018152603160f81b90840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b6060600380546200013f9062000312565b80601f01602080910402602001604051908101604052809291908181526020018280546200016d9062000312565b8015620001be5780601f106200019257610100808354040283529160200191620001be565b820191906000526020600020905b815481529060010190602001808311620001a057829003601f168201915b5050505050905090565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620001f057600080fd5b81516001600160401b03808211156200020d576200020d620001c8565b604051601f8301601f19908116603f01168101908282118183101715620002385762000238620001c8565b816040528381526020925086838588010111156200025557600080fd5b600091505b838210156200027957858201830151818301840152908201906200025a565b600093810190920192909252949350505050565b600080600060608486031215620002a357600080fd5b83516001600160401b0380821115620002bb57600080fd5b620002c987838801620001de565b94506020860151915080821115620002e057600080fd5b50620002ef86828701620001de565b925050604084015160ff811681146200030757600080fd5b809150509250925092565b600181811c908216806200032757607f821691505b6020821081036200034857634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200039c57600081815260208120601f850160051c81016020861015620003775750805b601f850160051c820191505b81811015620003985782815560010162000383565b5050505b505050565b81516001600160401b03811115620003bd57620003bd620001c8565b620003d581620003ce845462000312565b846200034e565b602080601f8311600181146200040d5760008415620003f45750858301515b600019600386901b1c1916600185901b17855562000398565b600085815260208120601f198616915b828110156200043e578886015182559484019460019091019084016200041d565b50858210156200045d5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e05161118b620004bc60003960006102070152600081816102ca0152818161053301526105e6015260006104c701526000818161032f0152610491015261118b6000f3fe608060405234801561001057600080fd5b50600436106101475760003560e01c806370a08231116100c8578063a457c2d71161008c578063d505accf11610066578063d505accf14610351578063dd62ed3e14610364578063ffa1ad741461039d57600080fd5b8063a457c2d714610304578063a9059cbb14610317578063cd0d00961461032a57600080fd5b806370a08231146102615780637ecebe001461028a57806395d89b41146102aa5780639dc29fac146102b2578063a3c573eb146102c557600080fd5b806330adf81f1161010f57806330adf81f146101d9578063313ce567146102005780633644e51514610231578063395093511461023957806340c10f191461024c57600080fd5b806306fdde031461014c578063095ea7b31461016a57806318160ddd1461018d57806320606b701461019f57806323b872dd146101c6575b600080fd5b6101546103bd565b6040516101619190610f41565b60405180910390f35b61017d610178366004610fab565b61044f565b6040519015158152602001610161565b6002545b604051908152602001610161565b6101917f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f81565b61017d6101d4366004610fd5565b610469565b6101917f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60405160ff7f0000000000000000000000000000000000000000000000000000000000000000168152602001610161565b61019161048d565b61017d610247366004610fab565b6104e9565b61025f61025a366004610fab565b610528565b005b61019161026f366004611011565b6001600160a01b031660009081526020819052604090205490565b610191610298366004611011565b60056020526000908152604090205481565b6101546105cc565b61025f6102c0366004610fab565b6105db565b6102ec7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610161565b61017d610312366004610fab565b610676565b61017d610325366004610fab565b610708565b6101917f000000000000000000000000000000000000000000000000000000000000000081565b61025f61035f366004611033565b610716565b6101916103723660046110a6565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b610154604051806040016040528060018152602001603160f81b81525081565b6060600380546103cc906110d9565b80601f01602080910402602001604051908101604052809291908181526020018280546103f8906110d9565b80156104455780601f1061041a57610100808354040283529160200191610445565b820191906000526020600020905b81548152906001019060200180831161042857829003601f168201915b5050505050905090565b60003361045d818585610951565b60019150505b92915050565b600033610477858285610a76565b610482858585610b08565b506001949350505050565b60007f000000000000000000000000000000000000000000000000000000000000000046146104c4576104bf46610cac565b905090565b507f000000000000000000000000000000000000000000000000000000000000000090565b3360008181526001602090815260408083206001600160a01b038716845290915281205490919061045d9082908690610523908790611129565b610951565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146105be5760405162461bcd60e51b815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201526f6c79676f6e5a6b45564d42726964676560801b60648201526084015b60405180910390fd5b6105c88282610d58565b5050565b6060600480546103cc906110d9565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461066c5760405162461bcd60e51b815260206004820152603060248201527f546f6b656e577261707065643a3a6f6e6c794272696467653a204e6f7420506f60448201526f6c79676f6e5a6b45564d42726964676560801b60648201526084016105b5565b6105c88282610e17565b3360008181526001602090815260408083206001600160a01b0387168452909152812054909190838110156106fb5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084016105b5565b6104828286868403610951565b60003361045d818585610b08565b834211156107725760405162461bcd60e51b8152602060048201526024808201527f546f6b656e577261707065643a3a7065726d69743a20457870697265642070656044820152631c9b5a5d60e21b60648201526084016105b5565b6001600160a01b038716600090815260056020526040812080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918a918a918a9190866107bf8361113c565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810186905260e001604051602081830303815290604052805190602001209050600061081d61048d565b60405161190160f01b602082015260228101919091526042810183905260620160408051601f198184030181528282528051602091820120600080855291840180845281905260ff89169284019290925260608301879052608083018690529092509060019060a0016020604051602081039080840390855afa1580156108a8573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116158015906108de5750896001600160a01b0316816001600160a01b0316145b61093a5760405162461bcd60e51b815260206004820152602760248201527f546f6b656e577261707065643a3a7065726d69743a20496e76616c6964207369604482015266676e617475726560c81b60648201526084016105b5565b6109458a8a8a610951565b50505050505050505050565b6001600160a01b0383166109b35760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b60648201526084016105b5565b6001600160a01b038216610a145760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b60648201526084016105b5565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b6001600160a01b038381166000908152600160209081526040808320938616835292905220546000198114610b025781811015610af55760405162461bcd60e51b815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e636500000060448201526064016105b5565b610b028484848403610951565b50505050565b6001600160a01b038316610b6c5760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b60648201526084016105b5565b6001600160a01b038216610bce5760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b60648201526084016105b5565b6001600160a01b03831660009081526020819052604090205481811015610c465760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b60648201526084016105b5565b6001600160a01b03848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a3610b02565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f610cd76103bd565b805160209182012060408051808201825260018152603160f81b90840152805192830193909352918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc66060820152608081018390523060a082015260c001604051602081830303815290604052805190602001209050919050565b6001600160a01b038216610dae5760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016105b5565b8060026000828254610dc09190611129565b90915550506001600160a01b038216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b6001600160a01b038216610e775760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b60648201526084016105b5565b6001600160a01b03821660009081526020819052604090205481811015610eeb5760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b60648201526084016105b5565b6001600160a01b0383166000818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610a69565b600060208083528351808285015260005b81811015610f6e57858101830151858201604001528201610f52565b506000604082860101526040601f19601f8301168501019250505092915050565b80356001600160a01b0381168114610fa657600080fd5b919050565b60008060408385031215610fbe57600080fd5b610fc783610f8f565b946020939093013593505050565b600080600060608486031215610fea57600080fd5b610ff384610f8f565b925061100160208501610f8f565b9150604084013590509250925092565b60006020828403121561102357600080fd5b61102c82610f8f565b9392505050565b600080600080600080600060e0888a03121561104e57600080fd5b61105788610f8f565b965061106560208901610f8f565b95506040880135945060608801359350608088013560ff8116811461108957600080fd5b9699959850939692959460a0840135945060c09093013592915050565b600080604083850312156110b957600080fd5b6110c283610f8f565b91506110d060208401610f8f565b90509250929050565b600181811c908216806110ed57607f821691505b60208210810361110d57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b8082018082111561046357610463611113565b60006001820161114e5761114e611113565b506001019056fea2646970667358221220d4cb82bc88213c43d8b5c62f4d331143446d2fc32fa8fd0ae3cc66be4016b28e64736f6c634300081400336021fa82de881996a3e5fd2d032f74dfe72746b8a66c5510d4ab1a3cb7891507a2646970667358221220dfe64c725d53f0f2b8b6ddd55aa6f0aa922ebbf1612d3cae55e6adf07f3616c664736f6c63430008140033" + }, + { + "contractName": "PolygonZkEVMBridge proxy", + "balance": "200000000000000000000000000", + "nonce": "1", + "address": "0x97808CA57F5c83F283a8B03a5F7C3b5B20b7327E", + "bytecode": "0x60806040523661001357610011610017565b005b6100115b61001f610169565b6001600160a01b0316330361015f5760606001600160e01b0319600035166364d3180d60e11b810161005a5761005361019c565b9150610157565b63587086bd60e11b6001600160e01b031982160161007a576100536101f3565b63070d7c6960e41b6001600160e01b031982160161009a57610053610239565b621eb96f60e61b6001600160e01b03198216016100b95761005361026a565b63a39f25e560e01b6001600160e01b03198216016100d9576100536102aa565b60405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b815160208301f35b6101676102be565b565b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b60606101a66102ce565b60006101b53660048184610690565b8101906101c291906106d6565b90506101df816040518060200160405280600081525060006102d9565b505060408051602081019091526000815290565b60606000806102053660048184610690565b8101906102129190610707565b91509150610222828260016102d9565b604051806020016040528060008152509250505090565b60606102436102ce565b60006102523660048184610690565b81019061025f91906106d6565b90506101df81610305565b60606102746102ce565b600061027e610169565b604080516001600160a01b03831660208201529192500160405160208183030381529060405291505090565b60606102b46102ce565b600061027e61035c565b6101676102c961035c565b61036b565b341561016757600080fd5b6102e28361038f565b6000825111806102ef5750805b15610300576102fe83836103cf565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f61032e610169565b604080516001600160a01b03928316815291841660208301520160405180910390a1610359816103fb565b50565b60006103666104b1565b905090565b3660008037600080366000845af43d6000803e80801561038a573d6000f35b3d6000fd5b610398816104d9565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606103f4838360405180606001604052806027815260200161083d6027913961056d565b9392505050565b6001600160a01b0381166104605760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b606482015260840161014e565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b039290921691909117905550565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61018d565b6001600160a01b0381163b6105465760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161014e565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610483565b6060600080856001600160a01b03168560405161058a91906107ed565b600060405180830381855af49150503d80600081146105c5576040519150601f19603f3d011682016040523d82523d6000602084013e6105ca565b606091505b50915091506105db868383876105e5565b9695505050505050565b6060831561065457825160000361064d576001600160a01b0385163b61064d5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161014e565b508161065e565b61065e8383610666565b949350505050565b8151156106765781518083602001fd5b8060405162461bcd60e51b815260040161014e9190610809565b600080858511156106a057600080fd5b838611156106ad57600080fd5b5050820193919092039150565b80356001600160a01b03811681146106d157600080fd5b919050565b6000602082840312156106e857600080fd5b6103f4826106ba565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561071a57600080fd5b610723836106ba565b9150602083013567ffffffffffffffff8082111561074057600080fd5b818501915085601f83011261075457600080fd5b813581811115610766576107666106f1565b604051601f8201601f19908116603f0116810190838211818310171561078e5761078e6106f1565b816040528281528860208487010111156107a757600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b60005b838110156107e45781810151838201526020016107cc565b50506000910152565b600082516107ff8184602087016107c9565b9190910192915050565b60208152600082518060208401526108288160408501602087016107c9565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a264697066735822122027e421639419fb8b093349f6a0996f07f871b4bb9ef828d59ed844a28dfad04164736f6c63430008140033", + "storage": { + "0x0000000000000000000000000000000000000000000000000000000000000000": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000000000000000000000000000001": "0x0000000000000000000000000000000000000000000000000000000000000001", + "0x000000000000000000000000000000000000000000000000000000000000006b": "0x000000000000000000000101f782c0a4708e9c9ed84c66f8c4011f137a5e30e5", + "0x000000000000000000000000000000000000000000000000000000000000006c": "0x000000000000000000000000a40d5f56745a118d0906a34e69aec8c0db1cb8fa", + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x0000000000000000000000009029c03d935adc24b3164bd289d5eac8209afcc0", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x00000000000000000000000091d8785bba30e09255ec906f2bdfdf5919109b4f" + } + }, + { + "contractName": "PolygonZkEVMGlobalExitRootL2 implementation", + "balance": "0", + "nonce": "1", + "address": "0x181aD6D0D7BE70cd2e7b2B40cC342Acae19b9683", + "bytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c806301fd904414610051578063257b36321461006d57806333d6247d1461008d578063a3c573eb146100a2575b600080fd5b61005a60015481565b6040519081526020015b60405180910390f35b61005a61007b366004610149565b60006020819052908152604090205481565b6100a061009b366004610149565b6100ee565b005b6100c97f00000000000000000000000097808ca57f5c83f283a8b03a5f7c3b5b20b7327e81565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610064565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000097808ca57f5c83f283a8b03a5f7c3b5b20b7327e16146101445760405163b49365dd60e01b815260040160405180910390fd5b600155565b60006020828403121561015b57600080fd5b503591905056fea264697066735822122034444de1b72266e426a53b1e541503207d32039c2b29b901bf1514d8f6d8ad3e64736f6c63430008140033" + }, + { + "contractName": "PolygonZkEVMGlobalExitRootL2 proxy", + "balance": "0", + "nonce": "1", + "address": "0xa40d5f56745a118d0906a34e69aec8c0db1cb8fa", + "bytecode": "0x60806040523661001357610011610017565b005b6100115b61001f6101b7565b6001600160a01b0316336001600160a01b0316141561016f5760606001600160e01b031960003516631b2ce7f360e11b8114156100655761005e6101ea565b9150610167565b6001600160e01b0319811663278f794360e11b14156100865761005e610241565b6001600160e01b031981166308f2839760e41b14156100a75761005e610287565b6001600160e01b031981166303e1469160e61b14156100c85761005e6102b8565b6001600160e01b03198116635c60da1b60e01b14156100e95761005e6102f8565b60405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b815160208301f35b61017761030c565b565b606061019e83836040518060600160405280602781526020016108576027913961031c565b9392505050565b90565b6001600160a01b03163b151590565b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b60606101f4610394565b600061020336600481846106a2565b81019061021091906106e8565b905061022d8160405180602001604052806000815250600061039f565b505060408051602081019091526000815290565b606060008061025336600481846106a2565b8101906102609190610719565b915091506102708282600161039f565b604051806020016040528060008152509250505090565b6060610291610394565b60006102a036600481846106a2565b8101906102ad91906106e8565b905061022d816103cb565b60606102c2610394565b60006102cc6101b7565b604080516001600160a01b03831660208201529192500160405160208183030381529060405291505090565b6060610302610394565b60006102cc610422565b610177610317610422565b610431565b6060600080856001600160a01b0316856040516103399190610807565b600060405180830381855af49150503d8060008114610374576040519150601f19603f3d011682016040523d82523d6000602084013e610379565b606091505b509150915061038a86838387610455565b9695505050505050565b341561017757600080fd5b6103a8836104d3565b6000825111806103b55750805b156103c6576103c48383610179565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103f46101b7565b604080516001600160a01b03928316815291841660208301520160405180910390a161041f81610513565b50565b600061042c6105bc565b905090565b3660008037600080366000845af43d6000803e808015610450573d6000f35b3d6000fd5b606083156104c15782516104ba576001600160a01b0385163b6104ba5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161015e565b50816104cb565b6104cb83836105e4565b949350505050565b6104dc8161060e565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6001600160a01b0381166105785760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b606482015260840161015e565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6101db565b8151156105f45781518083602001fd5b8060405162461bcd60e51b815260040161015e9190610823565b6001600160a01b0381163b61067b5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161015e565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61059b565b600080858511156106b257600080fd5b838611156106bf57600080fd5b5050820193919092039150565b80356001600160a01b03811681146106e357600080fd5b919050565b6000602082840312156106fa57600080fd5b61019e826106cc565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561072c57600080fd5b610735836106cc565b9150602083013567ffffffffffffffff8082111561075257600080fd5b818501915085601f83011261076657600080fd5b81358181111561077857610778610703565b604051601f8201601f19908116603f011681019083821181831017156107a0576107a0610703565b816040528281528860208487010111156107b957600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b60005b838110156107f65781810151838201526020016107de565b838111156103c45750506000910152565b600082516108198184602087016107db565b9190910192915050565b60208152600082518060208401526108428160408501602087016107db565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a264697066735822122012bb4f564f73959a03513dc74fc3c6e40e8386e6f02c16b78d6db00ce0aa16af64736f6c63430008090033", + "storage": { + "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103": "0x0000000000000000000000009029c03d935adc24b3164bd289d5eac8209afcc0", + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc": "0x000000000000000000000000181ad6d0d7be70cd2e7b2b40cc342acae19b9683" + } + }, + { + "accountName": "keyless Deployer", + "balance": "0", + "nonce": "1", + "address": "0xCD99076CE53424b73e3Aa592D76a54881D3C7C43" + }, + { + "accountName": "deployer", + "balance": "0", + "nonce": "9", + "address": "0x55ddcD448cE2f52c29965B882279F120ec3506f8" + } + ] +} \ No newline at end of file diff --git a/deployments/sepolia_1711689773/sepolia.json b/deployments/sepolia_1711689773/sepolia.json new file mode 100644 index 00000000..0e902338 --- /dev/null +++ b/deployments/sepolia_1711689773/sepolia.json @@ -0,0 +1,249 @@ +{ + "manifestVersion": "3.2", + "admin": { + "address": "0x10E279EfB64728c68Ee3156364C69560692A9c83", + "txHash": "0x14b320f059ef21607a4a8e95d3e8c6429f282c498d70bf37d7f746f22c99363e" + }, + "proxies": [ + { + "address": "0xF5E879b316836b69e6c4758DDfc7424114117A55", + "txHash": "0x42cc38e7b99d05ec29238b38babe3861470b95abaee1634cb6f38fd914ce575f", + "kind": "transparent" + }, + { + "address": "0x56d668aB764C65b9Ce3b4d2ebfA591302807e833", + "txHash": "0xebb479f54f630b8488408160917c9bed1a2ac3aa4f0dbc34a1751898fc791757", + "kind": "transparent" + }, + { + "address": "0xb85aD4d0c00b973DA042aD8D0bd0750CB283d1e4", + "txHash": "0x59e74a69161f81794dd3c65ffa80d771aff7d56da1115ee2a5f5af8dae98d9f2", + "kind": "transparent" + } + ], + "impls": { + "2f301487d4527a4ceab2cae79cbaa2518dca9554ffc7072eea6b060f6ffce48e": { + "address": "0x1E7Cac8f336f17B86e1348777C9cc9BB2348BEf3", + "txHash": "0x3c8fb78d3583edc3b7f52fb3363a1260ee6d2ea61486dcf6009fb73f3a025b21", + "layout": { + "solcVersion": "0.8.20", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:40" + }, + { + "label": "_balances", + "offset": 0, + "slot": "51", + "type": "t_mapping(t_address,t_uint256)", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:40" + }, + { + "label": "_allowances", + "offset": 0, + "slot": "52", + "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:42" + }, + { + "label": "_totalSupply", + "offset": 0, + "slot": "53", + "type": "t_uint256", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:44" + }, + { + "label": "_name", + "offset": 0, + "slot": "54", + "type": "t_string_storage", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:46" + }, + { + "label": "_symbol", + "offset": 0, + "slot": "55", + "type": "t_string_storage", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:47" + }, + { + "label": "__gap", + "offset": 0, + "slot": "56", + "type": "t_array(t_uint256)45_storage", + "contract": "ERC20Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol:376" + }, + { + "label": "forkmanager", + "offset": 0, + "slot": "101", + "type": "t_address", + "contract": "ForkableStructure", + "src": "contracts/mixin/ForkableStructure.sol:10" + }, + { + "label": "parentContract", + "offset": 0, + "slot": "102", + "type": "t_address", + "contract": "ForkableStructure", + "src": "contracts/mixin/ForkableStructure.sol:13" + }, + { + "label": "children", + "offset": 0, + "slot": "103", + "type": "t_mapping(t_uint256,t_address)", + "contract": "ForkableStructure", + "src": "contracts/mixin/ForkableStructure.sol:20" + }, + { + "label": "__gap", + "offset": 0, + "slot": "104", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC165Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:41" + }, + { + "label": "_roles", + "offset": 0, + "slot": "154", + "type": "t_mapping(t_bytes32,t_struct(RoleData)6951_storage)", + "contract": "AccessControlUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:57" + }, + { + "label": "__gap", + "offset": 0, + "slot": "155", + "type": "t_array(t_uint256)49_storage", + "contract": "AccessControlUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:260" + }, + { + "label": "childTokenAllowances", + "offset": 0, + "slot": "204", + "type": "t_mapping(t_address,t_mapping(t_bool,t_uint256))", + "contract": "ForkonomicToken", + "src": "contracts/ForkonomicToken.sol:23" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)45_storage": { + "label": "uint256[45]", + "numberOfBytes": "1440" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_mapping(t_address,t_uint256))": { + "label": "mapping(address => mapping(address => uint256))", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_mapping(t_bool,t_uint256))": { + "label": "mapping(address => mapping(bool => uint256))", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_mapping(t_bool,t_uint256)": { + "label": "mapping(bool => uint256)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_struct(RoleData)6951_storage)": { + "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)", + "numberOfBytes": "32" + }, + "t_mapping(t_uint256,t_address)": { + "label": "mapping(uint256 => address)", + "numberOfBytes": "32" + }, + "t_string_storage": { + "label": "string", + "numberOfBytes": "32" + }, + "t_struct(RoleData)6951_storage": { + "label": "struct AccessControlUpgradeable.RoleData", + "members": [ + { + "label": "members", + "type": "t_mapping(t_address,t_bool)", + "offset": 0, + "slot": "0" + }, + { + "label": "adminRole", + "type": "t_bytes32", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + }, + "namespaces": {} + } + } + } +}