diff --git a/contracts/common/constants/general.ts b/contracts/common/constants/general.ts new file mode 100644 index 000000000..ef58c2b55 --- /dev/null +++ b/contracts/common/constants/general.ts @@ -0,0 +1,9 @@ +import { ZeroHash } from "ethers"; + +export const HASH_ZERO = ZeroHash; + +export const LINEA_ROLLUP_INITIALIZE_SIGNATURE = + "initialize((bytes32,uint256,uint256,address,uint256,uint256,(address,bytes32)[],(uint8,bytes32)[],(uint8,bytes32)[],address,address))"; + +export const L2_MESSAGE_SERVICE_INITIALIZE_SIGNATURE = + "initialize(uint256,uint256,address,(address,bytes32)[],(uint8,bytes32)[],(uint8,bytes32)[])"; diff --git a/contracts/common/constants/index.ts b/contracts/common/constants/index.ts new file mode 100644 index 000000000..6bfa2eb4a --- /dev/null +++ b/contracts/common/constants/index.ts @@ -0,0 +1,3 @@ +export * from "./roles"; +export * from "./general"; +export * from "./pauseTypes"; diff --git a/contracts/common/constants/pauseTypes.ts b/contracts/common/constants/pauseTypes.ts new file mode 100644 index 000000000..560cf44ca --- /dev/null +++ b/contracts/common/constants/pauseTypes.ts @@ -0,0 +1,73 @@ +import { + PAUSE_ALL_ROLE, + PAUSE_COMPLETE_TOKEN_BRIDGING_ROLE, + PAUSE_FINALIZE_WITHPROOF_ROLE, + PAUSE_INITIATE_TOKEN_BRIDGING_ROLE, + PAUSE_L1_L2_ROLE, + PAUSE_BLOB_SUBMISSION_ROLE, + PAUSE_L2_L1_ROLE, + UNPAUSE_ALL_ROLE, + UNPAUSE_COMPLETE_TOKEN_BRIDGING_ROLE, + UNPAUSE_FINALIZE_WITHPROOF_ROLE, + UNPAUSE_INITIATE_TOKEN_BRIDGING_ROLE, + UNPAUSE_L1_L2_ROLE, + UNPAUSE_BLOB_SUBMISSION_ROLE, + UNPAUSE_L2_L1_ROLE, +} from "./roles"; + +export const GENERAL_PAUSE_TYPE = 1; +export const L1_L2_PAUSE_TYPE = 2; +export const L2_L1_PAUSE_TYPE = 3; +export const BLOB_SUBMISSION_PAUSE_TYPE = 4; +export const CALLDATA_SUBMISSION_PAUSE_TYPE = 5; +export const FINALIZATION_PAUSE_TYPE = 6; +export const INITIATE_TOKEN_BRIDGING_PAUSE_TYPE = 7; +export const COMPLETE_TOKEN_BRIDGING_PAUSE_TYPE = 8; + +export const BASE_PAUSE_TYPES_ROLES = [{ pauseType: GENERAL_PAUSE_TYPE, role: PAUSE_ALL_ROLE }]; +export const BASE_UNPAUSE_TYPES_ROLES = [{ pauseType: GENERAL_PAUSE_TYPE, role: UNPAUSE_ALL_ROLE }]; + +// LineaRollup +export const LINEA_ROLLUP_PAUSE_TYPES_ROLES = [ + ...BASE_PAUSE_TYPES_ROLES, + { pauseType: L1_L2_PAUSE_TYPE, role: PAUSE_L1_L2_ROLE }, + { pauseType: L2_L1_PAUSE_TYPE, role: PAUSE_L2_L1_ROLE }, + { pauseType: BLOB_SUBMISSION_PAUSE_TYPE, role: PAUSE_BLOB_SUBMISSION_ROLE }, + { pauseType: CALLDATA_SUBMISSION_PAUSE_TYPE, role: PAUSE_BLOB_SUBMISSION_ROLE }, + { pauseType: FINALIZATION_PAUSE_TYPE, role: PAUSE_FINALIZE_WITHPROOF_ROLE }, +]; + +export const LINEA_ROLLUP_UNPAUSE_TYPES_ROLES = [ + ...BASE_UNPAUSE_TYPES_ROLES, + { pauseType: L1_L2_PAUSE_TYPE, role: UNPAUSE_L1_L2_ROLE }, + { pauseType: L2_L1_PAUSE_TYPE, role: UNPAUSE_L2_L1_ROLE }, + { pauseType: BLOB_SUBMISSION_PAUSE_TYPE, role: UNPAUSE_BLOB_SUBMISSION_ROLE }, + { pauseType: CALLDATA_SUBMISSION_PAUSE_TYPE, role: UNPAUSE_BLOB_SUBMISSION_ROLE }, + { pauseType: FINALIZATION_PAUSE_TYPE, role: UNPAUSE_FINALIZE_WITHPROOF_ROLE }, +]; + +// L2MessageService +export const L2_MESSAGE_SERVICE_PAUSE_TYPES_ROLES = [ + ...BASE_PAUSE_TYPES_ROLES, + { pauseType: L1_L2_PAUSE_TYPE, role: PAUSE_L1_L2_ROLE }, + { pauseType: L2_L1_PAUSE_TYPE, role: PAUSE_L2_L1_ROLE }, +]; + +export const L2_MESSAGE_SERVICE_UNPAUSE_TYPES_ROLES = [ + ...BASE_UNPAUSE_TYPES_ROLES, + { pauseType: L1_L2_PAUSE_TYPE, role: UNPAUSE_L1_L2_ROLE }, + { pauseType: L2_L1_PAUSE_TYPE, role: UNPAUSE_L2_L1_ROLE }, +]; + +// TokenBridge +export const TOKEN_BRIDGE_PAUSE_TYPES_ROLES = [ + ...BASE_PAUSE_TYPES_ROLES, + { pauseType: INITIATE_TOKEN_BRIDGING_PAUSE_TYPE, role: PAUSE_INITIATE_TOKEN_BRIDGING_ROLE }, + { pauseType: COMPLETE_TOKEN_BRIDGING_PAUSE_TYPE, role: PAUSE_COMPLETE_TOKEN_BRIDGING_ROLE }, +]; + +export const TOKEN_BRIDGE_UNPAUSE_TYPES_ROLES = [ + ...BASE_UNPAUSE_TYPES_ROLES, + { pauseType: INITIATE_TOKEN_BRIDGING_PAUSE_TYPE, role: UNPAUSE_INITIATE_TOKEN_BRIDGING_ROLE }, + { pauseType: COMPLETE_TOKEN_BRIDGING_PAUSE_TYPE, role: UNPAUSE_COMPLETE_TOKEN_BRIDGING_ROLE }, +]; diff --git a/contracts/common/constants/roles.ts b/contracts/common/constants/roles.ts new file mode 100644 index 000000000..7cf223ae8 --- /dev/null +++ b/contracts/common/constants/roles.ts @@ -0,0 +1,121 @@ +import { HASH_ZERO } from "./general"; +import { generateKeccak256 } from "../helpers"; + +// Roles hashes +export const DEFAULT_ADMIN_ROLE = HASH_ZERO; +export const FUNCTION_EXECUTOR_ROLE = generateKeccak256(["string"], ["FUNCTION_EXECUTOR_ROLE"], { encodePacked: true }); +export const RATE_LIMIT_SETTER_ROLE = generateKeccak256(["string"], ["RATE_LIMIT_SETTER_ROLE"], { encodePacked: true }); +export const USED_RATE_LIMIT_RESETTER_ROLE = generateKeccak256(["string"], ["USED_RATE_LIMIT_RESETTER_ROLE"], { + encodePacked: true, +}); +export const L1_L2_MESSAGE_SETTER_ROLE = generateKeccak256(["string"], ["L1_L2_MESSAGE_SETTER_ROLE"], { + encodePacked: true, +}); +export const PAUSE_ALL_ROLE = generateKeccak256(["string"], ["PAUSE_ALL_ROLE"], { encodePacked: true }); +export const UNPAUSE_ALL_ROLE = generateKeccak256(["string"], ["UNPAUSE_ALL_ROLE"], { encodePacked: true }); +export const PAUSE_L1_L2_ROLE = generateKeccak256(["string"], ["PAUSE_L1_L2_ROLE"], { encodePacked: true }); +export const UNPAUSE_L1_L2_ROLE = generateKeccak256(["string"], ["UNPAUSE_L1_L2_ROLE"], { encodePacked: true }); +export const PAUSE_L2_L1_ROLE = generateKeccak256(["string"], ["PAUSE_L2_L1_ROLE"], { encodePacked: true }); +export const UNPAUSE_L2_L1_ROLE = generateKeccak256(["string"], ["UNPAUSE_L2_L1_ROLE"], { encodePacked: true }); +export const PAUSE_BLOB_SUBMISSION_ROLE = generateKeccak256(["string"], ["PAUSE_BLOB_SUBMISSION_ROLE"], { + encodePacked: true, +}); +export const UNPAUSE_BLOB_SUBMISSION_ROLE = generateKeccak256(["string"], ["UNPAUSE_BLOB_SUBMISSION_ROLE"], { + encodePacked: true, +}); +export const PAUSE_FINALIZE_WITHPROOF_ROLE = generateKeccak256(["string"], ["PAUSE_FINALIZE_WITHPROOF_ROLE"], { + encodePacked: true, +}); +export const UNPAUSE_FINALIZE_WITHPROOF_ROLE = generateKeccak256(["string"], ["UNPAUSE_FINALIZE_WITHPROOF_ROLE"], { + encodePacked: true, +}); +export const MINIMUM_FEE_SETTER_ROLE = generateKeccak256(["string"], ["MINIMUM_FEE_SETTER_ROLE"], { + encodePacked: true, +}); +export const OPERATOR_ROLE = generateKeccak256(["string"], ["OPERATOR_ROLE"], { encodePacked: true }); +export const VERIFIER_SETTER_ROLE = generateKeccak256(["string"], ["VERIFIER_SETTER_ROLE"], { encodePacked: true }); +export const VERIFIER_UNSETTER_ROLE = generateKeccak256(["string"], ["VERIFIER_UNSETTER_ROLE"], { encodePacked: true }); +export const L1_MERKLE_ROOTS_SETTER_ROLE = generateKeccak256(["string"], ["L1_MERKLE_ROOTS_SETTER_ROLE"], { + encodePacked: true, +}); +export const L2_MERKLE_ROOTS_SETTER_ROLE = generateKeccak256(["string"], ["L2_MERKLE_ROOTS_SETTER_ROLE"], { + encodePacked: true, +}); +export const PAUSE_INITIATE_TOKEN_BRIDGING_ROLE = generateKeccak256( + ["string"], + ["PAUSE_INITIATE_TOKEN_BRIDGING_ROLE"], + { encodePacked: true }, +); +export const PAUSE_COMPLETE_TOKEN_BRIDGING_ROLE = generateKeccak256( + ["string"], + ["PAUSE_COMPLETE_TOKEN_BRIDGING_ROLE"], + { encodePacked: true }, +); +export const UNPAUSE_INITIATE_TOKEN_BRIDGING_ROLE = generateKeccak256( + ["string"], + ["UNPAUSE_INITIATE_TOKEN_BRIDGING_ROLE"], + { encodePacked: true }, +); +export const UNPAUSE_COMPLETE_TOKEN_BRIDGING_ROLE = generateKeccak256( + ["string"], + ["UNPAUSE_COMPLETE_TOKEN_BRIDGING_ROLE"], + { encodePacked: true }, +); +export const SET_REMOTE_TOKENBRIDGE_ROLE = generateKeccak256(["string"], ["SET_REMOTE_TOKENBRIDGE_ROLE"], { + encodePacked: true, +}); +export const SET_RESERVED_TOKEN_ROLE = generateKeccak256(["string"], ["SET_RESERVED_TOKEN_ROLE"], { + encodePacked: true, +}); +export const REMOVE_RESERVED_TOKEN_ROLE = generateKeccak256(["string"], ["REMOVE_RESERVED_TOKEN_ROLE"], { + encodePacked: true, +}); +export const SET_CUSTOM_CONTRACT_ROLE = generateKeccak256(["string"], ["SET_CUSTOM_CONTRACT_ROLE"], { + encodePacked: true, +}); +export const SET_MESSAGE_SERVICE_ROLE = generateKeccak256(["string"], ["SET_MESSAGE_SERVICE_ROLE"], { + encodePacked: true, +}); + +export const BASE_ROLES = [PAUSE_ALL_ROLE, UNPAUSE_ALL_ROLE]; + +export const LINEA_ROLLUP_ROLES = [ + ...BASE_ROLES, + VERIFIER_SETTER_ROLE, + VERIFIER_UNSETTER_ROLE, + RATE_LIMIT_SETTER_ROLE, + USED_RATE_LIMIT_RESETTER_ROLE, + PAUSE_L1_L2_ROLE, + PAUSE_L2_L1_ROLE, + UNPAUSE_L1_L2_ROLE, + UNPAUSE_L2_L1_ROLE, + PAUSE_BLOB_SUBMISSION_ROLE, + UNPAUSE_BLOB_SUBMISSION_ROLE, + PAUSE_FINALIZE_WITHPROOF_ROLE, + UNPAUSE_FINALIZE_WITHPROOF_ROLE, +]; + +export const L2_MESSAGE_SERVICE_ROLES = [ + ...BASE_ROLES, + MINIMUM_FEE_SETTER_ROLE, + RATE_LIMIT_SETTER_ROLE, + USED_RATE_LIMIT_RESETTER_ROLE, + PAUSE_L1_L2_ROLE, + PAUSE_L2_L1_ROLE, + UNPAUSE_L1_L2_ROLE, + UNPAUSE_L2_L1_ROLE, + L1_L2_MESSAGE_SETTER_ROLE, +]; + +export const TOKEN_BRIDGE_ROLES = [ + ...BASE_ROLES, + SET_MESSAGE_SERVICE_ROLE, + SET_REMOTE_TOKENBRIDGE_ROLE, + SET_RESERVED_TOKEN_ROLE, + REMOVE_RESERVED_TOKEN_ROLE, + SET_CUSTOM_CONTRACT_ROLE, + PAUSE_INITIATE_TOKEN_BRIDGING_ROLE, + UNPAUSE_INITIATE_TOKEN_BRIDGING_ROLE, + PAUSE_COMPLETE_TOKEN_BRIDGING_ROLE, + UNPAUSE_COMPLETE_TOKEN_BRIDGING_ROLE, +]; diff --git a/contracts/utils/auditedDeployVerifier.ts b/contracts/common/helpers/auditedDeployVerifier.ts similarity index 100% rename from contracts/utils/auditedDeployVerifier.ts rename to contracts/common/helpers/auditedDeployVerifier.ts diff --git a/contracts/utils/deployments.ts b/contracts/common/helpers/deployments.ts similarity index 95% rename from contracts/utils/deployments.ts rename to contracts/common/helpers/deployments.ts index 7fb6a95eb..c22ede442 100644 --- a/contracts/utils/deployments.ts +++ b/contracts/common/helpers/deployments.ts @@ -1,7 +1,7 @@ -import { GetContractTypeFromFactory } from "../typechain-types/common"; -import { ProxyAdmin, ProxyAdmin__factory, TransparentUpgradeableProxy__factory } from "../typechain-types"; import { ContractFactory, Overrides, Wallet, ethers } from "ethers"; import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers"; +import { GetContractTypeFromFactory } from "../../typechain-types/common"; +import { ProxyAdmin, ProxyAdmin__factory, TransparentUpgradeableProxy__factory } from "../../typechain-types"; export function getInitializerData( contractInterface: ethers.Interface, diff --git a/contracts/common/helpers/encoding.ts b/contracts/common/helpers/encoding.ts new file mode 100644 index 000000000..26283b24f --- /dev/null +++ b/contracts/common/helpers/encoding.ts @@ -0,0 +1,20 @@ +import { ethers, AbiCoder } from "ethers"; + +export const encodeData = (types: string[], values: unknown[], packed?: boolean) => { + if (packed) { + return ethers.solidityPacked(types, values); + } + return AbiCoder.defaultAbiCoder().encode(types, values); +}; + +export function convertStringToPaddedHexBytes(strVal: string, paddedSize: number): string { + if (strVal.length > paddedSize) { + throw "Length is longer than padded size!"; + } + + const strBytes = ethers.toUtf8Bytes(strVal); + const bytes = ethers.zeroPadBytes(strBytes, paddedSize); + const bytes8Hex = ethers.hexlify(bytes); + + return bytes8Hex; +} diff --git a/contracts/common/helpers/environment.ts b/contracts/common/helpers/environment.ts new file mode 100644 index 000000000..8ff0a950a --- /dev/null +++ b/contracts/common/helpers/environment.ts @@ -0,0 +1,32 @@ +export function getRequiredEnvVar(name: string): string { + const envValue = process.env[name]; + if (!envValue) { + throw new Error(`Required environment variable "${name}" is missing or empty.`); + } + console.log(`Using environment variable ${name}=${envValue}`); + return envValue; +} + +export function getEnvVarOrDefault(envVar: string, defaultValue: unknown) { + const envValue = process.env[envVar]; + + if (!envValue) { + console.log(`Using default ${envVar}`); + return defaultValue; + } + + console.log(`Using provided ${envVar} environment variable`); + try { + const parsedValue = JSON.parse(envValue); + if (typeof parsedValue === "object" && !Array.isArray(parsedValue)) { + return parsedValue; + } + + if (Array.isArray(parsedValue) && parsedValue.every((item) => typeof item === "object")) { + return parsedValue; + } + } catch (error) { + console.log(`Unable to parse ${envVar}, returning as string.`); + } + return envValue; +} diff --git a/contracts/utils/environmentHelper.ts b/contracts/common/helpers/environmentHelper.ts similarity index 100% rename from contracts/utils/environmentHelper.ts rename to contracts/common/helpers/environmentHelper.ts diff --git a/contracts/common/helpers/general.ts b/contracts/common/helpers/general.ts new file mode 100644 index 000000000..29a28bd11 --- /dev/null +++ b/contracts/common/helpers/general.ts @@ -0,0 +1 @@ +export const delay = (ms: number) => new Promise((res) => setTimeout(res, ms)); diff --git a/contracts/common/helpers/hashing.ts b/contracts/common/helpers/hashing.ts new file mode 100644 index 000000000..e69f329b7 --- /dev/null +++ b/contracts/common/helpers/hashing.ts @@ -0,0 +1,5 @@ +import { ethers } from "hardhat"; +import { encodeData } from "./encoding"; + +export const generateKeccak256 = (types: string[], values: unknown[], opts: { encodePacked?: boolean }) => + ethers.keccak256(encodeData(types, values, opts.encodePacked)); diff --git a/contracts/common/helpers/index.ts b/contracts/common/helpers/index.ts new file mode 100644 index 000000000..f8649bc97 --- /dev/null +++ b/contracts/common/helpers/index.ts @@ -0,0 +1,11 @@ +export * from "./roles"; +export * from "./hashing"; +export * from "./encoding"; +export * from "./environment"; +export * from "./auditedDeployVerifier"; +export * from "./deployments"; +export * from "./environmentHelper"; +export * from "./readAddress"; +export * from "./storeAddress"; +export * from "./verifyContract"; +export * from "./general"; diff --git a/contracts/utils/readAddress.ts b/contracts/common/helpers/readAddress.ts similarity index 84% rename from contracts/utils/readAddress.ts rename to contracts/common/helpers/readAddress.ts index 93f155a2e..3a075a1c0 100644 --- a/contracts/utils/readAddress.ts +++ b/contracts/common/helpers/readAddress.ts @@ -12,5 +12,3 @@ export const getDeployedContractOnNetwork = async ( const data = fs.readFileSync(filePath, "utf-8"); return JSON.parse(data).address; }; - -export const delay = (ms: number) => new Promise((res) => setTimeout(res, ms)); diff --git a/contracts/common/helpers/roles.ts b/contracts/common/helpers/roles.ts new file mode 100644 index 000000000..e0b834ac4 --- /dev/null +++ b/contracts/common/helpers/roles.ts @@ -0,0 +1,33 @@ +export function generateRoleAssignments( + roles: string[], + defaultAddress: string, + overrides: { role: string; addresses: string[] }[], +): { role: string; addressWithRole: string }[] { + const roleAssignments: { role: string; addressWithRole: string }[] = []; + + const overridesMap = new Map(); + for (const override of overrides) { + overridesMap.set(override.role, override.addresses); + } + + const allRolesSet = new Set(roles); + for (const override of overrides) { + allRolesSet.add(override.role); + } + + for (const role of allRolesSet) { + if (overridesMap.has(role)) { + const addresses = overridesMap.get(role); + + if (addresses && addresses.length > 0) { + for (const addressWithRole of addresses) { + roleAssignments.push({ role, addressWithRole }); + } + } + } else { + roleAssignments.push({ role, addressWithRole: defaultAddress }); + } + } + + return roleAssignments; +} diff --git a/contracts/utils/storeAddress.ts b/contracts/common/helpers/storeAddress.ts similarity index 97% rename from contracts/utils/storeAddress.ts rename to contracts/common/helpers/storeAddress.ts index 9f76f871d..0c5d3bd8a 100644 --- a/contracts/utils/storeAddress.ts +++ b/contracts/common/helpers/storeAddress.ts @@ -107,5 +107,3 @@ export const getDeployedContractAddress = async ( } return undefined; }; - -export const delay = (ms: number) => new Promise((res) => setTimeout(res, ms)); diff --git a/contracts/utils/verifyContract.ts b/contracts/common/helpers/verifyContract.ts similarity index 96% rename from contracts/utils/verifyContract.ts rename to contracts/common/helpers/verifyContract.ts index 0bfb86b9e..c0ab1cffb 100644 --- a/contracts/utils/verifyContract.ts +++ b/contracts/common/helpers/verifyContract.ts @@ -1,5 +1,5 @@ import { run } from "hardhat"; -import { delay } from "./storeAddress"; +import { delay } from "./general"; export async function tryVerifyContract(contractAddress: string) { if (process.env.VERIFY_CONTRACT) { diff --git a/contracts/utils/supportedNetworks.ts b/contracts/common/supportedNetworks.ts similarity index 100% rename from contracts/utils/supportedNetworks.ts rename to contracts/common/supportedNetworks.ts diff --git a/contracts/contracts/LineaRollup.sol b/contracts/contracts/LineaRollup.sol index 32cc23ab2..b049e169f 100644 --- a/contracts/contracts/LineaRollup.sol +++ b/contracts/contracts/LineaRollup.sol @@ -29,7 +29,6 @@ contract LineaRollup is bytes32 public constant VERIFIER_SETTER_ROLE = keccak256("VERIFIER_SETTER_ROLE"); bytes32 public constant VERIFIER_UNSETTER_ROLE = keccak256("VERIFIER_UNSETTER_ROLE"); - bytes32 public constant FINALIZE_WITHOUT_PROOF_ROLE = keccak256("FINALIZE_WITHOUT_PROOF_ROLE"); bytes32 public constant GENESIS_SHNARF = keccak256( abi.encode( @@ -103,6 +102,12 @@ contract LineaRollup is __MessageService_init(_initializationData.rateLimitPeriodInSeconds, _initializationData.rateLimitAmountInWei); + /** + * @dev DEFAULT_ADMIN_ROLE is set for the security council explicitly, + * as the permissions init purposefully does not allow DEFAULT_ADMIN_ROLE to be set. + */ + _grantRole(DEFAULT_ADMIN_ROLE, _initializationData.defaultAdmin); + __Permissions_init(_initializationData.roleAddresses); verifiers[0] = _initializationData.defaultVerifier; @@ -206,7 +211,7 @@ contract LineaRollup is BlobSubmissionData[] calldata _blobSubmissionData, bytes32 _parentShnarf, bytes32 _finalBlobShnarf - ) external whenTypeAndGeneralNotPaused(BLOB_SUBMISSION_PAUSE_TYPE) onlyRole(OPERATOR_ROLE) { + ) external whenTypeAndGeneralNotPaused(PauseType.BLOB_SUBMISSION) onlyRole(OPERATOR_ROLE) { uint256 blobSubmissionLength = _blobSubmissionData.length; if (blobSubmissionLength == 0) { @@ -290,7 +295,7 @@ contract LineaRollup is SubmissionDataV2 calldata _submissionData, bytes32 _parentShnarf, bytes32 _expectedShnarf - ) external whenTypeAndGeneralNotPaused(CALLDATA_SUBMISSION_PAUSE_TYPE) onlyRole(OPERATOR_ROLE) { + ) external whenTypeAndGeneralNotPaused(PauseType.CALLDATA_SUBMISSION) onlyRole(OPERATOR_ROLE) { if (_submissionData.compressedData.length == 0) { revert EmptySubmissionData(); } @@ -465,7 +470,7 @@ contract LineaRollup is bytes calldata _aggregatedProof, uint256 _proofType, FinalizationDataV2 calldata _finalizationData - ) external whenTypeAndGeneralNotPaused(FINALIZATION_PAUSE_TYPE) onlyRole(OPERATOR_ROLE) { + ) external whenTypeAndGeneralNotPaused(PauseType.FINALIZATION) onlyRole(OPERATOR_ROLE) { if (_aggregatedProof.length == 0) { revert ProofIsEmpty(); } diff --git a/contracts/contracts/interfaces/IGenericErrors.sol b/contracts/contracts/interfaces/IGenericErrors.sol index f53c68f23..53fccb1cf 100644 --- a/contracts/contracts/interfaces/IGenericErrors.sol +++ b/contracts/contracts/interfaces/IGenericErrors.sol @@ -12,6 +12,11 @@ interface IGenericErrors { */ error ZeroAddressNotAllowed(); + /** + * @dev Thrown when a parameter is the zero hash. + */ + error ZeroHashNotAllowed(); + /** * @dev Thrown when array lengths are mismatched. */ diff --git a/contracts/contracts/interfaces/IPauseManager.sol b/contracts/contracts/interfaces/IPauseManager.sol index 05cf7e1f3..c3525080e 100644 --- a/contracts/contracts/interfaces/IPauseManager.sol +++ b/contracts/contracts/interfaces/IPauseManager.sol @@ -9,57 +9,88 @@ pragma solidity >=0.8.19 <=0.8.26; interface IPauseManager { /** * @notice Structure defining a pause type and its associated role. - * @dev This struct is used for both the pauseTypeRoles and unPauseTypeRoles mappings. + * @dev This struct is used for both the `_pauseTypeRoles` and `_unPauseTypeRoles` mappings. * @param pauseType The type of pause. * @param role The role associated with the pause type. */ struct PauseTypeRole { - uint8 pauseType; + PauseType pauseType; bytes32 role; } + /** + * @notice Enum defining the different types of pausing. + * @dev The pause types are used to pause and unpause specific functionality. + * @dev The UNUSED pause type is used as a default value to avoid accidental general pausing. + */ + enum PauseType { + UNUSED, + GENERAL, + L1_L2, + L2_L1, + BLOB_SUBMISSION, + CALLDATA_SUBMISSION, + FINALIZATION, + INITIATE_TOKEN_BRIDGING, + COMPLETE_TOKEN_BRIDGING + } + /** * @notice Emitted when a pause type is paused. * @param messageSender The address performing the pause. * @param pauseType The indexed pause type that was paused. */ - event Paused(address messageSender, uint256 indexed pauseType); + event Paused(address messageSender, PauseType indexed pauseType); /** * @notice Emitted when a pause type is unpaused. * @param messageSender The address performing the unpause. * @param pauseType The indexed pause type that was unpaused. */ - event UnPaused(address messageSender, uint256 indexed pauseType); + event UnPaused(address messageSender, PauseType indexed pauseType); + + /** + * @notice Emitted when a pause type and its associated role are set in the `_pauseTypeRoles` mapping. + * @param pauseType The type of pause. + * @param role The role associated with the pause type. + */ + event PauseTypeRoleSet(PauseType pauseType, bytes32 role); + + /** + * @notice Emitted when an unpause type and its associated role are set in the `_unPauseTypeRoles` mapping. + * @param unPauseType The type of unpause. + * @param role The role associated with the unpause type. + */ + event UnPauseTypeRoleSet(PauseType unPauseType, bytes32 role); /** * @dev Thrown when a specific pause type is paused. */ - error IsPaused(uint256 pauseType); + error IsPaused(PauseType pauseType); /** * @dev Thrown when a specific pause type is not paused and expected to be. */ - error IsNotPaused(uint256 pauseType); + error IsNotPaused(PauseType pauseType); /** * @notice Pauses functionality by specific type. * @dev Requires the role mapped in pauseTypeRoles for the pauseType. * @param _pauseType The pause type value. */ - function pauseByType(uint8 _pauseType) external; + function pauseByType(PauseType _pauseType) external; /** * @notice Unpauses functionality by specific type. * @dev Requires the role mapped in unPauseTypeRoles for the pauseType. * @param _pauseType The pause type value. */ - function unPauseByType(uint8 _pauseType) external; + function unPauseByType(PauseType _pauseType) external; /** * @notice Check if a pause type is enabled. * @param _pauseType The pause type value. * @return boolean True if the pause type if enabled, false otherwise. */ - function isPaused(uint8 _pauseType) external view returns (bool); + function isPaused(PauseType _pauseType) external view returns (bool); } diff --git a/contracts/contracts/interfaces/l1/ILineaRollup.sol b/contracts/contracts/interfaces/l1/ILineaRollup.sol index 65c0f452a..7fd2819b6 100644 --- a/contracts/contracts/interfaces/l1/ILineaRollup.sol +++ b/contracts/contracts/interfaces/l1/ILineaRollup.sol @@ -22,6 +22,7 @@ interface ILineaRollup { * @param pauseTypeRoles The list of pause type roles. * @param unpauseTypeRoles The list of unpause type roles. * @param fallbackOperator The account to be given OPERATOR_ROLE on when the time since last finalization lapses. + * @param defaultAdmin The account to be given DEFAULT_ADMIN_ROLE on initialization. */ struct InitializationData { bytes32 initialStateRootHash; @@ -34,6 +35,7 @@ interface ILineaRollup { IPauseManager.PauseTypeRole[] pauseTypeRoles; IPauseManager.PauseTypeRole[] unpauseTypeRoles; address fallbackOperator; + address defaultAdmin; } /** diff --git a/contracts/contracts/lib/L2MessageServicePauseManager.sol b/contracts/contracts/lib/L2MessageServicePauseManager.sol new file mode 100644 index 000000000..75e551bd7 --- /dev/null +++ b/contracts/contracts/lib/L2MessageServicePauseManager.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity >=0.8.19 <=0.8.26; + +import { PauseManager } from "./PauseManager.sol"; + +/** + * @title Contract to manage cross-chain function pausing for LineaRollup. + * @author ConsenSys Software Inc. + * @custom:security-contact security-report@linea.build + */ +abstract contract L2MessageServicePauseManager is PauseManager { + bytes32 public constant PAUSE_L1_L2_ROLE = keccak256("PAUSE_L1_L2_ROLE"); + bytes32 public constant UNPAUSE_L1_L2_ROLE = keccak256("UNPAUSE_L1_L2_ROLE"); + bytes32 public constant PAUSE_L2_L1_ROLE = keccak256("PAUSE_L2_L1_ROLE"); + bytes32 public constant UNPAUSE_L2_L1_ROLE = keccak256("UNPAUSE_L2_L1_ROLE"); +} diff --git a/contracts/contracts/lib/LineaRollupPauseManager.sol b/contracts/contracts/lib/LineaRollupPauseManager.sol new file mode 100644 index 000000000..5dc8f7af3 --- /dev/null +++ b/contracts/contracts/lib/LineaRollupPauseManager.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity >=0.8.19 <=0.8.26; + +import { PauseManager } from "./PauseManager.sol"; + +/** + * @title Contract to manage cross-chain function pausing for LineaRollup. + * @author ConsenSys Software Inc. + * @custom:security-contact security-report@linea.build + */ +abstract contract LineaRollupPauseManager is PauseManager { + bytes32 public constant PAUSE_L1_L2_ROLE = keccak256("PAUSE_L1_L2_ROLE"); + bytes32 public constant UNPAUSE_L1_L2_ROLE = keccak256("UNPAUSE_L1_L2_ROLE"); + bytes32 public constant PAUSE_L2_L1_ROLE = keccak256("PAUSE_L2_L1_ROLE"); + bytes32 public constant UNPAUSE_L2_L1_ROLE = keccak256("UNPAUSE_L2_L1_ROLE"); + bytes32 public constant PAUSE_BLOB_SUBMISSION_ROLE = keccak256("PAUSE_BLOB_SUBMISSION_ROLE"); + bytes32 public constant UNPAUSE_BLOB_SUBMISSION_ROLE = keccak256("UNPAUSE_BLOB_SUBMISSION_ROLE"); + bytes32 public constant PAUSE_FINALIZE_WITHPROOF_ROLE = keccak256("PAUSE_FINALIZE_WITHPROOF_ROLE"); + bytes32 public constant UNPAUSE_FINALIZE_WITHPROOF_ROLE = keccak256("UNPAUSE_FINALIZE_WITHPROOF_ROLE"); +} diff --git a/contracts/contracts/lib/PauseManager.sol b/contracts/contracts/lib/PauseManager.sol index 8407a0e85..42dfa06e7 100644 --- a/contracts/contracts/lib/PauseManager.sol +++ b/contracts/contracts/lib/PauseManager.sol @@ -13,30 +13,13 @@ import { IPauseManager } from "../interfaces/IPauseManager.sol"; abstract contract PauseManager is Initializable, IPauseManager, AccessControlUpgradeable { bytes32 public constant PAUSE_ALL_ROLE = keccak256("PAUSE_ALL_ROLE"); bytes32 public constant UNPAUSE_ALL_ROLE = keccak256("UNPAUSE_ALL_ROLE"); - bytes32 public constant PAUSE_L1_L2_ROLE = keccak256("PAUSE_L1_L2_ROLE"); - bytes32 public constant UNPAUSE_L1_L2_ROLE = keccak256("UNPAUSE_L1_L2_ROLE"); - bytes32 public constant PAUSE_L2_L1_ROLE = keccak256("PAUSE_L2_L1_ROLE"); - bytes32 public constant UNPAUSE_L2_L1_ROLE = keccak256("UNPAUSE_L2_L1_ROLE"); - bytes32 public constant PAUSE_L2_BLOB_SUBMISSION_ROLE = keccak256("PAUSE_L2_BLOB_SUBMISSION_ROLE"); - bytes32 public constant UNPAUSE_L2_BLOB_SUBMISSION_ROLE = keccak256("UNPAUSE_L2_BLOB_SUBMISSION_ROLE"); - bytes32 public constant PAUSE_FINALIZE_WITHPROOF_ROLE = keccak256("PAUSE_FINALIZE_WITHPROOF_ROLE"); - bytes32 public constant UNPAUSE_FINALIZE_WITHPROOF_ROLE = keccak256("UNPAUSE_FINALIZE_WITHPROOF_ROLE"); - - uint8 public constant GENERAL_PAUSE_TYPE = 1; - uint8 public constant L1_L2_PAUSE_TYPE = 2; - uint8 public constant L2_L1_PAUSE_TYPE = 3; - uint8 public constant BLOB_SUBMISSION_PAUSE_TYPE = 4; - uint8 public constant CALLDATA_SUBMISSION_PAUSE_TYPE = 5; - uint8 public constant FINALIZATION_PAUSE_TYPE = 6; - uint8 public constant INITIATE_TOKEN_BRIDGING_PAUSE_TYPE = 7; - uint8 public constant COMPLETE_TOKEN_BRIDGING_PAUSE_TYPE = 8; // @dev DEPRECATED. USE _pauseTypeStatusesBitMap INSTEAD mapping(bytes32 pauseType => bool pauseStatus) public pauseTypeStatuses; uint256 private _pauseTypeStatusesBitMap; - mapping(uint8 pauseType => bytes32 role) private pauseTypeRoles; - mapping(uint8 unPauseType => bytes32 role) private unPauseTypeRoles; + mapping(PauseType pauseType => bytes32 role) private _pauseTypeRoles; + mapping(PauseType unPauseType => bytes32 role) private _unPauseTypeRoles; /// @dev Total contract storage is 11 slots with the gap below. /// @dev Keep 7 free storage slots for future implementation updates to avoid storage collision. @@ -50,7 +33,7 @@ abstract contract PauseManager is Initializable, IPauseManager, AccessControlUpg * * - The type must not be paused. */ - modifier whenTypeAndGeneralNotPaused(uint8 _pauseType) { + modifier whenTypeAndGeneralNotPaused(PauseType _pauseType) { _requireTypeAndGeneralNotPaused(_pauseType); _; } @@ -62,7 +45,7 @@ abstract contract PauseManager is Initializable, IPauseManager, AccessControlUpg * * - The type must not be paused. */ - modifier whenTypeNotPaused(uint8 _pauseType) { + modifier whenTypeNotPaused(PauseType _pauseType) { _requireTypeNotPaused(_pauseType); _; } @@ -70,20 +53,22 @@ abstract contract PauseManager is Initializable, IPauseManager, AccessControlUpg /** * @notice Initializes the pause manager with the given pause and unpause roles. * @dev This function is called during contract initialization to set up the pause and unpause roles. - * @param _pauseTypeRoles An array of PauseTypeRole structs defining the pause types and their associated roles. - * @param _unPauseTypeRoles An array of PauseTypeRole structs defining the unpause types and their associated roles. + * @param _pauseTypeRoleAssignments An array of PauseTypeRole structs defining the pause types and their associated roles. + * @param _unpauseTypeRoleAssignments An array of PauseTypeRole structs defining the unpause types and their associated roles. */ function __PauseManager_init( - PauseTypeRole[] calldata _pauseTypeRoles, - PauseTypeRole[] calldata _unPauseTypeRoles + PauseTypeRole[] calldata _pauseTypeRoleAssignments, + PauseTypeRole[] calldata _unpauseTypeRoleAssignments ) internal onlyInitializing { - uint256 arrayLength = _pauseTypeRoles.length; + uint256 arrayLength = _pauseTypeRoleAssignments.length; for (uint256 i; i < arrayLength; i++) { - pauseTypeRoles[_pauseTypeRoles[i].pauseType] = _pauseTypeRoles[i].role; + _pauseTypeRoles[_pauseTypeRoleAssignments[i].pauseType] = _pauseTypeRoleAssignments[i].role; + emit PauseTypeRoleSet(_pauseTypeRoleAssignments[i].pauseType, _pauseTypeRoleAssignments[i].role); } - arrayLength = _unPauseTypeRoles.length; + arrayLength = _unpauseTypeRoleAssignments.length; for (uint256 i; i < arrayLength; i++) { - unPauseTypeRoles[_unPauseTypeRoles[i].pauseType] = _unPauseTypeRoles[i].role; + _unPauseTypeRoles[_unpauseTypeRoleAssignments[i].pauseType] = _unpauseTypeRoleAssignments[i].role; + emit UnPauseTypeRoleSet(_unpauseTypeRoleAssignments[i].pauseType, _unpauseTypeRoleAssignments[i].role); } } @@ -92,15 +77,15 @@ abstract contract PauseManager is Initializable, IPauseManager, AccessControlUpg * @dev Checks the specific and general pause types. * @param _pauseType The pause type value being checked. */ - function _requireTypeAndGeneralNotPaused(uint8 _pauseType) internal view virtual { + function _requireTypeAndGeneralNotPaused(PauseType _pauseType) internal view virtual { uint256 pauseBitMap = _pauseTypeStatusesBitMap; if (pauseBitMap & (1 << uint256(_pauseType)) != 0) { revert IsPaused(_pauseType); } - if (pauseBitMap & (1 << uint256(GENERAL_PAUSE_TYPE)) != 0) { - revert IsPaused(GENERAL_PAUSE_TYPE); + if (pauseBitMap & (1 << uint256(PauseType.GENERAL)) != 0) { + revert IsPaused(PauseType.GENERAL); } } @@ -109,7 +94,7 @@ abstract contract PauseManager is Initializable, IPauseManager, AccessControlUpg * @dev Checks the specific pause type. * @param _pauseType The pause type value being checked. */ - function _requireTypeNotPaused(uint8 _pauseType) internal view virtual { + function _requireTypeNotPaused(PauseType _pauseType) internal view virtual { if (isPaused(_pauseType)) { revert IsPaused(_pauseType); } @@ -117,10 +102,10 @@ abstract contract PauseManager is Initializable, IPauseManager, AccessControlUpg /** * @notice Pauses functionality by specific type. - * @dev Requires the role mapped in pauseTypeRoles for the pauseType. + * @dev Requires the role mapped in `_pauseTypeRoles` for the pauseType. * @param _pauseType The pause type value. */ - function pauseByType(uint8 _pauseType) external onlyRole(pauseTypeRoles[_pauseType]) { + function pauseByType(PauseType _pauseType) external onlyRole(_pauseTypeRoles[_pauseType]) { if (isPaused(_pauseType)) { revert IsPaused(_pauseType); } @@ -131,10 +116,10 @@ abstract contract PauseManager is Initializable, IPauseManager, AccessControlUpg /** * @notice Unpauses functionality by specific type. - * @dev Requires the role mapped in unPauseTypeRoles for the pauseType. + * @dev Requires the role mapped in `_unPauseTypeRoles` for the pauseType. * @param _pauseType The pause type value. */ - function unPauseByType(uint8 _pauseType) external onlyRole(unPauseTypeRoles[_pauseType]) { + function unPauseByType(PauseType _pauseType) external onlyRole(_unPauseTypeRoles[_pauseType]) { if (!isPaused(_pauseType)) { revert IsNotPaused(_pauseType); } @@ -148,7 +133,7 @@ abstract contract PauseManager is Initializable, IPauseManager, AccessControlUpg * @param _pauseType The pause type value. * @return boolean True if the pause type if enabled, false otherwise. */ - function isPaused(uint8 _pauseType) public view returns (bool) { + function isPaused(PauseType _pauseType) public view returns (bool) { return (_pauseTypeStatusesBitMap & (1 << uint256(_pauseType))) != 0; } } diff --git a/contracts/contracts/lib/PermissionsManager.sol b/contracts/contracts/lib/PermissionsManager.sol index 2636220f1..5c8aca574 100644 --- a/contracts/contracts/lib/PermissionsManager.sol +++ b/contracts/contracts/lib/PermissionsManager.sol @@ -24,6 +24,11 @@ abstract contract PermissionsManager is Initializable, AccessControlUpgradeable, if (_roleAddresses[i].addressWithRole == address(0)) { revert ZeroAddressNotAllowed(); } + + if (_roleAddresses[i].role == 0x0) { + revert ZeroHashNotAllowed(); + } + _grantRole(_roleAddresses[i].role, _roleAddresses[i].addressWithRole); } } diff --git a/contracts/contracts/lib/TokenBridgePauseManager.sol b/contracts/contracts/lib/TokenBridgePauseManager.sol new file mode 100644 index 000000000..90250687d --- /dev/null +++ b/contracts/contracts/lib/TokenBridgePauseManager.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity >=0.8.19 <=0.8.26; + +import { PauseManager } from "./PauseManager.sol"; + +/** + * @title Contract to manage cross-chain function pausing for LineaRollup. + * @author ConsenSys Software Inc. + * @custom:security-contact security-report@linea.build + */ +abstract contract TokenBridgePauseManager is PauseManager { + bytes32 public constant PAUSE_INITIATE_TOKEN_BRIDGING_ROLE = keccak256("PAUSE_INITIATE_TOKEN_BRIDGING_ROLE"); + bytes32 public constant UNPAUSE_INITIATE_TOKEN_BRIDGING_ROLE = keccak256("UNPAUSE_INITIATE_TOKEN_BRIDGING_ROLE"); + bytes32 public constant PAUSE_COMPLETE_TOKEN_BRIDGING_ROLE = keccak256("PAUSE_COMPLETE_TOKEN_BRIDGING_ROLE"); + bytes32 public constant UNPAUSE_COMPLETE_TOKEN_BRIDGING_ROLE = keccak256("UNPAUSE_COMPLETE_TOKEN_BRIDGING_ROLE"); +} diff --git a/contracts/contracts/messageService/l1/L1MessageService.sol b/contracts/contracts/messageService/l1/L1MessageService.sol index 1ba733948..ef627eebc 100644 --- a/contracts/contracts/messageService/l1/L1MessageService.sol +++ b/contracts/contracts/messageService/l1/L1MessageService.sol @@ -60,7 +60,7 @@ abstract contract L1MessageService is address _to, uint256 _fee, bytes calldata _calldata - ) external payable whenTypeAndGeneralNotPaused(L1_L2_PAUSE_TYPE) { + ) external payable whenTypeAndGeneralNotPaused(PauseType.L1_L2) { if (_to == address(0)) { revert ZeroAddressNotAllowed(); } @@ -88,7 +88,7 @@ abstract contract L1MessageService is function claimMessageWithProof( ClaimMessageWithProofParams calldata _params ) external nonReentrant distributeFees(_params.fee, _params.to, _params.data, _params.feeRecipient) { - _requireTypeAndGeneralNotPaused(L2_L1_PAUSE_TYPE); + _requireTypeAndGeneralNotPaused(PauseType.L2_L1); uint256 merkleDepth = l2MerkleRootsDepths[_params.merkleRoot]; diff --git a/contracts/contracts/messageService/l1/v1/L1MessageServiceV1.sol b/contracts/contracts/messageService/l1/v1/L1MessageServiceV1.sol index adbd4f0a9..598e48a9d 100644 --- a/contracts/contracts/messageService/l1/v1/L1MessageServiceV1.sol +++ b/contracts/contracts/messageService/l1/v1/L1MessageServiceV1.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.26; import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; -import { PauseManager } from "../../../lib/PauseManager.sol"; +import { LineaRollupPauseManager } from "../../../lib/LineaRollupPauseManager.sol"; import { RateLimiter } from "../../lib/RateLimiter.sol"; import { L1MessageManagerV1 } from "./L1MessageManagerV1.sol"; import { TransientStorageReentrancyGuardUpgradeable } from "../TransientStorageReentrancyGuardUpgradeable.sol"; @@ -20,7 +20,7 @@ abstract contract L1MessageServiceV1 is RateLimiter, L1MessageManagerV1, TransientStorageReentrancyGuardUpgradeable, - PauseManager, + LineaRollupPauseManager, IMessageService { using MessageHashing for *; @@ -117,7 +117,7 @@ abstract contract L1MessageServiceV1 is bytes calldata _calldata, uint256 _nonce ) external nonReentrant distributeFees(_fee, _to, _calldata, _feeRecipient) { - _requireTypeAndGeneralNotPaused(L2_L1_PAUSE_TYPE); + _requireTypeAndGeneralNotPaused(PauseType.L2_L1); /// @dev This is placed earlier to fix the stack issue by using these two earlier on. TransientStorageHelpers.tstoreAddress(MESSAGE_SENDER_TRANSIENT_KEY, _from); diff --git a/contracts/contracts/messageService/l2/L2MessageManager.sol b/contracts/contracts/messageService/l2/L2MessageManager.sol index 48fa16b2d..20f033fe4 100644 --- a/contracts/contracts/messageService/l2/L2MessageManager.sol +++ b/contracts/contracts/messageService/l2/L2MessageManager.sol @@ -37,7 +37,7 @@ abstract contract L2MessageManager is AccessControlUpgradeable, IL2MessageManage uint256 _startingMessageNumber, uint256 _finalMessageNumber, bytes32 _finalRollingHash - ) external whenTypeNotPaused(GENERAL_PAUSE_TYPE) onlyRole(L1_L2_MESSAGE_SETTER_ROLE) { + ) external whenTypeNotPaused(PauseType.GENERAL) onlyRole(L1_L2_MESSAGE_SETTER_ROLE) { uint256 messageHashesLength = _messageHashes.length; if (messageHashesLength == 0) { diff --git a/contracts/contracts/messageService/l2/L2MessageService.sol b/contracts/contracts/messageService/l2/L2MessageService.sol index 430118038..e37510597 100644 --- a/contracts/contracts/messageService/l2/L2MessageService.sol +++ b/contracts/contracts/messageService/l2/L2MessageService.sol @@ -28,6 +28,7 @@ contract L2MessageService is AccessControlUpgradeable, L2MessageServiceV1, L2Mes * @notice Initializes underlying message service dependencies. * @param _rateLimitPeriod The period to rate limit against. * @param _rateLimitAmount The limit allowed for withdrawing the period. + * @param _defaultAdmin The account to be given DEFAULT_ADMIN_ROLE on initialization. * @param _roleAddresses The list of addresses to grant roles to. * @param _pauseTypeRoles The list of pause type roles. * @param _unpauseTypeRoles The list of unpause type roles. @@ -35,6 +36,7 @@ contract L2MessageService is AccessControlUpgradeable, L2MessageServiceV1, L2Mes function initialize( uint256 _rateLimitPeriod, uint256 _rateLimitAmount, + address _defaultAdmin, RoleAddress[] calldata _roleAddresses, PauseTypeRole[] calldata _pauseTypeRoles, PauseTypeRole[] calldata _unpauseTypeRoles @@ -47,6 +49,12 @@ contract L2MessageService is AccessControlUpgradeable, L2MessageServiceV1, L2Mes __ReentrancyGuard_init(); __PauseManager_init(_pauseTypeRoles, _unpauseTypeRoles); + /** + * @dev DEFAULT_ADMIN_ROLE is set for the security council explicitly, + * as the permissions init purposefully does not allow DEFAULT_ADMIN_ROLE to be set. + */ + _grantRole(DEFAULT_ADMIN_ROLE, _defaultAdmin); + __Permissions_init(_roleAddresses); nextMessageNumber = 1; diff --git a/contracts/contracts/messageService/l2/v1/L2MessageManagerV1.sol b/contracts/contracts/messageService/l2/v1/L2MessageManagerV1.sol index 68d2e6f11..4dfa206e9 100644 --- a/contracts/contracts/messageService/l2/v1/L2MessageManagerV1.sol +++ b/contracts/contracts/messageService/l2/v1/L2MessageManagerV1.sol @@ -3,14 +3,14 @@ pragma solidity 0.8.19; import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import { IL2MessageManagerV1 } from "../../../interfaces/l2/IL2MessageManagerV1.sol"; -import { PauseManager } from "../../../lib/PauseManager.sol"; +import { L2MessageServicePauseManager } from "../../../lib/L2MessageServicePauseManager.sol"; /** * @title Contract to manage cross-chain message hashes storage and statuses on L2. * @author ConsenSys Software Inc. * @custom:security-contact security-report@linea.build */ -abstract contract L2MessageManagerV1 is Initializable, PauseManager, IL2MessageManagerV1 { +abstract contract L2MessageManagerV1 is Initializable, L2MessageServicePauseManager, IL2MessageManagerV1 { uint8 public constant INBOX_STATUS_UNKNOWN = 0; uint8 public constant INBOX_STATUS_RECEIVED = 1; uint8 public constant INBOX_STATUS_CLAIMED = 2; diff --git a/contracts/contracts/messageService/l2/v1/L2MessageServiceV1.sol b/contracts/contracts/messageService/l2/v1/L2MessageServiceV1.sol index f31c534ef..34f53479f 100644 --- a/contracts/contracts/messageService/l2/v1/L2MessageServiceV1.sol +++ b/contracts/contracts/messageService/l2/v1/L2MessageServiceV1.sol @@ -63,7 +63,7 @@ abstract contract L2MessageServiceV1 is * @param _calldata The calldata to pass to the recipient. */ function sendMessage(address _to, uint256 _fee, bytes calldata _calldata) external payable { - _requireTypeAndGeneralNotPaused(L2_L1_PAUSE_TYPE); + _requireTypeAndGeneralNotPaused(PauseType.L2_L1); if (_to == address(0)) { revert ZeroAddressNotAllowed(); @@ -121,7 +121,7 @@ abstract contract L2MessageServiceV1 is bytes calldata _calldata, uint256 _nonce ) external nonReentrant distributeFees(_fee, _to, _calldata, _feeRecipient) { - _requireTypeAndGeneralNotPaused(L1_L2_PAUSE_TYPE); + _requireTypeAndGeneralNotPaused(PauseType.L1_L2); bytes32 messageHash = MessageHashing._hashMessage(_from, _to, _fee, _value, _nonce, _calldata); diff --git a/contracts/contracts/tokenBridge/TokenBridge.sol b/contracts/contracts/tokenBridge/TokenBridge.sol index 4cf2a5a30..82a96e92f 100644 --- a/contracts/contracts/tokenBridge/TokenBridge.sol +++ b/contracts/contracts/tokenBridge/TokenBridge.sol @@ -16,7 +16,7 @@ import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/I import { BridgedToken } from "./BridgedToken.sol"; import { MessageServiceBase } from "../messageService/MessageServiceBase.sol"; -import { PauseManager } from "../lib/PauseManager.sol"; +import { TokenBridgePauseManager } from "../lib/TokenBridgePauseManager.sol"; import { AccessControlUpgradeable } from "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol"; import { StorageFiller39 } from "./lib/StorageFiller39.sol"; import { PermissionsManager } from "../lib/PermissionsManager.sol"; @@ -34,7 +34,7 @@ contract TokenBridge is ReentrancyGuardUpgradeable, AccessControlUpgradeable, MessageServiceBase, - PauseManager, + TokenBridgePauseManager, PermissionsManager, StorageFiller39 { @@ -50,11 +50,6 @@ contract TokenBridge is bytes32 public constant REMOVE_RESERVED_TOKEN_ROLE = keccak256("REMOVE_RESERVED_TOKEN_ROLE"); bytes32 public constant SET_CUSTOM_CONTRACT_ROLE = keccak256("SET_CUSTOM_CONTRACT_ROLE"); - bytes32 public constant PAUSE_INITIATE_TOKEN_BRIDGING_ROLE = keccak256("PAUSE_INITIATE_TOKEN_BRIDGING_ROLE"); - bytes32 public constant UNPAUSE_INITIATE_TOKEN_BRIDGING_ROLE = keccak256("UNPAUSE_INITIATE_TOKEN_BRIDGING_ROLE"); - bytes32 public constant PAUSE_COMPLETE_TOKEN_BRIDGING_ROLE = keccak256("PAUSE_COMPLETE_TOKEN_BRIDGING_ROLE"); - bytes32 public constant UNPAUSE_COMPLETE_TOKEN_BRIDGING_ROLE = keccak256("UNPAUSE_COMPLETE_TOKEN_BRIDGING_ROLE"); - // solhint-disable-next-line var-name-mixedcase bytes4 internal constant _PERMIT_SELECTOR = IERC20PermitUpgradeable.permit.selector; @@ -133,6 +128,13 @@ contract TokenBridge is __PauseManager_init(_initializationData.pauseTypeRoles, _initializationData.unpauseTypeRoles); __MessageServiceBase_init(_initializationData.messageService); __ReentrancyGuard_init(); + + /** + * @dev DEFAULT_ADMIN_ROLE is set for the security council explicitly, + * as the permissions init purposefully does not allow DEFAULT_ADMIN_ROLE to be set. + */ + _grantRole(DEFAULT_ADMIN_ROLE, _initializationData.defaultAdmin); + __Permissions_init(_initializationData.roleAddresses); tokenBeacon = _initializationData.tokenBeacon; @@ -198,7 +200,7 @@ contract TokenBridge is uint256 _amount, address _recipient ) public payable nonZeroAddress(_token) nonZeroAddress(_recipient) nonZeroAmount(_amount) nonReentrant { - _requireTypeAndGeneralNotPaused(INITIATE_TOKEN_BRIDGING_PAUSE_TYPE); + _requireTypeAndGeneralNotPaused(PauseType.INITIATE_TOKEN_BRIDGING); uint256 sourceChainIdCache = sourceChainId; address nativeMappingValue = nativeToBridgedToken[sourceChainIdCache][_token]; if (nativeMappingValue == RESERVED_STATUS) { @@ -289,7 +291,7 @@ contract TokenBridge is nonReentrant onlyMessagingService onlyAuthorizedRemoteSender - whenTypeAndGeneralNotPaused(COMPLETE_TOKEN_BRIDGING_PAUSE_TYPE) + whenTypeAndGeneralNotPaused(PauseType.COMPLETE_TOKEN_BRIDGING) { address nativeMappingValue = nativeToBridgedToken[_chainId][_nativeToken]; address bridgedToken; diff --git a/contracts/contracts/tokenBridge/interfaces/ITokenBridge.sol b/contracts/contracts/tokenBridge/interfaces/ITokenBridge.sol index 19ae53645..8d392276d 100644 --- a/contracts/contracts/tokenBridge/interfaces/ITokenBridge.sol +++ b/contracts/contracts/tokenBridge/interfaces/ITokenBridge.sol @@ -12,6 +12,7 @@ import { IPermissionsManager } from "../../interfaces/IPermissionsManager.sol"; interface ITokenBridge { /** * @dev Contract will be used as proxy implementation. + * @param defaultAdmin The account to be given DEFAULT_ADMIN_ROLE on initialization. * @param messageService The address of the MessageService contract. * @param tokenBeacon The address of the tokenBeacon. * @param sourceChainId The source chain id of the current layer. @@ -22,6 +23,7 @@ interface ITokenBridge { * @param unpauseTypeRoles The list of unpause type roles. */ struct InitializationData { + address defaultAdmin; address messageService; address tokenBeacon; uint256 sourceChainId; diff --git a/contracts/contracts/tokenBridge/mocks/MessageBridgeV2/MockMessageServiceV2.sol b/contracts/contracts/tokenBridge/mocks/MessageBridgeV2/MockMessageServiceV2.sol index 6ab22ec91..cc4e83ba1 100644 --- a/contracts/contracts/tokenBridge/mocks/MessageBridgeV2/MockMessageServiceV2.sol +++ b/contracts/contracts/tokenBridge/mocks/MessageBridgeV2/MockMessageServiceV2.sol @@ -3,10 +3,10 @@ pragma solidity >=0.8.19 <=0.8.26; import { IMessageService } from "../../../interfaces/IMessageService.sol"; import { IGenericErrors } from "../../../interfaces/IGenericErrors.sol"; -import { PauseManager } from "../../../lib/PauseManager.sol"; +import { LineaRollupPauseManager } from "../../../lib/LineaRollupPauseManager.sol"; import { L1MessageManager } from "../../../messageService/l1/L1MessageManager.sol"; -contract MockMessageServiceV2 is L1MessageManager, IMessageService, PauseManager, IGenericErrors { +contract MockMessageServiceV2 is L1MessageManager, IMessageService, LineaRollupPauseManager, IGenericErrors { address internal messageSender = address(0); uint256 public nextMessageNumber = 1; @@ -22,7 +22,7 @@ contract MockMessageServiceV2 is L1MessageManager, IMessageService, PauseManager address _to, uint256 _fee, bytes calldata _calldata - ) external payable whenTypeAndGeneralNotPaused(L1_L2_PAUSE_TYPE) { + ) external payable whenTypeAndGeneralNotPaused(PauseType.L1_L2) { if (_to == address(0)) { revert ZeroAddressNotAllowed(); } diff --git a/contracts/deploy/01_deploy_PlonkVerifier.ts b/contracts/deploy/01_deploy_PlonkVerifier.ts index 16eed746e..587fd4114 100644 --- a/contracts/deploy/01_deploy_PlonkVerifier.ts +++ b/contracts/deploy/01_deploy_PlonkVerifier.ts @@ -1,16 +1,20 @@ +import { ethers } from "hardhat"; import { DeployFunction } from "hardhat-deploy/types"; import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { deployFromFactory, requireEnv } from "../scripts/hardhat/utils"; -import { validateDeployBranchAndTags } from "../utils/auditedDeployVerifier"; -import { getDeployedContractAddress, tryStoreAddress } from "../utils/storeAddress"; -import { tryVerifyContract } from "../utils/verifyContract"; -import { ethers } from "hardhat"; +import { deployFromFactory } from "../scripts/hardhat/utils"; +import { + tryVerifyContract, + getDeployedContractAddress, + tryStoreAddress, + validateDeployBranchAndTags, + getRequiredEnvVar, +} from "../common/helpers"; const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployments } = hre; validateDeployBranchAndTags(hre.network.name); - const contractName = requireEnv("PLONKVERIFIER_NAME"); + const contractName = getRequiredEnvVar("PLONKVERIFIER_NAME"); const existingContractAddress = await getDeployedContractAddress(contractName, deployments); const provider = ethers.provider; diff --git a/contracts/deploy/02_deploy_Timelock.ts b/contracts/deploy/02_deploy_Timelock.ts index 8a01e507b..27947bd30 100644 --- a/contracts/deploy/02_deploy_Timelock.ts +++ b/contracts/deploy/02_deploy_Timelock.ts @@ -1,11 +1,15 @@ import { ethers } from "hardhat"; import { DeployFunction } from "hardhat-deploy/types"; import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { deployFromFactory, requireEnv } from "../scripts/hardhat/utils"; +import { deployFromFactory } from "../scripts/hardhat/utils"; import { get1559Fees } from "../scripts/utils"; -import { validateDeployBranchAndTags } from "../utils/auditedDeployVerifier"; -import { getDeployedContractAddress, tryStoreAddress } from "../utils/storeAddress"; -import { tryVerifyContractWithConstructorArgs } from "../utils/verifyContract"; +import { + getDeployedContractAddress, + getRequiredEnvVar, + tryStoreAddress, + tryVerifyContractWithConstructorArgs, + validateDeployBranchAndTags, +} from "../common/helpers"; const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployments } = hre; @@ -17,13 +21,13 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const provider = ethers.provider; // This should be the safe - const timeLockProposers = requireEnv("TIMELOCK_PROPOSERS"); + const timeLockProposers = getRequiredEnvVar("TIMELOCK_PROPOSERS"); // This should be the safe - const timelockExecutors = requireEnv("TIMELOCK_EXECUTORS"); + const timelockExecutors = getRequiredEnvVar("TIMELOCK_EXECUTORS"); // This should be the safe - const adminAddress = requireEnv("TIMELOCK_ADMIN_ADDRESS"); + const adminAddress = getRequiredEnvVar("TIMELOCK_ADMIN_ADDRESS"); const minDelay = process.env.MIN_DELAY || 0; diff --git a/contracts/deploy/03_deploy_ImplementationForProxy.ts b/contracts/deploy/03_deploy_ImplementationForProxy.ts index c57ff0d05..55c159c59 100644 --- a/contracts/deploy/03_deploy_ImplementationForProxy.ts +++ b/contracts/deploy/03_deploy_ImplementationForProxy.ts @@ -1,19 +1,21 @@ import { ethers, upgrades } from "hardhat"; import { DeployFunction } from "hardhat-deploy/types"; import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { requireEnv } from "../scripts/hardhat/utils"; -import { validateDeployBranchAndTags } from "../utils/auditedDeployVerifier"; -import { getDeployedContractAddress } from "../utils/storeAddress"; -import { tryVerifyContract } from "../utils/verifyContract"; +import { + getDeployedContractAddress, + getRequiredEnvVar, + tryVerifyContract, + validateDeployBranchAndTags, +} from "../common/helpers"; const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployments } = hre; validateDeployBranchAndTags(hre.network.name); - const contractName = requireEnv("CONTRACT_NAME"); + const contractName = getRequiredEnvVar("CONTRACT_NAME"); const existingContractAddress = await getDeployedContractAddress(contractName, deployments); - const proxyAddress = requireEnv("PROXY_ADDRESS"); + const proxyAddress = getRequiredEnvVar("PROXY_ADDRESS"); const factory = await ethers.getContractFactory(contractName); diff --git a/contracts/deploy/03_deploy_LineaRollup.ts b/contracts/deploy/03_deploy_LineaRollup.ts index f8a9b85d8..9bc863508 100644 --- a/contracts/deploy/03_deploy_LineaRollup.ts +++ b/contracts/deploy/03_deploy_LineaRollup.ts @@ -1,33 +1,22 @@ import { DeployFunction } from "hardhat-deploy/types"; import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { deployUpgradableFromFactory, requireEnv } from "../scripts/hardhat/utils"; -import { validateDeployBranchAndTags } from "../utils/auditedDeployVerifier"; -import { getDeployedContractAddress, tryStoreAddress } from "../utils/storeAddress"; -import { tryVerifyContract } from "../utils/verifyContract"; +import { deployUpgradableFromFactory } from "../scripts/hardhat/utils"; +import { + generateRoleAssignments, + getEnvVarOrDefault, + getRequiredEnvVar, + tryVerifyContract, + getDeployedContractAddress, + tryStoreAddress, + validateDeployBranchAndTags, +} from "../common/helpers"; import { - BLOB_SUBMISSION_PAUSE_TYPE, - CALLDATA_SUBMISSION_PAUSE_TYPE, - DEFAULT_ADMIN_ROLE, - FINALIZATION_PAUSE_TYPE, - FINALIZE_WITHOUT_PROOF_ROLE, - GENERAL_PAUSE_TYPE, - L1_L2_PAUSE_TYPE, - L2_L1_PAUSE_TYPE, - PAUSE_ALL_ROLE, - PAUSE_FINALIZE_WITHPROOF_ROLE, - PAUSE_L1_L2_ROLE, - PAUSE_L2_BLOB_SUBMISSION_ROLE, - PAUSE_L2_L1_ROLE, - UNPAUSE_ALL_ROLE, - UNPAUSE_FINALIZE_WITHPROOF_ROLE, - UNPAUSE_L1_L2_ROLE, - UNPAUSE_L2_BLOB_SUBMISSION_ROLE, - UNPAUSE_L2_L1_ROLE, - VERIFIER_SETTER_ROLE, - VERIFIER_UNSETTER_ROLE, - OPERATOR_ROLE, LINEA_ROLLUP_INITIALIZE_SIGNATURE, -} from "contracts/test/utils/constants"; + LINEA_ROLLUP_PAUSE_TYPES_ROLES, + LINEA_ROLLUP_ROLES, + LINEA_ROLLUP_UNPAUSE_TYPES_ROLES, + OPERATOR_ROLE, +} from "../common/constants"; const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployments } = hre; @@ -37,111 +26,50 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const verifierName = "PlonkVerifier"; const existingContractAddress = await getDeployedContractAddress(contractName, deployments); let verifierAddress = await getDeployedContractAddress(verifierName, deployments); - if (verifierAddress === undefined) { - if (process.env["PLONKVERIFIER_ADDRESS"] !== undefined) { - console.log(`Using environment variable for PlonkVerifier , ${process.env["PLONKVERIFIER_ADDRESS"]}`); - verifierAddress = process.env["PLONKVERIFIER_ADDRESS"]; - } else { - throw "Missing PLONKVERIFIER_ADDRESS environment variable"; - } + if (!verifierAddress) { + verifierAddress = getRequiredEnvVar("PLONKVERIFIER_ADDRESS"); } else { console.log(`Using deployed variable for PlonkVerifier , ${verifierAddress}`); } // LineaRollup DEPLOYED AS UPGRADEABLE PROXY - const LineaRollup_initialStateRootHash = requireEnv("LINEA_ROLLUP_INITIAL_STATE_ROOT_HASH"); - const LineaRollup_initialL2BlockNumber = requireEnv("LINEA_ROLLUP_INITIAL_L2_BLOCK_NUMBER"); - const LineaRollup_securityCouncil = requireEnv("LINEA_ROLLUP_SECURITY_COUNCIL"); - const LineaRollup_operators = requireEnv("LINEA_ROLLUP_OPERATORS").split(","); - const LineaRollup_rateLimitPeriodInSeconds = requireEnv("LINEA_ROLLUP_RATE_LIMIT_PERIOD"); - const LineaRollup_rateLimitAmountInWei = requireEnv("LINEA_ROLLUP_RATE_LIMIT_AMOUNT"); - const LineaRollup_genesisTimestamp = requireEnv("LINEA_ROLLUP_GENESIS_TIMESTAMP"); + const lineaRollupInitialStateRootHash = getRequiredEnvVar("LINEA_ROLLUP_INITIAL_STATE_ROOT_HASH"); + const lineaRollupInitialL2BlockNumber = getRequiredEnvVar("LINEA_ROLLUP_INITIAL_L2_BLOCK_NUMBER"); + const lineaRollupSecurityCouncil = getRequiredEnvVar("LINEA_ROLLUP_SECURITY_COUNCIL"); + const lineaRollupOperators = getRequiredEnvVar("LINEA_ROLLUP_OPERATORS").split(","); + const lineaRollupRateLimitPeriodInSeconds = getRequiredEnvVar("LINEA_ROLLUP_RATE_LIMIT_PERIOD"); + const lineaRollupRateLimitAmountInWei = getRequiredEnvVar("LINEA_ROLLUP_RATE_LIMIT_AMOUNT"); + const lineaRollupGenesisTimestamp = getRequiredEnvVar("LINEA_ROLLUP_GENESIS_TIMESTAMP"); const MultiCallAddress = "0xcA11bde05977b3631167028862bE2a173976CA11"; - const LineaRollup_roleAddresses = process.env["LINEA_ROLLUP_ROLE_ADDRESSES"]; - const LineaRollup_pauseTypeRoles = process.env["LINEA_ROLLUP_PAUSE_TYPE_ROLES"]; - const LineaRollup_unpauseTypeRoles = process.env["LINEA_ROLLUP_UNPAUSE_TYPE_ROLES"]; - let pauseTypeRoles = []; - const pauseTypeRolesDefault = [ - { pauseType: GENERAL_PAUSE_TYPE, role: PAUSE_ALL_ROLE }, - { pauseType: L1_L2_PAUSE_TYPE, role: PAUSE_L1_L2_ROLE }, - { pauseType: L2_L1_PAUSE_TYPE, role: PAUSE_L2_L1_ROLE }, - { pauseType: BLOB_SUBMISSION_PAUSE_TYPE, role: PAUSE_L2_BLOB_SUBMISSION_ROLE }, - { pauseType: CALLDATA_SUBMISSION_PAUSE_TYPE, role: PAUSE_L2_BLOB_SUBMISSION_ROLE }, - { pauseType: FINALIZATION_PAUSE_TYPE, role: PAUSE_FINALIZE_WITHPROOF_ROLE }, - ]; + const pauseTypeRoles = getEnvVarOrDefault("LINEA_ROLLUP_PAUSE_TYPE_ROLES", LINEA_ROLLUP_PAUSE_TYPES_ROLES); + const unpauseTypeRoles = getEnvVarOrDefault("LINEA_ROLLUP_UNPAUSE_TYPE_ROLES", LINEA_ROLLUP_UNPAUSE_TYPES_ROLES); + const defaultRoleAddresses = generateRoleAssignments(LINEA_ROLLUP_ROLES, lineaRollupSecurityCouncil, [ + { role: OPERATOR_ROLE, addresses: lineaRollupOperators }, + ]); + const roleAddresses = getEnvVarOrDefault("LINEA_ROLLUP_ROLE_ADDRESSES", defaultRoleAddresses); - if (LineaRollup_pauseTypeRoles !== undefined) { - console.log("Using provided LINEA_ROLLUP_PAUSE_TYPE_ROLES environment variable"); - pauseTypeRoles = JSON.parse(LineaRollup_pauseTypeRoles); - } else { - console.log("Using default pauseTypeRoles"); - pauseTypeRoles = pauseTypeRolesDefault; - } - - let unpauseTypeRoles = []; - const unpauseTypeRolesDefault = [ - { pauseType: GENERAL_PAUSE_TYPE, role: UNPAUSE_ALL_ROLE }, - { pauseType: L1_L2_PAUSE_TYPE, role: UNPAUSE_L1_L2_ROLE }, - { pauseType: L2_L1_PAUSE_TYPE, role: UNPAUSE_L2_L1_ROLE }, - { pauseType: BLOB_SUBMISSION_PAUSE_TYPE, role: UNPAUSE_L2_BLOB_SUBMISSION_ROLE }, - { pauseType: CALLDATA_SUBMISSION_PAUSE_TYPE, role: UNPAUSE_L2_BLOB_SUBMISSION_ROLE }, - { pauseType: FINALIZATION_PAUSE_TYPE, role: UNPAUSE_FINALIZE_WITHPROOF_ROLE }, - ]; - - if (LineaRollup_unpauseTypeRoles !== undefined) { - console.log("Using provided LINEA_ROLLUP_UNPAUSE_TYPE_ROLES environment variable"); - unpauseTypeRoles = JSON.parse(LineaRollup_unpauseTypeRoles); - } else { - console.log("Using default unpauseTypeRoles"); - unpauseTypeRoles = unpauseTypeRolesDefault; - } - - let roleAddresses = []; - const roleAddressesDefault = [ - { addressWithRole: LineaRollup_securityCouncil, role: DEFAULT_ADMIN_ROLE }, - { addressWithRole: LineaRollup_securityCouncil, role: VERIFIER_SETTER_ROLE }, - { addressWithRole: LineaRollup_securityCouncil, role: VERIFIER_UNSETTER_ROLE }, - { addressWithRole: LineaRollup_securityCouncil, role: PAUSE_ALL_ROLE }, - { addressWithRole: LineaRollup_securityCouncil, role: UNPAUSE_ALL_ROLE }, - { addressWithRole: LineaRollup_securityCouncil, role: PAUSE_L2_BLOB_SUBMISSION_ROLE }, - { addressWithRole: LineaRollup_securityCouncil, role: UNPAUSE_L2_BLOB_SUBMISSION_ROLE }, - { addressWithRole: LineaRollup_securityCouncil, role: PAUSE_FINALIZE_WITHPROOF_ROLE }, - { addressWithRole: LineaRollup_securityCouncil, role: UNPAUSE_FINALIZE_WITHPROOF_ROLE }, - { addressWithRole: LineaRollup_securityCouncil, role: FINALIZE_WITHOUT_PROOF_ROLE }, - ]; - - for (let i = 0; i < LineaRollup_operators.length; i++) { - roleAddressesDefault.push({ addressWithRole: LineaRollup_operators[i], role: OPERATOR_ROLE }); - } - - if (LineaRollup_roleAddresses !== undefined) { - console.log("Using provided LINEA_ROLLUP_ROLE_ADDRESSES environment variable"); - roleAddresses = JSON.parse(LineaRollup_roleAddresses); - } else { - console.log("Using default roleAddresses"); - roleAddresses = roleAddressesDefault; - } - - if (existingContractAddress === undefined) { + if (!existingContractAddress) { console.log(`Deploying initial version, NB: the address will be saved if env SAVE_ADDRESS=true.`); } else { console.log(`Deploying new version, NB: ${existingContractAddress} will be overwritten if env SAVE_ADDRESS=true.`); } + const contract = await deployUpgradableFromFactory( "LineaRollup", [ { - initialStateRootHash: LineaRollup_initialStateRootHash, - initialL2BlockNumber: LineaRollup_initialL2BlockNumber, - genesisTimestamp: LineaRollup_genesisTimestamp, + initialStateRootHash: lineaRollupInitialStateRootHash, + initialL2BlockNumber: lineaRollupInitialL2BlockNumber, + genesisTimestamp: lineaRollupGenesisTimestamp, defaultVerifier: verifierAddress, - rateLimitPeriodInSeconds: LineaRollup_rateLimitPeriodInSeconds, - rateLimitAmountInWei: LineaRollup_rateLimitAmountInWei, - roleAddresses: roleAddresses, - pauseTypeRoles: pauseTypeRoles, - unpauseTypeRoles: unpauseTypeRoles, + rateLimitPeriodInSeconds: lineaRollupRateLimitPeriodInSeconds, + rateLimitAmountInWei: lineaRollupRateLimitAmountInWei, + roleAddresses, + pauseTypeRoles, + unpauseTypeRoles, fallbackOperator: MultiCallAddress, + defaultAdmin: lineaRollupSecurityCouncil, }, ], { diff --git a/contracts/deploy/03_deploy_LineaRollupAlphaV3.ts b/contracts/deploy/03_deploy_LineaRollupAlphaV3.ts index 55751522f..b8208369b 100644 --- a/contracts/deploy/03_deploy_LineaRollupAlphaV3.ts +++ b/contracts/deploy/03_deploy_LineaRollupAlphaV3.ts @@ -1,11 +1,14 @@ import { DeployFunction } from "hardhat-deploy/types"; import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { requireEnv } from "../scripts/hardhat/utils"; -import { validateDeployBranchAndTags } from "../utils/auditedDeployVerifier"; -import { getDeployedContractAddress, tryStoreAddress } from "../utils/storeAddress"; -import { tryVerifyContract } from "../utils/verifyContract"; -import { deployUpgradableContractWithProxyAdmin } from "contracts/utils/deployments"; import { LineaRollupAlphaV3__factory } from "../typechain-types"; +import { + tryVerifyContract, + deployUpgradableContractWithProxyAdmin, + getDeployedContractAddress, + tryStoreAddress, + validateDeployBranchAndTags, + getRequiredEnvVar, +} from "../common/helpers"; const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployments } = hre; @@ -27,13 +30,13 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { } // LineaRollup DEPLOYED AS UPGRADEABLE PROXY - const LineaRollup_initialStateRootHash = requireEnv("LINEA_ROLLUP_INITIAL_STATE_ROOT_HASH"); - const LineaRollup_initialL2BlockNumber = requireEnv("LINEA_ROLLUP_INITIAL_L2_BLOCK_NUMBER"); - const LineaRollup_securityCouncil = requireEnv("LINEA_ROLLUP_SECURITY_COUNCIL"); - const LineaRollup_operators = requireEnv("LINEA_ROLLUP_OPERATORS"); - const LineaRollup_rateLimitPeriodInSeconds = requireEnv("LINEA_ROLLUP_RATE_LIMIT_PERIOD"); - const LineaRollup_rateLimitAmountInWei = requireEnv("LINEA_ROLLUP_RATE_LIMIT_AMOUNT"); - const LineaRollup_genesisTimestamp = requireEnv("LINEA_ROLLUP_GENESIS_TIMESTAMP"); + const LineaRollup_initialStateRootHash = getRequiredEnvVar("LINEA_ROLLUP_INITIAL_STATE_ROOT_HASH"); + const LineaRollup_initialL2BlockNumber = getRequiredEnvVar("LINEA_ROLLUP_INITIAL_L2_BLOCK_NUMBER"); + const LineaRollup_securityCouncil = getRequiredEnvVar("LINEA_ROLLUP_SECURITY_COUNCIL"); + const LineaRollup_operators = getRequiredEnvVar("LINEA_ROLLUP_OPERATORS"); + const LineaRollup_rateLimitPeriodInSeconds = getRequiredEnvVar("LINEA_ROLLUP_RATE_LIMIT_PERIOD"); + const LineaRollup_rateLimitAmountInWei = getRequiredEnvVar("LINEA_ROLLUP_RATE_LIMIT_AMOUNT"); + const LineaRollup_genesisTimestamp = getRequiredEnvVar("LINEA_ROLLUP_GENESIS_TIMESTAMP"); console.log(`Setting operators ${LineaRollup_operators}`); diff --git a/contracts/deploy/03_deploy_LineaRollupWithReinitialization.ts b/contracts/deploy/03_deploy_LineaRollupWithReinitialization.ts index 1a6a099a6..6f7308549 100644 --- a/contracts/deploy/03_deploy_LineaRollupWithReinitialization.ts +++ b/contracts/deploy/03_deploy_LineaRollupWithReinitialization.ts @@ -1,11 +1,13 @@ import { ethers, upgrades } from "hardhat"; import { DeployFunction } from "hardhat-deploy/types"; import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { requireEnv } from "../scripts/hardhat/utils"; import { LineaRollupInit__factory } from "../typechain-types"; -import { validateDeployBranchAndTags } from "../utils/auditedDeployVerifier"; -import { getDeployedContractAddress } from "../utils/storeAddress"; -import { tryVerifyContract } from "../utils/verifyContract"; +import { + tryVerifyContract, + getDeployedContractAddress, + validateDeployBranchAndTags, + getRequiredEnvVar, +} from "../common/helpers"; const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployments } = hre; @@ -14,7 +16,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const contractName = "LineaRollupInit"; const existingContractAddress = await getDeployedContractAddress(contractName, deployments); - const proxyAddress = requireEnv("LINEA_ROLLUP_ADDRESS"); + const proxyAddress = getRequiredEnvVar("LINEA_ROLLUP_ADDRESS"); const initialL2BlockNumber = "3"; const initialStateRootHash = "0x3450000000000000000000000000000000000000000000000000000000000000"; diff --git a/contracts/deploy/04_deploy_L2MessageService.ts b/contracts/deploy/04_deploy_L2MessageService.ts index 60745d8d5..6c6e2d2ff 100644 --- a/contracts/deploy/04_deploy_L2MessageService.ts +++ b/contracts/deploy/04_deploy_L2MessageService.ts @@ -1,32 +1,22 @@ import { DeployFunction } from "hardhat-deploy/types"; import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { deployUpgradableFromFactory, requireEnv } from "../scripts/hardhat/utils"; -import { validateDeployBranchAndTags } from "../utils/auditedDeployVerifier"; -import { getDeployedContractAddress, tryStoreAddress } from "../utils/storeAddress"; -import { tryVerifyContract } from "../utils/verifyContract"; +import { deployUpgradableFromFactory } from "../scripts/hardhat/utils"; +import { + generateRoleAssignments, + getEnvVarOrDefault, + getRequiredEnvVar, + tryVerifyContract, + getDeployedContractAddress, + tryStoreAddress, + validateDeployBranchAndTags, +} from "../common/helpers"; import { - BLOB_SUBMISSION_PAUSE_TYPE, - CALLDATA_SUBMISSION_PAUSE_TYPE, - DEFAULT_ADMIN_ROLE, - FINALIZATION_PAUSE_TYPE, - GENERAL_PAUSE_TYPE, L1_L2_MESSAGE_SETTER_ROLE, - L1_L2_PAUSE_TYPE, - L2_L1_PAUSE_TYPE, - MINIMUM_FEE_SETTER_ROLE, - PAUSE_ALL_ROLE, - PAUSE_FINALIZE_WITHPROOF_ROLE, - PAUSE_L1_L2_ROLE, - PAUSE_L2_BLOB_SUBMISSION_ROLE, - PAUSE_L2_L1_ROLE, - RATE_LIMIT_SETTER_ROLE, - UNPAUSE_ALL_ROLE, - UNPAUSE_FINALIZE_WITHPROOF_ROLE, - UNPAUSE_L1_L2_ROLE, - UNPAUSE_L2_BLOB_SUBMISSION_ROLE, - UNPAUSE_L2_L1_ROLE, - USED_RATE_LIMIT_RESETTER_ROLE, -} from "contracts/test/utils/constants"; + L2_MESSAGE_SERVICE_INITIALIZE_SIGNATURE, + L2_MESSAGE_SERVICE_PAUSE_TYPES_ROLES, + L2_MESSAGE_SERVICE_ROLES, + L2_MESSAGE_SERVICE_UNPAUSE_TYPES_ROLES, +} from "../common/constants"; const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployments } = hre; @@ -35,73 +25,22 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const contractName = "L2MessageService"; const existingContractAddress = await getDeployedContractAddress(contractName, deployments); - const L2MessageService_securityCouncil = requireEnv("L2MSGSERVICE_SECURITY_COUNCIL"); - const L2MessageService_l1l2MessageSetter = requireEnv("L2MSGSERVICE_L1L2_MESSAGE_SETTER"); - const L2MessageService_rateLimitPeriod = requireEnv("L2MSGSERVICE_RATE_LIMIT_PERIOD"); - const L2MessageService_rateLimitAmount = requireEnv("L2MSGSERVICE_RATE_LIMIT_AMOUNT"); - const L2MessageService_roleAddress = process.env["L2MSGSERVICE_ROLE_ADDRESSES"]; - const L2MessageService_pauseTypeRoles = process.env["L2MSGSERVICE_PAUSE_TYPE_ROLES"]; - const L2MessageService_unpauseTypeRoles = process.env["L2MSGSERVICE_UNPAUSE_TYPE_ROLES"]; - - let pauseTypeRoles = {}; - const pauseTypeRolesDefault = [ - { pauseType: GENERAL_PAUSE_TYPE, role: PAUSE_ALL_ROLE }, - { pauseType: L1_L2_PAUSE_TYPE, role: PAUSE_L1_L2_ROLE }, - { pauseType: L2_L1_PAUSE_TYPE, role: PAUSE_L2_L1_ROLE }, - { pauseType: BLOB_SUBMISSION_PAUSE_TYPE, role: PAUSE_L2_BLOB_SUBMISSION_ROLE }, - { pauseType: CALLDATA_SUBMISSION_PAUSE_TYPE, role: PAUSE_L2_BLOB_SUBMISSION_ROLE }, - { pauseType: FINALIZATION_PAUSE_TYPE, role: PAUSE_FINALIZE_WITHPROOF_ROLE }, - ]; - - if (L2MessageService_pauseTypeRoles !== undefined) { - console.log("Using provided L2MSGSERVICE_PAUSE_TYPE_ROLES environment variable"); - pauseTypeRoles = L2MessageService_pauseTypeRoles; - } else { - console.log("Using default pauseTypeRoles"); - pauseTypeRoles = pauseTypeRolesDefault; - } - - let unpauseTypeRoles = {}; - const unpauseTypeRolesDefault = [ - { pauseType: GENERAL_PAUSE_TYPE, role: UNPAUSE_ALL_ROLE }, - { pauseType: L1_L2_PAUSE_TYPE, role: UNPAUSE_L1_L2_ROLE }, - { pauseType: L2_L1_PAUSE_TYPE, role: UNPAUSE_L2_L1_ROLE }, - { pauseType: BLOB_SUBMISSION_PAUSE_TYPE, role: UNPAUSE_L2_BLOB_SUBMISSION_ROLE }, - { pauseType: CALLDATA_SUBMISSION_PAUSE_TYPE, role: UNPAUSE_L2_BLOB_SUBMISSION_ROLE }, - { pauseType: FINALIZATION_PAUSE_TYPE, role: UNPAUSE_FINALIZE_WITHPROOF_ROLE }, - ]; + const l2MessageServiceSecurityCouncil = getRequiredEnvVar("L2MSGSERVICE_SECURITY_COUNCIL"); + const l2MessageServiceL1L2MessageSetter = getRequiredEnvVar("L2MSGSERVICE_L1L2_MESSAGE_SETTER"); + const l2MessageServiceRateLimitPeriod = getRequiredEnvVar("L2MSGSERVICE_RATE_LIMIT_PERIOD"); + const l2MessageServiceRateLimitAmount = getRequiredEnvVar("L2MSGSERVICE_RATE_LIMIT_AMOUNT"); - if (L2MessageService_unpauseTypeRoles !== undefined) { - console.log("Using provided L2MSGSERVICE_UNPAUSE_TYPE_ROLES environment variable"); - unpauseTypeRoles = L2MessageService_unpauseTypeRoles; - } else { - console.log("Using default unpauseTypeRoles"); - unpauseTypeRoles = unpauseTypeRolesDefault; - } - - let roleAddresses = {}; - const roleAddressDefault = [ - { addressWithRole: L2MessageService_securityCouncil, role: DEFAULT_ADMIN_ROLE }, - { addressWithRole: L2MessageService_securityCouncil, role: MINIMUM_FEE_SETTER_ROLE }, - { addressWithRole: L2MessageService_securityCouncil, role: RATE_LIMIT_SETTER_ROLE }, - { addressWithRole: L2MessageService_securityCouncil, role: USED_RATE_LIMIT_RESETTER_ROLE }, - { addressWithRole: L2MessageService_securityCouncil, role: PAUSE_ALL_ROLE }, - { addressWithRole: L2MessageService_securityCouncil, role: UNPAUSE_ALL_ROLE }, - { addressWithRole: L2MessageService_securityCouncil, role: PAUSE_L1_L2_ROLE }, - { addressWithRole: L2MessageService_securityCouncil, role: UNPAUSE_L1_L2_ROLE }, - { addressWithRole: L2MessageService_securityCouncil, role: PAUSE_L2_L1_ROLE }, - { addressWithRole: L2MessageService_securityCouncil, role: UNPAUSE_L2_L1_ROLE }, - { addressWithRole: L2MessageService_l1l2MessageSetter, role: L1_L2_MESSAGE_SETTER_ROLE }, - ]; - if (L2MessageService_roleAddress !== undefined) { - console.log("Using provided L2MSGSERVICE_ROLE_ADDRESSES environment variable"); - roleAddresses = L2MessageService_roleAddress; - } else { - console.log("Using default roleAddresses"); - roleAddresses = roleAddressDefault; - } + const pauseTypeRoles = getEnvVarOrDefault("L2MSGSERVICE_PAUSE_TYPE_ROLES", L2_MESSAGE_SERVICE_PAUSE_TYPES_ROLES); + const unpauseTypeRoles = getEnvVarOrDefault( + "L2MSGSERVICE_UNPAUSE_TYPE_ROLES", + L2_MESSAGE_SERVICE_UNPAUSE_TYPES_ROLES, + ); + const defaultRoleAddresses = generateRoleAssignments(L2_MESSAGE_SERVICE_ROLES, l2MessageServiceSecurityCouncil, [ + { role: L1_L2_MESSAGE_SETTER_ROLE, addresses: [l2MessageServiceL1L2MessageSetter] }, + ]); + const roleAddresses = getEnvVarOrDefault("L2MSGSERVICE_ROLE_ADDRESSES", defaultRoleAddresses); - if (existingContractAddress === undefined) { + if (!existingContractAddress) { console.log(`Deploying initial version, NB: the address will be saved if env SAVE_ADDRESS=true.`); } else { console.log(`Deploying new version, NB: ${existingContractAddress} will be overwritten if env SAVE_ADDRESS=true.`); @@ -110,14 +49,15 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const contract = await deployUpgradableFromFactory( "L2MessageService", [ - L2MessageService_rateLimitPeriod, - L2MessageService_rateLimitAmount, + l2MessageServiceRateLimitPeriod, + l2MessageServiceRateLimitAmount, + l2MessageServiceSecurityCouncil, roleAddresses, pauseTypeRoles, unpauseTypeRoles, ], { - initializer: "initialize(uint256,uint256,(address,bytes32)[],(uint8,bytes32)[],(uint8,bytes32)[])", + initializer: L2_MESSAGE_SERVICE_INITIALIZE_SIGNATURE, unsafeAllow: ["constructor"], }, ); diff --git a/contracts/deploy/04_deploy_L2MessageServiceImplementation.ts b/contracts/deploy/04_deploy_L2MessageServiceImplementation.ts index 761ef71c0..4984a5822 100644 --- a/contracts/deploy/04_deploy_L2MessageServiceImplementation.ts +++ b/contracts/deploy/04_deploy_L2MessageServiceImplementation.ts @@ -1,9 +1,7 @@ +import { ethers, upgrades } from "hardhat"; import { HardhatRuntimeEnvironment } from "hardhat/types"; import { DeployFunction } from "hardhat-deploy/types"; -import { getDeployedContractAddress } from "../utils/storeAddress"; -import { tryVerifyContract } from "../utils/verifyContract"; -import { validateDeployBranchAndTags } from "../utils/auditedDeployVerifier"; -import { ethers, upgrades } from "hardhat"; +import { validateDeployBranchAndTags, tryVerifyContract, getDeployedContractAddress } from "../common/helpers"; const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployments } = hre; diff --git a/contracts/deploy/04_deploy_L2MessageServiceV1Deployed.ts b/contracts/deploy/04_deploy_L2MessageServiceV1Deployed.ts index 91d5a41b0..1e7d91ea5 100644 --- a/contracts/deploy/04_deploy_L2MessageServiceV1Deployed.ts +++ b/contracts/deploy/04_deploy_L2MessageServiceV1Deployed.ts @@ -3,10 +3,14 @@ import { ethers } from "hardhat"; import { DeployFunction } from "hardhat-deploy/types"; import { HardhatRuntimeEnvironment } from "hardhat/types"; import path from "path"; -import { deployUpgradableWithAbiAndByteCode, requireEnv } from "../scripts/hardhat/utils"; -import { validateDeployBranchAndTags } from "../utils/auditedDeployVerifier"; -import { getDeployedContractAddress, tryStoreAddress } from "../utils/storeAddress"; -import { tryVerifyContract } from "../utils/verifyContract"; +import { deployUpgradableWithAbiAndByteCode } from "../scripts/hardhat/utils"; +import { + tryVerifyContract, + getDeployedContractAddress, + tryStoreAddress, + validateDeployBranchAndTags, + getRequiredEnvVar, +} from "../common/helpers"; import { abi, bytecode } from "./V1/L2MessageServiceV1Deployed.json"; const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { @@ -27,10 +31,10 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const contractName = "L2MessageServiceLineaMainnet"; const existingContractAddress = await getDeployedContractAddress(contractName, deployments); - const L2MessageService_securityCouncil = requireEnv("L2MSGSERVICE_SECURITY_COUNCIL"); - const L2MessageService_l1l2MessageSetter = requireEnv("L2MSGSERVICE_L1L2_MESSAGE_SETTER"); - const L2MessageService_rateLimitPeriod = requireEnv("L2MSGSERVICE_RATE_LIMIT_PERIOD"); - const L2MessageService_rateLimitAmount = requireEnv("L2MSGSERVICE_RATE_LIMIT_AMOUNT"); + const L2MessageService_securityCouncil = getRequiredEnvVar("L2MSGSERVICE_SECURITY_COUNCIL"); + const L2MessageService_l1l2MessageSetter = getRequiredEnvVar("L2MSGSERVICE_L1L2_MESSAGE_SETTER"); + const L2MessageService_rateLimitPeriod = getRequiredEnvVar("L2MSGSERVICE_RATE_LIMIT_PERIOD"); + const L2MessageService_rateLimitAmount = getRequiredEnvVar("L2MSGSERVICE_RATE_LIMIT_AMOUNT"); if (existingContractAddress === undefined) { console.log(`Deploying initial version, NB: the address will be saved if env SAVE_ADDRESS=true.`); diff --git a/contracts/deploy/05_deploy_BridgedToken.ts b/contracts/deploy/05_deploy_BridgedToken.ts index 4cf69463f..9d3588d54 100644 --- a/contracts/deploy/05_deploy_BridgedToken.ts +++ b/contracts/deploy/05_deploy_BridgedToken.ts @@ -2,9 +2,12 @@ import { ethers, network, upgrades } from "hardhat"; import { DeployFunction } from "hardhat-deploy/types"; import { HardhatRuntimeEnvironment } from "hardhat/types"; import { BridgedToken } from "../typechain-types"; -import { validateDeployBranchAndTags } from "../utils/auditedDeployVerifier"; -import { getDeployedContractAddress, tryStoreAddress } from "../utils/storeAddress"; -import { tryVerifyContract } from "../utils/verifyContract"; +import { + tryVerifyContract, + getDeployedContractAddress, + tryStoreAddress, + validateDeployBranchAndTags, +} from "../common/helpers"; const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployments } = hre; diff --git a/contracts/deploy/06_deploy_TokenBridge.ts b/contracts/deploy/06_deploy_TokenBridge.ts index f9725bdfe..469c431e8 100644 --- a/contracts/deploy/06_deploy_TokenBridge.ts +++ b/contracts/deploy/06_deploy_TokenBridge.ts @@ -1,10 +1,21 @@ import { ethers, network, upgrades } from "hardhat"; import { DeployFunction } from "hardhat-deploy/types"; import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { validateDeployBranchAndTags } from "../utils/auditedDeployVerifier"; -import { getDeployedContractAddress, tryStoreAddress, tryStoreProxyAdminAddress } from "../utils/storeAddress"; -import { tryVerifyContract } from "../utils/verifyContract"; -import { requireEnv } from "../scripts/hardhat/utils"; +import { + TOKEN_BRIDGE_PAUSE_TYPES_ROLES, + TOKEN_BRIDGE_ROLES, + TOKEN_BRIDGE_UNPAUSE_TYPES_ROLES, +} from "../common/constants"; +import { + generateRoleAssignments, + getEnvVarOrDefault, + tryVerifyContract, + getDeployedContractAddress, + tryStoreAddress, + tryStoreProxyAdminAddress, + validateDeployBranchAndTags, + getRequiredEnvVar, +} from "../common/helpers"; const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployments } = hre; @@ -13,26 +24,31 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const contractName = "TokenBridge"; const existingContractAddress = await getDeployedContractAddress(contractName, deployments); - const L2MessageServiceName = "L2MessageService"; - const LineaRollupName = "LineaRollup"; + const l2MessageServiceName = "L2MessageService"; + const lineaRollupName = "LineaRollup"; let l2MessageServiceAddress = process.env.L2_MESSAGE_SERVICE_ADDRESS; - let LineaRollupAddress = process.env.LINEA_ROLLUP_ADDRESS; - const remoteChainId = requireEnv("REMOTE_CHAIN_ID"); + let lineaRollupAddress = process.env.LINEA_ROLLUP_ADDRESS; + const remoteChainId = getRequiredEnvVar("REMOTE_CHAIN_ID"); + const tokenBridgeSecurityCouncil = getRequiredEnvVar("TOKEN_BRIDGE_SECURITY_COUNCIL"); + + const pauseTypeRoles = getEnvVarOrDefault("TOKEN_BRIDGE_PAUSE_TYPES_ROLES", TOKEN_BRIDGE_PAUSE_TYPES_ROLES); + const unpauseTypeRoles = getEnvVarOrDefault("TOKEN_BRIDGE_UNPAUSE_TYPES_ROLES", TOKEN_BRIDGE_UNPAUSE_TYPES_ROLES); + const defaultRoleAddresses = generateRoleAssignments(TOKEN_BRIDGE_ROLES, tokenBridgeSecurityCouncil, []); + const roleAddresses = getEnvVarOrDefault("TOKEN_BRIDGE_ROLE_ADDRESSES", defaultRoleAddresses); - const [owner] = await ethers.getSigners(); const chainId = (await ethers.provider.getNetwork()).chainId; console.log(`Current network's chainId is ${chainId}. Remote (target) network's chainId is ${remoteChainId}`); - if (l2MessageServiceAddress === undefined) { - l2MessageServiceAddress = await getDeployedContractAddress(L2MessageServiceName, deployments); + if (!l2MessageServiceAddress) { + l2MessageServiceAddress = await getDeployedContractAddress(l2MessageServiceName, deployments); } - if (LineaRollupAddress === undefined) { - LineaRollupAddress = await getDeployedContractAddress(LineaRollupName, deployments); + if (!lineaRollupAddress) { + lineaRollupAddress = await getDeployedContractAddress(lineaRollupName, deployments); } - if (existingContractAddress === undefined) { + if (!existingContractAddress) { console.log(`Deploying initial version, NB: the address will be saved if env SAVE_ADDRESS=true.`); } else { console.log(`Deploying new version, NB: ${existingContractAddress} will be overwritten if env SAVE_ADDRESS=true.`); @@ -47,7 +63,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { console.log( `TOKEN_BRIDGE_L1=${process.env.TOKEN_BRIDGE_L1}. Deploying TokenBridge on L1, using L1_RESERVED_TOKEN_ADDRESSES environment variable`, ); - deployingChainMessageService = LineaRollupAddress; + deployingChainMessageService = lineaRollupAddress; reservedAddresses = process.env.L1_RESERVED_TOKEN_ADDRESSES ? process.env.L1_RESERVED_TOKEN_ADDRESSES.split(",") : []; @@ -70,13 +86,19 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const TokenBridgeFactory = await ethers.getContractFactory(contractName); const tokenBridge = await upgrades.deployProxy(TokenBridgeFactory, [ - owner.address, - deployingChainMessageService, - bridgedTokenAddress, - chainId, - remoteChainId, - reservedAddresses, + { + defaultAdmin: tokenBridgeSecurityCouncil, + messageService: deployingChainMessageService, + tokenBeacon: bridgedTokenAddress, + sourceChainId: chainId, + targetChainId: remoteChainId, + reservedTokens: reservedAddresses, + roleAddresses, + pauseTypeRoles, + unpauseTypeRoles, + }, ]); + await tokenBridge.waitForDeployment(); const tokenBridgeAddress = await tokenBridge.getAddress(); diff --git a/contracts/deploy/07_deploy_LXPToken.ts b/contracts/deploy/07_deploy_LXPToken.ts index c165211b8..9719bb83f 100644 --- a/contracts/deploy/07_deploy_LXPToken.ts +++ b/contracts/deploy/07_deploy_LXPToken.ts @@ -1,11 +1,15 @@ import { ethers } from "hardhat"; import { DeployFunction } from "hardhat-deploy/types"; import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { deployFromFactory, requireEnv } from "../scripts/hardhat/utils"; +import { deployFromFactory } from "../scripts/hardhat/utils"; import { get1559Fees } from "../scripts/utils"; -import { validateDeployBranchAndTags } from "../utils/auditedDeployVerifier"; -import { getDeployedContractAddress, tryStoreAddress } from "../utils/storeAddress"; -import { tryVerifyContractWithConstructorArgs } from "../utils/verifyContract"; +import { + tryVerifyContractWithConstructorArgs, + getDeployedContractAddress, + tryStoreAddress, + validateDeployBranchAndTags, + getRequiredEnvVar, +} from "../common/helpers"; const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployments } = hre; @@ -15,7 +19,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const existingContractAddress = await getDeployedContractAddress(contractName, deployments); const provider = ethers.provider; - const adminAddress = requireEnv("LINEA_VOYAGE_XP_ADMIN_ADDRESS"); + const adminAddress = getRequiredEnvVar("LINEA_VOYAGE_XP_ADMIN_ADDRESS"); if (existingContractAddress === undefined) { console.log(`Deploying initial version, NB: the address will be saved if env SAVE_ADDRESS=true.`); diff --git a/contracts/deploy/07_deploy_SurgeXPToken.ts b/contracts/deploy/07_deploy_SurgeXPToken.ts index 0cd011fc0..da7838746 100644 --- a/contracts/deploy/07_deploy_SurgeXPToken.ts +++ b/contracts/deploy/07_deploy_SurgeXPToken.ts @@ -1,11 +1,15 @@ import { ethers } from "hardhat"; import { DeployFunction } from "hardhat-deploy/types"; import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { deployFromFactory, requireEnv } from "../scripts/hardhat/utils"; +import { deployFromFactory } from "../scripts/hardhat/utils"; import { get1559Fees } from "../scripts/utils"; -import { validateDeployBranchAndTags } from "../utils/auditedDeployVerifier"; -import { getDeployedContractAddress, tryStoreAddress } from "../utils/storeAddress"; -import { tryVerifyContractWithConstructorArgs } from "../utils/verifyContract"; +import { + tryVerifyContractWithConstructorArgs, + getDeployedContractAddress, + tryStoreAddress, + validateDeployBranchAndTags, + getRequiredEnvVar, +} from "../common/helpers"; const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployments } = hre; @@ -15,9 +19,9 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const existingContractAddress = await getDeployedContractAddress(contractName, deployments); const provider = ethers.provider; - const adminAddress = requireEnv("LINEA_SURGE_XP_ADMIN_ADDRESS"); - const minterAddress = requireEnv("LINEA_SURGE_XP_MINTER_ADDRESS"); - const transferAddresses = requireEnv("LINEA_SURGE_XP_TRANSFER_ADDRESSES")?.split(","); + const adminAddress = getRequiredEnvVar("LINEA_SURGE_XP_ADMIN_ADDRESS"); + const minterAddress = getRequiredEnvVar("LINEA_SURGE_XP_MINTER_ADDRESS"); + const transferAddresses = getRequiredEnvVar("LINEA_SURGE_XP_TRANSFER_ADDRESSES")?.split(","); console.log(transferAddresses); if (existingContractAddress === undefined) { diff --git a/contracts/deploy/08_deploy_CustomBridgedToken.ts b/contracts/deploy/08_deploy_CustomBridgedToken.ts index b94a94418..f05131e51 100644 --- a/contracts/deploy/08_deploy_CustomBridgedToken.ts +++ b/contracts/deploy/08_deploy_CustomBridgedToken.ts @@ -1,10 +1,14 @@ import { ethers, network } from "hardhat"; import { DeployFunction } from "hardhat-deploy/types"; import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { deployUpgradableFromFactory, requireEnv } from "../scripts/hardhat/utils"; -import { validateDeployBranchAndTags } from "../utils/auditedDeployVerifier"; -import { getDeployedContractAddress, tryStoreAddress } from "../utils/storeAddress"; -import { tryVerifyContract } from "../utils/verifyContract"; +import { deployUpgradableFromFactory } from "../scripts/hardhat/utils"; +import { + tryVerifyContract, + getDeployedContractAddress, + tryStoreAddress, + validateDeployBranchAndTags, + getRequiredEnvVar, +} from "../common/helpers"; const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployments } = hre; @@ -13,10 +17,10 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const contractName = "CustomBridgedToken"; const existingContractAddress = await getDeployedContractAddress(contractName, deployments); - const CustomTokenBridge_name = requireEnv("CUSTOMTOKENBRIDGE_NAME"); - const CustomTokenBridge_symbol = requireEnv("CUSTOMTOKENBRIDGE_SYMBOL"); - const CustomTokenBridge_decimals = requireEnv("CUSTOMTOKENBRIDGE_DECIMALS"); - const CustomTokenBridge_bridge_address = requireEnv("CUSTOMTOKENBRIDGE_BRIDGE_ADDRESS"); + const CustomTokenBridge_name = getRequiredEnvVar("CUSTOMTOKENBRIDGE_NAME"); + const CustomTokenBridge_symbol = getRequiredEnvVar("CUSTOMTOKENBRIDGE_SYMBOL"); + const CustomTokenBridge_decimals = getRequiredEnvVar("CUSTOMTOKENBRIDGE_DECIMALS"); + const CustomTokenBridge_bridge_address = getRequiredEnvVar("CUSTOMTOKENBRIDGE_BRIDGE_ADDRESS"); const chainId = (await ethers.provider.getNetwork()).chainId; console.log(`Current network's chainId is ${chainId}`); diff --git a/contracts/deploy/08_deploy_MYToken.ts b/contracts/deploy/08_deploy_MYToken.ts index 1eb4e1336..67bf63351 100644 --- a/contracts/deploy/08_deploy_MYToken.ts +++ b/contracts/deploy/08_deploy_MYToken.ts @@ -1,10 +1,14 @@ import { ethers } from "hardhat"; import { DeployFunction } from "hardhat-deploy/types"; import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { deployFromFactory, requireEnv } from "../scripts/hardhat/utils"; +import { deployFromFactory } from "../scripts/hardhat/utils"; import { get1559Fees } from "../scripts/utils"; -import { getDeployedContractAddress, tryStoreAddress } from "../utils/storeAddress"; -import { tryVerifyContractWithConstructorArgs } from "../utils/verifyContract"; +import { + tryVerifyContractWithConstructorArgs, + getDeployedContractAddress, + tryStoreAddress, + getRequiredEnvVar, +} from "../common/helpers"; const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployments } = hre; @@ -12,7 +16,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const existingContractAddress = await getDeployedContractAddress(contractName, deployments); const provider = ethers.provider; - const adminAddress = requireEnv("MYTOKEN_ADMIN_ADDRESS"); + const adminAddress = getRequiredEnvVar("MYTOKEN_ADMIN_ADDRESS"); if (existingContractAddress === undefined) { console.log(`Deploying initial version, NB: the address will be saved if env SAVE_ADDRESS=true.`); diff --git a/contracts/deploy/10_deploy_RecoverFunds.ts b/contracts/deploy/10_deploy_RecoverFunds.ts index 5c64f6204..586131e7b 100644 --- a/contracts/deploy/10_deploy_RecoverFunds.ts +++ b/contracts/deploy/10_deploy_RecoverFunds.ts @@ -1,8 +1,7 @@ import { DeployFunction } from "hardhat-deploy/types"; import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { deployUpgradableFromFactory, requireEnv } from "../scripts/hardhat/utils"; -import { getDeployedContractAddress, tryStoreAddress } from "../utils/storeAddress"; -import { tryVerifyContract } from "../utils/verifyContract"; +import { deployUpgradableFromFactory } from "../scripts/hardhat/utils"; +import { tryVerifyContract, getDeployedContractAddress, tryStoreAddress, getRequiredEnvVar } from "../common/helpers"; const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const { deployments } = hre; @@ -11,8 +10,8 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const existingContractAddress = await getDeployedContractAddress(contractName, deployments); // RecoverFunds DEPLOYED AS UPGRADEABLE PROXY - const RecoverFunds_securityCouncil = requireEnv("RECOVERFUNDS_SECURITY_COUNCIL"); - const RecoverFunds_executorAddress = requireEnv("RECOVERFUNDS_EXECUTOR_ADDRESS"); + const RecoverFunds_securityCouncil = getRequiredEnvVar("RECOVERFUNDS_SECURITY_COUNCIL"); + const RecoverFunds_executorAddress = getRequiredEnvVar("RECOVERFUNDS_EXECUTOR_ADDRESS"); console.log(`Setting security council ${RecoverFunds_securityCouncil}`); console.log(`Setting executor address ${RecoverFunds_executorAddress}`); diff --git a/contracts/scripts/gnosis/createZodiacL1.ts b/contracts/scripts/gnosis/createZodiacL1.ts index 4f169a939..397845a2b 100644 --- a/contracts/scripts/gnosis/createZodiacL1.ts +++ b/contracts/scripts/gnosis/createZodiacL1.ts @@ -1,7 +1,7 @@ import { deployAndSetUpModule, KnownContracts } from "@gnosis.pm/zodiac"; import Safe, { CreateTransactionProps, EthersAdapter } from "@safe-global/protocol-kit"; import { ethers } from "ethers"; -import { OPERATOR_ROLE } from "../../test/utils/constants"; +import { OPERATOR_ROLE } from "../../test/common/constants"; import { requireEnv } from "../hardhat/utils"; const main = async () => { diff --git a/contracts/scripts/gnosis/createZodiacL2.ts b/contracts/scripts/gnosis/createZodiacL2.ts index e9898d442..e1bca405f 100644 --- a/contracts/scripts/gnosis/createZodiacL2.ts +++ b/contracts/scripts/gnosis/createZodiacL2.ts @@ -1,7 +1,7 @@ import { deployAndSetUpModule, KnownContracts } from "@gnosis.pm/zodiac"; import Safe, { CreateTransactionProps, EthersAdapter } from "@safe-global/protocol-kit"; import { ethers } from "ethers"; -import { L1_L2_MESSAGE_SETTER_ROLE, OPERATOR_ROLE } from "../../test/utils/constants"; +import { L1_L2_MESSAGE_SETTER_ROLE, OPERATOR_ROLE } from "../../test/common/constants"; import { requireEnv } from "../hardhat/utils"; import { get1559Fees } from "../utils"; diff --git a/contracts/scripts/gnosis/encodingTX.ts b/contracts/scripts/gnosis/encodingTX.ts index f83baa2e6..db18eb049 100644 --- a/contracts/scripts/gnosis/encodingTX.ts +++ b/contracts/scripts/gnosis/encodingTX.ts @@ -1,5 +1,5 @@ import { ethers } from "hardhat"; -import { OPERATOR_ROLE } from "../../test/utils/constants"; +import { OPERATOR_ROLE } from "../../test/common/constants"; import { LineaRollupInit__factory, LineaRollup__factory } from "../../typechain-types"; const main = async () => { diff --git a/contracts/scripts/operational/getCurrentFinalizedBlockNumberTask.ts b/contracts/scripts/operational/getCurrentFinalizedBlockNumberTask.ts index e0df24c72..e0e0a71bd 100644 --- a/contracts/scripts/operational/getCurrentFinalizedBlockNumberTask.ts +++ b/contracts/scripts/operational/getCurrentFinalizedBlockNumberTask.ts @@ -1,5 +1,5 @@ import { task } from "hardhat/config"; -import { getTaskCliOrEnvValue } from "../../utils/environmentHelper"; +import { getTaskCliOrEnvValue } from "../../common/helpers/environmentHelper"; /* ******************************************************************************************* diff --git a/contracts/scripts/operational/grantContractRolesTask.ts b/contracts/scripts/operational/grantContractRolesTask.ts index 7217e64aa..0e11e708c 100644 --- a/contracts/scripts/operational/grantContractRolesTask.ts +++ b/contracts/scripts/operational/grantContractRolesTask.ts @@ -1,5 +1,5 @@ import { task } from "hardhat/config"; -import { getTaskCliOrEnvValue } from "../../utils/environmentHelper"; +import { getTaskCliOrEnvValue } from "../../common/helpers/environmentHelper"; /* ******************************************************************************************* diff --git a/contracts/scripts/operational/renounceContractRolesTask.ts b/contracts/scripts/operational/renounceContractRolesTask.ts index 5dba27903..059052aa4 100644 --- a/contracts/scripts/operational/renounceContractRolesTask.ts +++ b/contracts/scripts/operational/renounceContractRolesTask.ts @@ -1,5 +1,5 @@ import { task } from "hardhat/config"; -import { getTaskCliOrEnvValue } from "../../utils/environmentHelper"; +import { getTaskCliOrEnvValue } from "../../common/helpers/environmentHelper"; /* ******************************************************************************************* diff --git a/contracts/scripts/operational/setRateLimitTask.ts b/contracts/scripts/operational/setRateLimitTask.ts index 850985ce9..04c8fffc2 100644 --- a/contracts/scripts/operational/setRateLimitTask.ts +++ b/contracts/scripts/operational/setRateLimitTask.ts @@ -1,5 +1,5 @@ import { task } from "hardhat/config"; -import { getTaskCliOrEnvValue } from "../../utils/environmentHelper"; +import { getTaskCliOrEnvValue } from "../../common/helpers/environmentHelper"; /* ******************************************************************************************* diff --git a/contracts/scripts/operational/setVerifierAddressTask.ts b/contracts/scripts/operational/setVerifierAddressTask.ts index 2f558b638..62f2888b0 100644 --- a/contracts/scripts/operational/setVerifierAddressTask.ts +++ b/contracts/scripts/operational/setVerifierAddressTask.ts @@ -1,5 +1,5 @@ import { task } from "hardhat/config"; -import { getTaskCliOrEnvValue } from "../../utils/environmentHelper"; +import { getTaskCliOrEnvValue } from "../../common/helpers/environmentHelper"; /* ******************************************************************************************* diff --git a/contracts/scripts/operational/transferOwnershipAndSetRemoteTokenBridgeTask.ts b/contracts/scripts/operational/transferOwnershipAndSetRemoteTokenBridgeTask.ts index 38921e142..90726cf7e 100644 --- a/contracts/scripts/operational/transferOwnershipAndSetRemoteTokenBridgeTask.ts +++ b/contracts/scripts/operational/transferOwnershipAndSetRemoteTokenBridgeTask.ts @@ -1,8 +1,8 @@ // import { ethers, network, upgrades } from "hardhat"; import { task } from "hardhat/config"; import { ProxyAdminReplica, TokenBridge } from "../../typechain-types"; -import { getTaskCliOrEnvValue } from "../../utils/environmentHelper"; -import { getDeployedContractOnNetwork } from "../../utils/readAddress"; +import { getTaskCliOrEnvValue } from "../../common/helpers/environmentHelper"; +import { getDeployedContractOnNetwork } from "../../common/helpers/readAddress"; /* ******************************************************************************************* diff --git a/contracts/scripts/tokenBridge/test/deployBridgedTokenBeacon.ts b/contracts/scripts/tokenBridge/test/deployBridgedTokenBeacon.ts index 45ec8c32b..8d5febd6f 100644 --- a/contracts/scripts/tokenBridge/test/deployBridgedTokenBeacon.ts +++ b/contracts/scripts/tokenBridge/test/deployBridgedTokenBeacon.ts @@ -1,6 +1,5 @@ import { ethers, network, upgrades } from "hardhat"; -import { tryStoreAddress } from "../../../utils/storeAddress"; -import { tryVerifyContract } from "../../../utils/verifyContract"; +import { tryStoreAddress, tryVerifyContract } from "../../../common/helpers"; export async function deployBridgedTokenBeacon(verbose = false) { const BridgedToken = await ethers.getContractFactory("BridgedToken"); diff --git a/contracts/scripts/tokenBridge/test/deployTokenBridges.ts b/contracts/scripts/tokenBridge/test/deployTokenBridges.ts index 062566dc4..8b2ce344f 100644 --- a/contracts/scripts/tokenBridge/test/deployTokenBridges.ts +++ b/contracts/scripts/tokenBridge/test/deployTokenBridges.ts @@ -1,37 +1,17 @@ import { ethers, upgrades } from "hardhat"; import { TokenBridge } from "../../../typechain-types"; -import { SupportedChainIds } from "../../../utils/supportedNetworks"; +import { SupportedChainIds } from "../../../common/supportedNetworks"; import { deployBridgedTokenBeacon } from "./deployBridgedTokenBeacon"; -import { - SET_REMOTE_TOKENBRIDGE_ROLE, - SET_RESERVED_TOKEN_ROLE, - REMOVE_RESERVED_TOKEN_ROLE, - SET_CUSTOM_CONTRACT_ROLE, - SET_MESSAGE_SERVICE_ROLE, - PAUSE_INITIATE_TOKEN_BRIDGING_ROLE, - UNPAUSE_INITIATE_TOKEN_BRIDGING_ROLE, - PAUSE_COMPLETE_TOKEN_BRIDGING_ROLE, - UNPAUSE_COMPLETE_TOKEN_BRIDGING_ROLE, - pauseTypeRoles, - unpauseTypeRoles, -} from "contracts/test/utils/constants"; +import { pauseTypeRoles, unpauseTypeRoles } from "../../../test/common/constants"; +import { generateRoleAssignments } from "contracts/common/helpers"; +import { TOKEN_BRIDGE_ROLES } from "contracts/common/constants"; export async function deployTokenBridge(messageServiceAddress: string, verbose = false) { const [owner] = await ethers.getSigners(); const chainIds = [SupportedChainIds.GOERLI, SupportedChainIds.LINEA_TESTNET]; - const roleAddresses = [ - { addressWithRole: owner.address, role: SET_REMOTE_TOKENBRIDGE_ROLE }, - { addressWithRole: owner.address, role: SET_RESERVED_TOKEN_ROLE }, - { addressWithRole: owner.address, role: REMOVE_RESERVED_TOKEN_ROLE }, - { addressWithRole: owner.address, role: SET_CUSTOM_CONTRACT_ROLE }, - { addressWithRole: owner.address, role: SET_MESSAGE_SERVICE_ROLE }, - { addressWithRole: owner.address, role: PAUSE_INITIATE_TOKEN_BRIDGING_ROLE }, - { addressWithRole: owner.address, role: UNPAUSE_INITIATE_TOKEN_BRIDGING_ROLE }, - { addressWithRole: owner.address, role: PAUSE_COMPLETE_TOKEN_BRIDGING_ROLE }, - { addressWithRole: owner.address, role: UNPAUSE_COMPLETE_TOKEN_BRIDGING_ROLE }, - ]; + const roleAddresses = generateRoleAssignments(TOKEN_BRIDGE_ROLES, owner.address, []); // Deploy beacon for bridged tokens const tokenBeacons = await deployBridgedTokenBeacon(verbose); @@ -41,6 +21,7 @@ export async function deployTokenBridge(messageServiceAddress: string, verbose = const l1TokenBridge = (await upgrades.deployProxy(TokenBridgeFactory, [ { + defaultAdmin: owner.address, messageService: messageServiceAddress, tokenBeacon: await tokenBeacons.l1TokenBeacon.getAddress(), sourceChainId: chainIds[0], @@ -58,6 +39,7 @@ export async function deployTokenBridge(messageServiceAddress: string, verbose = const l2TokenBridge = (await upgrades.deployProxy(TokenBridgeFactory, [ { + defaultAdmin: owner.address, messageService: messageServiceAddress, tokenBeacon: await tokenBeacons.l2TokenBeacon.getAddress(), sourceChainId: chainIds[1], diff --git a/contracts/test/L1MessageService.ts b/contracts/test/L1MessageService.ts index 3ef6b0660..3a36c907a 100644 --- a/contracts/test/L1MessageService.ts +++ b/contracts/test/L1MessageService.ts @@ -37,8 +37,8 @@ import { PAUSE_L1_L2_ROLE, pauseTypeRoles, unpauseTypeRoles, -} from "./utils/constants"; -import { deployFromFactory, deployUpgradableFromFactory } from "./utils/deployment"; +} from "./common/constants"; +import { deployFromFactory, deployUpgradableFromFactory } from "./common/deployment"; import { buildAccessErrorMessage, calculateRollingHash, @@ -47,7 +47,7 @@ import { expectRevertWithCustomError, expectRevertWithReason, generateKeccak256Hash, -} from "./utils/helpers"; +} from "./common/helpers"; describe("L1MessageService", () => { let l1MessageService: TestL1MessageService; diff --git a/contracts/test/L2MessageManager.ts b/contracts/test/L2MessageManager.ts index 066183c61..5fa020e51 100644 --- a/contracts/test/L2MessageManager.ts +++ b/contracts/test/L2MessageManager.ts @@ -11,8 +11,8 @@ import { L1_L2_MESSAGE_SETTER_ROLE, pauseTypeRoles, unpauseTypeRoles, -} from "./utils/constants"; -import { deployUpgradableFromFactory } from "./utils/deployment"; +} from "./common/constants"; +import { deployUpgradableFromFactory } from "./common/deployment"; import { buildAccessErrorMessage, calculateRollingHashFromCollection, @@ -21,7 +21,7 @@ import { expectRevertWithReason, generateKeccak256Hash, generateNKeccak256Hashes, -} from "./utils/helpers"; +} from "./common/helpers"; describe("L2MessageManager", () => { let l2MessageManager: TestL2MessageManager; diff --git a/contracts/test/L2MessageService.ts b/contracts/test/L2MessageService.ts index 97436a46d..cec5c0963 100644 --- a/contracts/test/L2MessageService.ts +++ b/contracts/test/L2MessageService.ts @@ -26,25 +26,31 @@ import { UNPAUSE_ALL_ROLE, RATE_LIMIT_SETTER_ROLE, USED_RATE_LIMIT_RESETTER_ROLE, - unpauseTypeRoles, - pauseTypeRoles, - PAUSE_L1_L2_ROLE, - UNPAUSE_L1_L2_ROLE, - UNPAUSE_L2_L1_ROLE, - PAUSE_L2_L1_ROLE, -} from "./utils/constants"; -import { deployUpgradableFromFactory } from "./utils/deployment"; +} from "./common/constants"; +import { deployUpgradableFromFactory } from "./common/deployment"; import { buildAccessErrorMessage, calculateRollingHash, calculateRollingHashFromCollection, encodeSendMessage, expectEvent, + expectEvents, expectRevertWithCustomError, expectRevertWithReason, + generateKeccak256, generateKeccak256Hash, -} from "./utils/helpers"; +} from "./common/helpers"; import { ZeroAddress } from "ethers"; +import { generateRoleAssignments } from "../common/helpers"; +import { + L2_MESSAGE_SERVICE_PAUSE_TYPES_ROLES, + L2_MESSAGE_SERVICE_ROLES, + L2_MESSAGE_SERVICE_UNPAUSE_TYPES_ROLES, + PAUSE_L1_L2_ROLE, + PAUSE_L2_L1_ROLE, + UNPAUSE_L1_L2_ROLE, + UNPAUSE_L2_L1_ROLE, +} from "../common/constants"; describe("L2MessageService", () => { let l2MessageService: TestL2MessageService; @@ -54,33 +60,27 @@ describe("L2MessageService", () => { let l1l2MessageSetter: SignerWithAddress; let notAuthorizedAccount: SignerWithAddress; let postmanAddress: SignerWithAddress; + let roleAddresses: { role: string; addressWithRole: string }[]; async function deployL2MessageServiceFixture() { - const roleAddresses = [ - { addressWithRole: securityCouncil.address, role: DEFAULT_ADMIN_ROLE }, - { addressWithRole: securityCouncil.address, role: MINIMUM_FEE_SETTER_ROLE }, - { addressWithRole: securityCouncil.address, role: RATE_LIMIT_SETTER_ROLE }, - { addressWithRole: securityCouncil.address, role: USED_RATE_LIMIT_RESETTER_ROLE }, - { addressWithRole: securityCouncil.address, role: PAUSE_ALL_ROLE }, - { addressWithRole: securityCouncil.address, role: UNPAUSE_ALL_ROLE }, - { addressWithRole: securityCouncil.address, role: PAUSE_L1_L2_ROLE }, - { addressWithRole: securityCouncil.address, role: UNPAUSE_L1_L2_ROLE }, - { addressWithRole: securityCouncil.address, role: PAUSE_L2_L1_ROLE }, - { addressWithRole: securityCouncil.address, role: UNPAUSE_L2_L1_ROLE }, - { addressWithRole: l1l2MessageSetter.address, role: L1_L2_MESSAGE_SETTER_ROLE }, - ]; - return deployUpgradableFromFactory("TestL2MessageService", [ ONE_DAY_IN_SECONDS, INITIAL_WITHDRAW_LIMIT, + securityCouncil.address, roleAddresses, - pauseTypeRoles, - unpauseTypeRoles, + L2_MESSAGE_SERVICE_PAUSE_TYPES_ROLES, + L2_MESSAGE_SERVICE_UNPAUSE_TYPES_ROLES, ]) as unknown as Promise; } - beforeEach(async () => { + before(async () => { [admin, securityCouncil, l1l2MessageSetter, notAuthorizedAccount, postmanAddress] = await ethers.getSigners(); + roleAddresses = generateRoleAssignments(L2_MESSAGE_SERVICE_ROLES, securityCouncil.address, [ + { role: L1_L2_MESSAGE_SETTER_ROLE, addresses: [l1l2MessageSetter.address] }, + ]); + }); + + beforeEach(async () => { l2MessageService = await loadFixture(deployL2MessageServiceFixture); }); @@ -130,9 +130,10 @@ describe("L2MessageService", () => { const deployCall = deployUpgradableFromFactory("TestL2MessageService", [ ONE_DAY_IN_SECONDS, 0, - [{ addressWithRole: securityCouncil.address, role: DEFAULT_ADMIN_ROLE }], - pauseTypeRoles, - unpauseTypeRoles, + securityCouncil.address, + roleAddresses, + L2_MESSAGE_SERVICE_PAUSE_TYPES_ROLES, + L2_MESSAGE_SERVICE_UNPAUSE_TYPES_ROLES, ]); await expectRevertWithCustomError(l2MessageService, deployCall, "LimitIsZero"); @@ -142,22 +143,23 @@ describe("L2MessageService", () => { const deployCall = deployUpgradableFromFactory("TestL2MessageService", [ 0, MESSAGE_VALUE_1ETH + MESSAGE_VALUE_1ETH, - [{ addressWithRole: securityCouncil.address, role: DEFAULT_ADMIN_ROLE }], - pauseTypeRoles, - unpauseTypeRoles, + securityCouncil.address, + roleAddresses, + L2_MESSAGE_SERVICE_PAUSE_TYPES_ROLES, + L2_MESSAGE_SERVICE_UNPAUSE_TYPES_ROLES, ]); await expectRevertWithCustomError(l2MessageService, deployCall, "PeriodIsZero"); }); it("Should fail on second initialisation", async () => { - const roleAddresses = [{ addressWithRole: securityCouncil.address, role: DEFAULT_ADMIN_ROLE }]; const deployCall = l2MessageService.initialize( ONE_DAY_IN_SECONDS, INITIAL_WITHDRAW_LIMIT, + securityCouncil.address, roleAddresses, - pauseTypeRoles, - unpauseTypeRoles, + L2_MESSAGE_SERVICE_PAUSE_TYPES_ROLES, + L2_MESSAGE_SERVICE_UNPAUSE_TYPES_ROLES, ); await expectRevertWithReason(deployCall, INITIALIZED_ALREADY_MESSAGE); @@ -1412,6 +1414,8 @@ describe("L2MessageService", () => { }); describe("L2MessageService Upgradeable Tests", () => { + let newRoleAddresses: { addressWithRole: string; role: string }[]; + async function deployL2MessageServiceFixture() { return deployUpgradableFromFactory( "contracts/test-contracts/L2MessageServiceLineaMainnet.sol:L2MessageServiceLineaMainnet", @@ -1419,6 +1423,20 @@ describe("L2MessageService", () => { ) as unknown as Promise; } + before(async () => { + const securityCouncilAddress = securityCouncil.address; + + newRoleAddresses = [ + { addressWithRole: securityCouncilAddress, role: USED_RATE_LIMIT_RESETTER_ROLE }, + { addressWithRole: securityCouncilAddress, role: PAUSE_ALL_ROLE }, + { addressWithRole: securityCouncilAddress, role: PAUSE_L1_L2_ROLE }, + { addressWithRole: securityCouncilAddress, role: PAUSE_L2_L1_ROLE }, + { addressWithRole: securityCouncilAddress, role: UNPAUSE_ALL_ROLE }, + { addressWithRole: securityCouncilAddress, role: UNPAUSE_L1_L2_ROLE }, + { addressWithRole: securityCouncilAddress, role: UNPAUSE_L2_L1_ROLE }, + ]; + }); + beforeEach(async () => { [admin, securityCouncil, l1l2MessageSetter, notAuthorizedAccount, postmanAddress] = await ethers.getSigners(); l2MessageService = await loadFixture(deployL2MessageServiceFixture); @@ -1428,18 +1446,15 @@ describe("L2MessageService", () => { expect(await l2MessageService.nextMessageNumber()).to.equal(1); // Deploy new implementation - const NewL2MessageServiceFactory = await ethers.getContractFactory( + const newL2MessageServiceFactory = await ethers.getContractFactory( "contracts/messageService/l2/L2MessageService.sol:L2MessageService", ); - const newL2MessageService = await upgrades.upgradeProxy(l2MessageService, NewL2MessageServiceFactory); + const newL2MessageService = await upgrades.upgradeProxy(l2MessageService, newL2MessageServiceFactory); await newL2MessageService.reinitializePauseTypesAndPermissions( - [ - { addressWithRole: securityCouncil.address, role: DEFAULT_ADMIN_ROLE }, - { addressWithRole: securityCouncil.address, role: MINIMUM_FEE_SETTER_ROLE }, - ], - pauseTypeRoles, - unpauseTypeRoles, + newRoleAddresses, + L2_MESSAGE_SERVICE_PAUSE_TYPES_ROLES, + L2_MESSAGE_SERVICE_UNPAUSE_TYPES_ROLES, ); expect(await newL2MessageService.nextMessageNumber()).to.equal(1); @@ -1447,21 +1462,88 @@ describe("L2MessageService", () => { it("Should revert with ZeroAddressNotAllowed when addressWithRole is zero address in reinitializePauseTypesAndPermissions", async () => { // Deploy new implementation - const NewL2MessageServiceFactory = await ethers.getContractFactory( + const newL2MessageServiceFactory = await ethers.getContractFactory( "contracts/messageService/l2/L2MessageService.sol:L2MessageService", ); - const newL2MessageService = await upgrades.upgradeProxy(l2MessageService, NewL2MessageServiceFactory); + const newL2MessageService = await upgrades.upgradeProxy(l2MessageService, newL2MessageServiceFactory); - const roleAddresses = [ - { addressWithRole: ZeroAddress, role: DEFAULT_ADMIN_ROLE }, - { addressWithRole: securityCouncil.address, role: MINIMUM_FEE_SETTER_ROLE }, - ]; + const roleAddresses = [...newRoleAddresses, { addressWithRole: ZeroAddress, role: DEFAULT_ADMIN_ROLE }]; await expectRevertWithCustomError( newL2MessageService, - newL2MessageService.reinitializePauseTypesAndPermissions(roleAddresses, pauseTypeRoles, unpauseTypeRoles), + newL2MessageService.reinitializePauseTypesAndPermissions( + roleAddresses, + L2_MESSAGE_SERVICE_PAUSE_TYPES_ROLES, + L2_MESSAGE_SERVICE_UNPAUSE_TYPES_ROLES, + ), "ZeroAddressNotAllowed", ); }); + + it("Should set all permissions", async () => { + // Deploy new implementation + const newL2MessageServiceFactory = await ethers.getContractFactory( + "contracts/messageService/l2/L2MessageService.sol:L2MessageService", + ); + const newL2MessageService = await upgrades.upgradeProxy(l2MessageService, newL2MessageServiceFactory); + + await newL2MessageService.reinitializePauseTypesAndPermissions( + newRoleAddresses, + L2_MESSAGE_SERVICE_PAUSE_TYPES_ROLES, + L2_MESSAGE_SERVICE_UNPAUSE_TYPES_ROLES, + ); + + for (const { role, addressWithRole } of newRoleAddresses) { + expect(await newL2MessageService.hasRole(role, addressWithRole)).to.be.true; + } + }); + + it("Should set all pause types and unpause types in mappings and emit events", async () => { + // Deploy new implementation + const newL2MessageServiceFactory = await ethers.getContractFactory( + "contracts/messageService/l2/L2MessageService.sol:L2MessageService", + ); + const newL2MessageService = await upgrades.upgradeProxy(l2MessageService, newL2MessageServiceFactory); + + const reinitializePromise = newL2MessageService.reinitializePauseTypesAndPermissions( + newRoleAddresses, + L2_MESSAGE_SERVICE_PAUSE_TYPES_ROLES, + L2_MESSAGE_SERVICE_UNPAUSE_TYPES_ROLES, + ); + + await Promise.all([ + expectEvents( + newL2MessageService, + reinitializePromise, + L2_MESSAGE_SERVICE_PAUSE_TYPES_ROLES.map(({ pauseType, role }) => ({ + name: "PauseTypeRoleSet", + args: [pauseType, role], + })), + ), + expectEvents( + newL2MessageService, + reinitializePromise, + L2_MESSAGE_SERVICE_UNPAUSE_TYPES_ROLES.map(({ pauseType, role }) => ({ + name: "UnPauseTypeRoleSet", + args: [pauseType, role], + })), + ), + ]); + + const pauseTypeRolesMappingSlot = 167; + const unpauseTypeRolesMappingSlot = 168; + + for (const { pauseType, role } of L2_MESSAGE_SERVICE_PAUSE_TYPES_ROLES) { + const slot = generateKeccak256(["uint8", "uint256"], [pauseType, pauseTypeRolesMappingSlot]); + const roleInMapping = await ethers.provider.getStorage(newL2MessageService.getAddress(), slot); + expect(roleInMapping).to.equal(role); + } + + for (const { pauseType, role } of L2_MESSAGE_SERVICE_UNPAUSE_TYPES_ROLES) { + const slot = generateKeccak256(["uint8", "uint256"], [pauseType, unpauseTypeRolesMappingSlot]); + const roleInMapping = await ethers.provider.getStorage(newL2MessageService.getAddress(), slot); + expect(roleInMapping).to.equal(role); + } + }); }); }); diff --git a/contracts/test/LineaRollup.ts b/contracts/test/LineaRollup.ts index 6464d4c30..a355afaeb 100644 --- a/contracts/test/LineaRollup.ts +++ b/contracts/test/LineaRollup.ts @@ -29,24 +29,26 @@ import { GENESIS_L2_TIMESTAMP, EMPTY_CALLDATA, INITIALIZED_ALREADY_MESSAGE, - FINALIZE_WITHOUT_PROOF_ROLE, CALLDATA_SUBMISSION_PAUSE_TYPE, BLOB_SUBMISSION_PAUSE_TYPE, FINALIZATION_PAUSE_TYPE, PAUSE_ALL_ROLE, - unpauseTypeRoles, - pauseTypeRoles, DEFAULT_ADMIN_ROLE, UNPAUSE_ALL_ROLE, - PAUSE_L2_BLOB_SUBMISSION_ROLE, - UNPAUSE_L2_BLOB_SUBMISSION_ROLE, + PAUSE_BLOB_SUBMISSION_ROLE, + UNPAUSE_BLOB_SUBMISSION_ROLE, PAUSE_FINALIZE_WITHPROOF_ROLE, UNPAUSE_FINALIZE_WITHPROOF_ROLE, - LINEA_ROLLUP_INITIALIZE_SIGNATURE, DEFAULT_LAST_FINALIZED_TIMESTAMP, SIX_MONTHS_IN_SECONDS, -} from "./utils/constants"; -import { deployUpgradableFromFactory } from "./utils/deployment"; + USED_RATE_LIMIT_RESETTER_ROLE, + PAUSE_L1_L2_ROLE, + PAUSE_L2_L1_ROLE, + UNPAUSE_L1_L2_ROLE, + UNPAUSE_L2_L1_ROLE, + LINEA_ROLLUP_INITIALIZE_SIGNATURE, +} from "./common/constants"; +import { deployUpgradableFromFactory } from "./common/deployment"; import { calculateRollingHash, encodeData, @@ -65,14 +67,20 @@ import { generateParentShnarfData, generateBlobDataSubmission, generateBlobParentShnarfData, - ShnarfDataGenerator, convertStringToPaddedHexBytes, calculateLastFinalizedState, -} from "./utils/helpers"; -import { CalldataSubmissionData } from "./utils/types"; + expectEvents, +} from "./common/helpers"; +import { CalldataSubmissionData, ShnarfDataGenerator } from "./common/types"; import aggregatedProof1To81 from "./testData/compressedData/multipleProofs/aggregatedProof-1-81.json"; import aggregatedProof82To153 from "./testData/compressedData/multipleProofs/aggregatedProof-82-153.json"; import * as kzg from "c-kzg"; +import { + LINEA_ROLLUP_PAUSE_TYPES_ROLES, + LINEA_ROLLUP_ROLES, + LINEA_ROLLUP_UNPAUSE_TYPES_ROLES, +} from "contracts/common/constants"; +import { generateRoleAssignments } from "contracts/common/helpers"; kzg.loadTrustedSetup(`${__dirname}/testData/trusted_setup.txt`); @@ -86,6 +94,7 @@ describe("Linea Rollup contract", () => { let securityCouncil: SignerWithAddress; let operator: SignerWithAddress; let nonAuthorizedAccount: SignerWithAddress; + let roleAddresses: { addressWithRole: string; role: string }[]; const multiCallAddress = "0xcA11bde05977b3631167028862bE2a173976CA11"; @@ -107,21 +116,6 @@ describe("Linea Rollup contract", () => { verifier = await plonkVerifier.getAddress(); - const securityCouncilAddress = securityCouncil.address; - const roleAddresses = [ - { addressWithRole: securityCouncilAddress, role: DEFAULT_ADMIN_ROLE }, - { addressWithRole: securityCouncilAddress, role: VERIFIER_SETTER_ROLE }, - { addressWithRole: securityCouncilAddress, role: VERIFIER_UNSETTER_ROLE }, - { addressWithRole: securityCouncilAddress, role: PAUSE_ALL_ROLE }, - { addressWithRole: securityCouncilAddress, role: UNPAUSE_ALL_ROLE }, - { addressWithRole: securityCouncilAddress, role: PAUSE_L2_BLOB_SUBMISSION_ROLE }, - { addressWithRole: securityCouncilAddress, role: UNPAUSE_L2_BLOB_SUBMISSION_ROLE }, - { addressWithRole: securityCouncilAddress, role: PAUSE_FINALIZE_WITHPROOF_ROLE }, - { addressWithRole: securityCouncilAddress, role: UNPAUSE_FINALIZE_WITHPROOF_ROLE }, - { addressWithRole: securityCouncilAddress, role: FINALIZE_WITHOUT_PROOF_ROLE }, - { addressWithRole: operator.address, role: OPERATOR_ROLE }, - ]; - const initializationData = { initialStateRootHash: parentStateRootHash, initialL2BlockNumber: 0, @@ -129,10 +123,11 @@ describe("Linea Rollup contract", () => { defaultVerifier: verifier, rateLimitPeriodInSeconds: ONE_DAY_IN_SECONDS, rateLimitAmountInWei: INITIAL_WITHDRAW_LIMIT, - roleAddresses: roleAddresses, - pauseTypeRoles: pauseTypeRoles, - unpauseTypeRoles: unpauseTypeRoles, + roleAddresses, + pauseTypeRoles: LINEA_ROLLUP_PAUSE_TYPES_ROLES, + unpauseTypeRoles: LINEA_ROLLUP_UNPAUSE_TYPES_ROLES, fallbackOperator: multiCallAddress, + defaultAdmin: securityCouncil.address, }; const lineaRollup = (await deployUpgradableFromFactory("TestLineaRollup", [initializationData], { @@ -151,6 +146,14 @@ describe("Linea Rollup contract", () => { before(async () => { [admin, securityCouncil, operator, nonAuthorizedAccount] = await ethers.getSigners(); + const securityCouncilAddress = securityCouncil.address; + + roleAddresses = generateRoleAssignments(LINEA_ROLLUP_ROLES, securityCouncilAddress, [ + { + role: OPERATOR_ROLE, + addresses: [operator.address], + }, + ]); }); beforeEach(async () => { @@ -180,13 +183,11 @@ describe("Linea Rollup contract", () => { defaultVerifier: ADDRESS_ZERO, rateLimitPeriodInSeconds: ONE_DAY_IN_SECONDS, rateLimitAmountInWei: INITIAL_WITHDRAW_LIMIT, - roleAddresses: [ - { addressWithRole: securityCouncil.address, role: DEFAULT_ADMIN_ROLE }, - { addressWithRole: securityCouncil.address, role: VERIFIER_SETTER_ROLE }, - ], - pauseTypeRoles: pauseTypeRoles, - unpauseTypeRoles: unpauseTypeRoles, + roleAddresses, + pauseTypeRoles: LINEA_ROLLUP_PAUSE_TYPES_ROLES, + unpauseTypeRoles: LINEA_ROLLUP_UNPAUSE_TYPES_ROLES, fallbackOperator: multiCallAddress, + defaultAdmin: securityCouncil.address, }; const deployCall = deployUpgradableFromFactory("contracts/LineaRollup.sol:LineaRollup", [initializationData], { @@ -205,14 +206,11 @@ describe("Linea Rollup contract", () => { defaultVerifier: verifier, rateLimitPeriodInSeconds: ONE_DAY_IN_SECONDS, rateLimitAmountInWei: INITIAL_WITHDRAW_LIMIT, - roleAddresses: [ - { addressWithRole: securityCouncil.address, role: DEFAULT_ADMIN_ROLE }, - { addressWithRole: securityCouncil.address, role: VERIFIER_SETTER_ROLE }, - { addressWithRole: ADDRESS_ZERO, role: OPERATOR_ROLE }, - ], - pauseTypeRoles: pauseTypeRoles, - unpauseTypeRoles: unpauseTypeRoles, + roleAddresses: [{ addressWithRole: ADDRESS_ZERO, role: DEFAULT_ADMIN_ROLE }, ...roleAddresses.slice(1)], + pauseTypeRoles: LINEA_ROLLUP_PAUSE_TYPES_ROLES, + unpauseTypeRoles: LINEA_ROLLUP_UNPAUSE_TYPES_ROLES, fallbackOperator: multiCallAddress, + defaultAdmin: securityCouncil.address, }; const deployCall = deployUpgradableFromFactory("TestLineaRollup", [initializationData], { @@ -251,13 +249,11 @@ describe("Linea Rollup contract", () => { defaultVerifier: verifier, rateLimitPeriodInSeconds: ONE_DAY_IN_SECONDS, rateLimitAmountInWei: INITIAL_WITHDRAW_LIMIT, - roleAddresses: [ - { addressWithRole: securityCouncil.address, role: DEFAULT_ADMIN_ROLE }, - { addressWithRole: securityCouncil.address, role: VERIFIER_SETTER_ROLE }, - ], - pauseTypeRoles: pauseTypeRoles, - unpauseTypeRoles: unpauseTypeRoles, + roleAddresses, + pauseTypeRoles: LINEA_ROLLUP_PAUSE_TYPES_ROLES, + unpauseTypeRoles: LINEA_ROLLUP_UNPAUSE_TYPES_ROLES, fallbackOperator: multiCallAddress, + defaultAdmin: securityCouncil.address, }; const lineaRollup = await deployUpgradableFromFactory( @@ -280,14 +276,11 @@ describe("Linea Rollup contract", () => { defaultVerifier: verifier, rateLimitPeriodInSeconds: ONE_DAY_IN_SECONDS, rateLimitAmountInWei: INITIAL_WITHDRAW_LIMIT, - roleAddresses: [ - { addressWithRole: securityCouncil.address, role: DEFAULT_ADMIN_ROLE }, - { addressWithRole: securityCouncil.address, role: VERIFIER_SETTER_ROLE }, - { addressWithRole: operator.address, role: VERIFIER_SETTER_ROLE }, - ], - pauseTypeRoles: pauseTypeRoles, - unpauseTypeRoles: unpauseTypeRoles, + roleAddresses: [...roleAddresses, { addressWithRole: operator.address, role: VERIFIER_SETTER_ROLE }], + pauseTypeRoles: LINEA_ROLLUP_PAUSE_TYPES_ROLES, + unpauseTypeRoles: LINEA_ROLLUP_UNPAUSE_TYPES_ROLES, fallbackOperator: multiCallAddress, + defaultAdmin: securityCouncil.address, }; const lineaRollup = await deployUpgradableFromFactory( @@ -312,13 +305,11 @@ describe("Linea Rollup contract", () => { defaultVerifier: verifier, rateLimitPeriodInSeconds: ONE_DAY_IN_SECONDS, rateLimitAmountInWei: INITIAL_WITHDRAW_LIMIT, - roleAddresses: [ - { addressWithRole: securityCouncil.address, role: DEFAULT_ADMIN_ROLE }, - { addressWithRole: securityCouncil.address, role: VERIFIER_SETTER_ROLE }, - ], - pauseTypeRoles: pauseTypeRoles, - unpauseTypeRoles: unpauseTypeRoles, + roleAddresses, + pauseTypeRoles: LINEA_ROLLUP_PAUSE_TYPES_ROLES, + unpauseTypeRoles: LINEA_ROLLUP_UNPAUSE_TYPES_ROLES, fallbackOperator: multiCallAddress, + defaultAdmin: securityCouncil.address, }); await expectRevertWithReason(initializeCall, INITIALIZED_ALREADY_MESSAGE); @@ -2118,7 +2109,7 @@ describe("Linea Rollup contract", () => { }); describe("fallback operator Role", () => { - const expectedLastFinalizedState = calculateLastFinalizedState(0, HASH_ZERO, DEFAULT_LAST_FINALIZED_TIMESTAMP); + const expectedLastFinalizedState = calculateLastFinalizedState(0n, HASH_ZERO, DEFAULT_LAST_FINALIZED_TIMESTAMP); it("Should revert if trying to set fallback operator role before six months have passed", async () => { const initialBlock = await ethers.provider.getBlock("latest"); @@ -2274,9 +2265,11 @@ describe("Linea Rollup contract", () => { } describe("LineaRollup Upgradeable Tests", () => { + let newRoleAddresses: { addressWithRole: string; role: string }[]; + async function deployLineaRollupFixture() { - const PlonkVerifierFactory = await ethers.getContractFactory("TestPlonkVerifierForDataAggregation"); - const plonkVerifier = await PlonkVerifierFactory.deploy(); + const plonkVerifierFactory = await ethers.getContractFactory("TestPlonkVerifierForDataAggregation"); + const plonkVerifier = await plonkVerifierFactory.deploy(); await plonkVerifier.waitForDeployment(); verifier = await plonkVerifier.getAddress(); @@ -2302,6 +2295,25 @@ describe("Linea Rollup contract", () => { return lineaRollup; } + before(async () => { + const securityCouncilAddress = securityCouncil.address; + + newRoleAddresses = [ + { addressWithRole: securityCouncilAddress, role: USED_RATE_LIMIT_RESETTER_ROLE }, + { addressWithRole: securityCouncilAddress, role: VERIFIER_UNSETTER_ROLE }, + { addressWithRole: securityCouncilAddress, role: PAUSE_ALL_ROLE }, + { addressWithRole: securityCouncilAddress, role: PAUSE_L1_L2_ROLE }, + { addressWithRole: securityCouncilAddress, role: PAUSE_L2_L1_ROLE }, + { addressWithRole: securityCouncilAddress, role: UNPAUSE_ALL_ROLE }, + { addressWithRole: securityCouncilAddress, role: UNPAUSE_L1_L2_ROLE }, + { addressWithRole: securityCouncilAddress, role: UNPAUSE_L2_L1_ROLE }, + { addressWithRole: securityCouncilAddress, role: PAUSE_BLOB_SUBMISSION_ROLE }, + { addressWithRole: securityCouncilAddress, role: UNPAUSE_BLOB_SUBMISSION_ROLE }, + { addressWithRole: securityCouncilAddress, role: PAUSE_FINALIZE_WITHPROOF_ROLE }, + { addressWithRole: securityCouncilAddress, role: UNPAUSE_FINALIZE_WITHPROOF_ROLE }, + ]; + }); + beforeEach(async () => { lineaRollup = await loadFixture(deployLineaRollupFixture); }); @@ -2310,17 +2322,14 @@ describe("Linea Rollup contract", () => { expect(await lineaRollup.currentL2BlockNumber()).to.equal(0); // Deploy new implementation - const NewLineaRollupFactory = await ethers.getContractFactory("contracts/LineaRollup.sol:LineaRollup"); - const newLineaRollup = await upgrades.upgradeProxy(lineaRollup, NewLineaRollupFactory); + const newLineaRollupFactory = await ethers.getContractFactory("contracts/LineaRollup.sol:LineaRollup"); + const newLineaRollup = await upgrades.upgradeProxy(lineaRollup, newLineaRollupFactory); const upgradedContract = await newLineaRollup.waitForDeployment(); const upgradeCall = upgradedContract.reinitializeLineaRollupV6( - [ - { addressWithRole: securityCouncil.address, role: DEFAULT_ADMIN_ROLE }, - { addressWithRole: securityCouncil.address, role: VERIFIER_SETTER_ROLE }, - ], - pauseTypeRoles, - unpauseTypeRoles, + newRoleAddresses, + LINEA_ROLLUP_PAUSE_TYPES_ROLES, + LINEA_ROLLUP_UNPAUSE_TYPES_ROLES, multiCallAddress, ); @@ -2337,16 +2346,13 @@ describe("Linea Rollup contract", () => { expect(await lineaRollup.currentL2BlockNumber()).to.equal(0); // Deploy new implementation - const NewLineaRollupFactory = await ethers.getContractFactory("contracts/LineaRollup.sol:LineaRollup"); - const newLineaRollup = await upgrades.upgradeProxy(lineaRollup, NewLineaRollupFactory); + const newLineaRollupFactory = await ethers.getContractFactory("contracts/LineaRollup.sol:LineaRollup"); + const newLineaRollup = await upgrades.upgradeProxy(lineaRollup, newLineaRollupFactory); const upgradedContract = await newLineaRollup.waitForDeployment(); const upgradeCall = upgradedContract.reinitializeLineaRollupV6( - [ - { addressWithRole: securityCouncil.address, role: DEFAULT_ADMIN_ROLE }, - { addressWithRole: securityCouncil.address, role: VERIFIER_SETTER_ROLE }, - ], - pauseTypeRoles, - unpauseTypeRoles, + newRoleAddresses, + LINEA_ROLLUP_PAUSE_TYPES_ROLES, + LINEA_ROLLUP_UNPAUSE_TYPES_ROLES, multiCallAddress, ); @@ -2357,26 +2363,20 @@ describe("Linea Rollup contract", () => { expect(await lineaRollup.currentL2BlockNumber()).to.equal(0); // Deploy new implementation - const NewLineaRollupFactory = await ethers.getContractFactory("contracts/LineaRollup.sol:LineaRollup"); - const newLineaRollup = await upgrades.upgradeProxy(lineaRollup, NewLineaRollupFactory); + const newLineaRollupFactory = await ethers.getContractFactory("contracts/LineaRollup.sol:LineaRollup"); + const newLineaRollup = await upgrades.upgradeProxy(lineaRollup, newLineaRollupFactory); const upgradedContract = await newLineaRollup.waitForDeployment(); - upgradedContract.reinitializeLineaRollupV6( - [ - { addressWithRole: securityCouncil.address, role: DEFAULT_ADMIN_ROLE }, - { addressWithRole: securityCouncil.address, role: VERIFIER_SETTER_ROLE }, - ], - pauseTypeRoles, - unpauseTypeRoles, + await upgradedContract.reinitializeLineaRollupV6( + newRoleAddresses, + LINEA_ROLLUP_PAUSE_TYPES_ROLES, + LINEA_ROLLUP_UNPAUSE_TYPES_ROLES, multiCallAddress, ); const secondCall = upgradedContract.reinitializeLineaRollupV6( - [ - { addressWithRole: securityCouncil.address, role: DEFAULT_ADMIN_ROLE }, - { addressWithRole: securityCouncil.address, role: VERIFIER_SETTER_ROLE }, - ], - pauseTypeRoles, - unpauseTypeRoles, + newRoleAddresses, + LINEA_ROLLUP_PAUSE_TYPES_ROLES, + LINEA_ROLLUP_UNPAUSE_TYPES_ROLES, multiCallAddress, ); @@ -2385,20 +2385,87 @@ describe("Linea Rollup contract", () => { it("Should revert with ZeroAddressNotAllowed when addressWithRole is zero address in reinitializeLineaRollupV6", async () => { // Deploy new implementation - const NewLineaRollupFactory = await ethers.getContractFactory("contracts/LineaRollup.sol:LineaRollup"); - const newLineaRollup = await upgrades.upgradeProxy(lineaRollup, NewLineaRollupFactory); + const newLineaRollupFactory = await ethers.getContractFactory("contracts/LineaRollup.sol:LineaRollup"); + const newLineaRollup = await upgrades.upgradeProxy(lineaRollup, newLineaRollupFactory); const upgradedContract = await newLineaRollup.waitForDeployment(); - const roleAddresses = [ - { addressWithRole: ZeroAddress, role: DEFAULT_ADMIN_ROLE }, - { addressWithRole: securityCouncil.address, role: VERIFIER_SETTER_ROLE }, - { addressWithRole: operator.address, role: OPERATOR_ROLE }, - ]; + const roleAddresses = [{ addressWithRole: ZeroAddress, role: DEFAULT_ADMIN_ROLE }, ...newRoleAddresses.slice(1)]; await expectRevertWithCustomError( upgradedContract, - upgradedContract.reinitializeLineaRollupV6(roleAddresses, pauseTypeRoles, unpauseTypeRoles, multiCallAddress), + upgradedContract.reinitializeLineaRollupV6( + roleAddresses, + LINEA_ROLLUP_PAUSE_TYPES_ROLES, + LINEA_ROLLUP_UNPAUSE_TYPES_ROLES, + multiCallAddress, + ), "ZeroAddressNotAllowed", ); }); + + it("Should set all permissions", async () => { + // Deploy new implementation + const newLineaRollupFactory = await ethers.getContractFactory("contracts/LineaRollup.sol:LineaRollup"); + const newLineaRollup = await upgrades.upgradeProxy(lineaRollup, newLineaRollupFactory); + const upgradedContract = await newLineaRollup.waitForDeployment(); + + await upgradedContract.reinitializeLineaRollupV6( + newRoleAddresses, + LINEA_ROLLUP_PAUSE_TYPES_ROLES, + LINEA_ROLLUP_UNPAUSE_TYPES_ROLES, + multiCallAddress, + ); + + for (const { role, addressWithRole } of newRoleAddresses) { + expect(await upgradedContract.hasRole(role, addressWithRole)).to.be.true; + } + }); + + it("Should set all pause types and unpause types in mappings and emit events", async () => { + // Deploy new implementation + const newLineaRollupFactory = await ethers.getContractFactory("contracts/LineaRollup.sol:LineaRollup"); + const newLineaRollup = await upgrades.upgradeProxy(lineaRollup, newLineaRollupFactory); + const upgradedContract = await newLineaRollup.waitForDeployment(); + + const reinitializePromise = upgradedContract.reinitializeLineaRollupV6( + newRoleAddresses, + LINEA_ROLLUP_PAUSE_TYPES_ROLES, + LINEA_ROLLUP_UNPAUSE_TYPES_ROLES, + multiCallAddress, + ); + + await Promise.all([ + expectEvents( + upgradedContract, + reinitializePromise, + LINEA_ROLLUP_PAUSE_TYPES_ROLES.map(({ pauseType, role }) => ({ + name: "PauseTypeRoleSet", + args: [pauseType, role], + })), + ), + expectEvents( + upgradedContract, + reinitializePromise, + LINEA_ROLLUP_UNPAUSE_TYPES_ROLES.map(({ pauseType, role }) => ({ + name: "UnPauseTypeRoleSet", + args: [pauseType, role], + })), + ), + ]); + + const pauseTypeRolesMappingSlot = 219; + const unpauseTypeRolesMappingSlot = 220; + + for (const { pauseType, role } of LINEA_ROLLUP_PAUSE_TYPES_ROLES) { + const slot = generateKeccak256(["uint8", "uint256"], [pauseType, pauseTypeRolesMappingSlot]); + const roleInMapping = await ethers.provider.getStorage(upgradedContract.getAddress(), slot); + expect(roleInMapping).to.equal(role); + } + + for (const { pauseType, role } of LINEA_ROLLUP_UNPAUSE_TYPES_ROLES) { + const slot = generateKeccak256(["uint8", "uint256"], [pauseType, unpauseTypeRolesMappingSlot]); + const roleInMapping = await ethers.provider.getStorage(upgradedContract.getAddress(), slot); + expect(roleInMapping).to.equal(role); + } + }); }); }); diff --git a/contracts/test/LineaRollupInit.ts b/contracts/test/LineaRollupInit.ts index 387ec7d25..a5cd32fb2 100644 --- a/contracts/test/LineaRollupInit.ts +++ b/contracts/test/LineaRollupInit.ts @@ -4,19 +4,19 @@ import { expect } from "chai"; import { ethers } from "hardhat"; import { TestLineaRollup, LineaRollupInit__factory } from "../typechain-types"; import { - DEFAULT_ADMIN_ROLE, GENESIS_L2_TIMESTAMP, INITIALIZED_ALREADY_MESSAGE, INITIAL_WITHDRAW_LIMIT, LINEA_ROLLUP_INITIALIZE_SIGNATURE, ONE_DAY_IN_SECONDS, OPERATOR_ROLE, - VERIFIER_SETTER_ROLE, pauseTypeRoles, unpauseTypeRoles, -} from "./utils/constants"; -import { deployUpgradableFromFactory } from "./utils/deployment"; -import { expectRevertWithReason, generateRandomBytes } from "./utils/helpers"; +} from "./common/constants"; +import { deployUpgradableFromFactory } from "./common/deployment"; +import { expectRevertWithReason, generateRandomBytes } from "./common/helpers"; +import { generateRoleAssignments } from "contracts/common/helpers"; +import { LINEA_ROLLUP_ROLES } from "contracts/common/constants"; describe("LineaRollup Init contract", () => { let LineaRollup: TestLineaRollup; @@ -47,14 +47,13 @@ describe("LineaRollup Init contract", () => { defaultVerifier: verifier, rateLimitPeriodInSeconds: ONE_DAY_IN_SECONDS, rateLimitAmountInWei: INITIAL_WITHDRAW_LIMIT, - roleAddresses: [ - { addressWithRole: securityCouncil.address, role: DEFAULT_ADMIN_ROLE }, - { addressWithRole: securityCouncil.address, role: VERIFIER_SETTER_ROLE }, - { addressWithRole: operator.address, role: OPERATOR_ROLE }, - ], + roleAddresses: generateRoleAssignments(LINEA_ROLLUP_ROLES, securityCouncil.address, [ + { role: OPERATOR_ROLE, addresses: [operator.address] }, + ]), pauseTypeRoles: pauseTypeRoles, unpauseTypeRoles: unpauseTypeRoles, fallbackOperator: multiCallAddress, + defaultAdmin: securityCouncil.address, }; const LineaRollup = (await deployUpgradableFromFactory("TestLineaRollup", [genesisData], { diff --git a/contracts/test/LineaRollupNew.ts b/contracts/test/LineaRollupNew.ts index d98228966..9973e0006 100644 --- a/contracts/test/LineaRollupNew.ts +++ b/contracts/test/LineaRollupNew.ts @@ -9,9 +9,9 @@ import { INITIAL_WITHDRAW_LIMIT, ONE_DAY_IN_SECONDS, TEST_PUBLIC_VERIFIER_INDEX, -} from "./utils/constants"; -import { deployUpgradableFromFactory } from "./utils/deployment"; -import { generateFinalizationDataFromJSON, generateSubmissionDataFromJSON } from "./utils/helpers"; +} from "./common/constants"; +import { deployUpgradableFromFactory } from "./common/deployment"; +import { generateFinalizationDataFromJSON, generateSubmissionDataFromJSON } from "./common/helpers"; // This stores initialization data for the smart-contract import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; diff --git a/contracts/test/LineaSurgeXP.ts b/contracts/test/LineaSurgeXP.ts index 3c1631dbc..ed3abee80 100644 --- a/contracts/test/LineaSurgeXP.ts +++ b/contracts/test/LineaSurgeXP.ts @@ -3,8 +3,8 @@ import { loadFixture } from "@nomicfoundation/hardhat-network-helpers"; import { expect } from "chai"; import { ethers } from "hardhat"; import { LineaSurgeXP, TestLineaSurgeXP } from "../typechain-types"; -import { ADDRESS_ZERO, DEFAULT_ADMIN_ROLE, MINTER_ROLE, TRANSFER_ROLE } from "./utils/constants"; -import { deployFromFactory } from "./utils/deployment"; +import { ADDRESS_ZERO, DEFAULT_ADMIN_ROLE, MINTER_ROLE, TRANSFER_ROLE } from "./common/constants"; +import { deployFromFactory } from "./common/deployment"; describe("Linea Surge XP Token Tests", () => { let contract: LineaSurgeXP; diff --git a/contracts/test/LineaVoyageXP.ts b/contracts/test/LineaVoyageXP.ts index 8678ac577..dbe639ac3 100644 --- a/contracts/test/LineaVoyageXP.ts +++ b/contracts/test/LineaVoyageXP.ts @@ -3,9 +3,9 @@ import { loadFixture } from "@nomicfoundation/hardhat-network-helpers"; import { expect } from "chai"; import { ethers } from "hardhat"; import { LineaVoyageXP } from "../typechain-types"; -import { DEFAULT_ADMIN_ROLE, MINTER_ROLE } from "./utils/constants"; -import { deployFromFactory } from "./utils/deployment"; -import { buildAccessErrorMessage, expectRevertWithCustomError, expectRevertWithReason } from "./utils/helpers"; +import { DEFAULT_ADMIN_ROLE, MINTER_ROLE } from "./common/constants"; +import { deployFromFactory } from "./common/deployment"; +import { buildAccessErrorMessage, expectRevertWithCustomError, expectRevertWithReason } from "./common/helpers"; describe("Linea Voyage XP Token Tests", () => { let contract: LineaVoyageXP; diff --git a/contracts/test/MessageServiceBase.ts b/contracts/test/MessageServiceBase.ts index 42f0824f3..13c2b995d 100644 --- a/contracts/test/MessageServiceBase.ts +++ b/contracts/test/MessageServiceBase.ts @@ -4,16 +4,17 @@ import { expect } from "chai"; import { ethers } from "hardhat"; import { TestL2MessageService, TestMessageServiceBase } from "../typechain-types"; import { - DEFAULT_ADMIN_ROLE, INITIALIZED_ERROR_MESSAGE, INITIAL_WITHDRAW_LIMIT, L1_L2_MESSAGE_SETTER_ROLE, ONE_DAY_IN_SECONDS, pauseTypeRoles, unpauseTypeRoles, -} from "./utils/constants"; -import { deployUpgradableFromFactory } from "./utils/deployment"; -import { expectEvent, expectRevertWithCustomError, expectRevertWithReason } from "./utils/helpers"; +} from "./common/constants"; +import { deployUpgradableFromFactory } from "./common/deployment"; +import { expectEvent, expectRevertWithCustomError, expectRevertWithReason } from "./common/helpers"; +import { generateRoleAssignments } from "contracts/common/helpers"; +import { L2_MESSAGE_SERVICE_ROLES } from "contracts/common/constants"; describe("MessageServiceBase", () => { let messageServiceBase: TestMessageServiceBase; @@ -25,14 +26,14 @@ describe("MessageServiceBase", () => { let l1L2MessageSetter: SignerWithAddress; async function deployMessageServiceBaseFixture() { - const roleAddresses = [ - { addressWithRole: securityCouncil.address, role: DEFAULT_ADMIN_ROLE }, - { addressWithRole: l1L2MessageSetter.address, role: L1_L2_MESSAGE_SETTER_ROLE }, - ]; + const roleAddresses = generateRoleAssignments(L2_MESSAGE_SERVICE_ROLES, securityCouncil.address, [ + { role: L1_L2_MESSAGE_SETTER_ROLE, addresses: [l1L2MessageSetter.address] }, + ]); const messageService = (await deployUpgradableFromFactory("TestL2MessageService", [ ONE_DAY_IN_SECONDS, INITIAL_WITHDRAW_LIMIT, + securityCouncil.address, roleAddresses, pauseTypeRoles, unpauseTypeRoles, diff --git a/contracts/test/PauseManager.ts b/contracts/test/PauseManager.ts index 2dca31f10..d0c9eacb8 100644 --- a/contracts/test/PauseManager.ts +++ b/contracts/test/PauseManager.ts @@ -16,17 +16,17 @@ import { PAUSE_L2_L1_ROLE, UNPAUSE_L2_L1_ROLE, PAUSE_FINALIZE_WITHPROOF_ROLE, - PAUSE_L2_BLOB_SUBMISSION_ROLE, + PAUSE_BLOB_SUBMISSION_ROLE, UNPAUSE_FINALIZE_WITHPROOF_ROLE, - UNPAUSE_L2_BLOB_SUBMISSION_ROLE, + UNPAUSE_BLOB_SUBMISSION_ROLE, BLOB_SUBMISSION_PAUSE_TYPE, CALLDATA_SUBMISSION_PAUSE_TYPE, FINALIZATION_PAUSE_TYPE, pauseTypeRoles, unpauseTypeRoles, -} from "./utils/constants"; -import { deployUpgradableFromFactory } from "./utils/deployment"; -import { buildAccessErrorMessage, expectEvent } from "./utils/helpers"; +} from "./common/constants"; +import { deployUpgradableFromFactory } from "./common/deployment"; +import { buildAccessErrorMessage, expectEvent } from "./common/helpers"; async function deployTestPauseManagerFixture(): Promise { return deployUpgradableFromFactory("TestPauseManager", [ @@ -46,20 +46,18 @@ describe("PauseManager", () => { [defaultAdmin, pauseManagerAccount, nonManager] = await ethers.getSigners(); pauseManager = await loadFixture(deployTestPauseManagerFixture); - await pauseManager.grantRole(PAUSE_ALL_ROLE, pauseManagerAccount.address); - await pauseManager.grantRole(UNPAUSE_ALL_ROLE, pauseManagerAccount.address); - - await pauseManager.grantRole(PAUSE_L1_L2_ROLE, pauseManagerAccount.address); - await pauseManager.grantRole(UNPAUSE_L1_L2_ROLE, pauseManagerAccount.address); - - await pauseManager.grantRole(PAUSE_L2_L1_ROLE, pauseManagerAccount.address); - await pauseManager.grantRole(UNPAUSE_L2_L1_ROLE, pauseManagerAccount.address); - - await pauseManager.grantRole(PAUSE_L2_BLOB_SUBMISSION_ROLE, pauseManagerAccount.address); - await pauseManager.grantRole(UNPAUSE_L2_BLOB_SUBMISSION_ROLE, pauseManagerAccount.address); - - await pauseManager.grantRole(PAUSE_FINALIZE_WITHPROOF_ROLE, pauseManagerAccount.address); - await pauseManager.grantRole(UNPAUSE_FINALIZE_WITHPROOF_ROLE, pauseManagerAccount.address); + await Promise.all([ + pauseManager.grantRole(PAUSE_ALL_ROLE, pauseManagerAccount.address), + pauseManager.grantRole(UNPAUSE_ALL_ROLE, pauseManagerAccount.address), + pauseManager.grantRole(PAUSE_L1_L2_ROLE, pauseManagerAccount.address), + pauseManager.grantRole(UNPAUSE_L1_L2_ROLE, pauseManagerAccount.address), + pauseManager.grantRole(PAUSE_L2_L1_ROLE, pauseManagerAccount.address), + pauseManager.grantRole(UNPAUSE_L2_L1_ROLE, pauseManagerAccount.address), + pauseManager.grantRole(PAUSE_BLOB_SUBMISSION_ROLE, pauseManagerAccount.address), + pauseManager.grantRole(UNPAUSE_BLOB_SUBMISSION_ROLE, pauseManagerAccount.address), + pauseManager.grantRole(PAUSE_FINALIZE_WITHPROOF_ROLE, pauseManagerAccount.address), + pauseManager.grantRole(UNPAUSE_FINALIZE_WITHPROOF_ROLE, pauseManagerAccount.address), + ]); }); async function pauseByType(pauseType: number, account: SignerWithAddress = pauseManagerAccount) { @@ -226,7 +224,7 @@ describe("PauseManager", () => { it("cannot pause the BLOB_SUBMISSION_PAUSE_TYPE as non-manager", async () => { await expect(pauseByType(BLOB_SUBMISSION_PAUSE_TYPE, nonManager)).to.be.revertedWith( - buildAccessErrorMessage(nonManager, PAUSE_L2_BLOB_SUBMISSION_ROLE), + buildAccessErrorMessage(nonManager, PAUSE_BLOB_SUBMISSION_ROLE), ); }); @@ -234,13 +232,13 @@ describe("PauseManager", () => { await pauseByType(BLOB_SUBMISSION_PAUSE_TYPE); await expect(unPauseByType(BLOB_SUBMISSION_PAUSE_TYPE, nonManager)).to.be.revertedWith( - buildAccessErrorMessage(nonManager, UNPAUSE_L2_BLOB_SUBMISSION_ROLE), + buildAccessErrorMessage(nonManager, UNPAUSE_BLOB_SUBMISSION_ROLE), ); }); it("cannot pause the CALLDATA_SUBMISSION_PAUSE_TYPE as non-manager", async () => { await expect(pauseByType(CALLDATA_SUBMISSION_PAUSE_TYPE, nonManager)).to.be.revertedWith( - buildAccessErrorMessage(nonManager, PAUSE_L2_BLOB_SUBMISSION_ROLE), + buildAccessErrorMessage(nonManager, PAUSE_BLOB_SUBMISSION_ROLE), ); }); @@ -248,7 +246,7 @@ describe("PauseManager", () => { await pauseByType(CALLDATA_SUBMISSION_PAUSE_TYPE); await expect(unPauseByType(CALLDATA_SUBMISSION_PAUSE_TYPE, nonManager)).to.be.revertedWith( - buildAccessErrorMessage(nonManager, UNPAUSE_L2_BLOB_SUBMISSION_ROLE), + buildAccessErrorMessage(nonManager, UNPAUSE_BLOB_SUBMISSION_ROLE), ); }); diff --git a/contracts/test/RateLimiter.ts b/contracts/test/RateLimiter.ts index c835e951c..0f613b2cb 100644 --- a/contracts/test/RateLimiter.ts +++ b/contracts/test/RateLimiter.ts @@ -9,14 +9,14 @@ import { ONE_DAY_IN_SECONDS, RATE_LIMIT_SETTER_ROLE, USED_RATE_LIMIT_RESETTER_ROLE, -} from "./utils/constants"; -import { deployUpgradableFromFactory } from "./utils/deployment"; +} from "./common/constants"; +import { deployUpgradableFromFactory } from "./common/deployment"; import { buildAccessErrorMessage, expectEvent, expectRevertWithCustomError, expectRevertWithReason, -} from "./utils/helpers"; +} from "./common/helpers"; describe("Rate limiter", () => { let testRateLimiter: TestRateLimiter; diff --git a/contracts/test/RecoverFunds.ts b/contracts/test/RecoverFunds.ts index 197d8e2ed..e5d991495 100644 --- a/contracts/test/RecoverFunds.ts +++ b/contracts/test/RecoverFunds.ts @@ -10,9 +10,9 @@ import { FUNCTION_EXECUTOR_ROLE, INITIALIZED_ALREADY_MESSAGE, INITIAL_WITHDRAW_LIMIT, -} from "./utils/constants"; -import { deployUpgradableFromFactory } from "./utils/deployment"; -import { buildAccessErrorMessage, expectRevertWithCustomError, expectRevertWithReason } from "./utils/helpers"; +} from "./common/constants"; +import { deployUpgradableFromFactory } from "./common/deployment"; +import { buildAccessErrorMessage, expectRevertWithCustomError, expectRevertWithReason } from "./common/helpers"; describe("RecoverFunds contract", () => { let recoverFunds: RecoverFunds; diff --git a/contracts/test/SparseMerkleProof.ts b/contracts/test/SparseMerkleProof.ts index 21a29518c..9fbd68589 100644 --- a/contracts/test/SparseMerkleProof.ts +++ b/contracts/test/SparseMerkleProof.ts @@ -3,8 +3,8 @@ import { expect } from "chai"; import { ethers } from "hardhat"; import { Mimc, SparseMerkleProof } from "../typechain-types"; import merkleProofTestData from "./testData/merkle-proof-data.json"; -import { deployFromFactory } from "./utils/deployment"; -import { expectRevertWithCustomError } from "./utils/helpers"; +import { deployFromFactory } from "./common/deployment"; +import { expectRevertWithCustomError } from "./common/helpers"; describe("SparseMerkleProof", () => { let sparseMerkleProof: SparseMerkleProof; diff --git a/contracts/test/Timelock.ts b/contracts/test/Timelock.ts index 086c76fe0..1f17f2fd9 100644 --- a/contracts/test/Timelock.ts +++ b/contracts/test/Timelock.ts @@ -3,8 +3,8 @@ import { loadFixture } from "@nomicfoundation/hardhat-network-helpers"; import { expect } from "chai"; import { ethers } from "hardhat"; import { TimeLock } from "../typechain-types"; -import { CANCELLER_ROLE, EXECUTOR_ROLE, PROPOSER_ROLE, TIMELOCK_ADMIN_ROLE } from "./utils/constants"; -import { deployFromFactory } from "./utils/deployment"; +import { CANCELLER_ROLE, EXECUTOR_ROLE, PROPOSER_ROLE, TIMELOCK_ADMIN_ROLE } from "./common/constants"; +import { deployFromFactory } from "./common/deployment"; describe("Timelock", () => { let contract: TimeLock; diff --git a/contracts/test/TokenMintingRateLimiter.ts b/contracts/test/TokenMintingRateLimiter.ts index d16c5856f..f0bfe4777 100644 --- a/contracts/test/TokenMintingRateLimiter.ts +++ b/contracts/test/TokenMintingRateLimiter.ts @@ -8,11 +8,11 @@ import { MINTER_ROLE, ONE_DAY_IN_SECONDS, RATE_LIMIT_SETTER_ROLE, -} from "./utils/constants"; -import { deployFromFactory } from "./utils/deployment"; +} from "./common/constants"; +import { deployFromFactory } from "./common/deployment"; import { TokenMintingRateLimiter } from "../typechain-types/contracts/token/TokenMintingRateLimiter"; import { LineaVoyageXP } from "../typechain-types"; -import { buildAccessErrorMessage, expectRevertWithCustomError, expectRevertWithReason } from "./utils/helpers"; +import { buildAccessErrorMessage, expectRevertWithCustomError, expectRevertWithReason } from "./common/helpers"; describe("Token Minting Rate Limiter", () => { let tokenMintingRateLimiter: TokenMintingRateLimiter; diff --git a/contracts/test/Utils.ts b/contracts/test/Utils.ts index b077b1f02..55be95fe4 100644 --- a/contracts/test/Utils.ts +++ b/contracts/test/Utils.ts @@ -1,8 +1,8 @@ import { loadFixture } from "@nomicfoundation/hardhat-network-helpers"; import { expect } from "chai"; import { TestUtils } from "../typechain-types"; -import { deployFromFactory } from "./utils/deployment"; -import { generateKeccak256, generateRandomBytes } from "./utils/helpers"; +import { deployFromFactory } from "./common/deployment"; +import { generateKeccak256, generateRandomBytes } from "./common/helpers"; describe("Utils Library", () => { let contract: TestUtils; diff --git a/contracts/test/V2 Scenarios/MessageManager.md b/contracts/test/V2 Scenarios/MessageManager.md deleted file mode 100644 index 165780b44..000000000 --- a/contracts/test/V2 Scenarios/MessageManager.md +++ /dev/null @@ -1,38 +0,0 @@ - # Message Manager Test Scenarios - - -## Roles -- `ORIGIN_BATCH_SETTER` coordinator setting the origin block hashes -- `MESSAGE_SERVICE` for outbox messages - -## Tests -### Initialize tests - - Empty address check for `ORIGIN_BATCH_SETTER` - - Empty address check for `MESSAGE_SERVICE` - - Can't initialise a second time - - `pauserRoleAddress` not `zero address` - - `pauserRoleAddress` is set - -### Get claimedMessages message status (public mapping) -- can get message status for claimed hash -- returns empty value for non-existing hash - -### Add origin block and message hashes - - reverts `if paused` - - **If not paused:** - - can add non-existing batch of hashes as `ORIGIN_BATCH_SETTER` - - can't add batch of hashes where an existing duplicate exists as `ORIGIN_BATCH_SETTER` - reverts - - can't add batch of hashes as non-`ORIGIN_BATCH_SETTER` - reverts - - Any empty reference (sent data) reverts the batch - - Empty list of hashes reverts - - Block number 0 reverts - -### Add Single Message Reference set tests for outbox - - reverts `if paused` - - **If not paused:** - - can add non-existing as `MESSAGE_SERVICE` - - can't add duplicate existing as `MESSAGE_SERVICE` - - can't add duplicate existing as non-`MESSAGE_SERVICE` - - reference (sent data) cannot be empty - reverts \ No newline at end of file diff --git a/contracts/test/V2 Scenarios/MessageService.md b/contracts/test/V2 Scenarios/MessageService.md deleted file mode 100644 index fe8f09f89..000000000 --- a/contracts/test/V2 Scenarios/MessageService.md +++ /dev/null @@ -1,93 +0,0 @@ -# Message Service Test Scenarios - - -## Roles - -`LIMIT_MANAGER` controls daily withdrawal limits - -`CONTRACT_UPGRADER` controls contract limits - -- TimelockController for upgrades `CONTRACT_UPGRADER` -- Multisig for upgrades `LIMIT_MANAGER` - -## Tests - -### Initialize tests - - Access control is set for `CONTRACT_UPGRADER` - - Access control is set for `LIMIT_MANAGER` - - Can't initialise a second time - - `pauseManagerAddress` not `zero address` - - `pauseManagerAddress` is set - -### Access control tests -- add account to role ? -- remove account from role? -- cannot remove self as admin ?? -- cannot set `self` as `CONTRACT_UPGRADER` -- cannot set `zero address` as `CONTRACT_UPGRADER` -- cannot set `self` as `LIMIT_MANAGER` -- cannot set `zero address` as `LIMIT_MANAGER` - -### Upgrades -- can initiate upgrade - - **note**: this has to be the TimeLockController - - -### Withdrawal Limits -- Can set limits as `LIMIT_MANAGER` -- Cannot set limits as non-`LIMIT_MANAGER` - -### Send Message tests -- `paused` contract `reverts` - - **If not paused:** -- hash exists reverts -- value checks - - `_value` sent + `_fee` = `msg.value` -- `_destinationChainId` allowed ( is there an allowed network list ) -- `_to` is not empty -- `_value` and `_calldata` are both empty (pointless transport) ?? -- `_nonce` is default and hash does not exist -- `MessageSent` is emitted on success - - indexed params are set for topics -- `_destinationChainId` not same as `block.chainId` -- cannot reenter on send with same hash -- `cannot send` a message with a value if daily `withdrawal limit is reached` -- `can send` a message with a value if daily `withdrawal limit is not reached` - -- **CRITICAL HACK HERE IF DONE WRONG** `cannot set destination` when destination is message manager on other layer - reverts -- **CRITICAL HACK HERE IF DONE WRONG** `cannot set destination` when destination is message manager proxy on other layer - reverts - -### Claim Message tests -- `paused` contract `reverts` - - **If not paused:** -- hash does not exist reverts -- hash exists and is pending succeeds -- hash exists and is delivered reverts -- `BridgeMessageClaimed` emitted on success -- `_destinationChainId` matches `block.chainId` -- Call permutation tests - - error on ETH send only reverts - - error on contract call only reverts - - error on contract call with ETH send reverts - - no error on ETH send only does not revert - - no error on contract call only does not revert - - no error on contract call with ETH send does not rever - - `zero fee` does not try send ETH to fee recipient - - error on ETH Fee send reverts - - no error on ETH Fee send does not revert -- `cannot claim` a message with a value if daily `withdrawal limit is reached` -- `can claim` a message with a value if daily `withdrawal limit is not reached` -- delivery `fee` and sent `value` increments daily withdrawal amounts used -- `_feeRecipient` is `zero address`, the fee is sent to `msg.sender` -- `_feeRecipient` is `not zero address`, , the fee is sent to `_feeRecipient` - -### Reentry -- `cannot` enter with `claimMessage` -> `claimMessage` -- `can` enter `claimMessage` -> `sendMessage` - -### setting networks tests -- can add network -- network exists reverts -- not empty value \ No newline at end of file diff --git a/contracts/test/V2 Scenarios/PauseManager.md b/contracts/test/V2 Scenarios/PauseManager.md deleted file mode 100644 index 47d432d8a..000000000 --- a/contracts/test/V2 Scenarios/PauseManager.md +++ /dev/null @@ -1,7 +0,0 @@ -# Pause Manager Test Scenarios - -## Pausing -- `can pause` as `PAUSE_MANAGER_ROLE` -- `cannot pause` as non-`PAUSE_MANAGER_ROLE` -- `can unpause` as `PAUSE_MANAGER_ROLE` -- `cannot unpause` as non-`PAUSE_MANAGER_ROLE` \ No newline at end of file diff --git a/contracts/test/common/constants/calldata.ts b/contracts/test/common/constants/calldata.ts new file mode 100644 index 000000000..ad54ba958 --- /dev/null +++ b/contracts/test/common/constants/calldata.ts @@ -0,0 +1,22 @@ +import { generateKeccak256 } from "../helpers"; + +export const SAMPLE_FUNCTION_CALLDATA = generateKeccak256(["string"], ["callThisFunction()"], true).substring(0, 10); // 0x + 4 bytes +export const EMPTY_CALLDATA = "0x"; + +// TODO: CLEANUP TO MAKE THIS DYNAMIC AND NOT CONSTANT +export const Add_L1L2_Message_Hashes_Calldata_With_Empty_Array = + "0xf4b476e10000000000000000000000000000000000000000000000000000000000000000"; +export const Add_L1L2_Message_Hashes_Calldata_With_One_Hash = + "0xf4b476e100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001f57d2ce8b7fc0df7ae7cbddaa706242a118bd8b649abccfecfb3f8e419729ca9"; +export const Single_Item_L1L2_HashArray = ["0xf57d2ce8b7fc0df7ae7cbddaa706242a118bd8b649abccfecfb3f8e419729ca9"]; + +// TODO: CLEANUP TO MAKE THIS DYNAMIC AND NOT CONSTANT +export const Add_L1L2_Message_Hashes_Calldata_With_Five_Hashes = + "0xf4b476e100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000005f887bbc07b0e849fb625aafadf4cb6b65b98e492fbb689705312bf1db98ead7fdd87bbc07b0e849fb625aafadf4cb6b65b98e492fbb689705312bf1db98ead7faa87bbc07b0e849fb625aafadf4cb6b65b98e492fbb689705312bf1db98ead7fcc87bbc07b0e849fb625aafadf4cb6b65b98e492fbb689705312bf1db98ead7f1187bbc07b0e849fb625aafadf4cb6b65b98e492fbb689705312bf1db98ead7f"; +export const L1L2_FiveHashes = [ + "0xf887bbc07b0e849fb625aafadf4cb6b65b98e492fbb689705312bf1db98ead7f", + "0xdd87bbc07b0e849fb625aafadf4cb6b65b98e492fbb689705312bf1db98ead7f", + "0xaa87bbc07b0e849fb625aafadf4cb6b65b98e492fbb689705312bf1db98ead7f", + "0xcc87bbc07b0e849fb625aafadf4cb6b65b98e492fbb689705312bf1db98ead7f", + "0x1187bbc07b0e849fb625aafadf4cb6b65b98e492fbb689705312bf1db98ead7f", +]; diff --git a/contracts/test/common/constants/errorMessages.ts b/contracts/test/common/constants/errorMessages.ts new file mode 100644 index 000000000..4baab5f15 --- /dev/null +++ b/contracts/test/common/constants/errorMessages.ts @@ -0,0 +1,2 @@ +export const INITIALIZED_ERROR_MESSAGE = "Initializable: contract is not initializing"; +export const INITIALIZED_ALREADY_MESSAGE = "Initializable: contract is already initialized"; diff --git a/contracts/test/common/constants/fees.ts b/contracts/test/common/constants/fees.ts new file mode 100644 index 000000000..9d7190e3e --- /dev/null +++ b/contracts/test/common/constants/fees.ts @@ -0,0 +1,9 @@ +import { ethers } from "hardhat"; + +export const INITIAL_WITHDRAW_LIMIT = ethers.parseEther("5"); +export const MESSAGE_VALUE_1ETH = ethers.parseEther("1"); +export const ZERO_VALUE = 0; +export const MESSAGE_FEE = ethers.parseEther("0.05"); +export const LOW_NO_REFUND_MESSAGE_FEE = ethers.parseEther("0.00001"); +export const MINIMUM_FEE = ethers.parseEther("0.1"); +export const DEFAULT_MESSAGE_NONCE = ethers.parseEther("123456789"); diff --git a/contracts/test/common/constants/general.ts b/contracts/test/common/constants/general.ts new file mode 100644 index 000000000..fa1ec13fe --- /dev/null +++ b/contracts/test/common/constants/general.ts @@ -0,0 +1,12 @@ +import { ethers } from "hardhat"; + +export const HASH_ZERO = ethers.ZeroHash; +export const ADDRESS_ZERO = ethers.ZeroAddress; +export const HASH_WITHOUT_ZERO_FIRST_BYTE = "0xf887bbc07b0e849fb625aafadf4cb6b65b98e492fbb689705312bf1db98ead7f"; + +export const LINEA_ROLLUP_INITIALIZE_SIGNATURE = + "initialize((bytes32,uint256,uint256,address,uint256,uint256,(address,bytes32)[],(uint8,bytes32)[],(uint8,bytes32)[],address,address))"; + +export const BLS_CURVE_MODULUS = 52435875175126190479447740508185965837690552500527637822603658699938581184513n; + +export const BLOCK_COINBASE = "0xc014ba5ec014ba5ec014ba5ec014ba5ec014ba5e"; diff --git a/contracts/test/common/constants/index.ts b/contracts/test/common/constants/index.ts new file mode 100644 index 000000000..fda01cfe9 --- /dev/null +++ b/contracts/test/common/constants/index.ts @@ -0,0 +1,10 @@ +export * from "./general"; +export * from "./fees"; +export * from "./messageStatuses"; +export * from "./errorMessages"; +export * from "./submissionData"; +export * from "./time"; +export * from "./merkleTree"; +export * from "./calldata"; +export * from "./pauseTypes"; +export * from "./roles"; diff --git a/contracts/test/common/constants/merkleTree.ts b/contracts/test/common/constants/merkleTree.ts new file mode 100644 index 000000000..91cce15ce --- /dev/null +++ b/contracts/test/common/constants/merkleTree.ts @@ -0,0 +1,147 @@ +export const VALID_MERKLE_PROOF = { + //proof length 32 + proof: [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5", + "0xb4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d30", + "0x21ddb9a356815c3fac1026b6dec5df3124afbadb485c9ba5a3e3398a04b7ba85", + "0xe58769b32a1beaf1ea27375a44095a0d1fb664ce2dd358e7fcbfb78c26a19344", + "0x0eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d", + "0x887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a1968", + "0xffd70157e48063fc33c97a050f7f640233bf646cc98d9524c6b92bcf3ab56f83", + "0x9867cc5f7f196b93bae1e27e6320742445d290f2263827498b54fec539f756af", + "0xcefad4e508c098b9a7e1d8feb19955fb02ba9675585078710969d3440f5054e0", + "0xf9dc3e7fe016e050eff260334f18a5d4fe391d82092319f5964f2e2eb7c1c3a5", + "0xf8b13a49e282f609c317a833fb8d976d11517c571d1221a265d25af778ecf892", + "0x3490c6ceeb450aecdc82e28293031d10c7d73bf85e57bf041a97360aa2c5d99c", + "0xc1df82d9c4b87413eae2ef048f94b4d3554cea73d92b0f7af96e0271c691e2bb", + "0x5c67add7c6caf302256adedf7ab114da0acfe870d449a3a489f781d659e8becc", + "0xda7bce9f4e8618b6bd2f4132ce798cdc7a60e7e1460a7299e3c6342a579626d2", + "0x2733e50f526ec2fa19a22b31e8ed50f23cd1fdf94c9154ed3a7609a2f1ff981f", + "0xe1d3b5c807b281e4683cc6d6315cf95b9ade8641defcb32372f1c126e398ef7a", + "0x5a2dce0a8a7f68bb74560f8f71837c2c2ebbcbf7fffb42ae1896f13f7c7479a0", + "0xb46a28b6f55540f89444f63de0378e3d121be09e06cc9ded1c20e65876d36aa0", + "0xc65e9645644786b620e2dd2ad648ddfcbf4a7e5b1a3a4ecfe7f64667a3f0b7e2", + "0xf4418588ed35a2458cffeb39b93d26f18d2ab13bdce6aee58e7b99359ec2dfd9", + "0x5a9c16dc00d6ef18b7933a6f8dc65ccb55667138776f7dea101070dc8796e377", + "0x4df84f40ae0c8229d0d6069e5c8f39a7c299677a09d367fc7b05e3bc380ee652", + "0xcdc72595f74c7b1043d0e1ffbab734648c838dfb0527d971b602bc216c9619ef", + "0x0abf5ac974a1ed57f4050aa510dd9c74f508277b39d7973bb2dfccc5eeb0618d", + "0xb8cd74046ff337f0a7bf2c8e03e10f642c1886798d71806ab1e888d9e5ee87d0", + "0x838c5655cb21c6cb83313b5a631175dff4963772cce9108188b34ac87c81c41e", + "0x662ee4dd2dd7b2bc707961b1e646c4047669dcb6584f0d8d770daf5d7e7deb2e", + "0x388ab20e2573d171a88108e79d820e98f26c0b84aa8b2f4aa4968dbb818ea322", + "0x93237c50ba75ee485f4c22adf2f741400bdf8d6a9cc7df7ecae576221665d735", + "0x8448818bb4ae4562849e949e17ac16e0be16688e156b5cf15e098c627c0056a9", + ], + merkleRoot: "0x54e37f6a8efe3497d1b721d8a5a19786e78d16edabdefdfa94173ef104b132cb", + index: 0, +}; + +export const INVALID_MERKLE_PROOF = { + merkleRoot: "0xfbe8939cea4bb333e59120d35f318e3e7c88cdd0e70e66ae98b64efb9a5716ec", + index: 0, + proof: [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5", + "0xb4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d30", + "0x21ddb9a356815c3fac1026b6dec5df3124afbadb485c9ba5a3e3398a04b7ba85", + "0xe58769b32a1beaf1ea27375a44095a0d1fb664ce2dd358e7fcbfb78c26a19344", + "0x0eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d", + "0x887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a1968", + "0xffd70157e48063fc33c97a050f7f640233bf646cc98d9524c6b92bcf3ab56f83", + "0x9867cc5f7f196b93bae1e27e6320742445d290f2263827498b54fec539f756af", + "0xcefad4e508c098b9a7e1d8feb19955fb02ba9675585078710969d3440f5054e0", + "0xf9dc3e7fe016e050eff260334f18a5d4fe391d82092319f5964f2e2eb7c1c3a5", + "0xf8b13a49e282f609c317a833fb8d976d11517c571d1221a265d25af778ecf892", + "0x3490c6ceeb450aecdc82e28293031d10c7d73bf85e57bf041a97360aa2c5d99c", + "0xc1df82d9c4b87413eae2ef048f94b4d3554cea73d92b0f7af96e0271c691e2bb", + "0x5c67add7c6caf302256adedf7ab114da0acfe870d449a3a489f781d659e8becc", + "0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5", + "0x2733e50f526ec2fa19a22b31e8ed50f23cd1fdf94c9154ed3a7609a2f1ff981f", + "0xe1d3b5c807b281e4683cc6d6315cf95b9ade8641defcb32372f1c126e398ef7a", + "0x5a2dce0a8a7f68bb74560f8f71837c2c2ebbcbf7fffb42ae1896f13f7c7479a0", + "0xb46a28b6f55540f89444f63de0378e3d121be09e06cc9ded1c20e65876d36aa0", + "0xc65e9645644786b620e2dd2ad648ddfcbf4a7e5b1a3a4ecfe7f64667a3f0b7e2", + "0xf4418588ed35a2458cffeb39b93d26f18d2ab13bdce6aee58e7b99359ec2dfd9", + "0x5a9c16dc00d6ef18b7933a6f8dc65ccb55667138776f7dea101070dc8796e377", + "0x4df84f40ae0c8229d0d6069e5c8f39a7c299677a09d367fc7b05e3bc380ee652", + "0xcdc72595f74c7b1043d0e1ffbab734648c838dfb0527d971b602bc216c9619ef", + "0x0abf5ac974a1ed57f4050aa510dd9c74f508277b39d7973bb2dfccc5eeb0618d", + "0xb8cd74046ff337f0a7bf2c8e03e10f642c1886798d71806ab1e888d9e5ee87d0", + "0x838c5655cb21c6cb83313b5a631175dff4963772cce9108188b34ac87c81c41e", + "0x662ee4dd2dd7b2bc707961b1e646c4047669dcb6584f0d8d770daf5d7e7deb2e", + "0x388ab20e2573d171a88108e79d820e98f26c0b84aa8b2f4aa4968dbb818ea322", + "0x93237c50ba75ee485f4c22adf2f741400bdf8d6a9cc7df7ecae576221665d735", + "0x8448818bb4ae4562849e949e17ac16e0be16688e156b5cf15e098c627c0056a9", + ], +}; + +export const INVALID_MERKLE_PROOF_REVERT = { + proof: [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5", + "0xb4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d30", + "0x21ddb9a356815c3fac1026b6dec5df3124afbadb485c9ba5a3e3398a04b7ba85", + "0xe58769b32a1beaf1ea27375a44095a0d1fb664ce2dd358e7fcbfb78c26a19344", + "0x0eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d", + "0x887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a1968", + "0xffd70157e48063fc33c97a050f7f640233bf646cc98d9524c6b92bcf3ab56f83", + "0x9867cc5f7f196b93bae1e27e6320742445d290f2263827498b54fec539f756af", + "0xcefad4e508c098b9a7e1d8feb19955fb02ba9675585078710969d3440f5054e0", + "0xf9dc3e7fe016e050eff260334f18a5d4fe391d82092319f5964f2e2eb7c1c3a5", + "0xf8b13a49e282f609c317a833fb8d976d11517c571d1221a265d25af778ecf892", + "0x3490c6ceeb450aecdc82e28293031d10c7d73bf85e57bf041a97360aa2c5d99c", + "0xc1df82d9c4b87413eae2ef048f94b4d3554cea73d92b0f7af96e0271c691e2bb", + "0x5c67add7c6caf302256adedf7ab114da0acfe870d449a3a489f781d659e8becc", + "0xda7bce9f4e8618b6bd2f4132ce798cdc7a60e7e1460a7299e3c6342a579626d2", + "0x2733e50f526ec2fa19a22b31e8ed50f23cd1fdf94c9154ed3a7609a2f1ff981f", + "0xe1d3b5c807b281e4683cc6d6315cf95b9ade8641defcb32372f1c126e398ef7a", + "0x5a2dce0a8a7f68bb74560f8f71837c2c2ebbcbf7fffb42ae1896f13f7c7479a0", + "0xb46a28b6f55540f89444f63de0378e3d121be09e06cc9ded1c20e65876d36aa0", + "0xc65e9645644786b620e2dd2ad648ddfcbf4a7e5b1a3a4ecfe7f64667a3f0b7e2", + "0xf4418588ed35a2458cffeb39b93d26f18d2ab13bdce6aee58e7b99359ec2dfd9", + "0x5a9c16dc00d6ef18b7933a6f8dc65ccb55667138776f7dea101070dc8796e377", + "0x4df84f40ae0c8229d0d6069e5c8f39a7c299677a09d367fc7b05e3bc380ee652", + "0xcdc72595f74c7b1043d0e1ffbab734648c838dfb0527d971b602bc216c9619ef", + "0x0abf5ac974a1ed57f4050aa510dd9c74f508277b39d7973bb2dfccc5eeb0618d", + "0xb8cd74046ff337f0a7bf2c8e03e10f642c1886798d71806ab1e888d9e5ee87d0", + "0x838c5655cb21c6cb83313b5a631175dff4963772cce9108188b34ac87c81c41e", + "0x662ee4dd2dd7b2bc707961b1e646c4047669dcb6584f0d8d770daf5d7e7deb2e", + "0x388ab20e2573d171a88108e79d820e98f26c0b84aa8b2f4aa4968dbb818ea322", + "0x93237c50ba75ee485f4c22adf2f741400bdf8d6a9cc7df7ecae576221665d735", + "0x8448818bb4ae4562849e949e17ac16e0be16688e156b5cf15e098c627c0056a9", + ], + merkleRoot: "0xd1eb21c855a643efa2b5f6e45c6e19784aeca4d4edfed71d16f1a4235a259aa1", + index: 0, +}; + +export const MERKLE_PROOF_FALLBACK = { + proof: [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5", + "0xb4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d30", + "0x21ddb9a356815c3fac1026b6dec5df3124afbadb485c9ba5a3e3398a04b7ba85", + "0xe58769b32a1beaf1ea27375a44095a0d1fb664ce2dd358e7fcbfb78c26a19344", + "0x0eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d", + "0x887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a1968", + "0xffd70157e48063fc33c97a050f7f640233bf646cc98d9524c6b92bcf3ab56f83", + ], + merkleRoot: "0xcb9b5496c90542ac03009b37acf6ef8e8867856e2333e0eb9954290b9ce69272", + index: 0, +}; + +export const MERKLE_PROOF_REENTRY = { + proof: [ + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5", + "0xb4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d30", + "0x21ddb9a356815c3fac1026b6dec5df3124afbadb485c9ba5a3e3398a04b7ba85", + "0xe58769b32a1beaf1ea27375a44095a0d1fb664ce2dd358e7fcbfb78c26a19344", + "0x0eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d", + "0x887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a1968", + "0xffd70157e48063fc33c97a050f7f640233bf646cc98d9524c6b92bcf3ab56f83", + ], + merkleRoot: "0x494aab847e375519445b672ca9f5b4adac13ceb233c371978a18ab437483521b", + index: 0, +}; diff --git a/contracts/test/common/constants/messageStatuses.ts b/contracts/test/common/constants/messageStatuses.ts new file mode 100644 index 000000000..150b25283 --- /dev/null +++ b/contracts/test/common/constants/messageStatuses.ts @@ -0,0 +1,7 @@ +export const INBOX_STATUS_UNKNOWN = 0; +export const INBOX_STATUS_RECEIVED = 1; +export const INBOX_STATUS_CLAIMED = 2; + +export const OUTBOX_STATUS_UNKNOWN = 0; +export const OUTBOX_STATUS_SENT = 1; +export const OUTBOX_STATUS_RECEIVED = 2; diff --git a/contracts/test/common/constants/pauseTypes.ts b/contracts/test/common/constants/pauseTypes.ts new file mode 100644 index 000000000..a9b2e2201 --- /dev/null +++ b/contracts/test/common/constants/pauseTypes.ts @@ -0,0 +1,47 @@ +import { + PAUSE_ALL_ROLE, + UNPAUSE_ALL_ROLE, + PAUSE_L1_L2_ROLE, + UNPAUSE_L1_L2_ROLE, + PAUSE_L2_L1_ROLE, + UNPAUSE_L2_L1_ROLE, + PAUSE_BLOB_SUBMISSION_ROLE, + UNPAUSE_BLOB_SUBMISSION_ROLE, + PAUSE_FINALIZE_WITHPROOF_ROLE, + UNPAUSE_FINALIZE_WITHPROOF_ROLE, + PAUSE_INITIATE_TOKEN_BRIDGING_ROLE, + UNPAUSE_INITIATE_TOKEN_BRIDGING_ROLE, + PAUSE_COMPLETE_TOKEN_BRIDGING_ROLE, + UNPAUSE_COMPLETE_TOKEN_BRIDGING_ROLE, +} from "./roles"; + +export const GENERAL_PAUSE_TYPE = 1; +export const L1_L2_PAUSE_TYPE = 2; +export const L2_L1_PAUSE_TYPE = 3; +export const BLOB_SUBMISSION_PAUSE_TYPE = 4; +export const CALLDATA_SUBMISSION_PAUSE_TYPE = 5; +export const FINALIZATION_PAUSE_TYPE = 6; +export const INITIATE_TOKEN_BRIDGING_PAUSE_TYPE = 7; +export const COMPLETE_TOKEN_BRIDGING_PAUSE_TYPE = 8; + +export const pauseTypeRoles = [ + { pauseType: GENERAL_PAUSE_TYPE, role: PAUSE_ALL_ROLE }, + { pauseType: L1_L2_PAUSE_TYPE, role: PAUSE_L1_L2_ROLE }, + { pauseType: L2_L1_PAUSE_TYPE, role: PAUSE_L2_L1_ROLE }, + { pauseType: BLOB_SUBMISSION_PAUSE_TYPE, role: PAUSE_BLOB_SUBMISSION_ROLE }, + { pauseType: CALLDATA_SUBMISSION_PAUSE_TYPE, role: PAUSE_BLOB_SUBMISSION_ROLE }, + { pauseType: FINALIZATION_PAUSE_TYPE, role: PAUSE_FINALIZE_WITHPROOF_ROLE }, + { pauseType: INITIATE_TOKEN_BRIDGING_PAUSE_TYPE, role: PAUSE_INITIATE_TOKEN_BRIDGING_ROLE }, + { pauseType: COMPLETE_TOKEN_BRIDGING_PAUSE_TYPE, role: PAUSE_COMPLETE_TOKEN_BRIDGING_ROLE }, +]; + +export const unpauseTypeRoles = [ + { pauseType: GENERAL_PAUSE_TYPE, role: UNPAUSE_ALL_ROLE }, + { pauseType: L1_L2_PAUSE_TYPE, role: UNPAUSE_L1_L2_ROLE }, + { pauseType: L2_L1_PAUSE_TYPE, role: UNPAUSE_L2_L1_ROLE }, + { pauseType: BLOB_SUBMISSION_PAUSE_TYPE, role: UNPAUSE_BLOB_SUBMISSION_ROLE }, + { pauseType: CALLDATA_SUBMISSION_PAUSE_TYPE, role: UNPAUSE_BLOB_SUBMISSION_ROLE }, + { pauseType: FINALIZATION_PAUSE_TYPE, role: UNPAUSE_FINALIZE_WITHPROOF_ROLE }, + { pauseType: INITIATE_TOKEN_BRIDGING_PAUSE_TYPE, role: UNPAUSE_INITIATE_TOKEN_BRIDGING_ROLE }, + { pauseType: COMPLETE_TOKEN_BRIDGING_PAUSE_TYPE, role: UNPAUSE_COMPLETE_TOKEN_BRIDGING_ROLE }, +]; diff --git a/contracts/test/common/constants/roles.ts b/contracts/test/common/constants/roles.ts new file mode 100644 index 000000000..fe2a182b9 --- /dev/null +++ b/contracts/test/common/constants/roles.ts @@ -0,0 +1,63 @@ +import { generateKeccak256 } from "../helpers"; +import { HASH_ZERO } from "./general"; + +// Linea XP Token roles +export const MINTER_ROLE = generateKeccak256(["string"], ["MINTER_ROLE"], true); +export const TRANSFER_ROLE = generateKeccak256(["string"], ["TRANSFER_ROLE"], true); + +// TimeLock roles +export const TIMELOCK_ADMIN_ROLE = generateKeccak256(["string"], ["TIMELOCK_ADMIN_ROLE"], true); +export const PROPOSER_ROLE = generateKeccak256(["string"], ["PROPOSER_ROLE"], true); +export const EXECUTOR_ROLE = generateKeccak256(["string"], ["EXECUTOR_ROLE"], true); +export const CANCELLER_ROLE = generateKeccak256(["string"], ["CANCELLER_ROLE"], true); + +// Roles hashes +export const DEFAULT_ADMIN_ROLE = HASH_ZERO; +export const FUNCTION_EXECUTOR_ROLE = generateKeccak256(["string"], ["FUNCTION_EXECUTOR_ROLE"], true); +export const RATE_LIMIT_SETTER_ROLE = generateKeccak256(["string"], ["RATE_LIMIT_SETTER_ROLE"], true); +export const USED_RATE_LIMIT_RESETTER_ROLE = generateKeccak256(["string"], ["USED_RATE_LIMIT_RESETTER_ROLE"], true); +export const L1_L2_MESSAGE_SETTER_ROLE = generateKeccak256(["string"], ["L1_L2_MESSAGE_SETTER_ROLE"], true); +export const PAUSE_ALL_ROLE = generateKeccak256(["string"], ["PAUSE_ALL_ROLE"], true); +export const UNPAUSE_ALL_ROLE = generateKeccak256(["string"], ["UNPAUSE_ALL_ROLE"], true); +export const PAUSE_L1_L2_ROLE = generateKeccak256(["string"], ["PAUSE_L1_L2_ROLE"], true); +export const UNPAUSE_L1_L2_ROLE = generateKeccak256(["string"], ["UNPAUSE_L1_L2_ROLE"], true); +export const PAUSE_L2_L1_ROLE = generateKeccak256(["string"], ["PAUSE_L2_L1_ROLE"], true); +export const UNPAUSE_L2_L1_ROLE = generateKeccak256(["string"], ["UNPAUSE_L2_L1_ROLE"], true); +export const PAUSE_BLOB_SUBMISSION_ROLE = generateKeccak256(["string"], ["PAUSE_BLOB_SUBMISSION_ROLE"], true); +export const UNPAUSE_BLOB_SUBMISSION_ROLE = generateKeccak256(["string"], ["UNPAUSE_BLOB_SUBMISSION_ROLE"], true); +export const PAUSE_FINALIZE_WITHPROOF_ROLE = generateKeccak256(["string"], ["PAUSE_FINALIZE_WITHPROOF_ROLE"], true); +export const UNPAUSE_FINALIZE_WITHPROOF_ROLE = generateKeccak256(["string"], ["UNPAUSE_FINALIZE_WITHPROOF_ROLE"], true); +export const MINIMUM_FEE_SETTER_ROLE = generateKeccak256(["string"], ["MINIMUM_FEE_SETTER_ROLE"], true); +export const OPERATOR_ROLE = generateKeccak256(["string"], ["OPERATOR_ROLE"], true); +export const VERIFIER_SETTER_ROLE = generateKeccak256(["string"], ["VERIFIER_SETTER_ROLE"], true); +export const VERIFIER_UNSETTER_ROLE = generateKeccak256(["string"], ["VERIFIER_UNSETTER_ROLE"], true); +export const L1_MERKLE_ROOTS_SETTER_ROLE = generateKeccak256(["string"], ["L1_MERKLE_ROOTS_SETTER_ROLE"], true); +export const L2_MERKLE_ROOTS_SETTER_ROLE = generateKeccak256(["string"], ["L2_MERKLE_ROOTS_SETTER_ROLE"], true); +export const BAD_STARTING_HASH = generateKeccak256(["string"], ["BAD_STARTING_HASH"], true); + +// TokenBridge roles +export const PAUSE_INITIATE_TOKEN_BRIDGING_ROLE = generateKeccak256( + ["string"], + ["PAUSE_INITIATE_TOKEN_BRIDGING_ROLE"], + true, +); +export const PAUSE_COMPLETE_TOKEN_BRIDGING_ROLE = generateKeccak256( + ["string"], + ["PAUSE_COMPLETE_TOKEN_BRIDGING_ROLE"], + true, +); +export const UNPAUSE_INITIATE_TOKEN_BRIDGING_ROLE = generateKeccak256( + ["string"], + ["UNPAUSE_INITIATE_TOKEN_BRIDGING_ROLE"], + true, +); +export const UNPAUSE_COMPLETE_TOKEN_BRIDGING_ROLE = generateKeccak256( + ["string"], + ["UNPAUSE_COMPLETE_TOKEN_BRIDGING_ROLE"], + true, +); +export const SET_REMOTE_TOKENBRIDGE_ROLE = generateKeccak256(["string"], ["SET_REMOTE_TOKENBRIDGE_ROLE"], true); +export const SET_RESERVED_TOKEN_ROLE = generateKeccak256(["string"], ["SET_RESERVED_TOKEN_ROLE"], true); +export const REMOVE_RESERVED_TOKEN_ROLE = generateKeccak256(["string"], ["REMOVE_RESERVED_TOKEN_ROLE"], true); +export const SET_CUSTOM_CONTRACT_ROLE = generateKeccak256(["string"], ["SET_CUSTOM_CONTRACT_ROLE"], true); +export const SET_MESSAGE_SERVICE_ROLE = generateKeccak256(["string"], ["SET_MESSAGE_SERVICE_ROLE"], true); diff --git a/contracts/test/common/constants/submissionData.ts b/contracts/test/common/constants/submissionData.ts new file mode 100644 index 000000000..79f62ea7c --- /dev/null +++ b/contracts/test/common/constants/submissionData.ts @@ -0,0 +1,58 @@ +import { HASH_ZERO } from "./general"; + +import firstCompressedDataContent from "../../testData/compressedData/blocks-1-46.json"; +import fourthCompressedDataContent from "../../testData/compressedData/blocks-115-155.json"; +import secondCompressedDataContent from "../../testData/compressedData/blocks-47-81.json"; +import thirdCompressedDataContent from "../../testData/compressedData/blocks-82-114.json"; +import fourthBlobDataContent from "../../testData/compressedDataEip4844/blocks-115-155.json"; +import thirdBlobDataContent from "../../testData/compressedDataEip4844/blocks-82-114.json"; +import secondBlobDataContent from "../../testData/compressedDataEip4844/blocks-47-81.json"; +import firstBlobDataContent from "../../testData/compressedDataEip4844/blocks-1-46.json"; + +import firstCompressedDataContent_multiple from "../../testData/compressedData/multipleProofs/blocks-1-46.json"; +import secondCompressedDataContent_multiple from "../../testData/compressedData/multipleProofs/blocks-47-81.json"; +import thirdCompressedDataContent_multiple from "../../testData/compressedData/multipleProofs/blocks-82-119.json"; +import fourthCompressedDataContent_multiple from "../../testData/compressedData/multipleProofs/blocks-120-153.json"; + +import firstBlobContent_multiple from "../../testData/compressedDataEip4844/multipleProofs/blocks-1-46.json"; +import secondBlobContent_multiple from "../../testData/compressedDataEip4844/multipleProofs/blocks-47-81.json"; +import thirdBlobContent_multiple from "../../testData/compressedDataEip4844/multipleProofs/blocks-82-119.json"; +import fourthBlobContent_multiple from "../../testData/compressedDataEip4844/multipleProofs/blocks-120-153.json"; + +export const DEFAULT_SUBMISSION_DATA = { + dataParentHash: HASH_ZERO, + compressedData: "0x", + finalBlockInData: 0n, + firstBlockInData: 0n, + parentStateRootHash: HASH_ZERO, + finalStateRootHash: HASH_ZERO, + snarkHash: HASH_ZERO, +}; + +export const COMPRESSED_SUBMISSION_DATA = [ + firstCompressedDataContent, + secondCompressedDataContent, + thirdCompressedDataContent, + fourthCompressedDataContent, +]; + +export const BLOB_SUBMISSION_DATA = [ + firstBlobDataContent, + secondBlobDataContent, + thirdBlobDataContent, + fourthBlobDataContent, +]; + +export const COMPRESSED_SUBMISSION_DATA_MULTIPLE_PROOF = [ + firstCompressedDataContent_multiple, + secondCompressedDataContent_multiple, + thirdCompressedDataContent_multiple, + fourthCompressedDataContent_multiple, +]; + +export const BLOB_SUBMISSION_DATA_MULTIPLE_PROOF = [ + firstBlobContent_multiple, + secondBlobContent_multiple, + thirdBlobContent_multiple, + fourthBlobContent_multiple, +]; diff --git a/contracts/test/common/constants/time.ts b/contracts/test/common/constants/time.ts new file mode 100644 index 000000000..3057d43bc --- /dev/null +++ b/contracts/test/common/constants/time.ts @@ -0,0 +1,12 @@ +export const ONE_SECOND = 1; +export const ONE_MINUTE_IN_SECONDS = 60 * ONE_SECOND; +export const ONE_HOUR_IN_SECONDS = 60 * ONE_MINUTE_IN_SECONDS; +export const ONE_DAY_IN_SECONDS = 24 * ONE_HOUR_IN_SECONDS; +export const ONE_MONTH_IN_SECONDS = 30 * ONE_DAY_IN_SECONDS; +export const ONE_YEARS_IN_SECONDS = 365 * ONE_DAY_IN_SECONDS; + +export const INITIAL_MIGRATION_BLOCK = 0; +export const GENESIS_L2_TIMESTAMP = 0; +export const DEFAULT_LAST_FINALIZED_TIMESTAMP = 1683325137n; +export const SIX_MONTHS_IN_SECONDS = ONE_YEARS_IN_SECONDS / 2; +export const TEST_PUBLIC_VERIFIER_INDEX = 0; diff --git a/contracts/test/utils/deployment.ts b/contracts/test/common/deployment.ts similarity index 100% rename from contracts/test/utils/deployment.ts rename to contracts/test/common/deployment.ts diff --git a/contracts/test/utils/helpers.ts b/contracts/test/common/helpers/dataGeneration.ts similarity index 55% rename from contracts/test/utils/helpers.ts rename to contracts/test/common/helpers/dataGeneration.ts index 7ec4f1a38..11b2c6d1d 100644 --- a/contracts/test/utils/helpers.ts +++ b/contracts/test/common/helpers/dataGeneration.ts @@ -1,208 +1,24 @@ +import { ethers } from "ethers"; import { time as networkTime } from "@nomicfoundation/hardhat-network-helpers"; -import fs from "fs"; -import path from "path"; -import { expect } from "chai"; -import { DEFAULT_MESSAGE_NONCE, HASH_ZERO, MESSAGE_FEE, MESSAGE_VALUE_1ETH } from "./constants"; import { - DebugData, - FormattedBlockData, - RawBlockData, + HASH_ZERO, + COMPRESSED_SUBMISSION_DATA, + COMPRESSED_SUBMISSION_DATA_MULTIPLE_PROOF, + BLOB_SUBMISSION_DATA, + BLOB_SUBMISSION_DATA_MULTIPLE_PROOF, +} from "../constants"; +import { FinalizationData, - SubmissionData, - SubmissionAndCompressedData, CalldataSubmissionData, - ParentSubmissionData, + SubmissionAndCompressedData, + BlobSubmissionData, ShnarfData, + ParentSubmissionData, ParentAndExpectedShnarf, - BlobSubmissionData, -} from "./types"; - -import firstCompressedDataContent from "../testData/compressedData/blocks-1-46.json"; -import fourthCompressedDataContent from "../testData/compressedData/blocks-115-155.json"; -import secondCompressedDataContent from "../testData/compressedData/blocks-47-81.json"; -import thirdCompressedDataContent from "../testData/compressedData/blocks-82-114.json"; -import fourthBlobDataContent from "../testData/compressedDataEip4844/blocks-115-155.json"; -import thirdBlobDataContent from "../testData/compressedDataEip4844/blocks-82-114.json"; -import secondBlobDataContent from "../testData/compressedDataEip4844/blocks-47-81.json"; -import firstBlobDataContent from "../testData/compressedDataEip4844/blocks-1-46.json"; - -const COMPRESSED_SUBMISSION_DATA = [ - firstCompressedDataContent, - secondCompressedDataContent, - thirdCompressedDataContent, - fourthCompressedDataContent, -]; - -const BLOB_SUBMISSION_DATA = [firstBlobDataContent, secondBlobDataContent, thirdBlobDataContent, fourthBlobDataContent]; - -import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; -import { AbiCoder, ethers } from "ethers"; -import firstCompressedDataContent_multiple from "../testData/compressedData/multipleProofs/blocks-1-46.json"; -import secondCompressedDataContent_multiple from "../testData/compressedData/multipleProofs/blocks-47-81.json"; -import thirdCompressedDataContent_multiple from "../testData/compressedData/multipleProofs/blocks-82-119.json"; -import fourthCompressedDataContent_multiple from "../testData/compressedData/multipleProofs/blocks-120-153.json"; - -const COMPRESSED_SUBMISSION_DATA_MULTIPLE_PROOF = [ - firstCompressedDataContent_multiple, - secondCompressedDataContent_multiple, - thirdCompressedDataContent_multiple, - fourthCompressedDataContent_multiple, -]; - -import firstBlobContent_multiple from "../testData/compressedDataEip4844/multipleProofs/blocks-1-46.json"; -import secondBlobContent_multiple from "../testData/compressedDataEip4844/multipleProofs/blocks-47-81.json"; -import thirdBlobContent_multiple from "../testData/compressedDataEip4844/multipleProofs/blocks-82-119.json"; -import fourthBlobContent_multiple from "../testData/compressedDataEip4844/multipleProofs/blocks-120-153.json"; - -const BLOB_SUBMISSION_DATA_MULTIPLE_PROOF = [ - firstBlobContent_multiple, - secondBlobContent_multiple, - thirdBlobContent_multiple, - fourthBlobContent_multiple, -]; -export type ShnarfDataGenerator = (blobParentShnarfIndex: number, isMultiple?: boolean) => ShnarfData; - -export const generateKeccak256Hash = (str: string) => generateKeccak256(["string"], [str], true); - -export const generateKeccak256 = (types: string[], values: unknown[], packed?: boolean) => - ethers.keccak256(encodeData(types, values, packed)); - -export const encodeData = (types: string[], values: unknown[], packed?: boolean) => { - if (packed) { - return ethers.solidityPacked(types, values); - } - return AbiCoder.defaultAbiCoder().encode(types, values); -}; - -export const generateNKeccak256Hashes = (str: string, numberOfHashToGenerate: number): string[] => { - let arr: string[] = []; - for (let i = 1; i < numberOfHashToGenerate + 1; i++) { - arr = [...arr, generateKeccak256(["string"], [`${str}${i}`], true)]; - } - return arr; -}; - -export const generateRandomBytes = (length: number): string => ethers.hexlify(ethers.randomBytes(length)); - -export async function encodeSendMessageLog( - sender: SignerWithAddress, - receiver: SignerWithAddress, - messageHash: string, - calldata: string, -) { - const topic = ethers.id("MessageSent(address,address,uint256,uint256,uint256,bytes,bytes32)"); - const data = encodeData( - ["address", "address", "uint256", "uint256", "uint256", "bytes", "bytes32"], - [sender.address, receiver.address, MESSAGE_FEE, MESSAGE_VALUE_1ETH, DEFAULT_MESSAGE_NONCE, calldata, messageHash], - ); - - return { - topic, - data, - }; -} - -export async function encodeSendMessage( - sender: string, - receiver: string, - fee: bigint, - amount: bigint, - salt: bigint, - calldata: string, -) { - return encodeData( - ["address", "address", "uint256", "uint256", "uint256", "bytes"], - [sender, receiver, fee, amount, salt, calldata], - ); -} - -export function calculateLastFinalizedState( - l1RollingHashMessageNumber: bigint, - l1RollingHash: string, - finalTimestamp: bigint, -): string { - return generateKeccak256( - ["uint256", "bytes32", "uint256"], - [l1RollingHashMessageNumber, l1RollingHash, finalTimestamp], - ); -} - -export function calculateRollingHash(existingRollingHash: string, messageHash: string) { - return generateKeccak256(["bytes32", "bytes32"], [existingRollingHash, messageHash]); -} - -export function calculateRollingHashFromCollection(existingRollingHash: string, messageHashes: string[]) { - return messageHashes.reduce((rollingHash, hash) => calculateRollingHash(rollingHash, hash), existingRollingHash); -} - -export const range = (start: number, end: number) => Array.from(Array(end - start + 1).keys()).map((x) => x + start); - -export function getProverTestData( - folder: string, - filename: string, -): { - blocks: FormattedBlockData[]; - proverMode: string; - parentStateRootHash: string; - version: string; - firstBlockNumber: number; - proof: string; - debugData: DebugData; -} { - const testFilePath = path.resolve(__dirname, "..", "testData", folder, filename); - const testData = JSON.parse(fs.readFileSync(testFilePath, "utf8")); - - return { - blocks: testData.blocksData.map((block: RawBlockData) => ({ - blockRootHash: block.rootHash, - transactions: block.rlpEncodedTransactions, - l2BlockTimestamp: block.timestamp, - l2ToL1MsgHashes: block.l2ToL1MsgHashes, - fromAddresses: block.fromAddresses, - batchReceptionIndices: block.batchReceptionIndices, - })), - proverMode: testData.proverMode, - parentStateRootHash: testData.parentStateRootHash, - version: testData.version, - firstBlockNumber: testData.firstBlockNumber, - proof: testData.proof, - debugData: testData.DebugData, - }; -} - -export function getRLPEncodeTransactions(filename: string): { - shortEip1559Transaction: string; - eip1559Transaction: string; - eip1559TransactionHashes: string[]; - legacyTransaction: string; - legacyTransactionHashes: string[]; - eip2930Transaction: string; - eip2930TransactionHashes: string[]; -} { - const testFilePath = path.resolve(__dirname, "..", "testData", filename); - const testData = JSON.parse(fs.readFileSync(testFilePath, "utf8")); - - return { - shortEip1559Transaction: testData.shortEip1559Transaction, - eip1559Transaction: testData.eip1559Transaction, - eip1559TransactionHashes: testData.eip1559TransactionHashes, - legacyTransaction: testData.legacyTransaction, - legacyTransactionHashes: testData.legacyTransactionHashes, - eip2930Transaction: testData.eip2930Transaction, - eip2930TransactionHashes: testData.eip2930TransactionHashes, - }; -} - -export function getTransactionsToBeDecoded(blocks: FormattedBlockData[]): string[] { - const txsToBeDecoded = []; - for (let i = 0; i < blocks.length; i++) { - for (let j = 0; j < blocks[i].batchReceptionIndices.length; j++) { - const txIndex = blocks[i].batchReceptionIndices[j]; - txsToBeDecoded.push(blocks[i].transactions[txIndex]); - } - } - return txsToBeDecoded; -} + SubmissionData, +} from "../types"; +import { generateRandomBytes, range } from "./general"; +import { generateKeccak256 } from "./hashing"; export const generateL2MessagingBlocksOffsets = (start: number, end: number) => `0x${range(start, end) @@ -480,42 +296,3 @@ export function generateFinalizationDataFromJSON(parsedJSONData: any): Finalizat l2MessagingBlocksOffsets: data.l2MessagingBlocksOffsets, }; } - -/* eslint-disable @typescript-eslint/no-explicit-any */ -export async function expectRevertWithCustomError( - contract: any, - asyncCall: Promise, - errorName: string, - errorArgs: any[] = [], -) { - await expect(asyncCall) - .to.be.revertedWithCustomError(contract, errorName) - .withArgs(...errorArgs); -} - -/* eslint-disable @typescript-eslint/no-explicit-any */ -export async function expectRevertWithReason(asyncCall: Promise, reason: string) { - await expect(asyncCall).to.be.revertedWith(reason); -} -export function buildAccessErrorMessage(account: SignerWithAddress, role: string): string { - return `AccessControl: account ${account.address.toLowerCase()} is missing role ${role}`; -} - -/* eslint-disable @typescript-eslint/no-explicit-any */ -export async function expectEvent(contract: any, asyncCall: Promise, eventName: string, eventArgs: any[] = []) { - await expect(asyncCall) - .to.emit(contract, eventName) - .withArgs(...eventArgs); -} - -export function convertStringToPaddedHexBytes(strVal: string, paddedSize: number): string { - if (strVal.length > paddedSize) { - throw "Length is longer than padded size!"; - } - - const strBytes = ethers.toUtf8Bytes(strVal); - const bytes = ethers.zeroPadBytes(strBytes, paddedSize); - const bytes8Hex = ethers.hexlify(bytes); - - return bytes8Hex; -} diff --git a/contracts/test/common/helpers/dataLoader.ts b/contracts/test/common/helpers/dataLoader.ts new file mode 100644 index 000000000..19b999d0c --- /dev/null +++ b/contracts/test/common/helpers/dataLoader.ts @@ -0,0 +1,70 @@ +import fs from "fs"; +import path from "path"; +import { RawBlockData, FormattedBlockData, DebugData } from "../types"; + +export function getProverTestData( + folder: string, + filename: string, +): { + blocks: FormattedBlockData[]; + proverMode: string; + parentStateRootHash: string; + version: string; + firstBlockNumber: number; + proof: string; + debugData: DebugData; +} { + const testFilePath = path.resolve(__dirname, "..", "testData", folder, filename); + const testData = JSON.parse(fs.readFileSync(testFilePath, "utf8")); + + return { + blocks: testData.blocksData.map((block: RawBlockData) => ({ + blockRootHash: block.rootHash, + transactions: block.rlpEncodedTransactions, + l2BlockTimestamp: block.timestamp, + l2ToL1MsgHashes: block.l2ToL1MsgHashes, + fromAddresses: block.fromAddresses, + batchReceptionIndices: block.batchReceptionIndices, + })), + proverMode: testData.proverMode, + parentStateRootHash: testData.parentStateRootHash, + version: testData.version, + firstBlockNumber: testData.firstBlockNumber, + proof: testData.proof, + debugData: testData.DebugData, + }; +} + +export function getRLPEncodeTransactions(filename: string): { + shortEip1559Transaction: string; + eip1559Transaction: string; + eip1559TransactionHashes: string[]; + legacyTransaction: string; + legacyTransactionHashes: string[]; + eip2930Transaction: string; + eip2930TransactionHashes: string[]; +} { + const testFilePath = path.resolve(__dirname, "..", "testData", filename); + const testData = JSON.parse(fs.readFileSync(testFilePath, "utf8")); + + return { + shortEip1559Transaction: testData.shortEip1559Transaction, + eip1559Transaction: testData.eip1559Transaction, + eip1559TransactionHashes: testData.eip1559TransactionHashes, + legacyTransaction: testData.legacyTransaction, + legacyTransactionHashes: testData.legacyTransactionHashes, + eip2930Transaction: testData.eip2930Transaction, + eip2930TransactionHashes: testData.eip2930TransactionHashes, + }; +} + +export function getTransactionsToBeDecoded(blocks: FormattedBlockData[]): string[] { + const txsToBeDecoded = []; + for (let i = 0; i < blocks.length; i++) { + for (let j = 0; j < blocks[i].batchReceptionIndices.length; j++) { + const txIndex = blocks[i].batchReceptionIndices[j]; + txsToBeDecoded.push(blocks[i].transactions[txIndex]); + } + } + return txsToBeDecoded; +} diff --git a/contracts/test/common/helpers/encoding.ts b/contracts/test/common/helpers/encoding.ts new file mode 100644 index 000000000..26283b24f --- /dev/null +++ b/contracts/test/common/helpers/encoding.ts @@ -0,0 +1,20 @@ +import { ethers, AbiCoder } from "ethers"; + +export const encodeData = (types: string[], values: unknown[], packed?: boolean) => { + if (packed) { + return ethers.solidityPacked(types, values); + } + return AbiCoder.defaultAbiCoder().encode(types, values); +}; + +export function convertStringToPaddedHexBytes(strVal: string, paddedSize: number): string { + if (strVal.length > paddedSize) { + throw "Length is longer than padded size!"; + } + + const strBytes = ethers.toUtf8Bytes(strVal); + const bytes = ethers.zeroPadBytes(strBytes, paddedSize); + const bytes8Hex = ethers.hexlify(bytes); + + return bytes8Hex; +} diff --git a/contracts/test/common/helpers/expectations.ts b/contracts/test/common/helpers/expectations.ts new file mode 100644 index 000000000..b341eac84 --- /dev/null +++ b/contracts/test/common/helpers/expectations.ts @@ -0,0 +1,36 @@ +import { expect } from "chai"; +import { BaseContract, ContractFactory } from "ethers"; + +export async function expectRevertWithCustomError( + contract: T, + asyncCall: Promise, + errorName: string, + errorArgs: unknown[] = [], +) { + await expect(asyncCall) + .to.be.revertedWithCustomError(contract, errorName) + .withArgs(...errorArgs); +} + +export async function expectRevertWithReason(asyncCall: Promise, reason: string) { + await expect(asyncCall).to.be.revertedWith(reason); +} + +export async function expectEvent( + contract: T, + asyncCall: Promise, + eventName: string, + eventArgs: unknown[] = [], +) { + await expect(asyncCall) + .to.emit(contract, eventName) + .withArgs(...eventArgs); +} + +export async function expectEvents( + contract: T, + asyncCall: Promise, + events: { name: string; args: unknown[] }[], +) { + await Promise.all(events.map((event) => expectEvent(contract, asyncCall, event.name, event.args))); +} diff --git a/contracts/test/common/helpers/general.ts b/contracts/test/common/helpers/general.ts new file mode 100644 index 000000000..3c99d0411 --- /dev/null +++ b/contracts/test/common/helpers/general.ts @@ -0,0 +1,10 @@ +import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; +import { ethers } from "ethers"; + +export const range = (start: number, end: number) => Array.from(Array(end - start + 1).keys()).map((x) => x + start); + +export const generateRandomBytes = (length: number): string => ethers.hexlify(ethers.randomBytes(length)); + +export function buildAccessErrorMessage(account: SignerWithAddress, role: string): string { + return `AccessControl: account ${account.address.toLowerCase()} is missing role ${role}`; +} diff --git a/contracts/test/common/helpers/hashing.ts b/contracts/test/common/helpers/hashing.ts new file mode 100644 index 000000000..7c8815cca --- /dev/null +++ b/contracts/test/common/helpers/hashing.ts @@ -0,0 +1,34 @@ +import { ethers } from "ethers"; +import { encodeData } from "./encoding"; + +export const generateKeccak256Hash = (str: string) => generateKeccak256(["string"], [str], true); + +export const generateKeccak256 = (types: string[], values: unknown[], packed?: boolean) => + ethers.keccak256(encodeData(types, values, packed)); + +export const generateNKeccak256Hashes = (str: string, numberOfHashToGenerate: number): string[] => { + let arr: string[] = []; + for (let i = 1; i < numberOfHashToGenerate + 1; i++) { + arr = [...arr, generateKeccak256(["string"], [`${str}${i}`], true)]; + } + return arr; +}; + +export function calculateLastFinalizedState( + l1RollingHashMessageNumber: bigint, + l1RollingHash: string, + finalTimestamp: bigint, +): string { + return generateKeccak256( + ["uint256", "bytes32", "uint256"], + [l1RollingHashMessageNumber, l1RollingHash, finalTimestamp], + ); +} + +export function calculateRollingHash(existingRollingHash: string, messageHash: string) { + return generateKeccak256(["bytes32", "bytes32"], [existingRollingHash, messageHash]); +} + +export function calculateRollingHashFromCollection(existingRollingHash: string, messageHashes: string[]) { + return messageHashes.reduce((rollingHash, hash) => calculateRollingHash(rollingHash, hash), existingRollingHash); +} diff --git a/contracts/test/common/helpers/index.ts b/contracts/test/common/helpers/index.ts new file mode 100644 index 000000000..6ef0a6966 --- /dev/null +++ b/contracts/test/common/helpers/index.ts @@ -0,0 +1,7 @@ +export * from "./general"; +export * from "./messaging"; +export * from "./encoding"; +export * from "./hashing"; +export * from "./dataGeneration"; +export * from "./dataLoader"; +export * from "./expectations"; diff --git a/contracts/test/common/helpers/messaging.ts b/contracts/test/common/helpers/messaging.ts new file mode 100644 index 000000000..44d611baf --- /dev/null +++ b/contracts/test/common/helpers/messaging.ts @@ -0,0 +1,36 @@ +import { ethers } from "ethers"; +import { SignerWithAddress } from "@nomicfoundation/hardhat-ethers/signers"; +import { encodeData } from "./encoding"; +import { MESSAGE_FEE, MESSAGE_VALUE_1ETH, DEFAULT_MESSAGE_NONCE } from "../constants"; + +export async function encodeSendMessageLog( + sender: SignerWithAddress, + receiver: SignerWithAddress, + messageHash: string, + calldata: string, +) { + const topic = ethers.id("MessageSent(address,address,uint256,uint256,uint256,bytes,bytes32)"); + const data = encodeData( + ["address", "address", "uint256", "uint256", "uint256", "bytes", "bytes32"], + [sender.address, receiver.address, MESSAGE_FEE, MESSAGE_VALUE_1ETH, DEFAULT_MESSAGE_NONCE, calldata, messageHash], + ); + + return { + topic, + data, + }; +} + +export async function encodeSendMessage( + sender: string, + receiver: string, + fee: bigint, + amount: bigint, + salt: bigint, + calldata: string, +) { + return encodeData( + ["address", "address", "uint256", "uint256", "uint256", "bytes"], + [sender, receiver, fee, amount, salt, calldata], + ); +} diff --git a/contracts/test/utils/types.ts b/contracts/test/common/types.ts similarity index 95% rename from contracts/test/utils/types.ts rename to contracts/test/common/types.ts index 3dffd32d5..896b3011c 100644 --- a/contracts/test/utils/types.ts +++ b/contracts/test/common/types.ts @@ -92,3 +92,5 @@ export type FinalizationData = { lastFinalizedL1RollingHash: string; lastFinalizedL1RollingHashMessageNumber: bigint; }; + +export type ShnarfDataGenerator = (blobParentShnarfIndex: number, isMultiple?: boolean) => ShnarfData; diff --git a/contracts/test/messageService/l1/L1MessageManager.ts b/contracts/test/messageService/l1/L1MessageManager.ts index 624c25a05..c5e7f2689 100644 --- a/contracts/test/messageService/l1/L1MessageManager.ts +++ b/contracts/test/messageService/l1/L1MessageManager.ts @@ -1,15 +1,15 @@ import { loadFixture } from "@nomicfoundation/hardhat-network-helpers"; import { expect } from "chai"; import { TestL1MessageManager } from "../../../typechain-types"; -import { INBOX_STATUS_UNKNOWN, OUTBOX_STATUS_RECEIVED, OUTBOX_STATUS_SENT } from "../../utils/constants"; -import { deployFromFactory } from "../../utils/deployment"; +import { INBOX_STATUS_UNKNOWN, OUTBOX_STATUS_RECEIVED, OUTBOX_STATUS_SENT } from "../../common/constants"; +import { deployFromFactory } from "../../common/deployment"; import { generateKeccak256Hash, generateL2MessagingBlocksOffsets, generateNKeccak256Hashes, generateRandomBytes, range, -} from "../../utils/helpers"; +} from "../../common/helpers"; describe("L1MessageManager", () => { let l1MessageManager: TestL1MessageManager; diff --git a/contracts/test/messageService/lib/SparseMerkleTreeVerifier.ts b/contracts/test/messageService/lib/SparseMerkleTreeVerifier.ts index 76ce3c058..ad0cbada3 100644 --- a/contracts/test/messageService/lib/SparseMerkleTreeVerifier.ts +++ b/contracts/test/messageService/lib/SparseMerkleTreeVerifier.ts @@ -3,9 +3,9 @@ import { loadFixture } from "@nomicfoundation/hardhat-network-helpers"; import { expect } from "chai"; import { ethers } from "hardhat"; import { TestSparseMerkleTreeVerifier } from "../../../typechain-types"; -import { MESSAGE_FEE, MESSAGE_VALUE_1ETH } from "../../utils/constants"; -import { deployFromFactory } from "../../utils/deployment"; -import { expectRevertWithCustomError } from "contracts/test/utils/helpers"; +import { MESSAGE_FEE, MESSAGE_VALUE_1ETH } from "../../common/constants"; +import { deployFromFactory } from "../../common/deployment"; +import { expectRevertWithCustomError } from "contracts/test/common/helpers"; describe("SparseMerkleTreeVerifier", () => { let sparseMerkleTreeVerifier: TestSparseMerkleTreeVerifier; diff --git a/contracts/test/mimc.ts b/contracts/test/mimc.ts index 5d9ca1fda..d8c7e4c99 100644 --- a/contracts/test/mimc.ts +++ b/contracts/test/mimc.ts @@ -3,8 +3,8 @@ import { expect } from "chai"; import { ethers } from "hardhat"; import { Mimc } from "../typechain-types"; import mimcTestData from "./testData/mimc-test-data.json"; -import { deployFromFactory } from "./utils/deployment"; -import { expectRevertWithCustomError } from "./utils/helpers"; +import { deployFromFactory } from "./common/deployment"; +import { expectRevertWithCustomError } from "./common/helpers"; describe("Mimc", () => { let mimc: Mimc; diff --git a/contracts/test/tokenBridge/E2E.ts b/contracts/test/tokenBridge/E2E.ts index c97e56525..8ea0db06b 100644 --- a/contracts/test/tokenBridge/E2E.ts +++ b/contracts/test/tokenBridge/E2E.ts @@ -10,12 +10,12 @@ import { expectEvent, expectRevertWithCustomError, expectRevertWithReason, -} from "../utils/helpers"; +} from "../common/helpers"; import { COMPLETE_TOKEN_BRIDGING_PAUSE_TYPE, INITIATE_TOKEN_BRIDGING_PAUSE_TYPE, SET_MESSAGE_SERVICE_ROLE, -} from "../utils/constants"; +} from "../common/constants"; const initialUserBalance = BigInt(10 ** 9); const RESERVED_STATUS = ethers.getAddress("0x0000000000000000000000000000000000000111"); diff --git a/contracts/test/tokenBridge/TokenBridge.ts b/contracts/test/tokenBridge/TokenBridge.ts index 2f25d9b3e..7c27dd456 100644 --- a/contracts/test/tokenBridge/TokenBridge.ts +++ b/contracts/test/tokenBridge/TokenBridge.ts @@ -5,7 +5,7 @@ import { deployTokenBridgeWithMockMessaging } from "../../scripts/tokenBridge/te import { deployTokens } from "../../scripts/tokenBridge/test/deployTokens"; import { BridgedToken, TestTokenBridge, TokenBridge, ProxyAdmin } from "../../typechain-types"; import { getPermitData } from "./utils/permitHelper"; -import { Contract } from "ethers"; +import { Contract, ZeroAddress } from "ethers"; import { ADDRESS_ZERO, COMPLETE_TOKEN_BRIDGING_PAUSE_TYPE, @@ -18,19 +18,18 @@ import { SET_REMOTE_TOKENBRIDGE_ROLE, SET_RESERVED_TOKEN_ROLE, UNPAUSE_INITIATE_TOKEN_BRIDGING_ROLE, - DEFAULT_ADMIN_ROLE, pauseTypeRoles, unpauseTypeRoles, PAUSE_ALL_ROLE, UNPAUSE_ALL_ROLE, HASH_ZERO, -} from "../utils/constants"; +} from "../common/constants"; import { buildAccessErrorMessage, expectEvent, expectRevertWithCustomError, expectRevertWithReason, -} from "../utils/helpers"; +} from "../common/helpers"; const initialUserBalance = BigInt(10 ** 9); const mockName = "L1 DAI"; @@ -78,6 +77,7 @@ describe("TokenBridge", function () { const { user, l1TokenBridge, chainIds } = await loadFixture(deployContractsFixture); await expectRevertWithReason( l1TokenBridge.connect(user).initialize({ + defaultAdmin: PLACEHOLDER_ADDRESS, messageService: PLACEHOLDER_ADDRESS, tokenBeacon: PLACEHOLDER_ADDRESS, sourceChainId: chainIds[0], @@ -99,6 +99,7 @@ describe("TokenBridge", function () { TokenBridge, upgrades.deployProxy(TokenBridge, [ { + defaultAdmin: PLACEHOLDER_ADDRESS, messageService: ADDRESS_ZERO, tokenBeacon: PLACEHOLDER_ADDRESS, sourceChainId: chainIds[0], @@ -116,6 +117,7 @@ describe("TokenBridge", function () { TokenBridge, upgrades.deployProxy(TokenBridge, [ { + defaultAdmin: PLACEHOLDER_ADDRESS, messageService: PLACEHOLDER_ADDRESS, tokenBeacon: ADDRESS_ZERO, sourceChainId: chainIds[0], @@ -133,6 +135,7 @@ describe("TokenBridge", function () { TokenBridge, upgrades.deployProxy(TokenBridge, [ { + defaultAdmin: PLACEHOLDER_ADDRESS, messageService: PLACEHOLDER_ADDRESS, tokenBeacon: PLACEHOLDER_ADDRESS, sourceChainId: chainIds[0], @@ -153,6 +156,7 @@ describe("TokenBridge", function () { TokenBridge, upgrades.deployProxy(TokenBridge, [ { + defaultAdmin: PLACEHOLDER_ADDRESS, messageService: PLACEHOLDER_ADDRESS, tokenBeacon: PLACEHOLDER_ADDRESS, sourceChainId: chainIds[0], @@ -173,6 +177,7 @@ describe("TokenBridge", function () { const TestTokenBridgeFactory = await ethers.getContractFactory("TestTokenBridge"); const initData = { + defaultAdmin: PLACEHOLDER_ADDRESS, messageService: PLACEHOLDER_ADDRESS, tokenBeacon: PLACEHOLDER_ADDRESS, sourceChainId: 5, @@ -628,7 +633,7 @@ describe("TokenBridge", function () { l1TokenBridge, tokens: { L1DAI }, } = await loadFixture(deployContractsFixture); - l1TokenBridge.connect(user).bridgeToken(await L1DAI.getAddress(), 1, user.address); + await l1TokenBridge.connect(user).bridgeToken(await L1DAI.getAddress(), 1, user.address); await expectRevertWithCustomError( l1TokenBridge, @@ -643,6 +648,7 @@ describe("TokenBridge", function () { const TokenBridgeFactory = await ethers.getContractFactory("TokenBridge"); const l1TokenBridge = await upgrades.deployProxy(TokenBridgeFactory, [ { + defaultAdmin: PLACEHOLDER_ADDRESS, messageService: PLACEHOLDER_ADDRESS, tokenBeacon: PLACEHOLDER_ADDRESS, sourceChainId: chainIds[0], @@ -901,10 +907,7 @@ describe("TokenBridge", function () { it("Should revert with ZeroAddressNotAllowed when addressWithRole is zero address in reinitializePauseTypesAndPermissions", async function () { const { l1TokenBridge } = await loadFixture(deployContractsFixture); - const roleAddresses = [ - { addressWithRole: ADDRESS_ZERO, role: DEFAULT_ADMIN_ROLE }, - { addressWithRole: ethers.Wallet.createRandom().address, role: SET_RESERVED_TOKEN_ROLE }, - ]; + const roleAddresses = [{ addressWithRole: ZeroAddress, role: SET_RESERVED_TOKEN_ROLE }]; await expectRevertWithCustomError( l1TokenBridge, @@ -915,6 +918,18 @@ describe("TokenBridge", function () { }); describe("TokenBridge Upgradeable Tests", function () { + let newRoleAddresses: { addressWithRole: string; role: string }[]; + + before(async () => { + const [owner] = await ethers.getSigners(); + newRoleAddresses = [ + { addressWithRole: owner.address, role: PAUSE_ALL_ROLE }, + { addressWithRole: owner.address, role: UNPAUSE_ALL_ROLE }, + { addressWithRole: owner.address, role: PAUSE_INITIATE_TOKEN_BRIDGING_ROLE }, + { addressWithRole: owner.address, role: UNPAUSE_INITIATE_TOKEN_BRIDGING_ROLE }, + ]; + }); + it("Should deploy and manually upgrade the TokenBridge contract", async function () { const { owner, messageService, chainIds } = await loadFixture(deployContractsFixture); @@ -956,12 +971,7 @@ describe("TokenBridge", function () { await tokenBridgeV2Implementation.waitForDeployment(); const reinitializeCallData = TokenBridgeV2.interface.encodeFunctionData("reinitializePauseTypesAndPermissions", [ - [ - { addressWithRole: owner.address, role: PAUSE_ALL_ROLE }, - { addressWithRole: owner.address, role: UNPAUSE_ALL_ROLE }, - { addressWithRole: owner.address, role: PAUSE_INITIATE_TOKEN_BRIDGING_ROLE }, - { addressWithRole: owner.address, role: UNPAUSE_INITIATE_TOKEN_BRIDGING_ROLE }, - ], + newRoleAddresses, pauseTypeRoles, unpauseTypeRoles, ]); @@ -1008,10 +1018,73 @@ describe("TokenBridge", function () { expect(await upgradedTokenBridge.isPaused(COMPLETE_TOKEN_BRIDGING_PAUSE_TYPE)).to.be.false; await upgradedTokenBridge.connect(owner).pauseByType(INITIATE_TOKEN_BRIDGING_PAUSE_TYPE); - expect(await upgradedTokenBridge.isPaused(7)).to.be.true; + expect(await upgradedTokenBridge.isPaused(INITIATE_TOKEN_BRIDGING_PAUSE_TYPE)).to.be.true; await upgradedTokenBridge.connect(owner).unPauseByType(INITIATE_TOKEN_BRIDGING_PAUSE_TYPE); - expect(await upgradedTokenBridge.isPaused(7)).to.be.false; + expect(await upgradedTokenBridge.isPaused(INITIATE_TOKEN_BRIDGING_PAUSE_TYPE)).to.be.false; + }); + + it("Should set all permissions", async () => { + const { owner, messageService, chainIds } = await loadFixture(deployContractsFixture); + + const TokenBridgeV1 = await ethers.getContractFactory( + "contracts/tokenBridge/mocks/TokenBridgeFlatten.sol:TokenBridgeFlatten", + ); + const tokenBridgeV1 = (await upgrades.deployProxy(TokenBridgeV1, [ + owner.address, + await messageService.getAddress(), + PLACEHOLDER_ADDRESS, + chainIds[0], + chainIds[1], + [], + ])) as unknown as TokenBridge; + await tokenBridgeV1.waitForDeployment(); + + // Check initial state + expect(await tokenBridgeV1.sourceChainId()).to.equal(chainIds[0]); + const initialTargetChainId = await tokenBridgeV1.targetChainId(); + + // setCustomContract + const nativeToken = ethers.Wallet.createRandom().address; + const targetContract = ethers.Wallet.createRandom().address; + await tokenBridgeV1.connect(owner).setCustomContract(nativeToken, targetContract); + + // Verify the custom contract was set + expect(await tokenBridgeV1.nativeToBridgedToken(initialTargetChainId, nativeToken)).to.equal(targetContract); + expect(await tokenBridgeV1.bridgedToNativeToken(targetContract)).to.equal(nativeToken); + + const proxyAdminAddress = await upgrades.erc1967.getAdminAddress(await tokenBridgeV1.getAddress()); + const ProxyAdminFactory = await ethers.getContractFactory("ProxyAdmin"); + const proxyAdmin = (await ProxyAdminFactory.attach(proxyAdminAddress)) as ProxyAdmin; + + const TokenBridgeV2 = await ethers.getContractFactory("TokenBridge"); + const tokenBridgeV2Implementation = await TokenBridgeV2.deploy(); + await tokenBridgeV2Implementation.waitForDeployment(); + + const reinitializeCallData = TokenBridgeV2.interface.encodeFunctionData("reinitializePauseTypesAndPermissions", [ + newRoleAddresses, + pauseTypeRoles, + unpauseTypeRoles, + ]); + + expect(await ethers.provider.getStorage(await tokenBridgeV1.getAddress(), 101)).to.equal( + ethers.zeroPadValue(owner.address, 32), // _owner + ); + expect(await ethers.provider.getStorage(await tokenBridgeV1.getAddress(), 213)).to.equal( + ethers.zeroPadValue("0x01", 32), //_status + ); + + await proxyAdmin.upgradeAndCall( + await tokenBridgeV1.getAddress(), + await tokenBridgeV2Implementation.getAddress(), + reinitializeCallData, + ); + + const upgradedTokenBridge = (await TokenBridgeV2.attach(await tokenBridgeV1.getAddress())) as TokenBridge; + + for (const { role, addressWithRole } of newRoleAddresses) { + expect(await upgradedTokenBridge.hasRole(role, addressWithRole)).to.be.true; + } }); }); }); diff --git a/contracts/test/utils/constants.ts b/contracts/test/utils/constants.ts deleted file mode 100644 index 8c8e5fd69..000000000 --- a/contracts/test/utils/constants.ts +++ /dev/null @@ -1,308 +0,0 @@ -import { ethers } from "hardhat"; -import { generateKeccak256 } from "./helpers"; - -export const HASH_ZERO = ethers.ZeroHash; -export const ADDRESS_ZERO = ethers.ZeroAddress; -export const HASH_WITHOUT_ZERO_FIRST_BYTE = "0xf887bbc07b0e849fb625aafadf4cb6b65b98e492fbb689705312bf1db98ead7f"; - -export const LINEA_ROLLUP_INITIALIZE_SIGNATURE = - "initialize((bytes32,uint256,uint256,address,uint256,uint256,(address,bytes32)[],(uint8,bytes32)[],(uint8,bytes32)[],address))"; - -// Linea XP Token roles -export const MINTER_ROLE = generateKeccak256(["string"], ["MINTER_ROLE"], true); -export const TRANSFER_ROLE = generateKeccak256(["string"], ["TRANSFER_ROLE"], true); - -// TimeLock roles -export const TIMELOCK_ADMIN_ROLE = generateKeccak256(["string"], ["TIMELOCK_ADMIN_ROLE"], true); -export const PROPOSER_ROLE = generateKeccak256(["string"], ["PROPOSER_ROLE"], true); -export const EXECUTOR_ROLE = generateKeccak256(["string"], ["EXECUTOR_ROLE"], true); -export const CANCELLER_ROLE = generateKeccak256(["string"], ["CANCELLER_ROLE"], true); - -// Roles hashes -export const DEFAULT_ADMIN_ROLE = HASH_ZERO; -export const FUNCTION_EXECUTOR_ROLE = generateKeccak256(["string"], ["FUNCTION_EXECUTOR_ROLE"], true); -export const RATE_LIMIT_SETTER_ROLE = generateKeccak256(["string"], ["RATE_LIMIT_SETTER_ROLE"], true); -export const USED_RATE_LIMIT_RESETTER_ROLE = generateKeccak256(["string"], ["USED_RATE_LIMIT_RESETTER_ROLE"], true); -export const L1_L2_MESSAGE_SETTER_ROLE = generateKeccak256(["string"], ["L1_L2_MESSAGE_SETTER_ROLE"], true); -export const PAUSE_ALL_ROLE = generateKeccak256(["string"], ["PAUSE_ALL_ROLE"], true); -export const UNPAUSE_ALL_ROLE = generateKeccak256(["string"], ["UNPAUSE_ALL_ROLE"], true); -export const PAUSE_L1_L2_ROLE = generateKeccak256(["string"], ["PAUSE_L1_L2_ROLE"], true); -export const UNPAUSE_L1_L2_ROLE = generateKeccak256(["string"], ["UNPAUSE_L1_L2_ROLE"], true); -export const PAUSE_L2_L1_ROLE = generateKeccak256(["string"], ["PAUSE_L2_L1_ROLE"], true); -export const UNPAUSE_L2_L1_ROLE = generateKeccak256(["string"], ["UNPAUSE_L2_L1_ROLE"], true); -export const PAUSE_L2_BLOB_SUBMISSION_ROLE = generateKeccak256(["string"], ["PAUSE_L2_BLOB_SUBMISSION_ROLE"], true); -export const UNPAUSE_L2_BLOB_SUBMISSION_ROLE = generateKeccak256(["string"], ["UNPAUSE_L2_BLOB_SUBMISSION_ROLE"], true); -export const PAUSE_FINALIZE_WITHPROOF_ROLE = generateKeccak256(["string"], ["PAUSE_FINALIZE_WITHPROOF_ROLE"], true); -export const UNPAUSE_FINALIZE_WITHPROOF_ROLE = generateKeccak256(["string"], ["UNPAUSE_FINALIZE_WITHPROOF_ROLE"], true); -export const MINIMUM_FEE_SETTER_ROLE = generateKeccak256(["string"], ["MINIMUM_FEE_SETTER_ROLE"], true); -export const OPERATOR_ROLE = generateKeccak256(["string"], ["OPERATOR_ROLE"], true); -export const VERIFIER_SETTER_ROLE = generateKeccak256(["string"], ["VERIFIER_SETTER_ROLE"], true); -export const VERIFIER_UNSETTER_ROLE = generateKeccak256(["string"], ["VERIFIER_UNSETTER_ROLE"], true); -export const L1_MERKLE_ROOTS_SETTER_ROLE = generateKeccak256(["string"], ["L1_MERKLE_ROOTS_SETTER_ROLE"], true); -export const L2_MERKLE_ROOTS_SETTER_ROLE = generateKeccak256(["string"], ["L2_MERKLE_ROOTS_SETTER_ROLE"], true); -export const FINALIZE_WITHOUT_PROOF_ROLE = generateKeccak256(["string"], ["FINALIZE_WITHOUT_PROOF_ROLE"], true); -export const BAD_STARTING_HASH = generateKeccak256(["string"], ["BAD_STARTING_HASH"], true); -export const PAUSE_INITIATE_TOKEN_BRIDGING_ROLE = generateKeccak256( - ["string"], - ["PAUSE_INITIATE_TOKEN_BRIDGING_ROLE"], - true, -); -export const PAUSE_COMPLETE_TOKEN_BRIDGING_ROLE = generateKeccak256( - ["string"], - ["PAUSE_COMPLETE_TOKEN_BRIDGING_ROLE"], - true, -); -export const UNPAUSE_INITIATE_TOKEN_BRIDGING_ROLE = generateKeccak256( - ["string"], - ["UNPAUSE_INITIATE_TOKEN_BRIDGING_ROLE"], - true, -); -export const UNPAUSE_COMPLETE_TOKEN_BRIDGING_ROLE = generateKeccak256( - ["string"], - ["UNPAUSE_COMPLETE_TOKEN_BRIDGING_ROLE"], - true, -); -export const SET_REMOTE_TOKENBRIDGE_ROLE = generateKeccak256(["string"], ["SET_REMOTE_TOKENBRIDGE_ROLE"], true); -export const SET_RESERVED_TOKEN_ROLE = generateKeccak256(["string"], ["SET_RESERVED_TOKEN_ROLE"], true); -export const REMOVE_RESERVED_TOKEN_ROLE = generateKeccak256(["string"], ["REMOVE_RESERVED_TOKEN_ROLE"], true); -export const SET_CUSTOM_CONTRACT_ROLE = generateKeccak256(["string"], ["SET_CUSTOM_CONTRACT_ROLE"], true); -export const SET_MESSAGE_SERVICE_ROLE = generateKeccak256(["string"], ["SET_MESSAGE_SERVICE_ROLE"], true); - -export const GENERAL_PAUSE_TYPE = 1; -export const L1_L2_PAUSE_TYPE = 2; -export const L2_L1_PAUSE_TYPE = 3; -export const BLOB_SUBMISSION_PAUSE_TYPE = 4; -export const CALLDATA_SUBMISSION_PAUSE_TYPE = 5; -export const FINALIZATION_PAUSE_TYPE = 6; -export const INITIATE_TOKEN_BRIDGING_PAUSE_TYPE = 7; -export const COMPLETE_TOKEN_BRIDGING_PAUSE_TYPE = 8; - -export const pauseTypeRoles = [ - { pauseType: GENERAL_PAUSE_TYPE, role: PAUSE_ALL_ROLE }, - { pauseType: L1_L2_PAUSE_TYPE, role: PAUSE_L1_L2_ROLE }, - { pauseType: L2_L1_PAUSE_TYPE, role: PAUSE_L2_L1_ROLE }, - { pauseType: BLOB_SUBMISSION_PAUSE_TYPE, role: PAUSE_L2_BLOB_SUBMISSION_ROLE }, - { pauseType: CALLDATA_SUBMISSION_PAUSE_TYPE, role: PAUSE_L2_BLOB_SUBMISSION_ROLE }, - { pauseType: FINALIZATION_PAUSE_TYPE, role: PAUSE_FINALIZE_WITHPROOF_ROLE }, - { pauseType: INITIATE_TOKEN_BRIDGING_PAUSE_TYPE, role: PAUSE_INITIATE_TOKEN_BRIDGING_ROLE }, - { pauseType: COMPLETE_TOKEN_BRIDGING_PAUSE_TYPE, role: PAUSE_COMPLETE_TOKEN_BRIDGING_ROLE }, -]; - -export const unpauseTypeRoles = [ - { pauseType: GENERAL_PAUSE_TYPE, role: UNPAUSE_ALL_ROLE }, - { pauseType: L1_L2_PAUSE_TYPE, role: UNPAUSE_L1_L2_ROLE }, - { pauseType: L2_L1_PAUSE_TYPE, role: UNPAUSE_L2_L1_ROLE }, - { pauseType: BLOB_SUBMISSION_PAUSE_TYPE, role: UNPAUSE_L2_BLOB_SUBMISSION_ROLE }, - { pauseType: CALLDATA_SUBMISSION_PAUSE_TYPE, role: UNPAUSE_L2_BLOB_SUBMISSION_ROLE }, - { pauseType: FINALIZATION_PAUSE_TYPE, role: UNPAUSE_FINALIZE_WITHPROOF_ROLE }, - { pauseType: INITIATE_TOKEN_BRIDGING_PAUSE_TYPE, role: UNPAUSE_INITIATE_TOKEN_BRIDGING_ROLE }, - { pauseType: COMPLETE_TOKEN_BRIDGING_PAUSE_TYPE, role: UNPAUSE_COMPLETE_TOKEN_BRIDGING_ROLE }, -]; - -// Message statuses -export const INBOX_STATUS_UNKNOWN = 0; -export const INBOX_STATUS_RECEIVED = 1; -export const INBOX_STATUS_CLAIMED = 2; - -export const OUTBOX_STATUS_UNKNOWN = 0; -export const OUTBOX_STATUS_SENT = 1; -export const OUTBOX_STATUS_RECEIVED = 2; - -export const INITIAL_MIGRATION_BLOCK = 0; -export const ONE_DAY_IN_SECONDS = 86_400; -export const INITIAL_WITHDRAW_LIMIT = ethers.parseEther("5"); -export const GENESIS_L2_TIMESTAMP = 0; -export const DEFAULT_LAST_FINALIZED_TIMESTAMP = 1683325137n; -export const SIX_MONTHS_IN_SECONDS = (365 / 2) * 24 * 60 * 60; -export const TEST_PUBLIC_VERIFIER_INDEX = 0; - -export const MESSAGE_VALUE_1ETH = ethers.parseEther("1"); -export const ZERO_VALUE = 0; -export const MESSAGE_FEE = ethers.parseEther("0.05"); -export const LOW_NO_REFUND_MESSAGE_FEE = ethers.parseEther("0.00001"); -export const MINIMUM_FEE = ethers.parseEther("0.1"); -export const DEFAULT_MESSAGE_NONCE = ethers.parseEther("123456789"); -export const SAMPLE_FUNCTION_CALLDATA = generateKeccak256(["string"], ["callThisFunction()"], true).substring(0, 10); //0x + 4bytes -export const EMPTY_CALLDATA = "0x"; -export const BLOCK_COINBASE = "0xc014ba5ec014ba5ec014ba5ec014ba5ec014ba5e"; - -export const INITIALIZED_ERROR_MESSAGE = "Initializable: contract is not initializing"; -export const INITIALIZED_ALREADY_MESSAGE = "Initializable: contract is already initialized"; - -export const DEFAULT_SUBMISSION_DATA = { - dataParentHash: HASH_ZERO, - compressedData: "0x", - finalBlockInData: 0n, - firstBlockInData: 0n, - parentStateRootHash: HASH_ZERO, - finalStateRootHash: HASH_ZERO, - snarkHash: HASH_ZERO, -}; - -export const BLS_CURVE_MODULUS = 52435875175126190479447740508185965837690552500527637822603658699938581184513n; - -export const VALID_MERKLE_PROOF = { - //proof length 32 - proof: [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5", - "0xb4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d30", - "0x21ddb9a356815c3fac1026b6dec5df3124afbadb485c9ba5a3e3398a04b7ba85", - "0xe58769b32a1beaf1ea27375a44095a0d1fb664ce2dd358e7fcbfb78c26a19344", - "0x0eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d", - "0x887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a1968", - "0xffd70157e48063fc33c97a050f7f640233bf646cc98d9524c6b92bcf3ab56f83", - "0x9867cc5f7f196b93bae1e27e6320742445d290f2263827498b54fec539f756af", - "0xcefad4e508c098b9a7e1d8feb19955fb02ba9675585078710969d3440f5054e0", - "0xf9dc3e7fe016e050eff260334f18a5d4fe391d82092319f5964f2e2eb7c1c3a5", - "0xf8b13a49e282f609c317a833fb8d976d11517c571d1221a265d25af778ecf892", - "0x3490c6ceeb450aecdc82e28293031d10c7d73bf85e57bf041a97360aa2c5d99c", - "0xc1df82d9c4b87413eae2ef048f94b4d3554cea73d92b0f7af96e0271c691e2bb", - "0x5c67add7c6caf302256adedf7ab114da0acfe870d449a3a489f781d659e8becc", - "0xda7bce9f4e8618b6bd2f4132ce798cdc7a60e7e1460a7299e3c6342a579626d2", - "0x2733e50f526ec2fa19a22b31e8ed50f23cd1fdf94c9154ed3a7609a2f1ff981f", - "0xe1d3b5c807b281e4683cc6d6315cf95b9ade8641defcb32372f1c126e398ef7a", - "0x5a2dce0a8a7f68bb74560f8f71837c2c2ebbcbf7fffb42ae1896f13f7c7479a0", - "0xb46a28b6f55540f89444f63de0378e3d121be09e06cc9ded1c20e65876d36aa0", - "0xc65e9645644786b620e2dd2ad648ddfcbf4a7e5b1a3a4ecfe7f64667a3f0b7e2", - "0xf4418588ed35a2458cffeb39b93d26f18d2ab13bdce6aee58e7b99359ec2dfd9", - "0x5a9c16dc00d6ef18b7933a6f8dc65ccb55667138776f7dea101070dc8796e377", - "0x4df84f40ae0c8229d0d6069e5c8f39a7c299677a09d367fc7b05e3bc380ee652", - "0xcdc72595f74c7b1043d0e1ffbab734648c838dfb0527d971b602bc216c9619ef", - "0x0abf5ac974a1ed57f4050aa510dd9c74f508277b39d7973bb2dfccc5eeb0618d", - "0xb8cd74046ff337f0a7bf2c8e03e10f642c1886798d71806ab1e888d9e5ee87d0", - "0x838c5655cb21c6cb83313b5a631175dff4963772cce9108188b34ac87c81c41e", - "0x662ee4dd2dd7b2bc707961b1e646c4047669dcb6584f0d8d770daf5d7e7deb2e", - "0x388ab20e2573d171a88108e79d820e98f26c0b84aa8b2f4aa4968dbb818ea322", - "0x93237c50ba75ee485f4c22adf2f741400bdf8d6a9cc7df7ecae576221665d735", - "0x8448818bb4ae4562849e949e17ac16e0be16688e156b5cf15e098c627c0056a9", - ], - merkleRoot: "0x54e37f6a8efe3497d1b721d8a5a19786e78d16edabdefdfa94173ef104b132cb", - index: 0, -}; - -export const INVALID_MERKLE_PROOF = { - merkleRoot: "0xfbe8939cea4bb333e59120d35f318e3e7c88cdd0e70e66ae98b64efb9a5716ec", - index: 0, - proof: [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5", - "0xb4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d30", - "0x21ddb9a356815c3fac1026b6dec5df3124afbadb485c9ba5a3e3398a04b7ba85", - "0xe58769b32a1beaf1ea27375a44095a0d1fb664ce2dd358e7fcbfb78c26a19344", - "0x0eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d", - "0x887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a1968", - "0xffd70157e48063fc33c97a050f7f640233bf646cc98d9524c6b92bcf3ab56f83", - "0x9867cc5f7f196b93bae1e27e6320742445d290f2263827498b54fec539f756af", - "0xcefad4e508c098b9a7e1d8feb19955fb02ba9675585078710969d3440f5054e0", - "0xf9dc3e7fe016e050eff260334f18a5d4fe391d82092319f5964f2e2eb7c1c3a5", - "0xf8b13a49e282f609c317a833fb8d976d11517c571d1221a265d25af778ecf892", - "0x3490c6ceeb450aecdc82e28293031d10c7d73bf85e57bf041a97360aa2c5d99c", - "0xc1df82d9c4b87413eae2ef048f94b4d3554cea73d92b0f7af96e0271c691e2bb", - "0x5c67add7c6caf302256adedf7ab114da0acfe870d449a3a489f781d659e8becc", - "0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5", - "0x2733e50f526ec2fa19a22b31e8ed50f23cd1fdf94c9154ed3a7609a2f1ff981f", - "0xe1d3b5c807b281e4683cc6d6315cf95b9ade8641defcb32372f1c126e398ef7a", - "0x5a2dce0a8a7f68bb74560f8f71837c2c2ebbcbf7fffb42ae1896f13f7c7479a0", - "0xb46a28b6f55540f89444f63de0378e3d121be09e06cc9ded1c20e65876d36aa0", - "0xc65e9645644786b620e2dd2ad648ddfcbf4a7e5b1a3a4ecfe7f64667a3f0b7e2", - "0xf4418588ed35a2458cffeb39b93d26f18d2ab13bdce6aee58e7b99359ec2dfd9", - "0x5a9c16dc00d6ef18b7933a6f8dc65ccb55667138776f7dea101070dc8796e377", - "0x4df84f40ae0c8229d0d6069e5c8f39a7c299677a09d367fc7b05e3bc380ee652", - "0xcdc72595f74c7b1043d0e1ffbab734648c838dfb0527d971b602bc216c9619ef", - "0x0abf5ac974a1ed57f4050aa510dd9c74f508277b39d7973bb2dfccc5eeb0618d", - "0xb8cd74046ff337f0a7bf2c8e03e10f642c1886798d71806ab1e888d9e5ee87d0", - "0x838c5655cb21c6cb83313b5a631175dff4963772cce9108188b34ac87c81c41e", - "0x662ee4dd2dd7b2bc707961b1e646c4047669dcb6584f0d8d770daf5d7e7deb2e", - "0x388ab20e2573d171a88108e79d820e98f26c0b84aa8b2f4aa4968dbb818ea322", - "0x93237c50ba75ee485f4c22adf2f741400bdf8d6a9cc7df7ecae576221665d735", - "0x8448818bb4ae4562849e949e17ac16e0be16688e156b5cf15e098c627c0056a9", - ], -}; - -export const INVALID_MERKLE_PROOF_REVERT = { - proof: [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5", - "0xb4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d30", - "0x21ddb9a356815c3fac1026b6dec5df3124afbadb485c9ba5a3e3398a04b7ba85", - "0xe58769b32a1beaf1ea27375a44095a0d1fb664ce2dd358e7fcbfb78c26a19344", - "0x0eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d", - "0x887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a1968", - "0xffd70157e48063fc33c97a050f7f640233bf646cc98d9524c6b92bcf3ab56f83", - "0x9867cc5f7f196b93bae1e27e6320742445d290f2263827498b54fec539f756af", - "0xcefad4e508c098b9a7e1d8feb19955fb02ba9675585078710969d3440f5054e0", - "0xf9dc3e7fe016e050eff260334f18a5d4fe391d82092319f5964f2e2eb7c1c3a5", - "0xf8b13a49e282f609c317a833fb8d976d11517c571d1221a265d25af778ecf892", - "0x3490c6ceeb450aecdc82e28293031d10c7d73bf85e57bf041a97360aa2c5d99c", - "0xc1df82d9c4b87413eae2ef048f94b4d3554cea73d92b0f7af96e0271c691e2bb", - "0x5c67add7c6caf302256adedf7ab114da0acfe870d449a3a489f781d659e8becc", - "0xda7bce9f4e8618b6bd2f4132ce798cdc7a60e7e1460a7299e3c6342a579626d2", - "0x2733e50f526ec2fa19a22b31e8ed50f23cd1fdf94c9154ed3a7609a2f1ff981f", - "0xe1d3b5c807b281e4683cc6d6315cf95b9ade8641defcb32372f1c126e398ef7a", - "0x5a2dce0a8a7f68bb74560f8f71837c2c2ebbcbf7fffb42ae1896f13f7c7479a0", - "0xb46a28b6f55540f89444f63de0378e3d121be09e06cc9ded1c20e65876d36aa0", - "0xc65e9645644786b620e2dd2ad648ddfcbf4a7e5b1a3a4ecfe7f64667a3f0b7e2", - "0xf4418588ed35a2458cffeb39b93d26f18d2ab13bdce6aee58e7b99359ec2dfd9", - "0x5a9c16dc00d6ef18b7933a6f8dc65ccb55667138776f7dea101070dc8796e377", - "0x4df84f40ae0c8229d0d6069e5c8f39a7c299677a09d367fc7b05e3bc380ee652", - "0xcdc72595f74c7b1043d0e1ffbab734648c838dfb0527d971b602bc216c9619ef", - "0x0abf5ac974a1ed57f4050aa510dd9c74f508277b39d7973bb2dfccc5eeb0618d", - "0xb8cd74046ff337f0a7bf2c8e03e10f642c1886798d71806ab1e888d9e5ee87d0", - "0x838c5655cb21c6cb83313b5a631175dff4963772cce9108188b34ac87c81c41e", - "0x662ee4dd2dd7b2bc707961b1e646c4047669dcb6584f0d8d770daf5d7e7deb2e", - "0x388ab20e2573d171a88108e79d820e98f26c0b84aa8b2f4aa4968dbb818ea322", - "0x93237c50ba75ee485f4c22adf2f741400bdf8d6a9cc7df7ecae576221665d735", - "0x8448818bb4ae4562849e949e17ac16e0be16688e156b5cf15e098c627c0056a9", - ], - merkleRoot: "0xd1eb21c855a643efa2b5f6e45c6e19784aeca4d4edfed71d16f1a4235a259aa1", - index: 0, -}; - -export const MERKLE_PROOF_FALLBACK = { - proof: [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5", - "0xb4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d30", - "0x21ddb9a356815c3fac1026b6dec5df3124afbadb485c9ba5a3e3398a04b7ba85", - "0xe58769b32a1beaf1ea27375a44095a0d1fb664ce2dd358e7fcbfb78c26a19344", - "0x0eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d", - "0x887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a1968", - "0xffd70157e48063fc33c97a050f7f640233bf646cc98d9524c6b92bcf3ab56f83", - ], - merkleRoot: "0xcb9b5496c90542ac03009b37acf6ef8e8867856e2333e0eb9954290b9ce69272", - index: 0, -}; - -export const MERKLE_PROOF_REENTRY = { - proof: [ - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5", - "0xb4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d30", - "0x21ddb9a356815c3fac1026b6dec5df3124afbadb485c9ba5a3e3398a04b7ba85", - "0xe58769b32a1beaf1ea27375a44095a0d1fb664ce2dd358e7fcbfb78c26a19344", - "0x0eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d", - "0x887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a1968", - "0xffd70157e48063fc33c97a050f7f640233bf646cc98d9524c6b92bcf3ab56f83", - ], - merkleRoot: "0x494aab847e375519445b672ca9f5b4adac13ceb233c371978a18ab437483521b", - index: 0, -}; - -// TODO CLEANUP TO MAKE THIS DYNAMIC AND NOT CONSTANT -export const Add_L1L2_Message_Hashes_Calldata_With_Empty_Array = - "0xf4b476e10000000000000000000000000000000000000000000000000000000000000000"; -export const Add_L1L2_Message_Hashes_Calldata_With_One_Hash = - "0xf4b476e100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001f57d2ce8b7fc0df7ae7cbddaa706242a118bd8b649abccfecfb3f8e419729ca9"; -export const Single_Item_L1L2_HashArray = ["0xf57d2ce8b7fc0df7ae7cbddaa706242a118bd8b649abccfecfb3f8e419729ca9"]; - -// TODO CLEANUP TO MAKE THIS DYNAMIC AND NOT CONSTANT -export const Add_L1L2_Message_Hashes_Calldata_With_Five_Hashes = - "0xf4b476e100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000005f887bbc07b0e849fb625aafadf4cb6b65b98e492fbb689705312bf1db98ead7fdd87bbc07b0e849fb625aafadf4cb6b65b98e492fbb689705312bf1db98ead7faa87bbc07b0e849fb625aafadf4cb6b65b98e492fbb689705312bf1db98ead7fcc87bbc07b0e849fb625aafadf4cb6b65b98e492fbb689705312bf1db98ead7f1187bbc07b0e849fb625aafadf4cb6b65b98e492fbb689705312bf1db98ead7f"; -export const L1L2_FiveHashes = [ - "0xf887bbc07b0e849fb625aafadf4cb6b65b98e492fbb689705312bf1db98ead7f", - "0xdd87bbc07b0e849fb625aafadf4cb6b65b98e492fbb689705312bf1db98ead7f", - "0xaa87bbc07b0e849fb625aafadf4cb6b65b98e492fbb689705312bf1db98ead7f", - "0xcc87bbc07b0e849fb625aafadf4cb6b65b98e492fbb689705312bf1db98ead7f", - "0x1187bbc07b0e849fb625aafadf4cb6b65b98e492fbb689705312bf1db98ead7f", -];