Skip to content
42 changes: 42 additions & 0 deletions system-contracts/contracts/L2InteropRootStorage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,21 @@ error SidesLengthNotOne();
error InteropRootAlreadyExists();
error MessageRootIsZero();

/// @dev For both proof-based and commit-based interop, the `sides` parameter contains only the root.
/// @dev Once pre-commit interop is introduced, `sides` will include both the root and its associated sides.
/// @dev This interface is preserved now so that enabling pre-commit interop later requires no changes in interface.
/// @dev In proof-based and pre-commit interop, `blockOrBatchNumber` represents the block number, in commit-based interop,
/// it represents the batch number. This distinction reflects the implementation requirements of each interop finality form.
/// @param chainId The chain ID of the chain that the message root is for.
/// @param blockOrBatchNumber The block or batch number of the message root. Either of block number or batch number will be used,
/// depends on finality form of interop.
/// @param sides The message root sides. Note, that `sides` here are coming from `DynamicIncrementalMerkle` nomenclature.
struct InteropRoot {
uint256 chainId;
uint256 blockOrBatchNumber;
bytes32[] sides;
}

/**
* @author Matter Labs
* @custom:security-contact [email protected]
Expand All @@ -24,6 +39,7 @@ contract L2InteropRootStorage is SystemContractBase {
/// @dev This interface is preserved now so that enabling pre-commit interop later requires no changes in interface.
/// @dev In proof-based and pre-commit interop, `blockOrBatchNumber` represents the block number, in commit-based interop,
/// it represents the batch number. This distinction reflects the implementation requirements of each interop finality form.
/// @dev Note: should be removed in the next protocol version.
/// @param chainId The chain ID of the chain that the message root is for.
/// @param blockOrBatchNumber The block or batch number of the message root. Either of block number or batch number will be used,
/// depends on finality form of interop, mentioned above.
Expand All @@ -33,6 +49,32 @@ contract L2InteropRootStorage is SystemContractBase {
uint256 blockOrBatchNumber,
bytes32[] calldata sides
) external onlyCallFromBootloader {
_addInteropRoot(chainId, blockOrBatchNumber, sides);
}

/// @dev Adds a message root to the L2InteropRootStorage contract.
/// @dev Currently duplicates `addInteropRoot` for backward compatibility.
/// @param interopRoot The interop root to be added. See the description of the corresponding struct above.
function addSingleInteropRoot(InteropRoot calldata interopRoot) external onlyCallFromBootloader {
_addInteropRoot(interopRoot.chainId, interopRoot.blockOrBatchNumber, interopRoot.sides);
}

/// @dev Adds a group of interop roots to the L2InteropRootStorage contract.
/// @param interopRootsInput The array of interop roots to be added. See the description of the corresponding struct above.
function addInteropRootsInBatch(InteropRoot[] calldata interopRootsInput) external onlyCallFromBootloader {
unchecked {
uint256 amountOfRoots = interopRootsInput.length;
for (uint256 i; i < amountOfRoots; ++i) {
_addInteropRoot(
interopRootsInput[i].chainId,
interopRootsInput[i].blockOrBatchNumber,
interopRootsInput[i].sides
);
}
}
}

function _addInteropRoot(uint256 chainId, uint256 blockOrBatchNumber, bytes32[] calldata sides) private {
// In the current code sides should only contain the Interop Root itself, as mentioned above.
if (sides.length != 1) {
revert SidesLengthNotOne();
Expand Down
Loading