diff --git a/contracts/v2/AggLayerGateway.sol b/contracts/v2/AggLayerGateway.sol index 1579f2efc..620b1c3c5 100644 --- a/contracts/v2/AggLayerGateway.sol +++ b/contracts/v2/AggLayerGateway.sol @@ -1,18 +1,17 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.28; -// TODO: check to upgrade version (bugs in solidity?) Check optimism supports cancun import {ISP1Verifier} from "./interfaces/ISP1Verifier.sol"; import {IAggLayerGateway} from "./interfaces/IAggLayerGateway.sol"; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "@openzeppelin/contracts52/access/AccessControl.sol"; + // Based on https://github.com/succinctlabs/sp1-contracts/blob/main/contracts/src/SP1VerifierGateway.sol /** * @title AggLayerGateway * @notice Contract to handle the verification keys for the pessimistic proof. * It supports adding and freezing PP verification keys and verifying the PP. - * Also maintains the default verification keys of aggchains when the flag of using default - * keys is enabled (check aggchainBase contract) + * Also maintains the default verification keys of aggchains */ contract AggLayerGateway is Initializable, AccessControl, IAggLayerGateway { //////////////////////////////////////////////////////////// @@ -20,14 +19,19 @@ contract AggLayerGateway is Initializable, AccessControl, IAggLayerGateway { //////////////////////////////////////////////////////////// // Roles // Default admin role, can grant roles to addresses + // @dev value: 0x131410eab1236cee2db19035b0e825c94e5ab705dffe23321dd53856da531617 bytes32 internal constant AGGCHAIN_DEFAULT_VKEY_ROLE = keccak256("AGGCHAIN_DEFAULT_VKEY_ROLE"); + // Can add a route to a pessimistic verification key. - bytes32 internal constant AGGLAYER_ADD_ROUTE_ROLE = - keccak256("AGGLAYER_ADD_ROUTE_ROLE"); + // @dev value 0x0fdc2a718b96bc741c7544001e3dd7c26730802c54781668fa78a120e622629b + bytes32 internal constant AL_ADD_PP_ROUTE_ROLE = + keccak256("AL_ADD_PP_ROUTE_ROLE"); + // Can freeze a route to a pessimistic verification key. - bytes32 internal constant AGGLAYER_FREEZE_ROUTE_ROLE = - keccak256("AGGLAYER_FREEZE_ROUTE_ROLE"); + // @dev value 0xca75ae4228cde6195f9fa3dbde8dc352fb30aa63780717a378ccfc50274355dd + bytes32 internal constant AL_FREEZE_PP_ROUTE_ROLE = + keccak256("AL_FREEZE_PP_ROUTE_ROLE"); //////////////////////////////////////////////////////////// // Mappings // @@ -35,6 +39,7 @@ contract AggLayerGateway is Initializable, AccessControl, IAggLayerGateway { // Mapping with the default aggchain verification keys mapping(bytes4 defaultAggchainSelector => bytes32 defaultAggchainVKey) public defaultAggchainVKeys; + // Mapping with the pessimistic verification key routes mapping(bytes4 pessimisticVKeySelector => AggLayerVerifierRoute) public pessimisticVKeyRoutes; @@ -45,19 +50,6 @@ contract AggLayerGateway is Initializable, AccessControl, IAggLayerGateway { */ uint256[50] private _gap; - //////////////////////////////////////////////////////////// - // Events // - //////////////////////////////////////////////////////////// - /** - * @dev Emitted when the admin starts the two-step transfer role setting a new pending admin - */ - event TransferAggLayerAdminRole(address newPendingAggLayerAdmin); - - /** - * @dev Emitted when the pending admin accepts the admin role - */ - event AcceptAggLayerAdminRole(address newAggLayerAdmin); - //////////////////////////////////////////////////////////// // Constructor // //////////////////////////////////////////////////////////// @@ -75,25 +67,25 @@ contract AggLayerGateway is Initializable, AccessControl, IAggLayerGateway { /** * @notice Initializer function to set new rollup manager version. * @param defaultAdmin The address of the default admin. Can grant role to addresses. + * @dev This address is the highest privileged address so it's recommended to use a timelock * @param aggchainDefaultVKeyRole The address that can manage the aggchain verification keys. * @param addRouteRole The address that can add a route to a pessimistic verification key. * @param freezeRouteRole The address that can freeze a route to a pessimistic verification key. - * @dev This address is the highest privileged address so it's recommended to use a timelock */ function initialize( address defaultAdmin, address aggchainDefaultVKeyRole, address addRouteRole, address freezeRouteRole - ) external virtual initializer { + ) external initializer { _grantRole(DEFAULT_ADMIN_ROLE, defaultAdmin); _grantRole(AGGCHAIN_DEFAULT_VKEY_ROLE, aggchainDefaultVKeyRole); - _grantRole(AGGLAYER_ADD_ROUTE_ROLE, addRouteRole); - _grantRole(AGGLAYER_FREEZE_ROUTE_ROLE, freezeRouteRole); + _grantRole(AL_ADD_PP_ROUTE_ROLE, addRouteRole); + _grantRole(AL_FREEZE_PP_ROUTE_ROLE, freezeRouteRole); } //////////////////////////////////////////////////////////// - // Functions: views // + // Functions: AggLayerGateway (pessimistic) // //////////////////////////////////////////////////////////// /** * @notice Function to verify the pessimistic proof. @@ -109,12 +101,14 @@ contract AggLayerGateway is Initializable, AccessControl, IAggLayerGateway { bytes calldata proofBytes ) external view { bytes4 ppSelector = bytes4(proofBytes[:4]); + AggLayerVerifierRoute memory route = pessimisticVKeyRoutes[ppSelector]; if (route.verifier == address(0)) { revert RouteNotFound(ppSelector); } else if (route.frozen) { revert RouteIsFrozen(ppSelector); } + ISP1Verifier(route.verifier).verifyProof( route.pessimisticVKey, publicValues, @@ -122,9 +116,6 @@ contract AggLayerGateway is Initializable, AccessControl, IAggLayerGateway { ); } - //////////////////////////////////////////////////////////// - // Functions: AggLayerGateway // - //////////////////////////////////////////////////////////// /** * @notice Function to add a pessimistic verification key route * @param pessimisticVKeySelector The 4 bytes selector to add to the pessimistic verification keys. @@ -135,16 +126,19 @@ contract AggLayerGateway is Initializable, AccessControl, IAggLayerGateway { bytes4 pessimisticVKeySelector, address verifier, bytes32 pessimisticVKey - ) external onlyRole(AGGLAYER_ADD_ROUTE_ROLE) { + ) external onlyRole(AL_ADD_PP_ROUTE_ROLE) { if (pessimisticVKeySelector == bytes4(0)) { - revert SelectorCannotBeZero(); + revert PPSelectorCannotBeZero(); + } + if (pessimisticVKey == bytes32(0)) { + revert VKeyCannotBeZero(); } AggLayerVerifierRoute storage route = pessimisticVKeyRoutes[ pessimisticVKeySelector ]; if (route.verifier != address(0)) { - revert RouteAlreadyExists(route.verifier); + revert RouteAlreadyExists(pessimisticVKeySelector, route.verifier); } route.verifier = verifier; @@ -158,7 +152,7 @@ contract AggLayerGateway is Initializable, AccessControl, IAggLayerGateway { */ function freezePessimisticVKeyRoute( bytes4 pessimisticVKeySelector - ) external onlyRole(AGGLAYER_FREEZE_ROUTE_ROLE) { + ) external onlyRole(AL_FREEZE_PP_ROUTE_ROLE) { AggLayerVerifierRoute storage route = pessimisticVKeyRoutes[ pessimisticVKeySelector ]; @@ -166,12 +160,16 @@ contract AggLayerGateway is Initializable, AccessControl, IAggLayerGateway { revert RouteNotFound(pessimisticVKeySelector); } if (route.frozen) { - revert RouteIsFrozen(pessimisticVKeySelector); + revert RouteIsAlreadyFrozen(pessimisticVKeySelector); } route.frozen = true; - emit RouteFrozen(pessimisticVKeySelector, route.verifier); + emit RouteFrozen( + pessimisticVKeySelector, + route.verifier, + route.pessimisticVKey + ); } //////////////////////////////////////////////////////////// @@ -180,8 +178,8 @@ contract AggLayerGateway is Initializable, AccessControl, IAggLayerGateway { /** * @notice Function to add an aggchain verification key * @param defaultAggchainSelector The 4 bytes selector to add to the default aggchain verification keys. - * @dev First 2 bytes of the selector are the aggchain type (ex: FEP, ECDSA), the last 2 bytes are the 'verification key identifier' - * @param newAggchainVKey New pessimistic program verification key + * @dev First 2 bytes of the selector are the 'verification key identifier', the last 2 bytes are the aggchain type (ex: FEP, ECDSA) + * @param newAggchainVKey New default aggchain verification key to be added */ function addDefaultAggchainVKey( bytes4 defaultAggchainSelector, @@ -191,6 +189,10 @@ contract AggLayerGateway is Initializable, AccessControl, IAggLayerGateway { if (defaultAggchainVKeys[defaultAggchainSelector] != bytes32(0)) { revert AggchainVKeyAlreadyExists(); } + if (newAggchainVKey == bytes32(0)) { + revert VKeyCannotBeZero(); + } + // Add the new VKey to the mapping defaultAggchainVKeys[defaultAggchainSelector] = newAggchainVKey; @@ -200,7 +202,7 @@ contract AggLayerGateway is Initializable, AccessControl, IAggLayerGateway { /** * @notice Function to update a default aggchain verification key from the mapping * @param defaultAggchainSelector The 4 bytes selector to update the default aggchain verification keys. - * @param newDefaultAggchainVKey New pessimistic program verification key + * @param newDefaultAggchainVKey Updated default aggchain verification key value */ function updateDefaultAggchainVKey( bytes4 defaultAggchainSelector, @@ -210,11 +212,14 @@ contract AggLayerGateway is Initializable, AccessControl, IAggLayerGateway { if (defaultAggchainVKeys[defaultAggchainSelector] == bytes32(0)) { revert AggchainVKeyNotFound(); } + // Update the VKey + bytes32 previousVKey = defaultAggchainVKeys[defaultAggchainSelector]; defaultAggchainVKeys[defaultAggchainSelector] = newDefaultAggchainVKey; emit UpdateDefaultAggchainVKey( defaultAggchainSelector, + previousVKey, newDefaultAggchainVKey ); } @@ -230,6 +235,7 @@ contract AggLayerGateway is Initializable, AccessControl, IAggLayerGateway { if (defaultAggchainVKeys[defaultAggchainSelector] == bytes32(0)) { revert AggchainVKeyNotFound(); } + return defaultAggchainVKeys[defaultAggchainSelector]; } } diff --git a/contracts/v2/PolygonRollupManager.sol b/contracts/v2/PolygonRollupManager.sol index 23cdb67b4..2687cb5c7 100644 --- a/contracts/v2/PolygonRollupManager.sol +++ b/contracts/v2/PolygonRollupManager.sol @@ -18,7 +18,7 @@ import "./interfaces/IPolygonPessimisticConsensus.sol"; import "./interfaces/ISP1Verifier.sol"; import "./interfaces/IPolygonRollupManager.sol"; import "./interfaces/IAggchain.sol"; -import "./AggLayerGateway.sol"; +import "./interfaces/IAggLayerGateway.sol"; import "./lib/Hashes.sol"; /** @@ -239,6 +239,9 @@ contract PolygonRollupManager is // Current rollup manager version string public constant ROLLUP_MANAGER_VERSION = "al-v0.3.0"; + // Hardcoded address used to indicate that this address triggered in an event should not be considered as valid. + address private constant _NO_ADDRESS = 0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF; + // Global Exit Root address /// @custom:oz-upgrades-unsafe-allow state-variable-immutable IPolygonZkEVMGlobalExitRootV2 public immutable globalExitRootManager; @@ -253,7 +256,7 @@ contract PolygonRollupManager is // Polygon Verifier Gateway address /// @custom:oz-upgrades-unsafe-allow state-variable-immutable - AggLayerGateway public immutable aggLayerGateway; + IAggLayerGateway public immutable aggLayerGateway; // Number of rollup types added, every new type will be assigned sequentially a new ID uint32 public rollupTypeCount; @@ -403,6 +406,38 @@ contract PolygonRollupManager is */ event UpdateRollupManagerVersion(string rollupManagerVersion); + /** + * @notice Emitted when a ALGateway or Pessimistic chain verifies a pessimistic proof + * @param rollupID Rollup ID + * @param prevPessimisticRoot Previous pessimistic root + * @param newPessimisticRoot New pessimistic root + * @param prevLocalExitRoot Previous local exit root + * @param newLocalExitRoot New local exit root + * @param l1InfoRoot L1 info root + * @param trustedAggregator Trusted aggregator address + */ + event VerifyPessimisticStateTransition( + uint32 indexed rollupID, + bytes32 prevPessimisticRoot, + bytes32 newPessimisticRoot, + bytes32 prevLocalExitRoot, + bytes32 newLocalExitRoot, + bytes32 l1InfoRoot, + address indexed trustedAggregator + ); + + /** + * @dev Emitted when a new rollup is created based on a rollupType + */ + event CreateNewAggchain( + uint32 indexed rollupID, + uint32 rollupTypeID, + address rollupAddress, + uint64 chainID, + uint8 rollupVerifierType, + bytes initializeBytesCustomChain + ); + /** * @param _globalExitRootManager Global exit root manager address * @param _pol POL token address @@ -413,8 +448,17 @@ contract PolygonRollupManager is IPolygonZkEVMGlobalExitRootV2 _globalExitRootManager, IERC20Upgradeable _pol, IPolygonZkEVMBridge _bridgeAddress, - AggLayerGateway _aggLayerGateway + IAggLayerGateway _aggLayerGateway ) { + // Check non zero inputs + if ( + address(_globalExitRootManager) == address(0) || + address(_pol) == address(0) || + address(_bridgeAddress) == address(0) || + address(_aggLayerGateway) == address(0) + ) { + revert InvalidConstructorInputs(); + } globalExitRootManager = _globalExitRootManager; pol = _pol; bridgeAddress = _bridgeAddress; @@ -527,28 +571,19 @@ contract PolygonRollupManager is * @notice Create a new rollup * @param rollupTypeID Rollup type to deploy * @param chainID ChainID of the rollup, must be a new one, can not have more than 32 bits - * @param admin Admin of the new created rollup - * @param sequencer Sequencer of the new created rollup - * @param gasTokenAddress Indicates the token address that will be used to pay gas fees in the new rollup - * Note if a wrapped token of the bridge is used, the original network and address of this wrapped will be used instead - * @param sequencerURL Sequencer URL of the new created rollup - * @param networkName Network name of the new created rollup + * @param initializeBytesCustomChain Encoded params to initialize the chain. Each aggchain has its encoded params. + * @dev in case of rollupType state transition or pessimistic, the encoded params + * are the following: (address admin, address sequencer, address gasTokenAddress, string sequencerURL, string networkName) */ - function createNewRollup( + function attachAggchainToAL( uint32 rollupTypeID, uint64 chainID, - address admin, - address sequencer, - address gasTokenAddress, - string memory sequencerURL, - string memory networkName, bytes memory initializeBytesCustomChain ) external onlyRole(_CREATE_ROLLUP_ROLE) { // Check that rollup type exists if (rollupTypeID == 0 || rollupTypeID > rollupTypeCount) { revert RollupTypeDoesNotExist(); } - // Check rollup type is not obsolete RollupType storage rollupType = rollupTypeMap[rollupTypeID]; if (rollupType.obsolete) { @@ -560,7 +595,6 @@ contract PolygonRollupManager is if (chainID > type(uint32).max) { revert ChainIDOutOfRange(); } - // Check chainID nullifier if (chainIDToRollupID[chainID] != 0) { revert ChainIDAlreadyExist(); @@ -577,34 +611,70 @@ contract PolygonRollupManager is ) ); - // Set chainID nullifier + // Set chainID to rollup id mapping chainIDToRollupID[chainID] = rollupID; - - // Store rollup data + // Set rollup address to rollup id mapping rollupAddressToID[rollupAddress] = rollupID; + // Set rollup data RollupData storage rollup = _rollupIDToRollupData[rollupID]; rollup.rollupContract = rollupAddress; - rollup.forkID = rollupType.forkID; - rollup.verifier = rollupType.verifier; rollup.chainID = chainID; - rollup.batchNumToStateRoot[0] = rollupType.genesis; rollup.rollupTypeID = rollupTypeID; rollup.rollupVerifierType = rollupType.rollupVerifierType; - rollup.programVKey = rollupType.programVKey; - - emit CreateNewRollup( - rollupID, - rollupTypeID, - rollupAddress, - chainID, - gasTokenAddress - ); if (rollupType.rollupVerifierType == VerifierType.ALGateway) { + // Emit create new aggchain event + emit CreateNewAggchain( + rollupID, + rollupTypeID, + rollupAddress, + chainID, + uint8(rollupType.rollupVerifierType), + initializeBytesCustomChain + ); + + // This event is emitted for backwards compatibility + /// @dev the address is hardcoded as it doesn't apply for aggchains and zero address is used for ether + emit CreateNewRollup( + rollupID, + rollupTypeID, + rollupAddress, + chainID, + _NO_ADDRESS + ); + + // Initialize aggchain with the custom chain bytes IAggchain(rollupAddress).initialize(initializeBytesCustomChain); } else { + // assign non ALGateway values to rollup data + rollup.forkID = rollupType.forkID; + rollup.verifier = rollupType.verifier; + rollup.batchNumToStateRoot[0] = rollupType.genesis; + rollup.programVKey = rollupType.programVKey; + + // custom parsing of the initializeBytesCustomChain for a sate transition or pessimistic rollup + ( + address admin, + address sequencer, + address gasTokenAddress, + string memory sequencerURL, + string memory networkName + ) = abi.decode( + initializeBytesCustomChain, + (address, address, address, string, string) + ); + + // Emit create new rollup event + emit CreateNewRollup( + rollupID, + rollupTypeID, + rollupAddress, + chainID, + gasTokenAddress + ); + // Initialize new rollup IPolygonRollupBase(rollupAddress).initialize( admin, @@ -627,7 +697,7 @@ contract PolygonRollupManager is * @param initRoot Genesis block for StateTransitionChains & localExitRoot for pessimistic chain * @param rollupVerifierType Compatibility ID for the added rollup * @param programVKey Hashed program that will be executed in case of using a "general purpose ZK verifier" e.g SP1 - * @param initPessimisticRoot Pessimistic root to init the chain, contains the local balance tree and the local nullifier tree hashed + * @param initPessimisticRoot Pessimistic root to init the chain. */ function addExistingRollup( address rollupAddress, @@ -722,8 +792,6 @@ contract PolygonRollupManager is // Only allowed to update to an older rollup type id if the destination rollup type is ALGateway if ( - rollupTypeMap[newRollupTypeID].rollupVerifierType != - VerifierType.ALGateway && rollup.rollupTypeID >= newRollupTypeID ) { revert UpdateToOldRollupTypeID(); @@ -793,10 +861,6 @@ contract PolygonRollupManager is // If not upgrading to ALGateway if (newRollupType.rollupVerifierType != VerifierType.ALGateway) { - // Current rollup type cant be ALGateway - if (rollup.rollupVerifierType == VerifierType.ALGateway) { - revert UpdateNotCompatible(); - } // Current rollup type must be same than new rollup type if (rollup.rollupVerifierType != newRollupType.rollupVerifierType) { revert UpdateNotCompatible(); @@ -1103,7 +1167,7 @@ contract PolygonRollupManager is * @param newPessimisticRoot New pessimistic information, Hash(localBalanceTreeRoot, nullifierTreeRoot) * @param proof SP1 proof (Plonk) * @param customChainData Specific custom data to verify Aggregation layer chains - * @dev A reentrancy measure has been applied because this function calls `getAggchainHash`, is an open function implemented by the aggchains + * @dev A reentrancy measure has been applied because this function calls `onVerifyPessimistic`, is an open function implemented by the aggchains * @dev the function can not be a view because the nonReentrant uses a transient storage variable */ function verifyPessimisticTrustedAggregator( @@ -1116,7 +1180,7 @@ contract PolygonRollupManager is ) external onlyRole(_TRUSTED_AGGREGATOR_ROLE) nonReentrant { RollupData storage rollup = _rollupIDToRollupData[rollupID]; - // Only for pessimistic verifiers + // Not for state transition chains if (rollup.rollupVerifierType == VerifierType.StateTransition) { revert StateTransitionChainsNotAllowed(); } @@ -1159,20 +1223,38 @@ contract PolygonRollupManager is lastAggregationTimestamp = uint64(block.timestamp); // Consolidate state + bytes32 prevLocalExitRoot = rollup.lastLocalExitRoot; rollup.lastLocalExitRoot = newLocalExitRoot; + bytes32 prevPessimisticRoot = rollup.lastPessimisticRoot; rollup.lastPessimisticRoot = newPessimisticRoot; // Interact with globalExitRootManager globalExitRootManager.updateExitRoot(getRollupExitRoot()); // Same event as verifyBatches to support current bridge service to synchronize everything + /// @dev moved newLocalExitRoot to aux variable to avoid stack too deep errors at compilation + bytes32 newLocalExitRootAux = newLocalExitRoot; emit VerifyBatchesTrustedAggregator( rollupID, 0, // final batch: does not apply in pessimistic bytes32(0), // new state root: does not apply in pessimistic - newLocalExitRoot, + newLocalExitRootAux, msg.sender ); + + // If rollup verifier type is not state transition but ALGateway or pessimistic, emit specific event + if (rollup.rollupVerifierType != VerifierType.StateTransition) { + emit VerifyPessimisticStateTransition( + rollupID, + prevPessimisticRoot, + newPessimisticRoot, + prevLocalExitRoot, + newLocalExitRootAux, + l1InfoRoot, + msg.sender + ); + } + if (rollup.rollupVerifierType == VerifierType.ALGateway) { // Allow chains to manage customData // Callback to the rollup address @@ -1292,16 +1374,25 @@ contract PolygonRollupManager is for (uint256 i = 0; i < nextIterationNodes; i++) { // if we are on the last iteration of the current level and the nodes are odd if (i == nextIterationNodes - 1 && (currentNodes % 2) == 1) { - nextTmpTree[i] = Hashes.efficientKeccak256(tmpTree[i * 2], currentZeroHashHeight); + nextTmpTree[i] = Hashes.efficientKeccak256( + tmpTree[i * 2], + currentZeroHashHeight + ); } else { - nextTmpTree[i] = Hashes.efficientKeccak256(tmpTree[i * 2], tmpTree[(i * 2) + 1]); + nextTmpTree[i] = Hashes.efficientKeccak256( + tmpTree[i * 2], + tmpTree[(i * 2) + 1] + ); } } // Update tree variables tmpTree = nextTmpTree; currentNodes = nextIterationNodes; - currentZeroHashHeight = Hashes.efficientKeccak256(currentZeroHashHeight, currentZeroHashHeight); + currentZeroHashHeight = Hashes.efficientKeccak256( + currentZeroHashHeight, + currentZeroHashHeight + ); remainingLevels--; } @@ -1309,8 +1400,14 @@ contract PolygonRollupManager is // Calculate remaining levels, since it's a sequential merkle tree, the rest of the tree are zeroes for (uint256 i = 0; i < remainingLevels; i++) { - currentRoot = Hashes.efficientKeccak256(currentRoot, currentZeroHashHeight); - currentZeroHashHeight = Hashes.efficientKeccak256(currentZeroHashHeight, currentZeroHashHeight); + currentRoot = Hashes.efficientKeccak256( + currentRoot, + currentZeroHashHeight + ); + currentZeroHashHeight = Hashes.efficientKeccak256( + currentZeroHashHeight, + currentZeroHashHeight + ); } return currentRoot; } @@ -1364,7 +1461,7 @@ contract PolygonRollupManager is } /** - * @notice Function to calculate the pessimistic or aggregation layer input bytes + * @notice Function to calculate the pessimistic input bytes * @param rollupID Rollup id used to calculate the input snark bytes * @param l1InfoTreeRoot L1 Info tree root to proof imported bridges * @param newLocalExitRoot New local exit root @@ -1588,6 +1685,47 @@ contract PolygonRollupManager is rollupData.rollupVerifierType = rollup.rollupVerifierType; } + /** + * @notice Get rollup data: VerifierType State transition + * @param rollupID Rollup identifier + */ + function rollupIDToRollupDataDeserialized( + uint32 rollupID + ) + public + view + returns ( + address rollupContract, + uint64 chainID, + address verifier, + uint64 forkID, + bytes32 lastLocalExitRoot, + uint64 lastBatchSequenced, + uint64 lastVerifiedBatch, + uint64 _legacyLastPendingState, + uint64 _legacyLastPendingStateConsolidated, + uint64 lastVerifiedBatchBeforeUpgrade, + uint64 rollupTypeID, + VerifierType rollupVerifierType + ) + { + RollupData storage rollup = _rollupIDToRollupData[rollupID]; + + rollupContract = rollup.rollupContract; + chainID = rollup.chainID; + verifier = rollup.verifier; + forkID = rollup.forkID; + lastLocalExitRoot = rollup.lastLocalExitRoot; + lastBatchSequenced = rollup.lastBatchSequenced; + lastVerifiedBatch = rollup.lastVerifiedBatch; + _legacyLastPendingState = rollup._legacyLastPendingState; + _legacyLastPendingStateConsolidated = rollup + ._legacyLastPendingStateConsolidated; + lastVerifiedBatchBeforeUpgrade = rollup.lastVerifiedBatchBeforeUpgrade; + rollupTypeID = rollup.rollupTypeID; + rollupVerifierType = rollup.rollupVerifierType; + } + /** * @notice Get rollup data: VerifierType Pessimistic * @param rollupID Rollup identifier @@ -1617,7 +1755,7 @@ contract PolygonRollupManager is * @dev A deserialized version of the rollup data done for a better parsing from etherscan * @param rollupID Rollup identifier */ - function rollupIDToRollupDataDeserialized( + function rollupIDToRollupDataV2Deserialized( uint32 rollupID ) public diff --git a/contracts/v2/PolygonZkEVMBridgeV2.sol b/contracts/v2/PolygonZkEVMBridgeV2.sol index 5f17f0d54..506bbd9c0 100644 --- a/contracts/v2/PolygonZkEVMBridgeV2.sol +++ b/contracts/v2/PolygonZkEVMBridgeV2.sol @@ -462,7 +462,7 @@ contract PolygonZkEVMBridgeV2 is address destinationAddress, uint256 amount, bytes calldata metadata - ) external ifNotEmergencyState { + ) external ifNotEmergencyState nonReentrant { // Destination network must be this networkID if (destinationNetwork != networkID) { revert DestinationNetworkInvalid(); diff --git a/contracts/v2/aggchains/AggchainECDSA.sol b/contracts/v2/aggchains/AggchainECDSA.sol index 76b0dde36..b21aa3c4d 100644 --- a/contracts/v2/aggchains/AggchainECDSA.sol +++ b/contracts/v2/aggchains/AggchainECDSA.sol @@ -8,7 +8,7 @@ import "../interfaces/IAggchain.sol"; * @title AggchainECDSA * @notice Generic aggchain based on ECDSA signature. * An address signs the new_ler and the commit_imported_bridge_exits in order to do state - * transitions on the pessimistic trees (local_exit_tree, local_balance_tree & nullifier_tree). + * transitions on the pessimistic trees (local_exit_tree, local_balance_tree, nullifier_tree & height). * That address is the trustedSequencer and is set during the chain initialization. */ contract AggchainECDSA is AggchainBase, IAggchain { @@ -20,16 +20,23 @@ contract AggchainECDSA is AggchainBase, IAggchain { //////////////////////////////////////////////////////////// // Constants & Immutables // //////////////////////////////////////////////////////////// - // Aggchain type selector, hardcoded value used to force the first 2 byes of aggchain selector to retrieve the aggchain verification key + // Aggchain type selector, hardcoded value used to force the last 2 bytes of aggchain selector to retrieve the aggchain verification key bytes2 public constant AGGCHAIN_TYPE_SELECTOR = 0; //////////////////////////////////////////////////////////// // Events // //////////////////////////////////////////////////////////// /** - * @dev Emitted when Pessimistic proof is verified. + * @notice Emitted when Pessimistic proof is verified. + * @param newStateRoot New state root after processing state transition. */ - event OnVerifyPessimistic(bytes32 newStateRoot); + event OnVerifyPessimisticECDSA(bytes32 newStateRoot); + + //////////////////////////////////////////////////////////// + // Errors // + //////////////////////////////////////////////////////////// + /// @notice Thrown when trying to initialize the wrong initialize function. + error InvalidInitializer(); //////////////////////////////////////////////////////////// // Modifiers // @@ -45,7 +52,11 @@ contract AggchainECDSA is AggchainBase, IAggchain { // Constructor // //////////////////////////////////////////////////////////// /** - * @param _rollupManager Rollup manager address. + * @param _globalExitRootManager Global exit root manager address. + * @param _pol POL token contract address. + * @param _bridgeAddress Bridge contract address. + * @param _rollupManager Rollup manager contract address. + * @param _aggLayerGateway AggLayerGateway contract address. */ constructor( IPolygonZkEVMGlobalExitRootV2 _globalExitRootManager, @@ -67,10 +78,12 @@ contract AggchainECDSA is AggchainBase, IAggchain { // Functions: initialization // //////////////////////////////////////////////////////////// /** - * @param initializeBytesAggchain Encoded params to initialize the chain. + * @param initializeBytesAggchain Encoded bytes to initialize the chain. * Each aggchain has its decoded params. - * @dev for this type of aggChain, there is no need to initialize again when upgrading from pessimistic type because the initialize is exactly the same. - * @dev The reinitializer(2) is set because it can also be initialized differently with 'initializeAfterUpgrade' function but only be initialized once. + * @custom:security First initialization takes into account this contracts and all the inheritance contracts + * Second initialization does not initialize PolygonConsensusBase parameters + * Second initialization can happen if a chain is upgraded from a PolygonPessimisticConsensus + * @dev The reinitializer(2) is set to support the upgrade from PolygonPessimisticConsensus to AggchainECDSA, where PolygonPessimisticConsensus is already initialized */ function initialize( bytes memory initializeBytesAggchain @@ -81,8 +94,8 @@ contract AggchainECDSA is AggchainBase, IAggchain { ( // aggchainBase params bool _useDefaultGateway, - bytes32[] memory _ownedAggchainVKeys, - bytes4[] memory _aggchainVKeySelectors, + bytes32 _initOwnedAggchainVKey, + bytes2 _initAggchainVKeySelector, address _vKeyManager, // PolygonConsensusBase params address _admin, @@ -94,8 +107,8 @@ contract AggchainECDSA is AggchainBase, IAggchain { initializeBytesAggchain, ( bool, - bytes32[], - bytes4[], + bytes32, + bytes2, address, address, address, @@ -105,12 +118,8 @@ contract AggchainECDSA is AggchainBase, IAggchain { ) ); // Set aggchainBase variables - _initializeAggchainBase( - _useDefaultGateway, - _ownedAggchainVKeys, - _aggchainVKeySelectors, - _vKeyManager - ); + _initializeAggchainBase(_useDefaultGateway, _initOwnedAggchainVKey, _initAggchainVKeySelector, _vKeyManager); + // init polygonConsensusBase params _initializePolygonConsensusBase( _admin, @@ -124,18 +133,18 @@ contract AggchainECDSA is AggchainBase, IAggchain { // aggchainBase params ( bool _useDefaultGateway, - bytes32[] memory _ownedAggchainVKeys, - bytes4[] memory _aggchainVKeySelectors, + bytes32 _initOwnedAggchainVKey, + bytes2 _initAggchainVKeySelector, address _vKeyManager ) = abi.decode( initializeBytesAggchain, - (bool, bytes32[], bytes4[], address) + (bool, bytes32, bytes2, address) ); // Set aggchainBase variables _initializeAggchainBase( _useDefaultGateway, - _ownedAggchainVKeys, - _aggchainVKeySelectors, + _initOwnedAggchainVKey, + _initAggchainVKeySelector, _vKeyManager ); } else { @@ -144,31 +153,31 @@ contract AggchainECDSA is AggchainBase, IAggchain { } } - /// @notice Initializer AggchainBase storage - /// @param _useDefaultGateway Flag to setup initial values for the owned gateway - /// @param _initOwnedAggchainVKey Initial owned aggchain verification key - /// @param _initAggchainVKeySelector Initial aggchain selector - /// @param _vKeyManager Initial vKeyManager - function _initializeAggchainBase( - bool _useDefaultGateway, - bytes32[] memory _initOwnedAggchainVKey, - bytes4[] memory _initAggchainVKeySelector, - address _vKeyManager - ) internal { - useDefaultGateway = _useDefaultGateway; + /** + * @notice Initializer AggchainBase storage + * @param _useOwnedGateway Flag to setup initial values for the owned gateway + * @param _initOwnedAggchainVKey Initial owned aggchain verification key + * @param _initAggchainVKeySelector Initial aggchain selector + * @param _vKeyManager Initial vKeyManager + */ + function _initializeAggchainBase(bool _useOwnedGateway, bytes32 _initOwnedAggchainVKey, bytes2 _initAggchainVKeySelector, address _vKeyManager) internal { + useDefaultGateway = _useOwnedGateway; + // set the initial aggchain keys + ownedAggchainVKeys[getFinalAggchainVKeySelectorFromType(_initAggchainVKeySelector, AGGCHAIN_TYPE_SELECTOR)] = _initOwnedAggchainVKey; + // set initial vKeyManager vKeyManager = _vKeyManager; - // set the owned verification keys - if (_initOwnedAggchainVKey.length != _initAggchainVKeySelector.length) { - revert OwnedAggchainVKeyLengthMismatch(); - } - - for (uint256 i = 0; i < _initOwnedAggchainVKey.length; i++) { - ownedAggchainVKeys[ - _initAggchainVKeySelector[i] - ] = _initOwnedAggchainVKey[i]; - } } + + /** + * @notice Initializer PolygonConsensusBase storage + * @param _admin Admin address + * @param sequencer Trusted sequencer address + * @param _gasTokenAddress Indicates the token address in mainnet that will be used as a gas token + * Note if a wrapped token of the bridge is used, the original network and address of this wrapped are used instead + * @param sequencerURL Trusted sequencer URL + * @param _networkName L2 network name + */ function _initializePolygonConsensusBase( address _admin, address sequencer, @@ -207,7 +216,7 @@ contract AggchainECDSA is AggchainBase, IAggchain { aggChainData, (bytes2, bytes32) ); - bytes4 finalAggchainSelector = _getFinalAggchainVKeySelectorFromType( + bytes4 finalAggchainVKeySelector = getFinalAggchainVKeySelectorFromType( aggchainVKeySelector, AGGCHAIN_TYPE_SELECTOR ); @@ -216,7 +225,7 @@ contract AggchainECDSA is AggchainBase, IAggchain { keccak256( abi.encodePacked( AGGCHAIN_TYPE, - getAggchainVKey(finalAggchainSelector), + getAggchainVKey(finalAggchainVKeySelector), keccak256(abi.encodePacked(trustedSequencer)) ) ); @@ -231,7 +240,8 @@ contract AggchainECDSA is AggchainBase, IAggchain { bytes calldata aggChainData ) external onlyRollupManager { (, bytes32 newStateRoot) = abi.decode(aggChainData, (bytes2, bytes32)); + // Emit event - emit OnVerifyPessimistic(newStateRoot); + emit OnVerifyPessimisticECDSA(newStateRoot); } } diff --git a/contracts/v2/aggchains/AggchainFEP.sol b/contracts/v2/aggchains/AggchainFEP.sol deleted file mode 100644 index d91f29865..000000000 --- a/contracts/v2/aggchains/AggchainFEP.sol +++ /dev/null @@ -1,274 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0 -pragma solidity 0.8.28; - -import "../lib/AggchainBase.sol"; -import "../interfaces/IAggchain.sol"; -import "../AggLayerGateway.sol"; - -/** - * @title AggchainFEP - * @notice Generic aggchain based on full execution proof. - * This proof, along with bridge checks, constitutes the final FEP proof. - */ -contract AggchainFEP is AggchainBase, IAggchain { - //////////////////////////////////////////////////////////// - // Transient Storage // - //////////////////////////////////////////////////////////// - uint8 private transient _initializerVersion; - // Struct to store the chain data every time pessimistic proof is verified - struct ChainData { - bytes32 lastStateRoot; - uint128 timestamp; - uint128 l2BlockNumber; - } - - // Aggchain type selector, hardcoded value used to force the first 2 byes of aggchain selector to retrieve the aggchain verification key - bytes2 public constant AGGCHAIN_TYPE_SELECTOR = 0x0001; - - // fep-stack parameters - bytes32 public aggregationVkey; - bytes32 public chainConfigHash; - bytes32 public rangeVkeyCommitment; - - // Array of stored chain data - ChainData[] public chainData; - - ////////// - // Events - ///////// - - /** - * @dev Emitted when Pessimistic proof is verified - * @param initStateRoot Initial state root - * @param initTimestamp Initial timestamp - * @param initL2BlockNumber Initial L2 block number - */ - event OnVerifyPessimistic( - bytes32 initStateRoot, - uint128 initTimestamp, - uint128 initL2BlockNumber - ); - - //////////////////////////////////////////////////////////// - // Modifiers // - //////////////////////////////////////////////////////////// - // @dev Modifier to retrieve initializer version value previous on using the reinitializer modifier, its used in the initialize function. - modifier retrieveInitializerVersion() { - // Get initializer version from OZ initializer smart contract - _initializerVersion = _getInitializedVersion(); - _; - } - - /** - * @param _rollupManager Rollup manager address. - * @param _globalExitRootManager Global exit root manager address. - * @param _pol POL token address. - * @param _bridgeAddress Bridge address. - * @param _aggLayerGateway AggLayerGateway address. - */ - constructor( - IPolygonZkEVMGlobalExitRootV2 _globalExitRootManager, - IERC20Upgradeable _pol, - IPolygonZkEVMBridgeV2 _bridgeAddress, - PolygonRollupManager _rollupManager, - AggLayerGateway _aggLayerGateway - ) - AggchainBase( - _globalExitRootManager, - _pol, - _bridgeAddress, - _rollupManager, - _aggLayerGateway - ) - {} - /** - * @param initializeBytesCustomChain Encoded params to initialize the chain. Each aggchain has its custom decoded params - * @dev The reinitializer(2) is set because it can also be initialized differently with 'initializeAfterUpgrade' function but only be initialized once. - */ - function initialize( - bytes calldata initializeBytesCustomChain - ) - external - override - onlyRollupManager - retrieveInitializerVersion - reinitializer(2) - { - // If initializer version is 0, it means that the chain is being initialized for the first time, so the contract has just been deployed, is not an upgrade - if (_initializerVersion == 0) { - // custom parsing of the initializeBytesCustomChain - // todo: question: gasTokenNetwork?? gasToken metadata? - ( - address _admin, - address _trustedSequencer, - address _gasTokenAddress, - string memory _trustedSequencerURL, - string memory _networkName, - bytes32 _aggregationVkey, - bytes32 _chainConfigHash, - bytes32 _rangeVkeyCommitment, - bytes32 initStateRoot, - uint128 initTimestamp, - uint128 initL2BlockNumber, - address _vKeyManager - ) = abi.decode( - initializeBytesCustomChain, - ( - address, - address, - address, - string, - string, - bytes32, - bytes32, - bytes32, - bytes32, - uint128, - uint128, - address - ) - ); - - // set chain variables - admin = _admin; - trustedSequencer = _trustedSequencer; - gasTokenAddress = _gasTokenAddress; - trustedSequencerURL = _trustedSequencerURL; - networkName = _networkName; - aggregationVkey = _aggregationVkey; - chainConfigHash = _chainConfigHash; - rangeVkeyCommitment = _rangeVkeyCommitment; - // Set aggchainBase variables - vKeyManager = _vKeyManager; - // storage first chainData struct - chainData.push( - ChainData(initStateRoot, initTimestamp, initL2BlockNumber) - ); - } else if (_initializerVersion == 1) { - // Only need to initialize values that are specific for FEP because we are performing an upgrade from a Pessimistic chain - ( - bytes32 _aggregationVkey, - bytes32 _chainConfigHash, - bytes32 _rangeVkeyCommitment, - bytes32 initStateRoot, - uint128 initTimestamp, - uint128 initL2BlockNumber, - address _vKeyManager - ) = abi.decode( - initializeBytesCustomChain, - ( - bytes32, - bytes32, - bytes32, - bytes32, - uint128, - uint128, - address - ) - ); - aggregationVkey = _aggregationVkey; - chainConfigHash = _chainConfigHash; - rangeVkeyCommitment = _rangeVkeyCommitment; - // Set aggchainBase variables - vKeyManager = _vKeyManager; - // storage first chainData struct - chainData.push( - ChainData(initStateRoot, initTimestamp, initL2BlockNumber) - ); - } else { - // This case should never happen because reinitializer is 2 so initializer version is 0 or 1, but it's here to avoid any possible future issue if the reinitializer version is increased - revert InvalidInitializer(); - } - // By default, the gateway is used to manage the aggchain keys - useDefaultGateway = true; - } - - /** - * Note Return the necessary aggchain information for the proof hashed - * AggchainHash: - * Field: | AGGCHAIN_TYPE | aggchainVKey | aggchainParams | - * length (bits): | 32 | 256 | 256 | - * uint256 aggchainParams = keccak256(abi.encodePacked(l1Head, l2PreRoot, claimRoot, claimBlockNum, chainConfigHash, rangeVkeyCommitment, aggregationVkey)) - */ - /// @inheritdoc IAggchain - function getAggchainHash( - bytes memory customChainData - ) external view returns (bytes32) { - ( - bytes2 aggchainVKeySelector, - bytes32 l1Head, - bytes32 l2PreRoot, - bytes32 claimRoot, - uint256 claimBlockNum - ) = abi.decode( - customChainData, - (bytes2, bytes32, bytes32, bytes32, uint256) - ); - bytes32 aggchainParams = keccak256( - abi.encodePacked( - l1Head, - l2PreRoot, - claimRoot, - claimBlockNum, - chainConfigHash, - rangeVkeyCommitment, - aggregationVkey - ) - ); - bytes4 finalAggchainVKeySelector = _getFinalAggchainVKeySelectorFromType( - aggchainVKeySelector, - AGGCHAIN_TYPE_SELECTOR - ); - return - keccak256( - abi.encodePacked( - AGGCHAIN_TYPE, - getAggchainVKey(finalAggchainVKeySelector), - aggchainParams - ) - ); - } - - /** - * Note Update the custom params set at initialization - * TODO: add a timelock delay to avoid invalidate proofs - * @param customInitializeData Encoded custom params to update - */ - function updateCustomInitializeData( - bytes calldata customInitializeData - ) external onlyAdmin { - // custom parsing of the customInitializeData - ( - bytes32 _aggregationVkey, - bytes32 _chainConfigHash, - bytes32 _rangeVkeyCommitment - ) = abi.decode(customInitializeData, (bytes32, bytes32, bytes32)); - aggregationVkey = _aggregationVkey; - chainConfigHash = _chainConfigHash; - rangeVkeyCommitment = _rangeVkeyCommitment; - } - - /** - * @notice Callback function called after verifying a pessimistic proof - * @param customData Encoded custom data of the chain data to store - */ - function onVerifyPessimistic( - bytes memory customData - ) external onlyRollupManager { - ( - bytes32 initStateRoot, - uint128 initTimestamp, - uint128 initL2BlockNumber - ) = abi.decode(customData, (bytes32, uint128, uint128)); - // storage chainData struct - chainData.push( - ChainData(initStateRoot, initTimestamp, initL2BlockNumber) - ); - - emit OnVerifyPessimistic( - initStateRoot, - initTimestamp, - initL2BlockNumber - ); - } -} diff --git a/contracts/v2/interfaces/IAggLayerGateway.sol b/contracts/v2/interfaces/IAggLayerGateway.sol index 01b55c63f..a41cab3aa 100644 --- a/contracts/v2/interfaces/IAggLayerGateway.sol +++ b/contracts/v2/interfaces/IAggLayerGateway.sol @@ -1,5 +1,6 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.28; + // based on: https://github.com/succinctlabs/sp1-contracts/blob/main/contracts/src/ISP1VerifierGateway.sol interface IAggLayerGatewayEvents { @@ -16,20 +17,30 @@ interface IAggLayerGatewayEvents { /// @notice Emitted when a verifier route is frozen. /// @param selector The verifier selector that was frozen. /// @param verifier The address of the verifier contract. - event RouteFrozen(bytes4 selector, address verifier); - - /** - * @notice Emitted when the aggLayerAdmin updates the pessimistic program verification key - */ - event UpdatePessimisticVKey( + event RouteFrozen( bytes4 selector, address verifier, - bytes32 newPessimisticVKey + bytes32 pessimisticVKey ); + /** + * Emitted when a new default aggchain verification key is added + * @param selector The 4 bytes selector of the added default aggchain verification key. + * @param newVKey New aggchain verification key to be added + */ event AddDefaultAggchainVKey(bytes4 selector, bytes32 newVKey); - event UpdateDefaultAggchainVKey(bytes4 selector, bytes32 newVKey); + /** + * Emitted when a default aggchain verification key is update + * @param selector The 4 bytes selector of the updated default aggchain verification key. + * @param previousVKey Aggchain verification key previous value + * @param newVKey Aggchain verification key updated value + */ + event UpdateDefaultAggchainVKey( + bytes4 selector, + bytes32 previousVKey, + bytes32 newVKey + ); } /// @dev Extended error events from https://github.com/succinctlabs/sp1-contracts/blob/main/contracts/src/ISP1VerifierGateway.sol @@ -42,13 +53,21 @@ interface IAggLayerGatewayErrors { /// @param selector The verifier selector that was specified. error RouteIsFrozen(bytes4 selector); + /// @notice Thrown when trying to freeze a route that is already frozen. + /// @param selector The pessimistic verification key selector that was specified. + error RouteIsAlreadyFrozen(bytes4 selector); + /// @notice Thrown when adding a verifier route and the selector already contains a route. + /// @param selector The pessimistic verification key selector that was specified. /// @param verifier The address of the verifier contract in the existing route. - error RouteAlreadyExists(address verifier); + error RouteAlreadyExists(bytes4 selector, address verifier); /// @notice Thrown when adding a verifier route and the selector returned by the verifier is /// zero. - error SelectorCannotBeZero(); + error PPSelectorCannotBeZero(); + + /// @notice Thrown when adding a verifier key with value zero + error VKeyCannotBeZero(); /// @notice Thrown when the caller is not the AggLayerAdmin error OnlyAggLayerAdmin(); @@ -67,6 +86,12 @@ interface IAggLayerGatewayErrors { /// @notice This contract is the interface for the AggLayerGateway. /// @notice Based on https://github.com/succinctlabs/sp1-contracts/blob/main/contracts/src/ISP1VerifierGateway.sol interface IAggLayerGateway is IAggLayerGatewayEvents, IAggLayerGatewayErrors { + /** + * Struct that defines a verifier route + * @param verifier The address of the verifier contract. + * @param pessimisticVKey The verification key to be used for verifying pessimistic proofs. + * @param frozen Whether the route is frozen. + */ struct AggLayerVerifierRoute { address verifier; // SP1 Verifier. It contains sanity check SP1 version with the 4 first bytes of the proof. proof[4:] bytes32 pessimisticVKey; diff --git a/contracts/v2/interfaces/IAggchainBase.sol b/contracts/v2/interfaces/IAggchainBase.sol index 8986e84a5..daa118043 100644 --- a/contracts/v2/interfaces/IAggchainBase.sol +++ b/contracts/v2/interfaces/IAggchainBase.sol @@ -4,52 +4,71 @@ pragma solidity 0.8.28; interface IAggchainBaseEvents { /** - * @dev Emitted when the admin adds an aggchain verification key. + * @notice Emitted when the admin adds an aggchain verification key. + * @param selector The selector of the verification key to add. + * @param newAggchainVKey The new aggchain verification key. */ event AddAggchainVKey(bytes4 selector, bytes32 newAggchainVKey); /** - * @dev Emitted when the admin updates the aggchain verification key. + * @notice Emitted when the admin updates the aggchain verification key. + * @param selector The selector of the verification key to update. + * @param previousAggchainVKey The previous aggchain verification key. + * @param newAggchainVKey The new new aggchain verification key. */ - event UpdateAggchainVKey(bytes4 selector, bytes32 newAggchainVKey); + event UpdateAggchainVKey( + bytes4 selector, + bytes32 previousAggchainVKey, + bytes32 newAggchainVKey + ); /** - * @dev Emitted when the admin switches the use of the default gateway to manage the aggchain keys. + * @notice Emitted when the admin set the flag useDefaultGateway to true. */ - event UpdateUseDefaultGatewayFlag(bool useDefaultGateway); + event EnableUseDefaultGatewayFlag(); + + /** + * @notice Emitted when the admin set the flag useDefaultGateway to false. + */ + event DisableUseDefaultGatewayFlag(); + /** - * @dev Emitted when the vKeyManager starts the two-step transfer role setting a new pending vKeyManager. + * @notice Emitted when the vKeyManager starts the two-step transfer role setting a new pending vKeyManager. * @param newVKeyManager The new vKeyManager. */ event TransferVKeyManagerRole(address newVKeyManager); /** - * @dev Emitted when the pending vKeyManager accepts the vKeyManager role. + * @notice Emitted when the pending vKeyManager accepts the vKeyManager role. + * @param newVKeyManager The new vKeyManager. + * @param oldVKeyManager The previous vKeyManager. */ - event AcceptVKeyManagerRole(address newVKeyManager); + event AcceptVKeyManagerRole(address oldVKeyManager, address newVKeyManager); } interface IAggchainBaseErrors { - /// @notice Thrown when trying to add an invalid verification key. - error InvalidAggchainVKey(); + /// @notice Thrown when trying to add zero value verification key. + error ZeroValueAggchainVKey(); /// @notice Thrown when trying to add an aggchain verification key that already exists. error OwnedAggchainVKeyAlreadyAdded(); /// @notice Thrown when trying to retrieve an aggchain verification key that does not exist. error OwnedAggchainVKeyNotFound(); /// @notice Thrown when trying to initialize the incorrect initialize function. error InvalidInitializeFunction(); - /// @notice Thrown when trying to enable or disable the default gateway when it is already set. - error UseDefaultGatewayAlreadySet(); - /// @notice Thrown when trying to initialize the wrong initialize function. - error InvalidInitializer(); + /// @notice Thrown when trying to enable the default gateway when it is already enabled. + error UseDefaultGatewayAlreadyEnabled(); + /// @notice Thrown when trying to disable the default gateway when it is already disabled. + error UseDefaultGatewayAlreadyDisabled(); /// @notice Thrown when trying to call a function that only the VKeyManager can call. error OnlyVKeyManager(); /// @notice Thrown when trying to call a function that only the pending VKeyManager can call. error OnlyPendingVKeyManager(); /// @notice Thrown when trying to retrieve an aggchain verification key from the mapping that doesn't exists. error AggchainVKeyNotFound(); - /// @notice owned vKeys and selectors length mismatch. - error OwnedAggchainVKeyLengthMismatch(); } + /** * @title IAggchainBase * @notice Shared interface for native aggchain implementations. */ -interface IAggchainBase is IAggchainBaseErrors, IAggchainBaseEvents {} +interface IAggchainBase is IAggchainBaseErrors, IAggchainBaseEvents { + /// @notice Returns the unique aggchain type selector identifier. + function AGGCHAIN_TYPE_SELECTOR() external view returns (bytes2); +} diff --git a/contracts/v2/interfaces/IPolygonRollupManager.sol b/contracts/v2/interfaces/IPolygonRollupManager.sol index 8286ea343..f4109d38a 100644 --- a/contracts/v2/interfaces/IPolygonRollupManager.sol +++ b/contracts/v2/interfaces/IPolygonRollupManager.sol @@ -309,6 +309,16 @@ interface IPolygonRollupManager { */ error InvalidVerifierType(); + /** + * @dev Thrown when trying to create a new ALGateway verifier type rollup with invalid inputs + */ + error InvalidALGatewayInputs(); + + /** + * @dev Thrown when trying to deploy rollup Manager with some zero address as the input + */ + error InvalidConstructorInputs(); + enum VerifierType { StateTransition, Pessimistic, @@ -327,14 +337,9 @@ interface IPolygonRollupManager { function obsoleteRollupType(uint32 rollupTypeID) external; - function createNewRollup( + function attachAggchainToAL( uint32 rollupTypeID, uint64 chainID, - address admin, - address sequencer, - address gasTokenAddress, - string memory sequencerURL, - string memory networkName, bytes memory initializeBytesCustomChain ) external; diff --git a/contracts/v2/lib/AggchainBase.sol b/contracts/v2/lib/AggchainBase.sol index b39c52cab..c20abd6e1 100644 --- a/contracts/v2/lib/AggchainBase.sol +++ b/contracts/v2/lib/AggchainBase.sol @@ -8,26 +8,33 @@ import "../interfaces/IAggchainBase.sol"; /** * @title AggchainBase - * @notice Contract responsible for managing the states and the updates of L2 network. - * There will be a trusted sequencer, which is able to send transactions. - * Any user can force some transaction and the sequencer will have a timeout to add them in the queue. - * The sequenced state is deterministic and can be precalculated before it's actually verified by a zkProof. - * The aggregators will be able to verify the sequenced state with zkProofs and therefore make available the withdrawals from L2 network. - * To enter and exit of the L2 network will be used a PolygonZkEVMBridge smart contract that will be deployed in both networks. + * @notice Base contract for aggchain implementations. This contract is imported by other aggchain implementations to reuse the common logic. */ abstract contract AggchainBase is PolygonConsensusBase, IAggchainBase { + //////////////////////////////////////////////////////////// + // Constants & Immutables // + //////////////////////////////////////////////////////////// // Aggchain type that support generic aggchain hash uint32 public constant AGGCHAIN_TYPE = 1; + // AggLayerGateway address, used in case the flag `useDefaultGateway` is set to true, the aggchains keys are managed by the gateway IAggLayerGateway public immutable aggLayerGateway; + //////////////////////////////////////////////////////////// + // Variables // + //////////////////////////////////////////////////////////// // Address that will be able to manage the aggchain verification keys and swap the useDefaultGateway flag. address public vKeyManager; + // This account will be able to accept the vKeyManager role address public pendingVKeyManager; + // Flag to enable/disable the use of the custom chain gateway to handle the aggchain keys. In case of true, the keys are managed by the aggregation layer gateway bool public useDefaultGateway; + //////////////////////////////////////////////////////////// + // Mappings // + //////////////////////////////////////////////////////////// // AggchainVKeys mapping mapping(bytes4 aggchainVKeySelector => bytes32 ownedAggchainVKey) public ownedAggchainVKeys; @@ -38,6 +45,9 @@ abstract contract AggchainBase is PolygonConsensusBase, IAggchainBase { */ uint256[50] private _gap; + //////////////////////////////////////////////////////////// + // Constructor // + //////////////////////////////////////////////////////////// /** * @param _globalExitRootManager Global exit root manager address. * @param _pol POL token address. @@ -62,8 +72,12 @@ abstract contract AggchainBase is PolygonConsensusBase, IAggchainBase { aggLayerGateway = _aggLayerGateway; } + //////////////////////////////////////////////////////////// + // Initialization // + //////////////////////////////////////////////////////////// /** * @notice Override the function to prevent the contract from being initialized with the initializer implemented at PolygonConsensusBase. + * @dev removing this function can cause critical security issues. */ function initialize( address, // _admin @@ -77,9 +91,9 @@ abstract contract AggchainBase is PolygonConsensusBase, IAggchainBase { revert InvalidInitializeFunction(); } - ////////////////// - // modifiers - ////////////////// + ////////////////////////// + // modifiers // + ///////////////////////// // Modifier to check if the caller is the vKeyManager modifier onlyVKeyManager() { if (vKeyManager != msg.sender) { @@ -88,9 +102,9 @@ abstract contract AggchainBase is PolygonConsensusBase, IAggchainBase { _; } - ////////////////// - // admin functions - ////////////////// + /////////////////////////////// + // VKeyManager functions // + ////////////////////////////// /** * @notice Starts the vKeyManager role transfer @@ -101,8 +115,10 @@ abstract contract AggchainBase is PolygonConsensusBase, IAggchainBase { address newVKeyManager ) external onlyVKeyManager { pendingVKeyManager = newVKeyManager; + emit TransferVKeyManagerRole(newVKeyManager); } + /** * @notice Allow the current pending vKeyManager to accept the vKeyManager role */ @@ -110,19 +126,26 @@ abstract contract AggchainBase is PolygonConsensusBase, IAggchainBase { if (pendingVKeyManager != msg.sender) { revert OnlyPendingVKeyManager(); } + + address oldVKeyManager = vKeyManager; vKeyManager = pendingVKeyManager; - emit AcceptVKeyManagerRole(pendingVKeyManager); + delete pendingVKeyManager; + + emit AcceptVKeyManagerRole(oldVKeyManager, vKeyManager); } + /** * @notice Enable the use of the default gateway to manage the aggchain keys. */ function enableUseDefaultGatewayFlag() external onlyVKeyManager { if (useDefaultGateway) { - revert UseDefaultGatewayAlreadySet(); + revert UseDefaultGatewayAlreadyEnabled(); } + useDefaultGateway = true; + // Emit event - emit UpdateUseDefaultGatewayFlag(useDefaultGateway); + emit EnableUseDefaultGatewayFlag(); } /** @@ -130,11 +153,13 @@ abstract contract AggchainBase is PolygonConsensusBase, IAggchainBase { */ function disableUseDefaultGatewayFlag() external onlyVKeyManager { if (!useDefaultGateway) { - revert UseDefaultGatewayAlreadySet(); + revert UseDefaultGatewayAlreadyDisabled(); } + useDefaultGateway = false; + // Emit event - emit UpdateUseDefaultGatewayFlag(useDefaultGateway); + emit DisableUseDefaultGatewayFlag(); } /** @@ -147,14 +172,15 @@ abstract contract AggchainBase is PolygonConsensusBase, IAggchainBase { bytes32 newAggchainVKey ) external onlyVKeyManager { if (newAggchainVKey == bytes32(0)) { - revert InvalidAggchainVKey(); + revert ZeroValueAggchainVKey(); } - - // Check already added + // Check if proposed selector has already a verification key assigned if (ownedAggchainVKeys[aggchainSelector] != bytes32(0)) { revert OwnedAggchainVKeyAlreadyAdded(); } + ownedAggchainVKeys[aggchainSelector] = newAggchainVKey; + emit AddAggchainVKey(aggchainSelector, newAggchainVKey); } @@ -171,8 +197,15 @@ abstract contract AggchainBase is PolygonConsensusBase, IAggchainBase { if (ownedAggchainVKeys[aggchainSelector] == bytes32(0)) { revert OwnedAggchainVKeyNotFound(); } + + bytes32 previousAggchainVKey = ownedAggchainVKeys[aggchainSelector]; ownedAggchainVKeys[aggchainSelector] = updatedAggchainVKey; - emit UpdateAggchainVKey(aggchainSelector, updatedAggchainVKey); + + emit UpdateAggchainVKey( + aggchainSelector, + previousAggchainVKey, + updatedAggchainVKey + ); } /** @@ -184,6 +217,7 @@ abstract contract AggchainBase is PolygonConsensusBase, IAggchainBase { ) public view returns (bytes32 aggchainVKey) { if (useDefaultGateway == false) { aggchainVKey = ownedAggchainVKeys[aggchainSelector]; + if (aggchainVKey == bytes32(0)) { revert AggchainVKeyNotFound(); } @@ -200,11 +234,14 @@ abstract contract AggchainBase is PolygonConsensusBase, IAggchainBase { * @dev It joins two bytes2 values into a bytes4 value. * @param aggchainVKeySelector The aggchain verification key selector, used to identify the aggchain verification key. * @param aggchainType The aggchain type, hardcoded in the aggchain contract. + * [ finalAggchainVKeySelector ] + * [ aggchainVKeySelector | AGGCHAIN_TYPE_SELECTOR ] + * [ 2 bytes | 2 bytes ] */ - function _getFinalAggchainVKeySelectorFromType( + function getFinalAggchainVKeySelectorFromType( bytes2 aggchainVKeySelector, bytes2 aggchainType - ) internal pure returns (bytes4) { + ) public pure returns (bytes4) { return bytes4(aggchainVKeySelector) | (bytes4(aggchainType) >> 16); } } diff --git a/contracts/v2/mocks/AggchainBaseMock.sol b/contracts/v2/mocks/AggchainBaseMock.sol deleted file mode 100644 index 659217a64..000000000 --- a/contracts/v2/mocks/AggchainBaseMock.sol +++ /dev/null @@ -1,47 +0,0 @@ -// SPDX-License-Identifier: AGPL-3.0 -pragma solidity 0.8.28; - -import "../lib/AggchainBase.sol"; -/** - * @title AggchainBase - * @notice Contract responsible for managing the states and the updates of L2 network. - * There will be a trusted sequencer, which is able to send transactions. - * Any user can force some transaction and the sequencer will have a timeout to add them in the queue. - * The sequenced state is deterministic and can be precalculated before it's actually verified by a zkProof. - * The aggregators will be able to verify the sequenced state with zkProofs and therefore make available the withdrawals from L2 network. - * To enter and exit of the L2 network will be used a PolygonZkEVMBridge smart contract that will be deployed in both networks. - */ -contract AggchainBaseMock is AggchainBase { - constructor( - IPolygonZkEVMGlobalExitRootV2 _globalExitRootManager, - IERC20Upgradeable _pol, - IPolygonZkEVMBridgeV2 _bridgeAddress, - PolygonRollupManager _rollupManager, - IAggLayerGateway _aggLayerGateway - ) - AggchainBase( - _globalExitRootManager, - _pol, - _bridgeAddress, - _rollupManager, - _aggLayerGateway - ) - {} - - /** - * @notice Computes the selector for the aggchain verification key from the aggchain type and the aggchainVKeySelector. - * @dev It joins two bytes2 values into a bytes4 value. - * @param aggchainVKeySelector The aggchain verification key selector, used to identify the aggchain verification key. - * @param aggchainType The aggchain type, hardcoded in the aggchain contract. - */ - function getFinalAggchainVKeySelectorFromType( - bytes2 aggchainVKeySelector, - bytes2 aggchainType - ) public pure returns (bytes4) { - return - _getFinalAggchainVKeySelectorFromType( - aggchainVKeySelector, - aggchainType - ); - } -} diff --git a/contracts/v2/mocks/PolygonRollupManagerMock.sol b/contracts/v2/mocks/PolygonRollupManagerMock.sol index 7374ac1fa..018d4eecc 100644 --- a/contracts/v2/mocks/PolygonRollupManagerMock.sol +++ b/contracts/v2/mocks/PolygonRollupManagerMock.sol @@ -15,7 +15,7 @@ contract PolygonRollupManagerMock is PolygonRollupManager { IPolygonZkEVMGlobalExitRootV2 _globalExitRootManager, IERC20Upgradeable _pol, IPolygonZkEVMBridge _bridgeAddress, - AggLayerGateway _aggLayerGateway + IAggLayerGateway _aggLayerGateway ) PolygonRollupManager(_globalExitRootManager, _pol, _bridgeAddress, _aggLayerGateway) {} function initializeMock( diff --git a/contracts/v2/newDeployments/PolygonRollupManagerNotUpgraded.sol b/contracts/v2/newDeployments/PolygonRollupManagerNotUpgraded.sol index 5169d383d..495ab557c 100644 --- a/contracts/v2/newDeployments/PolygonRollupManagerNotUpgraded.sol +++ b/contracts/v2/newDeployments/PolygonRollupManagerNotUpgraded.sol @@ -15,7 +15,7 @@ contract PolygonRollupManagerNotUpgraded is PolygonRollupManager { IPolygonZkEVMGlobalExitRootV2 _globalExitRootManager, IERC20Upgradeable _pol, IPolygonZkEVMBridge _bridgeAddress, - AggLayerGateway _aggLayerGateway + IAggLayerGateway _aggLayerGateway ) PolygonRollupManager( _globalExitRootManager, diff --git a/contracts/v2/sovereignChains/GlobalExitRootManagerL2SovereignChain.sol b/contracts/v2/sovereignChains/GlobalExitRootManagerL2SovereignChain.sol index 0668f8809..23ed4c4dc 100644 --- a/contracts/v2/sovereignChains/GlobalExitRootManagerL2SovereignChain.sol +++ b/contracts/v2/sovereignChains/GlobalExitRootManagerL2SovereignChain.sol @@ -21,7 +21,7 @@ contract GlobalExitRootManagerL2SovereignChain is // Inserted GER counter /// @custom:oz-renamed-from insertedGERCount - uint256 public _legacyInsertedGERCount; + uint256 internal _legacyInsertedGERCount; // Value of the global exit roots hash chain after last insertion bytes32 public insertedGERHashChain; @@ -82,7 +82,7 @@ contract GlobalExitRootManagerL2SovereignChain is function initialize( address _globalExitRootUpdater, address _globalExitRootRemover - ) external virtual reinitializer(2) { + ) external virtual initializer { // set globalExitRootUpdater globalExitRootUpdater = _globalExitRootUpdater; // set globalExitRootRemover @@ -124,7 +124,7 @@ contract GlobalExitRootManagerL2SovereignChain is globalExitRootMap[_newRoot] = block.timestamp; // Update hash chain value insertedGERHashChain = Hashes.efficientKeccak256(insertedGERHashChain, _newRoot); - // @dev we are emitting to events for backwards compatibility, should deprecate InsertGlobalExitRoot event in the future + // @dev we are emitting two events for backwards compatibility, should deprecate InsertGlobalExitRoot event in the future emit InsertGlobalExitRoot(_newRoot); emit UpdateHashChainValue(_newRoot, insertedGERHashChain); } else { @@ -132,17 +132,6 @@ contract GlobalExitRootManagerL2SovereignChain is } } - /** - * @notice Legacy function to remove Last global exit roots - * @dev Now this function logic is moved to _removeGlobalExitRoots, in the past only last inserted GERs were allowed to remove, that is the reason for the name of the function. - * @param gersToRemove Array of gers to remove - */ - function removeLastGlobalExitRoots( - bytes32[] calldata gersToRemove - ) external onlyGlobalExitRootRemover { - _removeGlobalExitRoots(gersToRemove); - } - /** * @notice Remove global exit roots * @dev After removing a global exit root, the removal hash chain value is updated. diff --git a/deployment/v2/4_createRollup.ts b/deployment/v2/4_createRollup.ts index 129ae80e5..d4b42bc3d 100644 --- a/deployment/v2/4_createRollup.ts +++ b/deployment/v2/4_createRollup.ts @@ -21,6 +21,7 @@ import updateVanillaGenesis from "./utils/updateVanillaGenesis"; const dateStr = new Date().toISOString(); const pathOutputJson = path.join(__dirname, `./create_rollup_output_${dateStr}.json`); import utilsECDSA from "../../src/utils-aggchain-ECDSA" +const { encodeInitializeBytesPessimistic } = require("../../src/utils-common-aggchain"); import { PolygonRollupManager, @@ -293,8 +294,8 @@ async function main() { if(consensusContract == "AggchainECDSA") { initializeBytesCustomChain = utilsECDSA.encodeInitializeBytesAggchainECDSAv0( createRollupParameters.aggchainParams.useDefaultGateway, - createRollupParameters.aggchainParams.ownedAggchainVKeys, - createRollupParameters.aggchainParams.aggchainVKeySelectors, + createRollupParameters.aggchainParams.ownedAggchainVKey, + createRollupParameters.aggchainParams.aggchainVKeySelector, createRollupParameters.aggchainParams.vKeyManager, adminZkEVM, trustedSequencer, @@ -330,7 +331,7 @@ async function main() { await verifierContract.waitForDeployment(); } verifierAddress = verifierContract.target; - initializeBytesCustomChain = "0x" + initializeBytesCustomChain = encodeInitializeBytesPessimistic(adminZkEVM, trustedSequencer, gasTokenAddress, trustedSequencerURL, networkName); console.log("#######################\n"); console.log("Verifier name:", verifierName); console.log("Verifier deployed to:", verifierAddress); @@ -382,17 +383,11 @@ async function main() { const newRollupTypeID = await rollupManagerContract.rollupTypeCount(); // Create new rollup - const txDeployRollup = await rollupManagerContract.createNewRollup( + const txDeployRollup = await rollupManagerContract.attachAggchainToAL( newRollupTypeID, chainID, - adminZkEVM, - trustedSequencer, - gasTokenAddress, - trustedSequencerURL, - networkName, initializeBytesCustomChain ); - const receipt = (await txDeployRollup.wait()) as any; const blockDeploymentRollup = await receipt?.getBlock(); const timestampReceipt = blockDeploymentRollup.timestamp; diff --git a/deployment/v3/AggLayerGateway/README.md b/deployment/v3/AggLayerGateway/README.md index 842885aba..dfaa12cec 100644 --- a/deployment/v3/AggLayerGateway/README.md +++ b/deployment/v3/AggLayerGateway/README.md @@ -30,7 +30,6 @@ cp ./deployment/v3/AggLayerGateway/deploy_parameters.json.example ./deployment/v - "aggchainDefaultVKeyRoleAddress": "0x.." -> The address of the AGGCHAIN_DEFAULT_VKEY_ROLE role - "addRouteRoleAddress": "0x.." -> The address of the AGGLAYER_ADD_ROUTE_ROLE role - "freezeRouteRoleAddress": "0x..." -> The address of the AGGLAYER_FREEZE_ROUTE_ROLE role - - - "deployerPvtKey": "0x...", -> Optional: The private key of the wallet used to deploy the new implementation - Run tool: diff --git a/deployment/v3/AggLayerGateway/deployAggLayerGateway.ts b/deployment/v3/AggLayerGateway/deployAggLayerGateway.ts index ec6948ace..458a9ac73 100644 --- a/deployment/v3/AggLayerGateway/deployAggLayerGateway.ts +++ b/deployment/v3/AggLayerGateway/deployAggLayerGateway.ts @@ -64,14 +64,14 @@ async function main() { // Check initializer params (ROLES) const AGGCHAIN_DEFAULT_VKEY_ROLE = ethers.id("AGGCHAIN_DEFAULT_VKEY_ROLE"); - const AGGLAYER_ADD_ROUTE_ROLE = ethers.id("AGGLAYER_ADD_ROUTE_ROLE"); - const AGGLAYER_FREEZE_ROUTE_ROLE = ethers.id("AGGLAYER_FREEZE_ROUTE_ROLE"); + const AL_ADD_PP_ROUTE_ROLE = ethers.id("AL_ADD_PP_ROUTE_ROLE"); + const AL_FREEZE_PP_ROUTE_ROLE = ethers.id("AL_FREEZE_PP_ROUTE_ROLE"); // Admin role expect(await aggLayerGateway.hasRole(ethers.ZeroHash, defaultAdminAddress)).to.be.true; // Other roles expect(await aggLayerGateway.hasRole(AGGCHAIN_DEFAULT_VKEY_ROLE, aggchainDefaultVKeyRoleAddress)).to.be.true; - expect(await aggLayerGateway.hasRole(AGGLAYER_ADD_ROUTE_ROLE, addRouteRoleAddress)).to.be.true; - expect(await aggLayerGateway.hasRole(AGGLAYER_FREEZE_ROUTE_ROLE, freezeRouteRoleAddress)).to.be.true; + expect(await aggLayerGateway.hasRole(AL_ADD_PP_ROUTE_ROLE, addRouteRoleAddress)).to.be.true; + expect(await aggLayerGateway.hasRole(AL_FREEZE_PP_ROUTE_ROLE, freezeRouteRoleAddress)).to.be.true; // Compute output diff --git a/docker/README.md b/docker/README.md index 6db1166af..1d1fa791a 100644 --- a/docker/README.md +++ b/docker/README.md @@ -62,8 +62,8 @@ You can change the deployment `mnemonic` creating a `.env` file in the project r - `globalExitRootRemover`: Address of globalExitRootRemover for sovereign chains - `aggchainParams`: Only mandatory if consensusContract is AggchainECDSA or AggchainFEP - `useDefaultGateway`: bool, flag to setup initial values for the owned gateway - - `ownedAggchainVKeys`: bytes32, Initial owned aggchain verification key - - `aggchainVKeySelectors`: bytes4, Initial aggchain selector + - `ownedAggchainVKey`: bytes32, Initial owned aggchain verification key + - `aggchainVKeySelector`: bytes2, Initial aggchain selector - `vKeyManager`: address, Initial vKeyManager ## Run script diff --git a/docker/docker-tests.test.ts b/docker/docker-tests.test.ts index 98aa13b1e..c68e1ce6b 100644 --- a/docker/docker-tests.test.ts +++ b/docker/docker-tests.test.ts @@ -85,11 +85,11 @@ describe("Docker build tests Contract", () => { expect(AggLayerGatewayContract.target).to.equal(aggLayerGatewayAddress); const DEFAULT_ADMIN_ROLE = ethers.ZeroHash; const AGGCHAIN_DEFAULT_VKEY_ROLE = ethers.id("AGGCHAIN_DEFAULT_VKEY_ROLE"); - const AGGLAYER_ADD_ROUTE_ROLE = ethers.id("AGGLAYER_ADD_ROUTE_ROLE"); - const AGGLAYER_FREEZE_ROUTE_ROLE = ethers.id("AGGLAYER_FREEZE_ROUTE_ROLE"); + const AL_ADD_PP_ROUTE_ROLE = ethers.id("AL_ADD_PP_ROUTE_ROLE"); + const AL_FREEZE_PP_ROUTE_ROLE = ethers.id("AL_FREEZE_PP_ROUTE_ROLE"); expect(await AggLayerGatewayContract.hasRole(DEFAULT_ADMIN_ROLE, admin)).to.be.true; expect(await AggLayerGatewayContract.hasRole(AGGCHAIN_DEFAULT_VKEY_ROLE, admin)).to.be.true; - expect(await AggLayerGatewayContract.hasRole(AGGLAYER_ADD_ROUTE_ROLE, admin)).to.be.true; - expect(await AggLayerGatewayContract.hasRole(AGGLAYER_FREEZE_ROUTE_ROLE, admin)).to.be.true; + expect(await AggLayerGatewayContract.hasRole(AL_ADD_PP_ROUTE_ROLE, admin)).to.be.true; + expect(await AggLayerGatewayContract.hasRole(AL_FREEZE_PP_ROUTE_ROLE, admin)).to.be.true; }); }); diff --git a/docker/scripts/v2/create_rollup_parameters_docker.json b/docker/scripts/v2/create_rollup_parameters_docker.json index 105c75fa9..06e0eb77f 100644 --- a/docker/scripts/v2/create_rollup_parameters_docker.json +++ b/docker/scripts/v2/create_rollup_parameters_docker.json @@ -24,12 +24,8 @@ }, "aggchainParams": { "useDefaultGateway": true, - "ownedAggchainVKeys": [ - "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef" - ], - "aggchainVKeySelectors": [ - "0x12345678" - ], + "ownedAggchainVKey": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", + "aggchainVKeySelector": "0x1234", "vKeyManager": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" } } diff --git a/src/constants.js b/src/constants.js index 941fbbe64..cdfe3fa6f 100644 --- a/src/constants.js +++ b/src/constants.js @@ -41,3 +41,4 @@ TIMELOCK.MINDELAY_STORAGE_POS = 2; /// ///////////////////////////////// module.exports.STORAGE_ONE_VALUE = '0x0000000000000000000000000000000000000000000000000000000000000001'; module.exports.STORAGE_ZERO_VALUE = '0x0000000000000000000000000000000000000000000000000000000000000000'; +module.exports.NO_ADDRESS = '0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF'; diff --git a/src/utils-aggchain-ECDSA.js b/src/utils-aggchain-ECDSA.js index f373622b3..a5043daab 100644 --- a/src/utils-aggchain-ECDSA.js +++ b/src/utils-aggchain-ECDSA.js @@ -29,7 +29,7 @@ const AGGCHAIN_TYPE_SELECTOR_ECDSA = '0x0000'; function encodeInitializeBytesAggchainECDSAv0( useDefaultGateway, ownedAggchainVKey, - aggchainVKeySelectors, + aggchainVKeySelector, vKeyManager, admin, trustedSequencer, @@ -38,11 +38,11 @@ function encodeInitializeBytesAggchainECDSAv0( networkName, ) { return ethers.AbiCoder.defaultAbiCoder().encode( - ['bool', 'bytes32[]', 'bytes4[]', 'address', 'address', 'address', 'address', 'string', 'string'], + ['bool', 'bytes32', 'bytes2', 'address', 'address', 'address', 'address', 'string', 'string'], [ useDefaultGateway, ownedAggchainVKey, - aggchainVKeySelectors, + aggchainVKeySelector, vKeyManager, admin, trustedSequencer, @@ -64,15 +64,15 @@ function encodeInitializeBytesAggchainECDSAv0( function encodeInitializeBytesAggchainECDSAv1( useDefaultGateway, ownedAggchainVKey, - aggchainVKeySelectors, + aggchainVKeySelector, vKeyManager, ) { return ethers.AbiCoder.defaultAbiCoder().encode( - ['bool', 'bytes32[]', 'bytes4[]', 'address'], + ['bool', 'bytes32', 'bytes2', 'address'], [ useDefaultGateway, ownedAggchainVKey, - aggchainVKeySelectors, + aggchainVKeySelector, vKeyManager, ], ); diff --git a/src/utils-common-aggchain.js b/src/utils-common-aggchain.js index 00b0811aa..287689eb3 100644 --- a/src/utils-common-aggchain.js +++ b/src/utils-common-aggchain.js @@ -62,8 +62,37 @@ function getFinalAggchainVKeySelectorFromType(_aggchainVKeySelector, _aggchainTy return `0x${aggchainVKeySelector}${aggChainType}`; } +/** + * Function to encode the initialize bytes for pessimistic or state transition rollups + * @param {String} admin Admin address + * @param {String} trustedSequencer Trusted sequencer address + * @param {String} gasTokenAddress Indicates the token address in mainnet that will be used as a gas token + * @param {String} trustedSequencerURL Trusted sequencer URL + * @param {String} networkName L2 network name + * @returns {String} encoded value in hexadecimal string + */ +function encodeInitializeBytesPessimistic( + admin, + sequencer, + gasTokenAddress, + sequencerURL, + networkName, +) { + return ethers.AbiCoder.defaultAbiCoder().encode( + ['address', 'address', 'address', 'string', 'string'], + [ + admin, + sequencer, + gasTokenAddress, + sequencerURL, + networkName, + ], + ); +} + module.exports = { AggchainType, computeAggchainHash, getFinalAggchainVKeySelectorFromType, + encodeInitializeBytesPessimistic, }; diff --git a/test/contractsv2/AggLayerGateway.test.ts b/test/contractsv2/AggLayerGateway.test.ts index 61852342e..ad21c23aa 100644 --- a/test/contractsv2/AggLayerGateway.test.ts +++ b/test/contractsv2/AggLayerGateway.test.ts @@ -20,8 +20,8 @@ describe("AggLayerGateway tests", () => { const DEFAULT_ADMIN_ROLE = ethers.ZeroHash; const AGGCHAIN_DEFAULT_VKEY_ROLE = ethers.id("AGGCHAIN_DEFAULT_VKEY_ROLE"); - const AGGLAYER_ADD_ROUTE_ROLE = ethers.id("AGGLAYER_ADD_ROUTE_ROLE"); - const AGGLAYER_FREEZE_ROUTE_ROLE = ethers.id("AGGLAYER_FREEZE_ROUTE_ROLE"); + const AL_ADD_PP_ROUTE_ROLE = ethers.id("AL_ADD_PP_ROUTE_ROLE"); + const AL_FREEZE_PP_ROUTE_ROLE = ethers.id("AL_FREEZE_PP_ROUTE_ROLE"); const selector = input["proof"].slice(0, 10); const pessimisticVKey = input["vkey"]; @@ -78,23 +78,23 @@ describe("AggLayerGateway tests", () => { aggLayerGatewayContract.addPessimisticVKeyRoute(selector, verifierContract.target, pessimisticVKey) ) .to.be.revertedWithCustomError(aggLayerGatewayContract, "AccessControlUnauthorizedAccount") - .withArgs(deployer.address, AGGLAYER_ADD_ROUTE_ROLE); + .withArgs(deployer.address, AL_ADD_PP_ROUTE_ROLE); - // grantRole AGGLAYER_ADD_ROUTE_ROLE --> aggLayerAdmin + // grantRole AL_ADD_PP_ROUTE_ROLE --> aggLayerAdmin await expect( - aggLayerGatewayContract.connect(defaultAdmin).grantRole(AGGLAYER_ADD_ROUTE_ROLE, aggLayerAdmin.address) + aggLayerGatewayContract.connect(defaultAdmin).grantRole(AL_ADD_PP_ROUTE_ROLE, aggLayerAdmin.address) ) .to.emit(aggLayerGatewayContract, "RoleGranted") - .withArgs(AGGLAYER_ADD_ROUTE_ROLE, aggLayerAdmin.address, defaultAdmin.address); + .withArgs(AL_ADD_PP_ROUTE_ROLE, aggLayerAdmin.address, defaultAdmin.address); - expect(await aggLayerGatewayContract.hasRole(AGGLAYER_ADD_ROUTE_ROLE, aggLayerAdmin.address)).to.be.true; + expect(await aggLayerGatewayContract.hasRole(AL_ADD_PP_ROUTE_ROLE, aggLayerAdmin.address)).to.be.true; - // check SelectorCannotBeZero + // check PPSelectorCannotBeZero await expect( aggLayerGatewayContract .connect(aggLayerAdmin) .addPessimisticVKeyRoute("0x00000000", verifierContract.target, pessimisticVKey) - ).to.be.revertedWithCustomError(aggLayerGatewayContract, "SelectorCannotBeZero"); + ).to.be.revertedWithCustomError(aggLayerGatewayContract, "PPSelectorCannotBeZero"); // check RouteAdded await expect( @@ -112,20 +112,20 @@ describe("AggLayerGateway tests", () => { .addPessimisticVKeyRoute(selector, verifierContract.target, pessimisticVKey) ) .to.be.revertedWithCustomError(aggLayerGatewayContract, "RouteAlreadyExists") - .withArgs(verifierContract.target); + .withArgs(selector, verifierContract.target); }); it("freezePessimisticVKeyRoute", async () => { const testSelector = "0x00000002"; - // grantRole AGGLAYER_ADD_ROUTE_ROLE --> aggLayerAdmin + // grantRole AL_ADD_PP_ROUTE_ROLE --> aggLayerAdmin await expect( - aggLayerGatewayContract.connect(defaultAdmin).grantRole(AGGLAYER_ADD_ROUTE_ROLE, aggLayerAdmin.address) + aggLayerGatewayContract.connect(defaultAdmin).grantRole(AL_ADD_PP_ROUTE_ROLE, aggLayerAdmin.address) ) .to.emit(aggLayerGatewayContract, "RoleGranted") - .withArgs(AGGLAYER_ADD_ROUTE_ROLE, aggLayerAdmin.address, defaultAdmin.address); + .withArgs(AL_ADD_PP_ROUTE_ROLE, aggLayerAdmin.address, defaultAdmin.address); - expect(await aggLayerGatewayContract.hasRole(AGGLAYER_ADD_ROUTE_ROLE, aggLayerAdmin.address)).to.be.true; + expect(await aggLayerGatewayContract.hasRole(AL_ADD_PP_ROUTE_ROLE, aggLayerAdmin.address)).to.be.true; // add pessimistic vkey route await expect( @@ -140,16 +140,16 @@ describe("AggLayerGateway tests", () => { // check onlyRole await expect(aggLayerGatewayContract.freezePessimisticVKeyRoute(selector)) .to.be.revertedWithCustomError(aggLayerGatewayContract, "AccessControlUnauthorizedAccount") - .withArgs(deployer.address, AGGLAYER_FREEZE_ROUTE_ROLE); + .withArgs(deployer.address, AL_FREEZE_PP_ROUTE_ROLE); - // grantRole AGGLAYER_FREEZE_ROUTE_ROLE --> aggLayerAdmin + // grantRole AL_FREEZE_PP_ROUTE_ROLE --> aggLayerAdmin await expect( - aggLayerGatewayContract.connect(defaultAdmin).grantRole(AGGLAYER_FREEZE_ROUTE_ROLE, aggLayerAdmin.address) + aggLayerGatewayContract.connect(defaultAdmin).grantRole(AL_FREEZE_PP_ROUTE_ROLE, aggLayerAdmin.address) ) .to.emit(aggLayerGatewayContract, "RoleGranted") - .withArgs(AGGLAYER_FREEZE_ROUTE_ROLE, aggLayerAdmin.address, defaultAdmin.address); + .withArgs(AL_FREEZE_PP_ROUTE_ROLE, aggLayerAdmin.address, defaultAdmin.address); - expect(await aggLayerGatewayContract.hasRole(AGGLAYER_FREEZE_ROUTE_ROLE, aggLayerAdmin.address)).to.be.true; + expect(await aggLayerGatewayContract.hasRole(AL_FREEZE_PP_ROUTE_ROLE, aggLayerAdmin.address)).to.be.true; // check RouteNotFound await expect(aggLayerGatewayContract.connect(aggLayerAdmin).freezePessimisticVKeyRoute(testSelector)) @@ -159,11 +159,11 @@ describe("AggLayerGateway tests", () => { // check RouteFrozen await expect(aggLayerGatewayContract.connect(aggLayerAdmin).freezePessimisticVKeyRoute(selector)) .to.emit(aggLayerGatewayContract, "RouteFrozen") - .withArgs(selector, verifierContract.target); + .withArgs(selector, verifierContract.target, pessimisticVKey); // check RouteIsFrozen await expect(aggLayerGatewayContract.connect(aggLayerAdmin).freezePessimisticVKeyRoute(selector)) - .to.be.revertedWithCustomError(aggLayerGatewayContract, "RouteIsFrozen") + .to.be.revertedWithCustomError(aggLayerGatewayContract, "RouteIsAlreadyFrozen") .withArgs(selector); }); @@ -237,7 +237,7 @@ describe("AggLayerGateway tests", () => { aggLayerGatewayContract.connect(aggLayerAdmin).updateDefaultAggchainVKey(selector, newPessimisticVKey) ) .to.emit(aggLayerGatewayContract, "UpdateDefaultAggchainVKey") - .withArgs(selector, newPessimisticVKey); + .withArgs(selector, pessimisticVKey, newPessimisticVKey); // check getDefaultAggchainVKey --> newPessimisticVKey expect(await aggLayerGatewayContract.getDefaultAggchainVKey(selector)).to.be.equal(newPessimisticVKey); @@ -250,14 +250,14 @@ describe("AggLayerGateway tests", () => { .to.be.revertedWithCustomError(aggLayerGatewayContract, "RouteNotFound") .withArgs(selector); - // grantRole AGGLAYER_ADD_ROUTE_ROLE --> aggLayerAdmin + // grantRole AL_ADD_PP_ROUTE_ROLE --> aggLayerAdmin await expect( - aggLayerGatewayContract.connect(defaultAdmin).grantRole(AGGLAYER_ADD_ROUTE_ROLE, aggLayerAdmin.address) + aggLayerGatewayContract.connect(defaultAdmin).grantRole(AL_ADD_PP_ROUTE_ROLE, aggLayerAdmin.address) ) .to.emit(aggLayerGatewayContract, "RoleGranted") - .withArgs(AGGLAYER_ADD_ROUTE_ROLE, aggLayerAdmin.address, defaultAdmin.address); + .withArgs(AL_ADD_PP_ROUTE_ROLE, aggLayerAdmin.address, defaultAdmin.address); - expect(await aggLayerGatewayContract.hasRole(AGGLAYER_ADD_ROUTE_ROLE, aggLayerAdmin.address)).to.be.true; + expect(await aggLayerGatewayContract.hasRole(AL_ADD_PP_ROUTE_ROLE, aggLayerAdmin.address)).to.be.true; await expect( aggLayerGatewayContract @@ -270,21 +270,21 @@ describe("AggLayerGateway tests", () => { // check verifyProof await expect(aggLayerGatewayContract.verifyPessimisticProof(input["public-values"], input["proof"])); - // grantRole AGGLAYER_FREEZE_ROUTE_ROLE --> aggLayerAdmin + // grantRole AL_FREEZE_PP_ROUTE_ROLE --> aggLayerAdmin await expect( - aggLayerGatewayContract.connect(defaultAdmin).grantRole(AGGLAYER_FREEZE_ROUTE_ROLE, aggLayerAdmin.address) + aggLayerGatewayContract.connect(defaultAdmin).grantRole(AL_FREEZE_PP_ROUTE_ROLE, aggLayerAdmin.address) ) .to.emit(aggLayerGatewayContract, "RoleGranted") - .withArgs(AGGLAYER_FREEZE_ROUTE_ROLE, aggLayerAdmin.address, defaultAdmin.address); + .withArgs(AL_FREEZE_PP_ROUTE_ROLE, aggLayerAdmin.address, defaultAdmin.address); - expect(await aggLayerGatewayContract.hasRole(AGGLAYER_FREEZE_ROUTE_ROLE, aggLayerAdmin.address)).to.be.true; + expect(await aggLayerGatewayContract.hasRole(AL_FREEZE_PP_ROUTE_ROLE, aggLayerAdmin.address)).to.be.true; // frozen route await expect(aggLayerGatewayContract.connect(aggLayerAdmin).freezePessimisticVKeyRoute(selector)) .to.emit(aggLayerGatewayContract, "RouteFrozen") - .withArgs(selector, verifierContract.target); + .withArgs(selector, verifierContract.target, pessimisticVKey); - // check RouteFrozen + // check RouteIsFrozen await expect(aggLayerGatewayContract.verifyPessimisticProof(input["public-values"], input["proof"])) .to.be.revertedWithCustomError(aggLayerGatewayContract, "RouteIsFrozen") .withArgs(selector); diff --git a/test/contractsv2/AggchainECDSA.test.ts b/test/contractsv2/AggchainECDSA.test.ts index 31a98f183..cdebc99ea 100644 --- a/test/contractsv2/AggchainECDSA.test.ts +++ b/test/contractsv2/AggchainECDSA.test.ts @@ -35,18 +35,18 @@ describe("AggchainECDSA", () => { // aggchain variables let initializeBytesAggchain: string; let initializeBytesAggchainError: string; - const AGGCHAIN_TYPE_SELECTOR = "0x00"; + const AGGCHAIN_TYPE_SELECTOR = "0x0000"; const AGGCHAIN_TYPE = 1; const aggchainSelector = "0x22222222"; const newAggChainVKey = "0x2222222222222222222222222222222222222222222222222222222222222222"; const aggchainSelector2 = "0x11111111"; const newAggChainVKey2 = "0x1111111111111111111111111111111111111111111111111111111111111111"; - const aggchainVkeySelector = "0x1234"; + const aggchainVkeySelector = "0x1235"; const newStateRoot = "0x1122334455667788990011223344556677889900112233445566778899001122"; const useDefaultGateway = true; - const aggchainSelectors = ["0x12345678"]; - const ownedAggchainVKeys = ["0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"]; + const aggchainSelector3 = "0x1234"; + const ownedAggchainVKey = "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"; beforeEach("Deploy contract", async () => { upgrades.silenceWarnings(); @@ -65,8 +65,8 @@ describe("AggchainECDSA", () => { initializeBytesAggchain = utilsECDSA.encodeInitializeBytesAggchainECDSAv0( useDefaultGateway, - ownedAggchainVKeys, - aggchainSelectors, + ownedAggchainVKey, + aggchainSelector3, vKeyManager.address, admin.address, trustedSequencer.address, @@ -132,7 +132,7 @@ describe("AggchainECDSA", () => { await aggchainECDSAcontract.waitForDeployment(); }); - it("should check the initalized parameters", async () => { + it("should check the initialized parameters", async () => { // initialize zkEVM using non admin address await expect(aggchainECDSAcontract.initialize(initializeBytesAggchain)).to.be.revertedWithCustomError( aggchainECDSAcontract, @@ -150,7 +150,7 @@ describe("AggchainECDSA", () => { expect(await aggchainECDSAcontract.trustedSequencerURL()).to.be.equal(urlSequencer); expect(await aggchainECDSAcontract.networkName()).to.be.equal(networkName); expect(await aggchainECDSAcontract.gasTokenAddress()).to.be.equal(gasTokenAddress); - expect(await aggchainECDSAcontract.ownedAggchainVKeys(aggchainSelectors[0])).to.be.equal(ownedAggchainVKeys[0]); + expect(await aggchainECDSAcontract.ownedAggchainVKeys(`${aggchainSelector3}${AGGCHAIN_TYPE_SELECTOR.slice(2)}`)).to.be.equal(ownedAggchainVKey); // initialize again await expect( @@ -216,12 +216,11 @@ describe("AggchainECDSA", () => { ); await expect(aggchainECDSAcontract.connect(vKeyManager).disableUseDefaultGatewayFlag()) - .to.emit(aggchainECDSAcontract, "UpdateUseDefaultGatewayFlag") - .withArgs(false); + .to.emit(aggchainECDSAcontract, "DisableUseDefaultGatewayFlag"); await expect( aggchainECDSAcontract.connect(vKeyManager).disableUseDefaultGatewayFlag() - ).to.be.revertedWithCustomError(aggchainECDSAcontract, "UseDefaultGatewayAlreadySet"); + ).to.be.revertedWithCustomError(aggchainECDSAcontract, "UseDefaultGatewayAlreadyDisabled"); // enableUseDefaultGatewayFlag await expect(aggchainECDSAcontract.enableUseDefaultGatewayFlag()).to.be.revertedWithCustomError( @@ -230,12 +229,11 @@ describe("AggchainECDSA", () => { ); await expect(aggchainECDSAcontract.connect(vKeyManager).enableUseDefaultGatewayFlag()) - .to.emit(aggchainECDSAcontract, "UpdateUseDefaultGatewayFlag") - .withArgs(true); + .to.emit(aggchainECDSAcontract, "EnableUseDefaultGatewayFlag"); await expect( aggchainECDSAcontract.connect(vKeyManager).enableUseDefaultGatewayFlag() - ).to.be.revertedWithCustomError(aggchainECDSAcontract, "UseDefaultGatewayAlreadySet"); + ).to.be.revertedWithCustomError(aggchainECDSAcontract, "UseDefaultGatewayAlreadyEnabled"); // addOwnedAggchainVKey await expect( @@ -244,7 +242,7 @@ describe("AggchainECDSA", () => { await expect( aggchainECDSAcontract.connect(vKeyManager).addOwnedAggchainVKey(aggchainSelector, ethers.ZeroHash) - ).to.be.revertedWithCustomError(aggchainECDSAcontract, "InvalidAggchainVKey"); + ).to.be.revertedWithCustomError(aggchainECDSAcontract, "ZeroValueAggchainVKey"); await expect(aggchainECDSAcontract.connect(vKeyManager).addOwnedAggchainVKey(aggchainSelector, newAggChainVKey)) .to.emit(aggchainECDSAcontract, "AddAggchainVKey") @@ -267,14 +265,13 @@ describe("AggchainECDSA", () => { aggchainECDSAcontract.connect(vKeyManager).updateOwnedAggchainVKey(aggchainSelector, newAggChainVKey2) ) .to.emit(aggchainECDSAcontract, "UpdateAggchainVKey") - .withArgs(aggchainSelector, newAggChainVKey2); + .withArgs(aggchainSelector, newAggChainVKey, newAggChainVKey2); // getAggchainVKey useDefaultGateway === true expect(await aggchainECDSAcontract.getAggchainVKey(aggchainSelector)).to.be.equal(newAggChainVKey); await expect(aggchainECDSAcontract.connect(vKeyManager).disableUseDefaultGatewayFlag()) - .to.emit(aggchainECDSAcontract, "UpdateUseDefaultGatewayFlag") - .withArgs(false); + .to.emit(aggchainECDSAcontract, "DisableUseDefaultGatewayFlag"); // getAggchainVKey useDefaultGateway === false expect(await aggchainECDSAcontract.getAggchainVKey(aggchainSelector)).to.be.equal(newAggChainVKey2); @@ -297,7 +294,10 @@ describe("AggchainECDSA", () => { await expect(aggchainECDSAcontract.connect(admin).acceptVKeyManagerRole()) .to.emit(aggchainECDSAcontract, "AcceptVKeyManagerRole") - .withArgs(admin.address); + .withArgs(vKeyManager.address, admin.address); + + // Check now pendingVKeyManager address is zero + expect(await aggchainECDSAcontract.pendingVKeyManager()).to.be.equal(ethers.ZeroAddress); }); it("should check getAggchainHash", async () => { @@ -327,8 +327,7 @@ describe("AggchainECDSA", () => { // disable default gateway flag await expect(aggchainECDSAcontract.connect(vKeyManager).disableUseDefaultGatewayFlag()) - .to.emit(aggchainECDSAcontract, "UpdateUseDefaultGatewayFlag") - .withArgs(false); + .to.emit(aggchainECDSAcontract, "DisableUseDefaultGatewayFlag"); // getAggchainHash expect(await aggchainECDSAcontract.getAggchainHash(aggchainData)).to.be.equal(aggchainHash); @@ -352,7 +351,7 @@ describe("AggchainECDSA", () => { await expect( aggchainECDSAcontract.connect(rollupManagerSigner).onVerifyPessimistic(aggchainData, {gasPrice: 0}) ) - .to.emit(aggchainECDSAcontract, "OnVerifyPessimistic") + .to.emit(aggchainECDSAcontract, "OnVerifyPessimisticECDSA") .withArgs(newStateRoot); }); @@ -396,22 +395,18 @@ describe("AggchainECDSA", () => { initializeBytesAggchain = utilsECDSA.encodeInitializeBytesAggchainECDSAv1( useDefaultGateway, - ownedAggchainVKeys, - aggchainSelectors, + ownedAggchainVKey, + aggchainSelector3, vKeyManager.address ); initializeBytesAggchainError = utilsECDSA.encodeInitializeBytesAggchainECDSAv1( useDefaultGateway, - ownedAggchainVKeys, - [], + ownedAggchainVKey, + "0x0000", vKeyManager.address ); - await expect( - ppConsensusContract.connect(rollupManagerSigner).initialize(initializeBytesAggchainError, {gasPrice: 0}) - ).to.be.revertedWithCustomError(aggchainECDSAcontract, "OwnedAggchainVKeyLengthMismatch"); - await ppConsensusContract.connect(rollupManagerSigner).initialize(initializeBytesAggchain, {gasPrice: 0}); // check initializeBytesAggchain @@ -421,6 +416,6 @@ describe("AggchainECDSA", () => { expect(await ppConsensusContract.trustedSequencerURL()).to.be.equal(urlSequencer); expect(await ppConsensusContract.networkName()).to.be.equal(networkName); expect(await ppConsensusContract.gasTokenAddress()).to.be.equal(gasTokenAddress); - expect(await ppConsensusContract.ownedAggchainVKeys(aggchainSelectors[0])).to.be.equal(ownedAggchainVKeys[0]); + expect(await ppConsensusContract.ownedAggchainVKeys(`${aggchainSelector3}${AGGCHAIN_TYPE_SELECTOR.slice(2)}`)).to.be.equal(ownedAggchainVKey); }); }); diff --git a/test/contractsv2/BridgeL2GasTokenMappedSovereignChains.test.ts b/test/contractsv2/BridgeL2GasTokenMappedSovereignChains.test.ts index 12fdd8c4c..ab0dd6b6f 100644 --- a/test/contractsv2/BridgeL2GasTokenMappedSovereignChains.test.ts +++ b/test/contractsv2/BridgeL2GasTokenMappedSovereignChains.test.ts @@ -68,7 +68,7 @@ describe("SovereignChainBridge Gas tokens tests", () => { const BridgeL2SovereignChainFactory = await ethers.getContractFactory("BridgeL2SovereignChain"); sovereignChainBridgeContract = (await upgrades.deployProxy(BridgeL2SovereignChainFactory, [], { initializer: false, - unsafeAllow: ["constructor", "missing-initializer", "missing-initializer-call"], + unsafeAllow: ["constructor","missing-initializer","missing-initializer-call"], })) as unknown as BridgeL2SovereignChain; // deploy global exit root manager diff --git a/test/contractsv2/BridgeL2GasTokensSovereignChains.test.ts b/test/contractsv2/BridgeL2GasTokensSovereignChains.test.ts index 176ffdb02..1dffdfd36 100644 --- a/test/contractsv2/BridgeL2GasTokensSovereignChains.test.ts +++ b/test/contractsv2/BridgeL2GasTokensSovereignChains.test.ts @@ -68,7 +68,7 @@ describe("SovereignChainBridge Gas tokens tests", () => { const BridgeL2SovereignChainFactory = await ethers.getContractFactory("BridgeL2SovereignChain"); sovereignChainBridgeContract = (await upgrades.deployProxy(BridgeL2SovereignChainFactory, [], { initializer: false, - unsafeAllow: ["constructor", "missing-initializer", "missing-initializer-call"], + unsafeAllow: ["constructor","missing-initializer", "missing-initializer-call"], })) as unknown as BridgeL2SovereignChain; // deploy global exit root manager diff --git a/test/contractsv2/BridgeL2SovereignChainUpgradeAL.test.ts b/test/contractsv2/BridgeL2SovereignChainUpgradeAL.test.ts index a3efe68ba..188801c76 100644 --- a/test/contractsv2/BridgeL2SovereignChainUpgradeAL.test.ts +++ b/test/contractsv2/BridgeL2SovereignChainUpgradeAL.test.ts @@ -92,10 +92,6 @@ describe("BridgeL2SovereignChain Contract", () => { } )) as unknown as GlobalExitRootManagerL2SovereignChain; - // initialize GlobalExitRootManagerL2SovereignChain - await sovereignChainGlobalExitRootContract.initialize( - ethers.ZeroAddress, deployer.address - ); // cannot initialize bridgeV2 initializer from Sovereign bridge await expect( sovereignChainBridgeContract.initialize( diff --git a/test/contractsv2/PolygonRollupManager-Pessimistic.test.ts b/test/contractsv2/PolygonRollupManager-Pessimistic.test.ts index 1dc57227e..bca0ec9bd 100644 --- a/test/contractsv2/PolygonRollupManager-Pessimistic.test.ts +++ b/test/contractsv2/PolygonRollupManager-Pessimistic.test.ts @@ -1,21 +1,17 @@ /* eslint-disable no-plusplus, no-await-in-loop */ -import {expect} from "chai"; -import {ethers, upgrades} from "hardhat"; +import { expect } from "chai"; +import { ethers, upgrades } from "hardhat"; import { VerifierRollupHelperMock, ERC20PermitMock, PolygonRollupManagerMock, PolygonZkEVMGlobalExitRootV2, PolygonZkEVMBridgeV2, - PolygonZkEVMEtrog, - PolygonRollupBaseEtrog, - TokenWrapped, Address, - PolygonDataCommittee, PolygonPessimisticConsensus, } from "../../typechain-types"; -import {takeSnapshot, time} from "@nomicfoundation/hardhat-network-helpers"; -const {VerifierType, computeInputPessimisticBytes, computeConsensusHashEcdsa} = require("../../src/pessimistic-utils"); +const { VerifierType, computeInputPessimisticBytes, computeConsensusHashEcdsa } = require("../../src/pessimistic-utils"); +const { encodeInitializeBytesPessimistic } = require("../../src/utils-common-aggchain"); describe("Polygon Rollup Manager with Polygon Pessimistic Consensus", () => { let deployer: any; @@ -88,6 +84,14 @@ describe("Polygon Rollup Manager with Polygon Pessimistic Consensus", () => { if ((await upgrades.admin.getInstance()).target !== "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0") { firstDeployment = false; } + + // deploy AggLayerGateway + const AggLayerGatewayFactory = await ethers.getContractFactory("AggLayerGateway"); + const aggLayerGatewayContract = (await upgrades.deployProxy(AggLayerGatewayFactory, [], { + initializer: false, + unsafeAllow: ["constructor"], + })); + const nonceProxyBridge = Number(await ethers.provider.getTransactionCount(deployer.address)) + (firstDeployment ? 3 : 2); @@ -126,9 +130,9 @@ describe("Polygon Rollup Manager with Polygon Pessimistic Consensus", () => { polygonZkEVMGlobalExitRoot.target, polTokenContract.target, polygonZkEVMBridgeContract.target, - ethers.ZeroAddress, // aggLayerGateway + aggLayerGatewayContract.target, ], - unsafeAllow: ["constructor", "state-variable-immutable"], + unsafeAllow: ["constructor", "missing-initializer", "missing-initializer-call", "state-variable-immutable"], })) as unknown as PolygonRollupManagerMock; await rollupManagerContract.waitForDeployment(); @@ -344,30 +348,21 @@ describe("Polygon Rollup Manager with Polygon Pessimistic Consensus", () => { const nonExistentRollupID = 4; // Only admin can create new zkEVMs + const initializeBytesCustomChain = encodeInitializeBytesPessimistic(admin.address, trustedSequencer.address, gasTokenAddress, urlSequencer, networkName); await expect( - rollupManagerContract.createNewRollup( + rollupManagerContract.attachAggchainToAL( newRollupTypeID, chainID, - admin.address, - trustedSequencer.address, - gasTokenAddress, - urlSequencer, - networkName, - "0x" // initializeBytesCustomChain + initializeBytesCustomChain ) ).to.be.revertedWithCustomError(rollupManagerContract, "AddressDoNotHaveRequiredRole"); // rollupTypeID does not exist await expect( - rollupManagerContract.connect(admin).createNewRollup( + rollupManagerContract.connect(admin).attachAggchainToAL( nonExistentRollupID, chainID, - admin.address, - trustedSequencer.address, - gasTokenAddress, - urlSequencer, - networkName, - "0x" // initializeBytesCustomChain + initializeBytesCustomChain ) ).to.be.revertedWithCustomError(rollupManagerContract, "RollupTypeDoesNotExist"); @@ -379,15 +374,10 @@ describe("Polygon Rollup Manager with Polygon Pessimistic Consensus", () => { const newZkEVMContract = ppConsensusFactory.attach(newZKEVMAddress) as PolygonPessimisticConsensus; await expect( - rollupManagerContract.connect(admin).createNewRollup( + rollupManagerContract.connect(admin).attachAggchainToAL( newRollupTypeID, chainID, - admin.address, - trustedSequencer.address, - gasTokenAddress, - urlSequencer, - networkName, - "0x" // initializeBytesCustomChain + initializeBytesCustomChain ) ) .to.emit(rollupManagerContract, "CreateNewRollup") @@ -496,15 +486,12 @@ describe("Polygon Rollup Manager with Polygon Pessimistic Consensus", () => { const pessimisticRollupID = 1; // create new pessimistic - await rollupManagerContract.connect(admin).createNewRollup( + const initializeBytesCustomChain = encodeInitializeBytesPessimistic(admin.address, trustedSequencer.address, gasTokenAddress, urlSequencer, networkName); + + rollupManagerContract.connect(admin).attachAggchainToAL( newRollupTypeID, chainID, - admin.address, - trustedSequencer.address, - gasTokenAddress, - urlSequencer, - networkName, - "0x" // initializeBytesCustomChain + initializeBytesCustomChain ); // Create zkEVM implementation @@ -554,15 +541,10 @@ describe("Polygon Rollup Manager with Polygon Pessimistic Consensus", () => { ); // create new rollup - await rollupManagerContract.connect(admin).createNewRollup( + await rollupManagerContract.connect(admin).attachAggchainToAL( newRollupTypeID2, chainID2, - admin.address, - trustedSequencer.address, - gasTokenAddress, - urlSequencer, - networkName, - "0x" // initializeBytesCustomChain + initializeBytesCustomChain ); // get rollup data @@ -641,15 +623,11 @@ describe("Polygon Rollup Manager with Polygon Pessimistic Consensus", () => { nonce: 1, }); - await rollupManagerContract.connect(admin).createNewRollup( + const initializeBytesCustomChain = encodeInitializeBytesPessimistic(admin.address, trustedSequencer.address, gasTokenAddress, urlSequencer, networkName); + await rollupManagerContract.connect(admin).attachAggchainToAL( rollupTypeID, chainID, - admin.address, - trustedSequencer.address, - gasTokenAddress, - urlSequencer, - networkName, - "0x" // initializeBytesCustomChain + initializeBytesCustomChain ); // Try to add a new rollup type @@ -740,15 +718,12 @@ describe("Polygon Rollup Manager with Polygon Pessimistic Consensus", () => { const pessimisticRollupID = 1; // create new pessimistic - await rollupManagerContract.connect(admin).createNewRollup( + const initializeBytesCustomChain = encodeInitializeBytesPessimistic(admin.address, trustedSequencer.address, gasTokenAddress, urlSequencer, networkName); + + await rollupManagerContract.connect(admin).attachAggchainToAL( rollupTypeID, chainID, - admin.address, - trustedSequencer.address, - gasTokenAddress, - urlSequencer, - networkName, - "0x" // initializeBytesCustomChain + initializeBytesCustomChain ); // get rollup data @@ -805,15 +780,11 @@ describe("Polygon Rollup Manager with Polygon Pessimistic Consensus", () => { nonce: 1, }); - await rollupManagerContract.connect(admin).createNewRollup( + const initializeBytesCustomChain = encodeInitializeBytesPessimistic(admin.address, trustedSequencer.address, gasTokenAddress, urlSequencer, networkName); + await rollupManagerContract.connect(admin).attachAggchainToAL( rollupTypeID, chainID, - admin.address, - trustedSequencer.address, - gasTokenAddress, - urlSequencer, - networkName, - "0x" // initializeBytesCustomChain + initializeBytesCustomChain ); // select unexistent global exit root @@ -994,15 +965,11 @@ describe("Polygon Rollup Manager with Polygon Pessimistic Consensus", () => { ); // create new rollup - await rollupManagerContract.connect(admin).createNewRollup( + const initializeBytesCustomChain = encodeInitializeBytesPessimistic(admin.address, trustedSequencer.address, gasTokenAddress, urlSequencer, networkName); + await rollupManagerContract.connect(admin).attachAggchainToAL( newRollupTypeID, chainID, - admin.address, - trustedSequencer.address, - gasTokenAddress, - urlSequencer, - networkName, - "0x" // initializeBytesCustomChain + initializeBytesCustomChain ); // try to verify diff --git a/test/contractsv2/PolygonRollupManager.test.ts b/test/contractsv2/PolygonRollupManager.test.ts index a92eb28bc..cc4ab0690 100644 --- a/test/contractsv2/PolygonRollupManager.test.ts +++ b/test/contractsv2/PolygonRollupManager.test.ts @@ -1,6 +1,6 @@ /* eslint-disable no-plusplus, no-await-in-loop */ -import {expect} from "chai"; -import {ethers, upgrades} from "hardhat"; +import { expect } from "chai"; +import { ethers, upgrades } from "hardhat"; import { VerifierRollupHelperMock, ERC20PermitMock, @@ -13,13 +13,14 @@ import { Address, PolygonDataCommittee, } from "../../typechain-types"; -import {takeSnapshot, time} from "@nomicfoundation/hardhat-network-helpers"; -import {processorUtils, contractUtils, MTBridge, mtBridgeUtils, utils} from "@0xpolygonhermez/zkevm-commonjs"; +import { takeSnapshot, time } from "@nomicfoundation/hardhat-network-helpers"; +import { processorUtils, contractUtils, MTBridge, mtBridgeUtils, utils } from "@0xpolygonhermez/zkevm-commonjs"; type BatchDataStructEtrog = PolygonRollupBaseEtrog.BatchDataStruct; const MerkleTreeBridge = MTBridge; -const {verifyMerkleProof, getLeafValue} = mtBridgeUtils; +const { verifyMerkleProof, getLeafValue } = mtBridgeUtils; +const { encodeInitializeBytesPessimistic } = require("../../src/utils-common-aggchain"); function calculateGlobalExitRoot(mainnetExitRoot: any, rollupExitRoot: any) { return ethers.solidityPackedKeccak256(["bytes32", "bytes32"], [mainnetExitRoot, rollupExitRoot]); @@ -104,6 +105,14 @@ describe("Polygon Rollup Manager", () => { if ((await upgrades.admin.getInstance()).target !== "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0") { firstDeployment = false; } + + // deploy AggLayerGateway + const AggLayerGatewayFactory = await ethers.getContractFactory("AggLayerGateway"); + const aggLayerGatewayContract = (await upgrades.deployProxy(AggLayerGatewayFactory, [], { + initializer: false, + unsafeAllow: ["constructor"], + })) + const nonceProxyBridge = Number(await ethers.provider.getTransactionCount(deployer.address)) + (firstDeployment ? 3 : 2); @@ -118,7 +127,7 @@ describe("Polygon Rollup Manager", () => { nonce: nonceProxyZkevm, }); firstDeployment = false; - + // deploy globalExitRoot const PolygonZkEVMGlobalExitRootFactory = await ethers.getContractFactory("PolygonZkEVMGlobalExitRootV2"); polygonZkEVMGlobalExitRoot = await upgrades.deployProxy(PolygonZkEVMGlobalExitRootFactory, [], { @@ -126,12 +135,12 @@ describe("Polygon Rollup Manager", () => { unsafeAllow: ["constructor", "state-variable-immutable"], }); - // deploy PolygonZkEVMBridge - const polygonZkEVMBridgeFactory = await ethers.getContractFactory("PolygonZkEVMBridgeV2"); - polygonZkEVMBridgeContract = await upgrades.deployProxy(polygonZkEVMBridgeFactory, [], { - initializer: false, - unsafeAllow: ["constructor", "missing-initializer"], - }); + // deploy PolygonZkEVMBridge + const polygonZkEVMBridgeFactory = await ethers.getContractFactory("PolygonZkEVMBridgeV2"); + polygonZkEVMBridgeContract = await upgrades.deployProxy(polygonZkEVMBridgeFactory, [], { + initializer: false, + unsafeAllow: ["constructor", "missing-initializer"], + }); // deploy PolygonRollupManager const PolygonRollupManagerFactory = await ethers.getContractFactory("PolygonRollupManagerMock"); @@ -142,9 +151,9 @@ describe("Polygon Rollup Manager", () => { polygonZkEVMGlobalExitRoot.target, polTokenContract.target, polygonZkEVMBridgeContract.target, - ethers.ZeroAddress, // aggLayerGateway + aggLayerGatewayContract.target, ], - unsafeAllow: ["constructor", "state-variable-immutable"], + unsafeAllow: ["constructor", "missing-initializer", "missing-initializer-call", "state-variable-immutable"], })) as unknown as PolygonRollupManagerMock; await rollupManagerContract.waitForDeployment(); @@ -378,44 +387,30 @@ describe("Polygon Rollup Manager", () => { expect(expectedRollupType).to.be.deep.equal(await rollupManagerContract.rollupTypeMap(newRollupTypeID)); // Only admin can create new zkEVMs + const initializeBytesCustomChain = encodeInitializeBytesPessimistic(admin.address, trustedSequencer.address, gasTokenAddress, urlSequencer, networkName); await expect( - rollupManagerContract.createNewRollup( + rollupManagerContract.attachAggchainToAL( newRollupTypeID, chainID, - admin.address, - trustedSequencer.address, - gasTokenAddress, - urlSequencer, - networkName, - "0x" // initializeBytesCustomChain + initializeBytesCustomChain ) ).to.be.revertedWithCustomError(rollupManagerContract, "AddressDoNotHaveRequiredRole"); // ChainId greater than 31 bits await expect( - rollupManagerContract.connect(admin).createNewRollup( + rollupManagerContract.connect(admin).attachAggchainToAL( newRollupTypeID, - 4294967296, // 2**32 - admin.address, - trustedSequencer.address, - gasTokenAddress, - urlSequencer, - networkName, - "0x" // initializeBytesCustomChain + 4294967296, // 2**32, + initializeBytesCustomChain ) ).to.be.revertedWithCustomError(rollupManagerContract, "ChainIDOutOfRange"); // UNexisting rollupType await expect( - rollupManagerContract.connect(admin).createNewRollup( + rollupManagerContract.connect(admin).attachAggchainToAL( 0, chainID, - admin.address, - trustedSequencer.address, - gasTokenAddress, - urlSequencer, - networkName, - "0x" // initializeBytesCustomChain + initializeBytesCustomChain ) ).to.be.revertedWithCustomError(rollupManagerContract, "RollupTypeDoesNotExist"); @@ -426,15 +421,10 @@ describe("Polygon Rollup Manager", () => { .withArgs(newRollupTypeID); await expect( - rollupManagerContract.connect(admin).createNewRollup( + rollupManagerContract.connect(admin).attachAggchainToAL( newRollupTypeID, chainID, - admin.address, - trustedSequencer.address, - gasTokenAddress, - urlSequencer, - networkName, - "0x" // initializeBytesCustomChain + initializeBytesCustomChain ) ).to.be.revertedWithCustomError(rollupManagerContract, "RollupTypeObsolete"); await snapshot2.restore(); @@ -449,15 +439,10 @@ describe("Polygon Rollup Manager", () => { const newSequencedBatch = 1; await expect( - rollupManagerContract.connect(admin).createNewRollup( + rollupManagerContract.connect(admin).attachAggchainToAL( newRollupTypeID, chainID, - admin.address, - trustedSequencer.address, - gasTokenAddress, - urlSequencer, - networkName, - "0x" // initializeBytesCustomChain + initializeBytesCustomChain ) ) .to.emit(rollupManagerContract, "CreateNewRollup") @@ -482,15 +467,10 @@ describe("Polygon Rollup Manager", () => { // Cannot create 2 chains with the same chainID await expect( - rollupManagerContract.connect(admin).createNewRollup( + rollupManagerContract.connect(admin).attachAggchainToAL( newRollupTypeID, chainID, - admin.address, - trustedSequencer.address, - gasTokenAddress, - urlSequencer, - networkName, - "0x" // initializeBytesCustomChain + initializeBytesCustomChain ) ).to.be.revertedWithCustomError(rollupManagerContract, "ChainIDAlreadyExist"); @@ -584,7 +564,7 @@ describe("Polygon Rollup Manager", () => { const zkEVMContractSigner = await ethers.getSigner(newZkEVMContract.target as any); await expect( - rollupManagerContract.connect(zkEVMContractSigner).onSequenceBatches(0, ethers.ZeroHash, {gasPrice: 0}) + rollupManagerContract.connect(zkEVMContractSigner).onSequenceBatches(0, ethers.ZeroHash, { gasPrice: 0 }) ).to.be.revertedWithCustomError(rollupManagerContract, "MustSequenceSomeBatch"); // Sequence Batches @@ -1384,44 +1364,31 @@ describe("Polygon Rollup Manager", () => { expect(expectedRollupType).to.be.deep.equal(await rollupManagerContract.rollupTypeMap(newRollupTypeID)); // Only admin can create new zkEVMs + const initializeBytesCustomChain = encodeInitializeBytesPessimistic(admin.address, trustedSequencer.address, gasTokenAddress, urlSequencer, networkName); await expect( - rollupManagerContract.createNewRollup( + rollupManagerContract.attachAggchainToAL( newRollupTypeID, chainID, - admin.address, - trustedSequencer.address, - gasTokenAddress, - urlSequencer, - networkName, - "0x" // initializeBytesCustomChain + initializeBytesCustomChain ) ).to.be.revertedWithCustomError(rollupManagerContract, "AddressDoNotHaveRequiredRole"); // ChainId greater than 31 bits await expect( - rollupManagerContract.connect(admin).createNewRollup( + rollupManagerContract.connect(admin).attachAggchainToAL( newRollupTypeID, - 4294967296, // 2**32 - admin.address, - trustedSequencer.address, - gasTokenAddress, - urlSequencer, - networkName, - "0x" // initializeBytesCustomChain + 4294967296, // 2**32, + initializeBytesCustomChain ) + ).to.be.revertedWithCustomError(rollupManagerContract, "ChainIDOutOfRange"); // Unexisting rollupType await expect( - rollupManagerContract.connect(admin).createNewRollup( + rollupManagerContract.connect(admin).attachAggchainToAL( 0, chainID, - admin.address, - trustedSequencer.address, - gasTokenAddress, - urlSequencer, - networkName, - "0x" // initializeBytesCustomChain + initializeBytesCustomChain ) ).to.be.revertedWithCustomError(rollupManagerContract, "RollupTypeDoesNotExist"); @@ -1432,15 +1399,10 @@ describe("Polygon Rollup Manager", () => { .withArgs(newRollupTypeID); await expect( - rollupManagerContract.connect(admin).createNewRollup( + rollupManagerContract.connect(admin).attachAggchainToAL( newRollupTypeID, chainID, - admin.address, - trustedSequencer.address, - gasTokenAddress, - urlSequencer, - networkName, - "0x" // initializeBytesCustomChain + initializeBytesCustomChain ) ).to.be.revertedWithCustomError(rollupManagerContract, "RollupTypeObsolete"); await snapshot2.restore(); @@ -1455,15 +1417,10 @@ describe("Polygon Rollup Manager", () => { const newSequencedBatch = 1; await expect( - rollupManagerContract.connect(admin).createNewRollup( + rollupManagerContract.connect(admin).attachAggchainToAL( newRollupTypeID, chainID, - admin.address, - trustedSequencer.address, - gasTokenAddress, - urlSequencer, - networkName, - "0x" // initializeBytesCustomChain + initializeBytesCustomChain ) ) .to.emit(rollupManagerContract, "CreateNewRollup") @@ -1484,15 +1441,10 @@ describe("Polygon Rollup Manager", () => { // Cannot create 2 chains with the same chainID await expect( - rollupManagerContract.connect(admin).createNewRollup( + rollupManagerContract.connect(admin).attachAggchainToAL( newRollupTypeID, chainID, - admin.address, - trustedSequencer.address, - gasTokenAddress, - urlSequencer, - networkName, - "0x" // initializeBytesCustomChain + initializeBytesCustomChain ) ).to.be.revertedWithCustomError(rollupManagerContract, "ChainIDAlreadyExist"); @@ -2013,44 +1965,30 @@ describe("Polygon Rollup Manager", () => { // Create a // Only admin can create new zkEVMs + const initializeBytesCustomChain = encodeInitializeBytesPessimistic(admin.address, trustedSequencer.address, gasTokenAddress, urlSequencer, networkName); await expect( - rollupManagerContract.createNewRollup( + rollupManagerContract.attachAggchainToAL( newRollupTypeID, chainID, - admin.address, - trustedSequencer.address, - gasTokenAddress, - urlSequencer, - networkName, - "0x" // initializeBytesCustomChain + initializeBytesCustomChain ) ).to.be.revertedWithCustomError(rollupManagerContract, "AddressDoNotHaveRequiredRole"); // ChainId greater than 31 bits await expect( - rollupManagerContract.connect(admin).createNewRollup( + rollupManagerContract.connect(admin).attachAggchainToAL( newRollupTypeID, 4294967296, // 2**32 - admin.address, - trustedSequencer.address, - gasTokenAddress, - urlSequencer, - networkName, - "0x" // initializeBytesCustomChain + initializeBytesCustomChain ) ).to.be.revertedWithCustomError(rollupManagerContract, "ChainIDOutOfRange"); // Unexisting rollupType await expect( - rollupManagerContract.connect(admin).createNewRollup( + rollupManagerContract.connect(admin).attachAggchainToAL( 0, chainID, - admin.address, - trustedSequencer.address, - gasTokenAddress, - urlSequencer, - networkName, - "0x" // initializeBytesCustomChain + initializeBytesCustomChain ) ).to.be.revertedWithCustomError(rollupManagerContract, "RollupTypeDoesNotExist"); @@ -2061,15 +1999,10 @@ describe("Polygon Rollup Manager", () => { .withArgs(newRollupTypeID); await expect( - rollupManagerContract.connect(admin).createNewRollup( + rollupManagerContract.connect(admin).attachAggchainToAL( newRollupTypeID, chainID, - admin.address, - trustedSequencer.address, - gasTokenAddress, - urlSequencer, - networkName, - "0x" // initializeBytesCustomChain + initializeBytesCustomChain ) ).to.be.revertedWithCustomError(rollupManagerContract, "RollupTypeObsolete"); await snapshot2.restore(); @@ -2084,15 +2017,10 @@ describe("Polygon Rollup Manager", () => { const newSequencedBatch = 1; await expect( - rollupManagerContract.connect(admin).createNewRollup( + rollupManagerContract.connect(admin).attachAggchainToAL( newRollupTypeID, chainID, - admin.address, - trustedSequencer.address, - gasTokenAddress, - urlSequencer, - networkName, - "0x" // initializeBytesCustomChain + initializeBytesCustomChain ) ) .to.emit(rollupManagerContract, "CreateNewRollup") @@ -2113,15 +2041,10 @@ describe("Polygon Rollup Manager", () => { // Cannot create 2 chains with the same chainID await expect( - rollupManagerContract.connect(admin).createNewRollup( + rollupManagerContract.connect(admin).attachAggchainToAL( newRollupTypeID, chainID, - admin.address, - trustedSequencer.address, - gasTokenAddress, - urlSequencer, - networkName, - "0x" // initializeBytesCustomChain + initializeBytesCustomChain ) ).to.be.revertedWithCustomError(rollupManagerContract, "ChainIDAlreadyExist"); @@ -2782,16 +2705,13 @@ describe("Polygon Rollup Manager", () => { const newZkEVMContract = PolygonValidiumPreviousVersion.attach(newZKEVMAddress) as PolygonValidiumEtrogPrevious; const newSequencedBatch = 1; + const initializeBytesCustomChain = encodeInitializeBytesPessimistic(admin.address, trustedSequencer.address, gasTokenAddress, urlSequencer, networkName); + await expect( - rollupManagerContract.connect(admin).createNewRollup( + rollupManagerContract.connect(admin).attachAggchainToAL( newRollupTypeID, chainID, - admin.address, - trustedSequencer.address, - gasTokenAddress, - urlSequencer, - networkName, - "0x" // initializeBytesCustomChain + initializeBytesCustomChain ) ) .to.emit(rollupManagerContract, "CreateNewRollup") diff --git a/test/contractsv2/PolygonRollupManagerAL.test.ts b/test/contractsv2/PolygonRollupManagerAL.test.ts index 8ed5d4631..78703cf43 100644 --- a/test/contractsv2/PolygonRollupManagerAL.test.ts +++ b/test/contractsv2/PolygonRollupManagerAL.test.ts @@ -19,6 +19,8 @@ const { encodeInitializeBytesAggchainECDSAv0, } = require("../../src/utils-aggchain-ECDSA"); const {getFinalAggchainVKeySelectorFromType} = require("../../src/utils-common-aggchain"); +const {encodeInitializeBytesPessimistic} = require("../../src/utils-common-aggchain"); +const {NO_ADDRESS} = require("../../src/constants"); describe("Polygon rollup manager aggregation layer v3", () => { // SIGNERS @@ -52,7 +54,7 @@ describe("Polygon rollup manager aggregation layer v3", () => { const NETWORK_ID_MAINNET = 0; // AGGLAYER CONSTANTS const AGGCHAIN_DEFAULT_VKEY_ROLE = ethers.id("AGGCHAIN_DEFAULT_VKEY_ROLE"); - const AGGLAYER_ADD_ROUTE_ROLE = ethers.id("AGGLAYER_ADD_ROUTE_ROLE"); + const AL_ADD_PP_ROUTE_ROLE = ethers.id("AL_ADD_PP_ROUTE_ROLE"); const PESSIMISTIC_SELECTOR = "0x00000001"; // AGGCHAIN CONSTANTS const AGGCHAIN_VKEY_SELECTOR = "0x0001"; @@ -107,7 +109,7 @@ describe("Polygon rollup manager aggregation layer v3", () => { freezePPRoute.address ); // Grant role to agglayer admin - await aggLayerGatewayContract.connect(admin).grantRole(AGGLAYER_ADD_ROUTE_ROLE, aggLayerAdmin.address); + await aggLayerGatewayContract.connect(admin).grantRole(AL_ADD_PP_ROUTE_ROLE, aggLayerAdmin.address); // Add permission to add default aggchain verification key await aggLayerGatewayContract.connect(admin).grantRole(AGGCHAIN_DEFAULT_VKEY_ROLE, aggLayerAdmin.address); expect(await aggLayerGatewayContract.hasRole(AGGCHAIN_DEFAULT_VKEY_ROLE, aggLayerAdmin.address)).to.be.true; @@ -266,7 +268,7 @@ describe("Polygon rollup manager aggregation layer v3", () => { ); await expect(aggchainECDSAContract.connect(admin).acceptVKeyManagerRole()) .to.emit(aggchainECDSAContract, "AcceptVKeyManagerRole") - .withArgs(admin.address); + .withArgs(vKeyManager.address, admin.address); }); it("should getAggchainHash using default gateway", async () => { // Add default aggchain verification key @@ -406,16 +408,12 @@ describe("Polygon rollup manager aggregation layer v3", () => { const urlSequencer = "https://pessimistic:8545"; const networkName = "testPessimistic"; const pessimisticRollupID = 1; // Already aggchainECDSA rollup created created + const initializeBytesPessimistic = encodeInitializeBytesPessimistic(admin.address, trustedSequencer.address, gasTokenAddress, urlSequencer, networkName); await expect( - rollupManagerContract.connect(admin).createNewRollup( + rollupManagerContract.connect(admin).attachAggchainToAL( pessimisticRollupTypeID, chainID, - admin.address, - trustedSequencer.address, - gasTokenAddress, - urlSequencer, - networkName, - "0x" // initializeBytesCustomChain + initializeBytesPessimistic ) ) .to.emit(rollupManagerContract, "CreateNewRollup") @@ -471,8 +469,8 @@ describe("Polygon rollup manager aggregation layer v3", () => { const aggchainECDSAFactory = await ethers.getContractFactory("AggchainECDSA"); const initializeBytesCustomChain = encodeInitializeBytesAggchainECDSAv1( true, //useDefaultGateway - [], //ownedAggchainVKeys - [], // aggchainVkeySelector + ethers.ZeroHash, //ownedAggchainVKey + "0x0000", // aggchainVkeySelector vKeyManager.address ); const upgradeData = aggchainECDSAFactory.interface.encodeFunctionData("initialize(bytes)", [ @@ -491,9 +489,28 @@ describe("Polygon rollup manager aggregation layer v3", () => { // Create a new pessimistic rollup type await createPessimisticRollupType(); - // Check new rollup data + // Check rollup data deserialized const resRollupData = await rollupManagerContract.rollupIDToRollupDataDeserialized(pessimisticRollupID); const expectedRollupData = [ + ECDSARollupContract.target, + chainID, + ethers.ZeroAddress, // newVerifier address, for ECDSA is zero because it is internally replaced by aggLayerGateway address + 0, // newForkID + newLER, // lastLocalExitRoot + 0, // lastBatchSequenced + 0, // lastBatchVerified + 0, // _legacyLastPendingState + 0, // _legacyLastPendingStateConsolidated + 0, // lastVerifiedBatchBeforeUpgrade + rollupTypeECDSAId, + VerifierType.ALGateway + ]; + + expect(expectedRollupData).to.be.deep.equal(resRollupData); + + // Check rollup data deserialized V2 + const resRollupDataV2 = await rollupManagerContract.rollupIDToRollupDataV2Deserialized(pessimisticRollupID); + const expectedRollupDataV2 = [ ECDSARollupContract.target, chainID, ethers.ZeroAddress, // newVerifier address, for ECDSA is zero because it is internally replaced by aggLayerGateway address @@ -508,7 +525,7 @@ describe("Polygon rollup manager aggregation layer v3", () => { ethers.ZeroHash, // newProgramVKey ]; - expect(expectedRollupData).to.be.deep.equal(resRollupData); + expect(expectedRollupDataV2).to.be.deep.equal(resRollupDataV2); // Add route with verifier to the gateway const randomPessimisticVKey = computeRandomBytes(32); @@ -560,7 +577,7 @@ describe("Polygon rollup manager aggregation layer v3", () => { ) ) .to.emit(rollupManagerContract, "VerifyBatchesTrustedAggregator") - .to.emit(ECDSARollupContract, "OnVerifyPessimistic") + .to.emit(ECDSARollupContract, "OnVerifyPessimisticECDSA") .withArgs(randomNewStateRoot); }); @@ -613,16 +630,12 @@ describe("Polygon rollup manager aggregation layer v3", () => { nonce: rollupManagerNonce, }); // Create pessimistic rollup - await rollupManagerContract.connect(admin).createNewRollup( + const initializeBytesCustomChain = encodeInitializeBytesPessimistic(admin.address, trustedSequencer.address, ethers.ZeroAddress, "", ""); + await rollupManagerContract.connect(admin).attachAggchainToAL( pessimisticRollupTypeID2, 2, // chainID - admin.address, - trustedSequencer.address, - ethers.ZeroAddress, // gas token address - "", // sequencer url - "", // network name - "0x" // initializeBytesCustomChain - ); + initializeBytesCustomChain + ) expect(await rollupManagerContract.rollupAddressToID(pessimisticRollupAddress)).to.be.equal(1); // Try to upgrade from rollupType1 to rollupType2 should revert (lowest rollup typed id) @@ -715,8 +728,8 @@ describe("Polygon rollup manager aggregation layer v3", () => { async function createECDSARollup(rollupTypeIdECDSA: number) { const initializeBytesCustomChain = encodeInitializeBytesAggchainECDSAv0( true, // useDefaultGateway - [], // ownedAggchainVKeys - [], //aggchainVKeysSelectors + ethers.ZeroHash, // ownedAggchainVKeys + "0x0000", //aggchainVKeysSelectors vKeyManager.address, admin.address, trustedSequencer.address, @@ -731,15 +744,10 @@ describe("Polygon rollup manager aggregation layer v3", () => { nonce: rollupManagerNonce, }); await expect( - rollupManagerContract.connect(admin).createNewRollup( + rollupManagerContract.connect(admin).attachAggchainToAL( rollupTypeIdECDSA, // rollupTypeID 1001, // chainID - admin.address, - trustedSequencer.address, - ethers.ZeroAddress, // gas token address - "", // sequencer url - "", // network name - initializeBytesCustomChain // initialize bytes custom chain + initializeBytesCustomChain ) ) .to.emit(rollupManagerContract, "CreateNewRollup") @@ -748,7 +756,7 @@ describe("Polygon rollup manager aggregation layer v3", () => { rollupTypeIdECDSA, // rollupType ID precomputedAggchainECDSAAddress, 1001, // chainID - ethers.ZeroAddress // gasTokenAddress + NO_ADDRESS // gasTokenAddress ); return [Number(rollupsCount) + 1, precomputedAggchainECDSAAddress]; } diff --git a/test/contractsv2/PolygonRollupManagerALUpgrade.test.ts b/test/contractsv2/PolygonRollupManagerALUpgrade.test.ts index 11eef984c..3db375cad 100644 --- a/test/contractsv2/PolygonRollupManagerALUpgrade.test.ts +++ b/test/contractsv2/PolygonRollupManagerALUpgrade.test.ts @@ -1,5 +1,5 @@ -import {expect} from "chai"; -import {ethers, upgrades} from "hardhat"; +import { expect } from "chai"; +import { ethers, upgrades } from "hardhat"; import { AggLayerGateway, ERC20PermitMock, @@ -10,15 +10,17 @@ import { VerifierRollupHelperMock, PolygonPessimisticConsensus, } from "../../typechain-types"; -const {VerifierType, computeRandomBytes} = require("../../src/pessimistic-utils"); +const { VerifierType, computeRandomBytes } = require("../../src/pessimistic-utils"); const { AGGCHAIN_TYPE_SELECTOR_ECDSA, encodeAggchainDataECDSA, encodeInitializeBytesAggchainECDSAv1, encodeInitializeBytesAggchainECDSAv0, } = require("../../src/utils-aggchain-ECDSA"); -const {AggchainType} = require("../../src/utils-common-aggchain"); -const {getFinalAggchainVKeySelectorFromType} = require("../../src/utils-common-aggchain"); +const { AggchainType } = require("../../src/utils-common-aggchain"); +const { getFinalAggchainVKeySelectorFromType } = require("../../src/utils-common-aggchain"); +const { encodeInitializeBytesPessimistic } = require("../../src/utils-common-aggchain"); +const {NO_ADDRESS} = require("../../src/constants"); describe("Polygon rollup manager aggregation layer v3 UPGRADED", () => { // SIGNERS @@ -52,7 +54,7 @@ describe("Polygon rollup manager aggregation layer v3 UPGRADED", () => { const NETWORK_ID_MAINNET = 0; // AGGLAYER CONSTANTS const AGGCHAIN_DEFAULT_VKEY_ROLE = ethers.id("AGGCHAIN_DEFAULT_VKEY_ROLE"); - const AGGLAYER_ADD_ROUTE_ROLE = ethers.id("AGGLAYER_ADD_ROUTE_ROLE"); + const AL_ADD_PP_ROUTE_ROLE = ethers.id("AL_ADD_PP_ROUTE_ROLE"); const PESSIMISTIC_SELECTOR = "0x00000001"; // AGGCHAIN CONSTANTS const AGGCHAIN_VKEY_SELECTOR = "0x0001"; @@ -106,7 +108,7 @@ describe("Polygon rollup manager aggregation layer v3 UPGRADED", () => { freezePPRoute.address ); // Grant role to agglayer admin - await aggLayerGatewayContract.connect(admin).grantRole(AGGLAYER_ADD_ROUTE_ROLE, aggLayerAdmin.address); + await aggLayerGatewayContract.connect(admin).grantRole(AL_ADD_PP_ROUTE_ROLE, aggLayerAdmin.address); // Add permission to add default aggchain verification key await aggLayerGatewayContract.connect(admin).grantRole(AGGCHAIN_DEFAULT_VKEY_ROLE, aggLayerAdmin.address); expect(await aggLayerGatewayContract.hasRole(AGGCHAIN_DEFAULT_VKEY_ROLE, aggLayerAdmin.address)).to.be.true; @@ -400,16 +402,12 @@ describe("Polygon rollup manager aggregation layer v3 UPGRADED", () => { const urlSequencer = "https://pessimistic:8545"; const networkName = "testPessimistic"; const pessimisticRollupID = 1; // Already aggchainECDSA rollup created created + const initializeBytesPessimistic = encodeInitializeBytesPessimistic(admin.address, trustedSequencer.address, gasTokenAddress, urlSequencer, networkName); await expect( - rollupManagerContract.connect(admin).createNewRollup( + rollupManagerContract.connect(admin).attachAggchainToAL( pessimisticRollupTypeID, chainID, - admin.address, - trustedSequencer.address, - gasTokenAddress, - urlSequencer, - networkName, - "0x" // initializeBytesCustomChain + initializeBytesPessimistic ) ) .to.emit(rollupManagerContract, "CreateNewRollup") @@ -465,8 +463,8 @@ describe("Polygon rollup manager aggregation layer v3 UPGRADED", () => { const aggchainECDSAFactory = await ethers.getContractFactory("AggchainECDSA"); const initializeBytesCustomChain = encodeInitializeBytesAggchainECDSAv1( true, //useDefaultGateway - [], //ownedAggchainVKeys - [], // aggchainVkeySelector + ethers.ZeroHash, //ownedAggchainVKeys + "0x0000", // aggchainVkeySelector vKeyManager.address ); const upgradeData = aggchainECDSAFactory.interface.encodeFunctionData("initialize(bytes)", [ @@ -486,7 +484,7 @@ describe("Polygon rollup manager aggregation layer v3 UPGRADED", () => { await createPessimisticRollupType(); // Check new rollup data - const resRollupData = await rollupManagerContract.rollupIDToRollupDataDeserialized(pessimisticRollupID); + const resRollupData = await rollupManagerContract.rollupIDToRollupDataV2Deserialized(pessimisticRollupID); const expectedRollupData = [ ECDSARollupContract.target, chainID, @@ -554,7 +552,7 @@ describe("Polygon rollup manager aggregation layer v3 UPGRADED", () => { ) ) .to.emit(rollupManagerContract, "VerifyBatchesTrustedAggregator") - .to.emit(ECDSARollupContract, "OnVerifyPessimistic") + .to.emit(ECDSARollupContract, "OnVerifyPessimisticECDSA") .withArgs(randomNewStateRoot); }); @@ -607,15 +605,11 @@ describe("Polygon rollup manager aggregation layer v3 UPGRADED", () => { nonce: rollupManagerNonce, }); // Create pessimistic rollup - await rollupManagerContract.connect(admin).createNewRollup( + const initializeBytesCustomChain = encodeInitializeBytesPessimistic(admin.address, trustedSequencer.address, ethers.ZeroAddress, "", ""); + await rollupManagerContract.connect(admin).attachAggchainToAL( pessimisticRollupTypeID2, 2, // chainID - admin.address, - trustedSequencer.address, - ethers.ZeroAddress, // gas token address - "", // sequencer url - "", // network name - "0x" // initializeBytesCustomChain + initializeBytesCustomChain ); expect(await rollupManagerContract.rollupAddressToID(pessimisticRollupAddress)).to.be.equal(1); @@ -709,8 +703,8 @@ describe("Polygon rollup manager aggregation layer v3 UPGRADED", () => { async function createECDSARollup(rollupTypeIdECDSA: number) { const initializeBytesCustomChain = encodeInitializeBytesAggchainECDSAv0( true, // useDefaultGateway - [], // ownedAggchainVKeys - [], //aggchainVKeysSelectors + ethers.ZeroHash, // ownedAggchainVKeys + "0x0000", //aggchainVKeysSelectors vKeyManager.address, admin.address, trustedSequencer.address, @@ -725,15 +719,10 @@ describe("Polygon rollup manager aggregation layer v3 UPGRADED", () => { nonce: rollupManagerNonce, }); await expect( - rollupManagerContract.connect(admin).createNewRollup( + rollupManagerContract.connect(admin).attachAggchainToAL( rollupTypeIdECDSA, // rollupTypeID 1001, // chainID - admin.address, - trustedSequencer.address, - ethers.ZeroAddress, // gas token address - "", // sequencer url - "", // network name - initializeBytesCustomChain // initialize bytes custom chain + initializeBytesCustomChain ) ) .to.emit(rollupManagerContract, "CreateNewRollup") @@ -742,7 +731,7 @@ describe("Polygon rollup manager aggregation layer v3 UPGRADED", () => { rollupTypeIdECDSA, // rollupType ID precomputedAggchainECDSAAddress, 1001, // chainID - ethers.ZeroAddress // gasTokenAddress + NO_ADDRESS // gasTokenAddress ); return [Number(rollupsCount) + 1, precomputedAggchainECDSAAddress]; } diff --git a/test/contractsv2/PolygonRollupManagerUpgrade.test.ts b/test/contractsv2/PolygonRollupManagerUpgrade.test.ts index 130a99d3c..e9e0b267d 100644 --- a/test/contractsv2/PolygonRollupManagerUpgrade.test.ts +++ b/test/contractsv2/PolygonRollupManagerUpgrade.test.ts @@ -13,10 +13,11 @@ import { Address, PolygonZkEVM, PolygonZkEVMExistentEtrog, + AggLayerGateway, } from "../../typechain-types"; -import { takeSnapshot, time } from "@nomicfoundation/hardhat-network-helpers"; -import { processorUtils, contractUtils, MTBridge, mtBridgeUtils } from "@0xpolygonhermez/zkevm-commonjs"; -const { calculateSnarkInput, calculateAccInputHash, calculateBatchHashData } = contractUtils; +import { takeSnapshot } from "@nomicfoundation/hardhat-network-helpers"; +import { processorUtils, MTBridge, mtBridgeUtils } from "@0xpolygonhermez/zkevm-commonjs"; +const { encodeInitializeBytesPessimistic } = require("../../src/utils-common-aggchain"); type BatchDataStructEtrog = PolygonRollupBaseEtrog.BatchDataStruct; @@ -257,7 +258,7 @@ describe("Polygon Rollup manager upgraded", () => { polTokenContract.target, polygonZkEVMBridgeContract.target, ], - unsafeAllow: ["constructor", "state-variable-immutable", "enum-definition", "struct-definition"], + unsafeAllow: ["constructor", "missing-initializer", "state-variable-immutable"], unsafeAllowRenames: true, unsafeAllowCustomTypes: true, unsafeSkipStorageCheck: true, @@ -274,14 +275,21 @@ describe("Polygon Rollup manager upgraded", () => { polTokenContract.target, polygonZkEVMBridgeContract.target, ], - unsafeAllow: ["constructor", "state-variable-immutable", "enum-definition", "struct-definition"], + unsafeAllow: ["constructor", "missing-initializer-call", "state-variable-immutable", "enum-definition", "struct-definition"], unsafeAllowRenames: true, unsafeAllowCustomTypes: true, unsafeSkipStorageCheck: true, } ); - // upgrade pessimistic to ALv3 + // deploy AggLayerGateway + const AggLayerGatewayFactory = await ethers.getContractFactory("AggLayerGateway"); + const aggLayerGatewayContract = (await upgrades.deployProxy(AggLayerGatewayFactory, [], { + initializer: false, + unsafeAllow: ["constructor"], + })) as unknown as AggLayerGateway; + + // upgrade pessimistic to ALv3 const txRollupManager4 = await upgrades.upgradeProxy( polygonZkEVMContract.target, PolygonRollupManagerFactoryCurrent, @@ -290,9 +298,9 @@ describe("Polygon Rollup manager upgraded", () => { polygonZkEVMGlobalExitRoot.target, polTokenContract.target, polygonZkEVMBridgeContract.target, - ethers.ZeroAddress, // aggLayerGateway + aggLayerGatewayContract.target, ], - unsafeAllow: ["constructor", "state-variable-immutable"], + unsafeAllow: ["constructor", "missing-initializer", "missing-initializer-call", "state-variable-immutable"], unsafeAllowRenames: true, unsafeAllowCustomTypes: true, unsafeSkipStorageCheck: true, @@ -467,30 +475,21 @@ describe("Polygon Rollup manager upgraded", () => { expect(expectedRollupType).to.be.deep.equal(await rollupManagerContract.rollupTypeMap(newRollupTypeID)); // Only admin can create new zkEVMs + const initializeBytesCustomChain = encodeInitializeBytesPessimistic(admin.address, trustedSequencer.address, gasTokenAddress, urlSequencer, networkName); await expect( - rollupManagerContract.createNewRollup( + rollupManagerContract.attachAggchainToAL( newRollupTypeID, chainID2, - admin.address, - trustedSequencer.address, - gasTokenAddress, - urlSequencer, - networkName, - "0x" // initializeBytesCustomChain + initializeBytesCustomChain ) ).to.be.revertedWithCustomError(rollupManagerContract, "AddressDoNotHaveRequiredRole"); // UNexisting rollupType await expect( - rollupManagerContract.connect(admin).createNewRollup( + rollupManagerContract.connect(admin).attachAggchainToAL( 0, chainID2, - admin.address, - trustedSequencer.address, - gasTokenAddress, - urlSequencer, - networkName, - "0x" // initializeBytesCustomChain + initializeBytesCustomChain ) ).to.be.revertedWithCustomError(rollupManagerContract, "RollupTypeDoesNotExist"); @@ -501,15 +500,10 @@ describe("Polygon Rollup manager upgraded", () => { .withArgs(newRollupTypeID); await expect( - rollupManagerContract.connect(admin).createNewRollup( + rollupManagerContract.connect(admin).attachAggchainToAL( newRollupTypeID, chainID2, - admin.address, - trustedSequencer.address, - gasTokenAddress, - urlSequencer, - networkName, - "0x" // initializeBytesCustomChain + initializeBytesCustomChain ) ).to.be.revertedWithCustomError(rollupManagerContract, "RollupTypeObsolete"); await snapshot2.restore(); @@ -524,15 +518,10 @@ describe("Polygon Rollup manager upgraded", () => { const newSequencedBatch = 1; await expect( - rollupManagerContract.connect(admin).createNewRollup( + rollupManagerContract.connect(admin).attachAggchainToAL( newRollupTypeID, chainID2, - admin.address, - trustedSequencer.address, - gasTokenAddress, - urlSequencer, - networkName, - "0x" // initializeBytesCustomChain + initializeBytesCustomChain ) ) .to.emit(rollupManagerContract, "CreateNewRollup") @@ -553,15 +542,10 @@ describe("Polygon Rollup manager upgraded", () => { // Cannot create 2 chains with the same chainID await expect( - rollupManagerContract.connect(admin).createNewRollup( + rollupManagerContract.connect(admin).attachAggchainToAL( newRollupTypeID, chainID2, - admin.address, - trustedSequencer.address, - gasTokenAddress, - urlSequencer, - networkName, - "0x" // initializeBytesCustomChain + initializeBytesCustomChain ) ).to.be.revertedWithCustomError(rollupManagerContract, "ChainIDAlreadyExist"); diff --git a/test/contractsv2/real-prover-sp1/e2e-verify-proof.test.ts b/test/contractsv2/real-prover-sp1/e2e-verify-proof.test.ts index 6eab7ea7f..01bc19487 100644 --- a/test/contractsv2/real-prover-sp1/e2e-verify-proof.test.ts +++ b/test/contractsv2/real-prover-sp1/e2e-verify-proof.test.ts @@ -15,6 +15,7 @@ const { computeConsensusHashEcdsa, } = require("../../../src/pessimistic-utils"); const inputProof = require("./test-inputs/input.json"); +const { encodeInitializeBytesPessimistic } = require("../../../src/utils-common-aggchain"); describe("Polygon Rollup Manager with Polygon Pessimistic Consensus", () => { let deployer: any; @@ -94,10 +95,18 @@ describe("Polygon Rollup Manager with Polygon Pessimistic Consensus", () => { if ((await upgrades.admin.getInstance()).target !== "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0") { firstDeployment = false; } + + // deploy AggLayerGateway + const AggLayerGatewayFactory = await ethers.getContractFactory("AggLayerGateway"); + const aggLayerGatewayContract = (await upgrades.deployProxy(AggLayerGatewayFactory, [], { + initializer: false, + unsafeAllow: ["constructor"], + })) + const nonceProxyBridge = Number(await ethers.provider.getTransactionCount(deployer.address)) + (firstDeployment ? 3 : 2); - const nonceProxyZkevm = nonceProxyBridge + 2; // Always have to redeploy impl since the polygonZkEVMGlobalExitRoot address changes + const nonceProxyZkevm = nonceProxyBridge + 2; // Always have to redeploy impl since the polygonZkEVMGlobalExitRoot address changes, const precalculateBridgeAddress = ethers.getCreateAddress({ from: deployer.address, @@ -132,7 +141,7 @@ describe("Polygon Rollup Manager with Polygon Pessimistic Consensus", () => { polygonZkEVMGlobalExitRoot.target, polTokenContract.target, polygonZkEVMBridgeContract.target, - ethers.ZeroAddress // AggLayer Gateway address + aggLayerGatewayContract.target, ], unsafeAllow: ["constructor", "state-variable-immutable"], })) as unknown as PolygonRollupManagerMock; @@ -234,7 +243,7 @@ describe("Polygon Rollup Manager with Polygon Pessimistic Consensus", () => { const urlSequencer = "https://pessimistic:8545"; const networkName = "testPessimistic"; const pessimisticRollupID = inputProof["pp-inputs"]["origin-network"]; - const initializeBytesCustomChain = "0x"; + const initializeBytesCustomChain = encodeInitializeBytesPessimistic(admin.address, trustedSequencer, gasTokenAddress, urlSequencer, networkName); // create new pessimistic const newZKEVMAddress = ethers.getCreateAddress({ from: rollupManagerContract.target as string, @@ -243,14 +252,9 @@ describe("Polygon Rollup Manager with Polygon Pessimistic Consensus", () => { await rollupManagerContract .connect(admin) - .createNewRollup( + .attachAggchainToAL( rollupTypeID, chainID, - admin.address, - trustedSequencer, - gasTokenAddress, - urlSequencer, - networkName, initializeBytesCustomChain ); diff --git a/test/src/aggchain-ECDSA.test.ts b/test/src/aggchain-ECDSA.test.ts index e6f04ed46..160b0f639 100644 --- a/test/src/aggchain-ECDSA.test.ts +++ b/test/src/aggchain-ECDSA.test.ts @@ -28,9 +28,10 @@ describe("Test vectors aggchain ECDSA", () => { let initializeBytesAggchainV0: string; let initializeBytesAggchainV1: string; let aggchainParams: string; - let aggchainSelectors: string[] = []; - let aggchainData: string[] = []; - let aggchainHash: string[] = []; + let aggchainSelectors: string; + let finalAggchainVKeySelector: string; + let aggchainData: string; + let aggchainHash: string; const data = dataECDSA[i].input; @@ -38,26 +39,15 @@ describe("Test vectors aggchain ECDSA", () => { // load signers [vKeyManager, admin] = await ethers.getSigners(); - if (data.aggchainVKeySelectors.length !== data.ownedAggchainVkeys.length) { - throw new Error("aggchainVKeySelectors and ownedAggchainVkeys must have the same length"); - } + finalAggchainVKeySelector = utilsCommon.getFinalAggchainVKeySelectorFromType( + data.initAggchainVKeySelector, + utilsECDSA.AGGCHAIN_TYPE_SELECTOR_ECDSA + ) - if (data.aggchainVKeySelectors.length !== 0) { - for (let j = 0; j < data.aggchainVKeySelectors.length; j++) { - // get final aggchainSelector - aggchainSelectors.push( - utilsCommon.getFinalAggchainVKeySelectorFromType( - data?.aggchainVKeySelectors[j], - utilsECDSA.AGGCHAIN_TYPE_SELECTOR_ECDSA - ) - ); - - // check final aggchainSelector - expect(aggchainSelectors[j]).to.be.equal( - `${data.aggchainVKeySelectors[j]}${utilsECDSA.AGGCHAIN_TYPE_SELECTOR_ECDSA.slice(2)}` - ); - } - } + // check final aggchainSelector + expect(finalAggchainVKeySelector).to.be.equal( + `${data.initAggchainVKeySelector}${utilsECDSA.AGGCHAIN_TYPE_SELECTOR_ECDSA.slice(2)}` + ); // deploy aggchain // create aggchainECDSA implementation @@ -78,8 +68,8 @@ describe("Test vectors aggchain ECDSA", () => { // encode initializeBytesAggchain initializeBytesAggchainV0 = utilsECDSA.encodeInitializeBytesAggchainECDSAv0( data.useDefaultGateway, - data.ownedAggchainVkeys, - aggchainSelectors, + data.initOwnedAggchainVKey, + data.initAggchainVKeySelector, vKeyManager.address, admin.address, data.trustedSequencer, @@ -102,12 +92,9 @@ describe("Test vectors aggchain ECDSA", () => { expect(await aggchainECDSAContract.trustedSequencerURL()).to.be.equal(data.trustedSequencerURL); expect(await aggchainECDSAContract.networkName()).to.be.equal(data.networkName); expect(await aggchainECDSAContract.gasTokenAddress()).to.be.equal(data.gasTokenAddress); - - for (let j = 0; j < aggchainSelectors.length; j++) { - expect(await aggchainECDSAContract.ownedAggchainVKeys(aggchainSelectors[j])).to.be.equal( - data.ownedAggchainVkeys[j] - ); - } + expect(await aggchainECDSAContract.ownedAggchainVKeys(finalAggchainVKeySelector)).to.be.equal( + data.initOwnedAggchainVKey + ); // encode aggchainParams aggchainParams = utilsECDSA.computeHashAggchainParamsECDSA(data.trustedSequencer); @@ -115,29 +102,24 @@ describe("Test vectors aggchain ECDSA", () => { // if useDefaultGateway is true, disable it if (data.useDefaultGateway) { await expect(aggchainECDSAContract.connect(vKeyManager).disableUseDefaultGatewayFlag()) - .to.emit(aggchainECDSAContract, "UpdateUseDefaultGatewayFlag") - .withArgs(false); + .to.emit(aggchainECDSAContract, "DisableUseDefaultGatewayFlag"); } - for (let j = 0; j < aggchainSelectors.length; j++) { - // encode aggchainData - aggchainData.push(utilsECDSA.encodeAggchainDataECDSA(data.aggchainVKeySelectors[j], data.newStateRoot)); - // get aggchainHash - aggchainHash.push( - utilsCommon.computeAggchainHash( - utilsCommon.AggchainType.GENERIC, - data.ownedAggchainVkeys[j], - aggchainParams - ) - ); - // get aggchainHash from contract - const aggchainHashContract = await aggchainECDSAContract.getAggchainHash(aggchainData[j], { - gasPrice: 0, - }); - // check aggchainHash === aggchainHash from contract - // with this check we can be sure that the aggchainParams & aggchainHash works correctly - expect(aggchainHash[j]).to.be.equal(aggchainHashContract); - } + // encode aggchainData + aggchainData = utilsECDSA.encodeAggchainDataECDSA(data.initAggchainVKeySelector, data.newStateRoot); + // get aggchainHash + aggchainHash = utilsCommon.computeAggchainHash( + utilsCommon.AggchainType.GENERIC, + data.initOwnedAggchainVKey, + aggchainParams + ); + // get aggchainHash from contract + const aggchainHashContract = await aggchainECDSAContract.getAggchainHash(aggchainData, { + gasPrice: 0, + }); + // check aggchainHash === aggchainHash from contract + // with this check we can be sure that the aggchainParams & aggchainHash works correctly + expect(aggchainHash).to.be.equal(aggchainHashContract); // reinitialize using rollup manager & initializeBytesAggchainECDSAv1 @@ -187,8 +169,8 @@ describe("Test vectors aggchain ECDSA", () => { // encode initializeBytesAggchain version 1 initializeBytesAggchainV1 = utilsECDSA.encodeInitializeBytesAggchainECDSAv1( data.useDefaultGateway, - data.ownedAggchainVkeys, - aggchainSelectors, + data.initOwnedAggchainVKey, + data.initAggchainVKeySelector, vKeyManager.address ); @@ -201,12 +183,9 @@ describe("Test vectors aggchain ECDSA", () => { expect(await aggchainECDSAContract.trustedSequencerURL()).to.be.equal(data.trustedSequencerURL); expect(await aggchainECDSAContract.networkName()).to.be.equal(data.networkName); expect(await aggchainECDSAContract.gasTokenAddress()).to.be.equal(data.gasTokenAddress); - - for (let j = 0; j < aggchainSelectors.length; j++) { - expect(await aggchainECDSAContract.ownedAggchainVKeys(aggchainSelectors[j])).to.be.equal( - data.ownedAggchainVkeys[j] - ); - } + expect(await aggchainECDSAContract.ownedAggchainVKeys(finalAggchainVKeySelector)).to.be.equal( + data.initOwnedAggchainVKey + ); // add data to test-vector if (update) { @@ -217,8 +196,8 @@ describe("Test vectors aggchain ECDSA", () => { dataECDSA[i].output.initializeBytesAggchainV0 = initializeBytesAggchainV0; dataECDSA[i].output.initializeBytesAggchainV1 = initializeBytesAggchainV1; dataECDSA[i].output.aggchainData = aggchainData; - dataECDSA[i].output.aggchainSelectors = aggchainSelectors; - dataECDSA[i].output.aggchainHashes = aggchainHash; + dataECDSA[i].output.finalAggchainVKeySelector = finalAggchainVKeySelector; + dataECDSA[i].output.aggchainHash = aggchainHash; dataECDSA[i].output.aggchainParams = aggchainParams; console.log(`Writing data to test-vector: ${i}. Path: ${pathTestVector}`); @@ -229,8 +208,8 @@ describe("Test vectors aggchain ECDSA", () => { expect(dataECDSA[i].output.initializeBytesAggchainV0).to.be.equal(initializeBytesAggchainV0); expect(dataECDSA[i].output.initializeBytesAggchainV1).to.be.equal(initializeBytesAggchainV1); expect(dataECDSA[i].output.aggchainData).to.be.deep.equal(aggchainData); - expect(dataECDSA[i].output.aggchainSelectors).to.be.deep.equal(aggchainSelectors); - expect(dataECDSA[i].output.aggchainHashes).to.be.deep.equal(aggchainHash); + expect(dataECDSA[i].output.finalAggchainVKeySelector).to.be.deep.equal(finalAggchainVKeySelector); + expect(dataECDSA[i].output.aggchainHash).to.be.deep.equal(aggchainHash); expect(dataECDSA[i].output.aggchainParams).to.be.equal(aggchainParams); } }); diff --git a/test/src/aggchain-utils-ECDSA.test.ts b/test/src/aggchain-utils-ECDSA.test.ts index 4e4397dba..fd27727ce 100644 --- a/test/src/aggchain-utils-ECDSA.test.ts +++ b/test/src/aggchain-utils-ECDSA.test.ts @@ -38,8 +38,8 @@ describe("Test vectors aggchain ECDSA utils", () => { const testVector = aggchainInitBytesV0[i].input; const initBytesAggchainECDSAv0 = utilsECDSA.encodeInitializeBytesAggchainECDSAv0( testVector.useDefaultGateway, - testVector.ownedAggchainVkeys, - testVector.aggchainVKeySelectors, + testVector.initOwnedAggchainVKey, + testVector.initAggchainVKeySelector, testVector.vKeyManager, testVector.admin, testVector.trustedSequencer, @@ -66,8 +66,8 @@ describe("Test vectors aggchain ECDSA utils", () => { const testVector = aggchainInitBytesV1[i].input; const initBytesAggchainECDSAv1 = utilsECDSA.encodeInitializeBytesAggchainECDSAv1( testVector.useDefaultGateway, - testVector.ownedAggchainVkeys, - testVector.aggchainVKeySelectors, + testVector.initOwnedAggchainVKey, + testVector.initAggchainVKeySelector, testVector.vKeyManager ); if (update) { diff --git a/test/src/aggchain-utils.test.ts b/test/src/aggchain-utils.test.ts index 0a34b1e4c..b68c97706 100644 --- a/test/src/aggchain-utils.test.ts +++ b/test/src/aggchain-utils.test.ts @@ -1,4 +1,4 @@ -import {ethers} from "hardhat"; +import {ethers, upgrades} from "hardhat"; import {expect} from "chai"; import fs = require("fs"); import path = require("path"); @@ -41,14 +41,20 @@ describe("Test vectors aggchain common utils", () => { testVector.aggchainType ); if (update) { - const AggchainBaseMockFactory = await ethers.getContractFactory("AggchainBaseMock"); - const aggchainContract = await AggchainBaseMockFactory.deploy( - "0xA00000000000000000000000000000000000000A", - "0xB00000000000000000000000000000000000000B", - "0xC00000000000000000000000000000000000000C", - "0xD00000000000000000000000000000000000000D", - "0xE00000000000000000000000000000000000000E" - ); + const aggchainECDSAFactory = await ethers.getContractFactory("AggchainECDSA"); + const aggchainContract = await upgrades.deployProxy(aggchainECDSAFactory, [], { + initializer: false, + constructorArgs: [ + "0xA00000000000000000000000000000000000000A", + "0xB00000000000000000000000000000000000000B", + "0xC00000000000000000000000000000000000000C", + "0xD00000000000000000000000000000000000000D", + "0xE00000000000000000000000000000000000000E" + ], + unsafeAllow: ["constructor", "state-variable-immutable"], + }); + await aggchainContract.waitForDeployment(); + finalAggchainSelectorTestVectors[i].output = {}; finalAggchainSelectorTestVectors[i].output.finalAggchainVKeySelector = await aggchainContract.getFinalAggchainVKeySelectorFromType( diff --git a/test/test-vectors/aggchainECDSA/aggchain-initBytesv0.json b/test/test-vectors/aggchainECDSA/aggchain-initBytesv0.json index bc817d3a2..3544a670f 100644 --- a/test/test-vectors/aggchainECDSA/aggchain-initBytesv0.json +++ b/test/test-vectors/aggchainECDSA/aggchain-initBytesv0.json @@ -2,12 +2,8 @@ { "input": { "useDefaultGateway": false, - "ownedAggchainVkeys": [ - "0x6666666666666666666666666666666666666666666666666666666666666666" - ], - "aggchainVKeySelectors": [ - "0x12340000" - ], + "initOwnedAggchainVKey": "0x6666666666666666666666666666666666666666666666666666666666666666", + "initAggchainVKeySelector": "0x1234", "vKeyManager": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", "admin": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", "trustedSequencer": "0x2222222222222222222222222222222222222222", @@ -16,18 +12,14 @@ "networkName": "namename" }, "output": { - "initBytesAggchainECDSAv0": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000160000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c80000000000000000000000002222222222222222222222222222222222222222000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000000166666666666666666666666666666666666666666666666666666666666666660000000000000000000000000000000000000000000000000000000000000001123400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000177472757374656453657175656e63657255524c2e636f6d00000000000000000000000000000000000000000000000000000000000000000000000000000000086e616d656e616d65000000000000000000000000000000000000000000000000" + "initBytesAggchainECDSAv0": "0x000000000000000000000000000000000000000000000000000000000000000066666666666666666666666666666666666666666666666666666666666666661234000000000000000000000000000000000000000000000000000000000000000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8000000000000000000000000222222222222222222222222222222222222222200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000177472757374656453657175656e63657255524c2e636f6d00000000000000000000000000000000000000000000000000000000000000000000000000000000086e616d656e616d65000000000000000000000000000000000000000000000000" } }, { "input": { "useDefaultGateway": true, - "ownedAggchainVkeys": [ - "0x6666666666666666666666666666666666666666666666666666666666666666" - ], - "aggchainVKeySelectors": [ - "0x12340000" - ], + "initOwnedAggchainVKey": "0x6666666666666666666666666666666666666666666666666666666666666666", + "initAggchainVKeySelector": "0x1234", "vKeyManager": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", "admin": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", "trustedSequencer": "0x2222222222222222222222222222222222222222", @@ -36,18 +28,14 @@ "networkName": "namename" }, "output": { - "initBytesAggchainECDSAv0": "0x000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000160000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c80000000000000000000000002222222222222222222222222222222222222222000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000000166666666666666666666666666666666666666666666666666666666666666660000000000000000000000000000000000000000000000000000000000000001123400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000177472757374656453657175656e63657255524c2e636f6d00000000000000000000000000000000000000000000000000000000000000000000000000000000086e616d656e616d65000000000000000000000000000000000000000000000000" + "initBytesAggchainECDSAv0": "0x000000000000000000000000000000000000000000000000000000000000000166666666666666666666666666666666666666666666666666666666666666661234000000000000000000000000000000000000000000000000000000000000000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8000000000000000000000000222222222222222222222222222222222222222200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000177472757374656453657175656e63657255524c2e636f6d00000000000000000000000000000000000000000000000000000000000000000000000000000000086e616d656e616d65000000000000000000000000000000000000000000000000" } }, { "input": { "useDefaultGateway": false, - "ownedAggchainVkeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000" - ], - "aggchainVKeySelectors": [ - "0x00000000" - ], + "initOwnedAggchainVKey": "0x0000000000000000000000000000000000000000000000000000000000000000", + "initAggchainVKeySelector": "0x0000", "vKeyManager": "0x0000000000000000000000000000000000000000", "admin": "0x0000000000000000000000000000000000000000", "trustedSequencer": "0x0000000000000000000000000000000000000000", @@ -56,18 +44,14 @@ "networkName": "" }, "output": { - "initBytesAggchainECDSAv0": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001c0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + "initBytesAggchainECDSAv0": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" } }, { "input": { "useDefaultGateway": true, - "ownedAggchainVkeys": [ - "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" - ], - "aggchainVKeySelectors": [ - "0xFFFFFFFF" - ], + "initOwnedAggchainVKey": "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + "initAggchainVKeySelector": "0xFFFF", "vKeyManager": "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", "admin": "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", "trustedSequencer": "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", @@ -76,7 +60,7 @@ "networkName": "bbbbbbbbbbbbbb" }, "output": { - "initBytesAggchainECDSAv0": "0x000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000160000000000000000000000000ffffffffffffffffffffffffffffffffffffffff000000000000000000000000ffffffffffffffffffffffffffffffffffffffff000000000000000000000000ffffffffffffffffffffffffffffffffffffffff000000000000000000000000ffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000001ffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000146161616161616161616161616161616161616161000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e6262626262626262626262626262000000000000000000000000000000000000" + "initBytesAggchainECDSAv0": "0x0000000000000000000000000000000000000000000000000000000000000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffff000000000000000000000000ffffffffffffffffffffffffffffffffffffffff000000000000000000000000ffffffffffffffffffffffffffffffffffffffff000000000000000000000000ffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000146161616161616161616161616161616161616161000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e6262626262626262626262626262000000000000000000000000000000000000" } } ] \ No newline at end of file diff --git a/test/test-vectors/aggchainECDSA/aggchain-initBytesv1.json b/test/test-vectors/aggchainECDSA/aggchain-initBytesv1.json index b42f8b689..19a2cee3b 100644 --- a/test/test-vectors/aggchainECDSA/aggchain-initBytesv1.json +++ b/test/test-vectors/aggchainECDSA/aggchain-initBytesv1.json @@ -2,61 +2,45 @@ { "input": { "useDefaultGateway": false, - "ownedAggchainVkeys": [ - "0x6666666666666666666666666666666666666666666666666666666666666666" - ], - "aggchainVKeySelectors": [ - "0x12340000" - ], + "initOwnedAggchainVKey": "0x6666666666666666666666666666666666666666666666666666666666666666", + "initAggchainVKeySelector": "0x1234", "vKeyManager": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" }, "output": { - "initBytesAggchainECDSAv1": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb922660000000000000000000000000000000000000000000000000000000000000001666666666666666666666666666666666666666666666666666666666666666600000000000000000000000000000000000000000000000000000000000000011234000000000000000000000000000000000000000000000000000000000000" + "initBytesAggchainECDSAv1": "0x000000000000000000000000000000000000000000000000000000000000000066666666666666666666666666666666666666666666666666666666666666661234000000000000000000000000000000000000000000000000000000000000000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266" } }, { "input": { "useDefaultGateway": true, - "ownedAggchainVkeys": [ - "0x6666666666666666666666666666666666666666666666666666666666666666" - ], - "aggchainVKeySelectors": [ - "0x12340000" - ], + "initOwnedAggchainVKey": "0x6666666666666666666666666666666666666666666666666666666666666666", + "initAggchainVKeySelector": "0x1234", "vKeyManager": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" }, "output": { - "initBytesAggchainECDSAv1": "0x0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb922660000000000000000000000000000000000000000000000000000000000000001666666666666666666666666666666666666666666666666666666666666666600000000000000000000000000000000000000000000000000000000000000011234000000000000000000000000000000000000000000000000000000000000" + "initBytesAggchainECDSAv1": "0x000000000000000000000000000000000000000000000000000000000000000166666666666666666666666666666666666666666666666666666666666666661234000000000000000000000000000000000000000000000000000000000000000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266" } }, { "input": { "useDefaultGateway": false, - "ownedAggchainVkeys": [ - "0x0000000000000000000000000000000000000000000000000000000000000000" - ], - "aggchainVKeySelectors": [ - "0x00000000" - ], + "initOwnedAggchainVKey": "0x0000000000000000000000000000000000000000000000000000000000000000", + "initAggchainVKeySelector": "0x0000", "vKeyManager": "0x0000000000000000000000000000000000000000" }, "output": { - "initBytesAggchainECDSAv1": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000" + "initBytesAggchainECDSAv1": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" } }, { "input": { "useDefaultGateway": true, - "ownedAggchainVkeys": [ - "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" - ], - "aggchainVKeySelectors": [ - "0xFFFFFFFF" - ], + "initOwnedAggchainVKey": "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + "initAggchainVKeySelector": "0xFFFF", "vKeyManager": "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" }, "output": { - "initBytesAggchainECDSAv1": "0x0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000ffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000001ffffffff00000000000000000000000000000000000000000000000000000000" + "initBytesAggchainECDSAv1": "0x0000000000000000000000000000000000000000000000000000000000000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffff" } } ] \ No newline at end of file diff --git a/test/test-vectors/aggchainECDSA/aggchainECDSA.json b/test/test-vectors/aggchainECDSA/aggchainECDSA.json index 823e838a4..8fa3bb930 100644 --- a/test/test-vectors/aggchainECDSA/aggchainECDSA.json +++ b/test/test-vectors/aggchainECDSA/aggchainECDSA.json @@ -8,27 +8,17 @@ "trustedSequencerURL": "trustedSequencerURL.com", "networkName": "namename", "newStateRoot": "0x5555555555555555555555555555555555555555555555555555555555555555", - "aggchainVKeySelectors": [ - "0x1234" - ], - "ownedAggchainVkeys": [ - "0x6666666666666666666666666666666666666666666666666666666666666666" - ] + "initAggchainVKeySelector": "0x1234", + "initOwnedAggchainVKey": "0x6666666666666666666666666666666666666666666666666666666666666666" }, "output": { "vKeyManager": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", "admin": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", - "initializeBytesAggchainV0": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000160000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c80000000000000000000000002222222222222222222222222222222222222222000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000000166666666666666666666666666666666666666666666666666666666666666660000000000000000000000000000000000000000000000000000000000000001123400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000177472757374656453657175656e63657255524c2e636f6d00000000000000000000000000000000000000000000000000000000000000000000000000000000086e616d656e616d65000000000000000000000000000000000000000000000000", - "initializeBytesAggchainV1": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb922660000000000000000000000000000000000000000000000000000000000000001666666666666666666666666666666666666666666666666666666666666666600000000000000000000000000000000000000000000000000000000000000011234000000000000000000000000000000000000000000000000000000000000", - "aggchainData": [ - "0x12340000000000000000000000000000000000000000000000000000000000005555555555555555555555555555555555555555555555555555555555555555" - ], - "aggchainSelectors": [ - "0x12340000" - ], - "aggchainHashes": [ - "0xa691f94fbadcedd6e27c79fc0e8ad216eef44da10297552d9890e77d284f1a85" - ], + "initializeBytesAggchainV0": "0x000000000000000000000000000000000000000000000000000000000000000066666666666666666666666666666666666666666666666666666666666666661234000000000000000000000000000000000000000000000000000000000000000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8000000000000000000000000222222222222222222222222222222222222222200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000177472757374656453657175656e63657255524c2e636f6d00000000000000000000000000000000000000000000000000000000000000000000000000000000086e616d656e616d65000000000000000000000000000000000000000000000000", + "initializeBytesAggchainV1": "0x000000000000000000000000000000000000000000000000000000000000000066666666666666666666666666666666666666666666666666666666666666661234000000000000000000000000000000000000000000000000000000000000000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "aggchainData": "0x12340000000000000000000000000000000000000000000000000000000000005555555555555555555555555555555555555555555555555555555555555555", + "finalAggchainVKeySelector": "0x12340000", + "aggchainHash": "0xa691f94fbadcedd6e27c79fc0e8ad216eef44da10297552d9890e77d284f1a85", "aggchainParams": "0x2ab0a4443bbea3fbe4d0e1503d11ff1367842fb0c8b28a5c8550f27599a40751" } }, @@ -41,28 +31,18 @@ "trustedSequencerURL": "urlurl.com", "networkName": "namename", "newStateRoot": "0x6666666666666666666666666666666666666666666666666666666666666666", - "aggchainVKeySelectors": [ - "0x4321" - ], - "ownedAggchainVkeys": [ - "0x7777777777777777777777777777777777777777777777777777777777777777" - ], + "initAggchainVKeySelector": "0x4321", + "initOwnedAggchainVKey": "0x7777777777777777777777777777777777777777777777777777777777777777", "output": {} }, "output": { "vKeyManager": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", "admin": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", - "initializeBytesAggchainV0": "0x000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000160000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c80000000000000000000000003333333333333333333333333333333333333333000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000001777777777777777777777777777777777777777777777777777777777777777700000000000000000000000000000000000000000000000000000000000000014321000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a75726c75726c2e636f6d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000086e616d656e616d65000000000000000000000000000000000000000000000000", - "initializeBytesAggchainV1": "0x0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb922660000000000000000000000000000000000000000000000000000000000000001777777777777777777777777777777777777777777777777777777777777777700000000000000000000000000000000000000000000000000000000000000014321000000000000000000000000000000000000000000000000000000000000", - "aggchainData": [ - "0x43210000000000000000000000000000000000000000000000000000000000006666666666666666666666666666666666666666666666666666666666666666" - ], - "aggchainSelectors": [ - "0x43210000" - ], - "aggchainHashes": [ - "0x4234530e13ccb8b4480bd2638f16b468d9dc78544d62eb0295b50bf0aebc2ac9" - ], + "initializeBytesAggchainV0": "0x000000000000000000000000000000000000000000000000000000000000000177777777777777777777777777777777777777777777777777777777777777774321000000000000000000000000000000000000000000000000000000000000000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c80000000000000000000000003333333333333333333333333333333333333333000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001200000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000000a75726c75726c2e636f6d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000086e616d656e616d65000000000000000000000000000000000000000000000000", + "initializeBytesAggchainV1": "0x000000000000000000000000000000000000000000000000000000000000000177777777777777777777777777777777777777777777777777777777777777774321000000000000000000000000000000000000000000000000000000000000000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266", + "aggchainData": "0x43210000000000000000000000000000000000000000000000000000000000006666666666666666666666666666666666666666666666666666666666666666", + "finalAggchainVKeySelector": "0x43210000", + "aggchainHash": "0x4234530e13ccb8b4480bd2638f16b468d9dc78544d62eb0295b50bf0aebc2ac9", "aggchainParams": "0x37d95e0aa71e34defa88b4c43498bc8b90207e31ad0ef4aa6f5bea78bd25a1ab" } } diff --git a/tools/createNewRollup/createNewRollup.ts b/tools/createNewRollup/createNewRollup.ts index c26235592..dd35c988a 100644 --- a/tools/createNewRollup/createNewRollup.ts +++ b/tools/createNewRollup/createNewRollup.ts @@ -1,15 +1,15 @@ /* eslint-disable no-await-in-loop, no-use-before-define, no-lonely-if */ /* eslint-disable no-console, no-inner-declarations, no-undef, import/no-unresolved */ -import {expect} from "chai"; +import { expect } from "chai"; import path = require("path"); import fs = require("fs"); import * as dotenv from "dotenv"; -dotenv.config({path: path.resolve(__dirname, "../../.env")}); -import {ethers, upgrades} from "hardhat"; -import {processorUtils, Constants} from "@0xpolygonhermez/zkevm-commonjs"; -import {VerifierType, ConsensusContracts} from "../../src/pessimistic-utils"; +dotenv.config({ path: path.resolve(__dirname, "../../.env") }); +import { ethers, upgrades } from "hardhat"; +import { processorUtils, Constants } from "@0xpolygonhermez/zkevm-commonjs"; +import { VerifierType, ConsensusContracts } from "../../src/pessimistic-utils"; const createRollupParameters = require("./create_new_rollup.json"); -import {genOperation, transactionTypes, convertBigIntsToNumbers} from "../utils"; +import { genOperation, transactionTypes, convertBigIntsToNumbers } from "../utils"; import updateVanillaGenesis from "../../deployment/v2/utils/updateVanillaGenesis"; import { @@ -152,7 +152,7 @@ async function main() { null, ((feeData.maxFeePerGas as bigint) * BigInt(createRollupParameters.multiplierGas)) / 1000n, ((feeData.maxPriorityFeePerGas as bigint) * BigInt(createRollupParameters.multiplierGas)) / - 1000n + 1000n ); } currentProvider.getFeeData = overrideFeeData; @@ -269,6 +269,9 @@ async function main() { outputJson.genesis = rollupType.genesis; outputJson.gasTokenAddress = createRollupParameters.gasTokenAddress; outputJson.rollupManagerAddress = createRollupParameters.rollupManagerAddress; + + const initializeBytesCustomChain = encodeInitializeBytesPessimistic(rollupAdminAddress, trustedSequencer, createRollupParameters.gasTokenAddress, trustedSequencerURL, networkName); + if (createRollupParameters.type === transactionTypes.TIMELOCK) { console.log("Creating timelock txs for rollup creation..."); const salt = createRollupParameters.timelockSalt || ethers.ZeroHash; @@ -277,14 +280,10 @@ async function main() { const operation = genOperation( createRollupParameters.rollupManagerAddress, 0, // value - PolygonRollupManagerFactory.interface.encodeFunctionData("createNewRollup", [ + PolygonRollupManagerFactory.interface.encodeFunctionData("attachAggchainToAL", [ createRollupParameters.rollupTypeId, chainID, - rollupAdminAddress, - trustedSequencer, - createRollupParameters.gasTokenAddress, - trustedSequencerURL, - networkName, + initializeBytesCustomChain ]), predecessor, // predecessor salt // salt @@ -306,12 +305,12 @@ async function main() { operation.predecessor, operation.salt, ]); - console.log({scheduleData}); - console.log({executeData}); + console.log({ scheduleData }); + console.log({ executeData }); outputJson.scheduleData = scheduleData; outputJson.executeData = executeData; // Decode the scheduleData for better readability - const timelockTx = timelockContractFactory.interface.parseTransaction({data: scheduleData}); + const timelockTx = timelockContractFactory.interface.parseTransaction({ data: scheduleData }); const paramsArray = timelockTx?.fragment.inputs; const objectDecoded = {}; for (let i = 0; i < paramsArray?.length; i++) { @@ -340,14 +339,10 @@ async function main() { process.exit(0); } else if (createRollupParameters.type === transactionTypes.MULTISIG) { console.log("Creating calldata for rollup creation from multisig..."); - const txDeployRollupCalldata = PolygonRollupManagerFactory.interface.encodeFunctionData("createNewRollup", [ + const txDeployRollupCalldata = PolygonRollupManagerFactory.interface.encodeFunctionData("attachAggchainToAL", [ createRollupParameters.rollupTypeId, chainID, - rollupAdminAddress, - trustedSequencer, - createRollupParameters.gasTokenAddress, - trustedSequencerURL, - networkName, + initializeBytesCustomChain ]); outputJson.txDeployRollupCalldata = txDeployRollupCalldata; fs.writeFileSync(destPath, JSON.stringify(outputJson, null, 1)); @@ -356,14 +351,10 @@ async function main() { } else { console.log("Deploying rollup...."); // Create new rollup - const txDeployRollup = await rollupManagerContract.createNewRollup( + const txDeployRollup = await rollupManagerContract.attachAggchainToAL( createRollupParameters.rollupTypeId, chainID, - rollupAdminAddress, - trustedSequencer, - createRollupParameters.gasTokenAddress, - trustedSequencerURL, - networkName + initializeBytesCustomChain ); const receipt = (await txDeployRollup.wait()) as any; @@ -491,7 +482,7 @@ async function main() { !ethers.isAddress(sovereignParams.sovereignWETHAddress)) ) { console.log("Rollup with custom gas token, adding WETH address to deployment output..."); - const wethObject = genesis.genesis.find(function (obj: {contractName: string}) { + const wethObject = genesis.genesis.find(function (obj: { contractName: string }) { return obj.contractName == "WETH"; }); outputJson.WETHAddress = wethObject.address; diff --git a/upgrade/upgradeSovereign/upgradeSovereignGER.ts b/upgrade/upgradeSovereign/upgradeSovereignGER.ts index 74d43f0c2..2326094ba 100644 --- a/upgrade/upgradeSovereign/upgradeSovereignGER.ts +++ b/upgrade/upgradeSovereign/upgradeSovereignGER.ts @@ -94,20 +94,13 @@ async function main() { ); console.log("Copy the following constructor arguments on: upgrade/arguments.js \n", [bridgeAddress]); } - // Get initialize values - const globalExitRootUpdater = await gerManagerL2SovereignChainContract.globalExitRootUpdater(); - const globalExitRootRemover = await gerManagerL2SovereignChainContract.globalExitRootRemover(); - + // gerManagerL2SovereignChainImplementation is upgraded but not initialized const timelockOperation = genTimelockOperation( proxyAdmin.target, 0, // value - proxyAdmin.interface.encodeFunctionData("upgradeAndCall", [ + proxyAdmin.interface.encodeFunctionData("upgrade", [ globalExitRootManagerL2SovereignChainAddress, gerManagerL2SovereignChainImplementation, - gerManagerL2SovereignChainFactory.interface.encodeFunctionData("initialize", [ - globalExitRootUpdater, - globalExitRootRemover, - ]), ]), // data ethers.ZeroHash, // predecessor salt // salt