diff --git a/l1-contracts/contracts/bridgehub/MessageRoot.sol b/l1-contracts/contracts/bridgehub/MessageRoot.sol index a3f7e4513..60fd7ee9b 100644 --- a/l1-contracts/contracts/bridgehub/MessageRoot.sol +++ b/l1-contracts/contracts/bridgehub/MessageRoot.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.24; // solhint-disable reason-string, gas-custom-errors -import {DynamicIncrementalMerkle} from "../common/libraries/openzeppelin/IncrementalMerkle.sol"; // todo figure out how to import from OZ +import {DynamicIncrementalMerkle} from "../common/libraries/DynamicIncrementalMerkle.sol"; import {IBridgehub} from "./IBridgehub.sol"; import {IMessageRoot} from "./IMessageRoot.sol"; diff --git a/l1-contracts/contracts/common/Config.sol b/l1-contracts/contracts/common/Config.sol index 072f8400f..1b343ea09 100644 --- a/l1-contracts/contracts/common/Config.sol +++ b/l1-contracts/contracts/common/Config.sol @@ -2,8 +2,6 @@ pragma solidity 0.8.24; -import {PriorityOperation} from "../state-transition/libraries/PriorityQueue.sol"; - /// @dev `keccak256("")` bytes32 constant EMPTY_STRING_KECCAK = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; @@ -120,6 +118,13 @@ struct StoredBatchHashInfo { bytes32 hash; } +struct PriorityTreeCommitment { + uint256 nextLeafIndex; + uint256 startIndex; + uint256 unprocessedIndex; + bytes32[] sides; +} + // Info that allows to restore a chain. struct HyperchainCommitment { /// @notice Total number of executed batches i.e. batches[totalBatchesExecuted] points at the latest executed batch @@ -130,13 +135,11 @@ struct HyperchainCommitment { /// @notice Total number of committed batches i.e. batches[totalBatchesCommitted] points at the latest committed /// batch uint256 totalBatchesCommitted; - /// @notice total number of priority txs ever executed - uint256 priorityQueueHead; - PriorityOperation[] priorityQueueTxs; /// @notice bytes32 l2SystemContractsUpgradeTxHash; /// @notice uint256 l2SystemContractsUpgradeBatchNumber; bytes32[] batchHashes; - /// TODO: add priority queue here. + /// @notice Commitment to the priority merkle tree + PriorityTreeCommitment priorityTree; } diff --git a/l1-contracts/contracts/common/libraries/openzeppelin/IncrementalMerkle.sol b/l1-contracts/contracts/common/libraries/DynamicIncrementalMerkle.sol similarity index 69% rename from l1-contracts/contracts/common/libraries/openzeppelin/IncrementalMerkle.sol rename to l1-contracts/contracts/common/libraries/DynamicIncrementalMerkle.sol index 7f181d5b2..f86f0858f 100644 --- a/l1-contracts/contracts/common/libraries/openzeppelin/IncrementalMerkle.sol +++ b/l1-contracts/contracts/common/libraries/DynamicIncrementalMerkle.sol @@ -2,8 +2,8 @@ pragma solidity ^0.8.0; -import {Hashes} from "./Hashes.sol"; -import {Arrays} from "./Arrays.sol"; +import {Merkle} from "./Merkle.sol"; +import {Arrays} from "@openzeppelin/contracts/utils/Arrays.sol"; /** * @dev Library for managing https://wikipedia.org/wiki/Merkle_Tree[Merkle Tree] data structures. @@ -18,7 +18,8 @@ import {Arrays} from "./Arrays.sol"; * * Zero value: The value that represents an empty leaf. Used to avoid regular zero values to be part of the tree. * * Hashing function: A cryptographic hash function used to produce internal nodes. * - * _Available since v5.1._ + * This is a fork of OpenZeppelin's [`MerkleTree`](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/9af280dc4b45ee5bda96ba47ff829b407eaab67e/contracts/utils/structs/MerkleTree.sol) + * library, with the changes to support dynamic tree growth (doubling the size when full). */ library DynamicIncrementalMerkle { /** @@ -26,9 +27,6 @@ library DynamicIncrementalMerkle { * * The `sides` and `zero` arrays are set to have a length equal to the depth of the tree during setup. * - * The hashing function used during initialization to compute the `zeros` values (value of a node at a given depth - * for which the subtree is full of zero leaves). This function is kept in the structure for handling insertions. - * * Struct members have an underscore prefix indicating that they are "private" and should not be read or written to * directly. Use the functions provided below instead. Modifying the struct manually may violate assumptions and * lead to unexpected behavior. @@ -41,10 +39,8 @@ library DynamicIncrementalMerkle { */ struct Bytes32PushTree { uint256 _nextLeafIndex; - uint256 _height; bytes32[] _sides; bytes32[] _zeros; - function(bytes32, bytes32) view returns (bytes32) _fnHash; } /** @@ -57,30 +53,10 @@ library DynamicIncrementalMerkle { * empty leaves. It should be a value that is not expected to be part of the tree. */ function setup(Bytes32PushTree storage self, bytes32 zero) internal returns (bytes32 initialRoot) { - return setup(self, zero, Hashes.Keccak256); - } - - /** - * @dev Same as {setup}, but allows to specify a custom hashing function. - * - * IMPORTANT: Providing a custom hashing function is a security-sensitive operation since it may - * compromise the soundness of the tree. Consider using functions from {Hashes}. - */ - function setup( - Bytes32PushTree storage self, - bytes32 zero, - function(bytes32, bytes32) view returns (bytes32) fnHash - ) internal returns (bytes32 initialRoot) { - // Store depth in the dynamic array - - Arrays.unsafeAccess(self._zeros, 0).value = zero; - - // Set the first root self._nextLeafIndex = 0; - self._fnHash = fnHash; - self._height = 0; - - return zero; + self._zeros.push(zero); + self._sides.push(bytes32(0)); + return bytes32(0); } /** @@ -92,38 +68,38 @@ library DynamicIncrementalMerkle { */ function push(Bytes32PushTree storage self, bytes32 leaf) internal returns (uint256 index, bytes32 newRoot) { // Cache read - uint256 levels = self._zeros.length; - function(bytes32, bytes32) view returns (bytes32) fnHash = self._fnHash; + uint256 levels = self._zeros.length - 1; // Get leaf index // solhint-disable-next-line gas-increment-by-one index = self._nextLeafIndex++; + // Check if tree is full. if (index == 1 << levels) { - // Tree is full, reset index add new level - bytes32 currentMaxZero = Arrays.unsafeAccess(self._zeros, levels).value; - ++self._height; + bytes32 zero = self._zeros[levels]; + bytes32 newZero = Merkle.efficientHash(zero, zero); + self._zeros.push(newZero); + self._sides.push(bytes32(0)); ++levels; - Arrays.unsafeAccess(self._zeros, levels).value = fnHash(currentMaxZero, currentMaxZero); - Arrays.unsafeSetLength(self._sides, levels); - Arrays.unsafeSetLength(self._zeros, levels); } // Rebuild branch from leaf to root uint256 currentIndex = index; bytes32 currentLevelHash = leaf; + bool updatedSides = false; for (uint32 i = 0; i < levels; ++i) { // Reaching the parent node, is currentLevelHash the left child? bool isLeft = currentIndex % 2 == 0; // If so, next time we will come from the right, so we need to save it - if (isLeft) { + if (isLeft && !updatedSides) { Arrays.unsafeAccess(self._sides, i).value = currentLevelHash; + updatedSides = true; } // Compute the current node hash by using the hash function - // with either the its sibling (side) or the zero value for that level. - currentLevelHash = fnHash( + // with either its sibling (side) or the zero value for that level. + currentLevelHash = Merkle.efficientHash( isLeft ? currentLevelHash : Arrays.unsafeAccess(self._sides, i).value, isLeft ? Arrays.unsafeAccess(self._zeros, i).value : currentLevelHash ); @@ -131,6 +107,7 @@ library DynamicIncrementalMerkle { // Update node index currentIndex >>= 1; } + Arrays.unsafeAccess(self._sides, levels).value = currentLevelHash; return (index, currentLevelHash); } @@ -138,8 +115,14 @@ library DynamicIncrementalMerkle { /** * @dev Tree's root. */ - function root(Bytes32PushTree storage self) internal view returns (bytes32) { - return Arrays.unsafeAccess(self._sides, self._height).value; + return Arrays.unsafeAccess(self._sides, self._sides.length - 1).value; + } + + /** + * @dev Tree's height (does not include the root node). + */ + function height(Bytes32PushTree storage self) internal view returns (uint256) { + return self._sides.length - 1; } } diff --git a/l1-contracts/contracts/common/libraries/FullMerkle.sol b/l1-contracts/contracts/common/libraries/FullMerkle.sol index 0951f5b4d..fc4161f17 100644 --- a/l1-contracts/contracts/common/libraries/FullMerkle.sol +++ b/l1-contracts/contracts/common/libraries/FullMerkle.sol @@ -5,9 +5,7 @@ pragma solidity 0.8.24; // solhint-disable reason-string, gas-custom-errors import {UncheckedMath} from "../../common/libraries/UncheckedMath.sol"; -// This importing issue should not be pushed to main, we only need this while we did not import OZ-v5 and v4 in parallel. Once we merge that it will be removed -import {Arrays} from "./openzeppelin/Arrays.sol"; -import {Hashes} from "./openzeppelin/Hashes.sol"; +import {Merkle} from "./Merkle.sol"; /// @author Matter Labs /// @custom:security-contact security@matterlabs.dev @@ -22,7 +20,7 @@ library FullMerkle { } /** - * @dev Initialize a {Bytes32PushTree} using {Hashes-Keccak256} to hash internal nodes. + * @dev Initialize a {Bytes32PushTree} using {Merkle.efficientHash} to hash internal nodes. * The capacity of the tree (i.e. number of leaves) is set to `2**levels`. * * Calling this function on MerkleTree that was already setup and used will reset it to a blank state. @@ -32,8 +30,7 @@ library FullMerkle { */ function setup(FullTree storage self, bytes32 zero) internal returns (bytes32 initialRoot) { // Store depth in the dynamic array - Arrays.unsafeSetLength(self._zeros, 1); - Arrays.unsafeAccess(self._zeros, 0).value = zero; + self._zeros.push(zero); self._nodes.push([zero]); return zero; @@ -47,7 +44,7 @@ library FullMerkle { uint256 newHeight = self._height.uncheckedInc(); self._height = newHeight; bytes32 topZero = self._zeros[newHeight - 1]; - bytes32 newZero = Hashes.Keccak256(topZero, topZero); + bytes32 newZero = Merkle.efficientHash(topZero, topZero); self._zeros.push(newZero); self._nodes.push([newZero]); } @@ -74,12 +71,12 @@ library FullMerkle { bytes32 currentHash = _itemHash; for (uint256 i; i < self._height; i = i.uncheckedInc()) { if (_index % 2 == 0) { - currentHash = Hashes.Keccak256( + currentHash = Merkle.efficientHash( currentHash, maxNodeNumber == _index ? self._zeros[i] : self._nodes[i][_index + 1] ); } else { - currentHash = Hashes.Keccak256(self._nodes[i][_index - 1], currentHash); + currentHash = Merkle.efficientHash(self._nodes[i][_index - 1], currentHash); } _index /= 2; maxNodeNumber /= 2; @@ -108,7 +105,7 @@ library FullMerkle { for (uint256 i; i < length; i = i.uncheckedAdd(2)) { self._nodes[_height][i] = _newNodes[i]; self._nodes[_height][i + 1] = _newNodes[i + 1]; - _newRow[i / 2] = Hashes.Keccak256(_newNodes[i], _newNodes[i + 1]); + _newRow[i / 2] = Merkle.efficientHash(_newNodes[i], _newNodes[i + 1]); } return updateAllNodesAtHeight(self, _height + 1, _newRow); } diff --git a/l1-contracts/contracts/common/libraries/Merkle.sol b/l1-contracts/contracts/common/libraries/Merkle.sol index 8680f9ac6..bee588b7a 100644 --- a/l1-contracts/contracts/common/libraries/Merkle.sol +++ b/l1-contracts/contracts/common/libraries/Merkle.sol @@ -30,16 +30,58 @@ library Merkle { bytes32 currentHash = _itemHash; for (uint256 i; i < pathLength; i = i.uncheckedInc()) { currentHash = (_index % 2 == 0) - ? _efficientHash(currentHash, _path[i]) - : _efficientHash(_path[i], currentHash); + ? efficientHash(currentHash, _path[i]) + : efficientHash(_path[i], currentHash); _index /= 2; } return currentHash; } + /// @dev Calculate Merkle root by the provided Merkle proof for a range of elements + /// NOTE: When using this function, check that the _startPath and _endPath lengths are equal to the tree height to prevent shorter/longer paths attack + /// @param _startPath Merkle path from the first element of the range to the root + /// @param _endPath Merkle path from the last element of the range to the root + /// @param _startIndex Index of the first element of the range in the tree + /// @param _itemHashes Hashes of the elements in the range + /// @return The Merkle root + function calculateRoot( + bytes32[] calldata _startPath, + bytes32[] calldata _endPath, + uint256 _startIndex, + bytes32[] calldata _itemHashes + ) internal pure returns (bytes32) { + uint256 pathLength = _startPath.length; + require(pathLength == _endPath.length, "Merkle: path length mismatch"); + require(pathLength < 256, "Merkle: path too long"); + uint256 levelLen = _itemHashes.length; + // Edge case: we want to be able to prove an element in a single-node tree. + require(pathLength > 0 || (_startIndex == 0 && levelLen == 1), "Merkle: empty paths"); + require(levelLen > 0, "Merkle: nothing to prove"); + require(_startIndex + levelLen <= (1 << pathLength), "Merkle: index/height mismatch"); + bytes32[] memory itemHashes = _itemHashes; + + for (uint256 level; level < pathLength; level = level.uncheckedInc()) { + uint256 parity = _startIndex % 2; + // We get an extra element on the next level if on the current level elements either + // start on an odd index (`parity == 1`) or end on an even index (`levelLen % 2 == 1`) + uint256 nextLevelLen = levelLen / 2 + (parity | (levelLen % 2)); + for (uint256 i; i < nextLevelLen; i = i.uncheckedInc()) { + bytes32 lhs = (i == 0 && parity == 1) ? _startPath[level] : itemHashes[2 * i - parity]; + bytes32 rhs = (i == nextLevelLen - 1 && (levelLen - parity) % 2 == 1) + ? _endPath[level] + : itemHashes[2 * i + 1 - parity]; + itemHashes[i] = efficientHash(lhs, rhs); + } + levelLen = nextLevelLen; + _startIndex /= 2; + } + + return itemHashes[0]; + } + /// @dev Keccak hash of the concatenation of two 32-byte words - function _efficientHash(bytes32 _lhs, bytes32 _rhs) private pure returns (bytes32 result) { + function efficientHash(bytes32 _lhs, bytes32 _rhs) internal pure returns (bytes32 result) { assembly { mstore(0x00, _lhs) mstore(0x20, _rhs) diff --git a/l1-contracts/contracts/common/libraries/openzeppelin/Arrays.sol b/l1-contracts/contracts/common/libraries/openzeppelin/Arrays.sol deleted file mode 100644 index af57d09c8..000000000 --- a/l1-contracts/contracts/common/libraries/openzeppelin/Arrays.sol +++ /dev/null @@ -1,487 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v5.0.0) (utils/Arrays.sol) -// This file was procedurally generated from scripts/generate/templates/Arrays.js. - -pragma solidity ^0.8.20; - -import {SlotDerivation} from "./SlotDerivation.sol"; -import {StorageSlot} from "@openzeppelin/contracts/utils/StorageSlot.sol"; -import {Math} from "@openzeppelin/contracts/utils/math/Math.sol"; - -/** - * @dev Collection of functions related to array types. - */ -library Arrays { - using SlotDerivation for bytes32; - using StorageSlot for bytes32; - - /** - * @dev Sort an array of bytes32 (in memory) following the provided comparator function. - * - * This function does the sorting "in place", meaning that it overrides the input. The object is returned for - * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array. - * - * NOTE: this function's cost is `O(n · log(n))` in average and `O(n²)` in the worst case, with n the length of the - * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful - * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may - * consume more gas than is available in a block, leading to potential DoS. - */ - function sort( - bytes32[] memory array, - function(bytes32, bytes32) pure returns (bool) comp - ) internal pure returns (bytes32[] memory) { - _quickSort(_begin(array), _end(array), comp); - return array; - } - - /** - * @dev Variant of {sort} that sorts an array of bytes32 in increasing order. - */ - function sort(bytes32[] memory array) internal pure returns (bytes32[] memory) { - sort(array, _defaultComp); - return array; - } - - /** - * @dev Sort an array of address (in memory) following the provided comparator function. - * - * This function does the sorting "in place", meaning that it overrides the input. The object is returned for - * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array. - * - * NOTE: this function's cost is `O(n · log(n))` in average and `O(n²)` in the worst case, with n the length of the - * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful - * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may - * consume more gas than is available in a block, leading to potential DoS. - */ - function sort( - address[] memory array, - function(address, address) pure returns (bool) comp - ) internal pure returns (address[] memory) { - sort(_castToBytes32Array(array), _castToBytes32Comp(comp)); - return array; - } - - /** - * @dev Variant of {sort} that sorts an array of address in increasing order. - */ - function sort(address[] memory array) internal pure returns (address[] memory) { - sort(_castToBytes32Array(array), _defaultComp); - return array; - } - - /** - * @dev Sort an array of uint256 (in memory) following the provided comparator function. - * - * This function does the sorting "in place", meaning that it overrides the input. The object is returned for - * convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array. - * - * NOTE: this function's cost is `O(n · log(n))` in average and `O(n²)` in the worst case, with n the length of the - * array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful - * when executing this as part of a transaction. If the array being sorted is too large, the sort operation may - * consume more gas than is available in a block, leading to potential DoS. - */ - function sort( - uint256[] memory array, - function(uint256, uint256) pure returns (bool) comp - ) internal pure returns (uint256[] memory) { - sort(_castToBytes32Array(array), _castToBytes32Comp(comp)); - return array; - } - - /** - * @dev Variant of {sort} that sorts an array of uint256 in increasing order. - */ - function sort(uint256[] memory array) internal pure returns (uint256[] memory) { - sort(_castToBytes32Array(array), _defaultComp); - return array; - } - - /** - * @dev Performs a quick sort of a segment of memory. The segment sorted starts at `begin` (inclusive), and stops - * at end (exclusive). Sorting follows the `comp` comparator. - * - * Invariant: `begin <= end`. This is the case when initially called by {sort} and is preserved in subcalls. - * - * IMPORTANT: Memory locations between `begin` and `end` are not validated/zeroed. This function should - * be used only if the limits are within a memory array. - */ - function _quickSort(uint256 begin, uint256 end, function(bytes32, bytes32) pure returns (bool) comp) private pure { - unchecked { - if (end - begin < 0x40) return; - - // Use first element as pivot - bytes32 pivot = _mload(begin); - // Position where the pivot should be at the end of the loop - uint256 pos = begin; - - for (uint256 it = begin + 0x20; it < end; it += 0x20) { - if (comp(_mload(it), pivot)) { - // If the value stored at the iterator's position comes before the pivot, we increment the - // position of the pivot and move the value there. - pos += 0x20; - _swap(pos, it); - } - } - - _swap(begin, pos); // Swap pivot into place - _quickSort(begin, pos, comp); // Sort the left side of the pivot - _quickSort(pos + 0x20, end, comp); // Sort the right side of the pivot - } - } - - /** - * @dev Pointer to the memory location of the first element of `array`. - */ - function _begin(bytes32[] memory array) private pure returns (uint256 ptr) { - /// @solidity memory-safe-assembly - assembly { - ptr := add(array, 0x20) - } - } - - /** - * @dev Pointer to the memory location of the first memory word (32bytes) after `array`. This is the memory word - * that comes just after the last element of the array. - */ - function _end(bytes32[] memory array) private pure returns (uint256 ptr) { - unchecked { - return _begin(array) + array.length * 0x20; - } - } - - /** - * @dev Load memory word (as a bytes32) at location `ptr`. - */ - function _mload(uint256 ptr) private pure returns (bytes32 value) { - assembly { - value := mload(ptr) - } - } - - /** - * @dev Swaps the elements memory location `ptr1` and `ptr2`. - */ - function _swap(uint256 ptr1, uint256 ptr2) private pure { - assembly { - let value1 := mload(ptr1) - let value2 := mload(ptr2) - mstore(ptr1, value2) - mstore(ptr2, value1) - } - } - - /// @dev Comparator for sorting arrays in increasing order. - function _defaultComp(bytes32 a, bytes32 b) private pure returns (bool) { - return a < b; - } - - /// @dev Helper: low level cast address memory array to uint256 memory array - function _castToBytes32Array(address[] memory input) private pure returns (bytes32[] memory output) { - assembly { - output := input - } - } - - /// @dev Helper: low level cast uint256 memory array to uint256 memory array - function _castToBytes32Array(uint256[] memory input) private pure returns (bytes32[] memory output) { - assembly { - output := input - } - } - - /// @dev Helper: low level cast address comp function to bytes32 comp function - function _castToBytes32Comp( - function(address, address) pure returns (bool) input - ) private pure returns (function(bytes32, bytes32) pure returns (bool) output) { - assembly { - output := input - } - } - - /// @dev Helper: low level cast uint256 comp function to bytes32 comp function - function _castToBytes32Comp( - function(uint256, uint256) pure returns (bool) input - ) private pure returns (function(bytes32, bytes32) pure returns (bool) output) { - assembly { - output := input - } - } - - /** - * @dev Searches a sorted `array` and returns the first index that contains - * a value greater or equal to `element`. If no such index exists (i.e. all - * values in the array are strictly less than `element`), the array length is - * returned. Time complexity O(log n). - * - * NOTE: The `array` is expected to be sorted in ascending order, and to - * contain no repeated elements. - * - * IMPORTANT: Deprecated. This implementation behaves as {lowerBound} but lacks - * support for repeated elements in the array. The {lowerBound} function should - * be used instead. - */ - function findUpperBound(uint256[] storage array, uint256 element) internal view returns (uint256) { - uint256 low = 0; - uint256 high = array.length; - - if (high == 0) { - return 0; - } - - while (low < high) { - uint256 mid = Math.average(low, high); - - // Note that mid will always be strictly less than high (i.e. it will be a valid array index) - // because Math.average rounds towards zero (it does integer division with truncation). - if (unsafeAccess(array, mid).value > element) { - high = mid; - } else { - low = mid + 1; - } - } - - // At this point `low` is the exclusive upper bound. We will return the inclusive upper bound. - if (low > 0 && unsafeAccess(array, low - 1).value == element) { - return low - 1; - } else { - return low; - } - } - - /** - * @dev Searches an `array` sorted in ascending order and returns the first - * index that contains a value greater or equal than `element`. If no such index - * exists (i.e. all values in the array are strictly less than `element`), the array - * length is returned. Time complexity O(log n). - * - * See C++'s https://en.cppreference.com/w/cpp/algorithm/lower_bound[lower_bound]. - */ - function lowerBound(uint256[] storage array, uint256 element) internal view returns (uint256) { - uint256 low = 0; - uint256 high = array.length; - - if (high == 0) { - return 0; - } - - while (low < high) { - uint256 mid = Math.average(low, high); - - // Note that mid will always be strictly less than high (i.e. it will be a valid array index) - // because Math.average rounds towards zero (it does integer division with truncation). - if (unsafeAccess(array, mid).value < element) { - // this cannot overflow because mid < high - unchecked { - low = mid + 1; - } - } else { - high = mid; - } - } - - return low; - } - - /** - * @dev Searches an `array` sorted in ascending order and returns the first - * index that contains a value strictly greater than `element`. If no such index - * exists (i.e. all values in the array are strictly less than `element`), the array - * length is returned. Time complexity O(log n). - * - * See C++'s https://en.cppreference.com/w/cpp/algorithm/upper_bound[upper_bound]. - */ - function upperBound(uint256[] storage array, uint256 element) internal view returns (uint256) { - uint256 low = 0; - uint256 high = array.length; - - if (high == 0) { - return 0; - } - - while (low < high) { - uint256 mid = Math.average(low, high); - - // Note that mid will always be strictly less than high (i.e. it will be a valid array index) - // because Math.average rounds towards zero (it does integer division with truncation). - if (unsafeAccess(array, mid).value > element) { - high = mid; - } else { - // this cannot overflow because mid < high - unchecked { - low = mid + 1; - } - } - } - - return low; - } - - /** - * @dev Same as {lowerBound}, but with an array in memory. - */ - function lowerBoundMemory(uint256[] memory array, uint256 element) internal pure returns (uint256) { - uint256 low = 0; - uint256 high = array.length; - - if (high == 0) { - return 0; - } - - while (low < high) { - uint256 mid = Math.average(low, high); - - // Note that mid will always be strictly less than high (i.e. it will be a valid array index) - // because Math.average rounds towards zero (it does integer division with truncation). - if (unsafeMemoryAccess(array, mid) < element) { - // this cannot overflow because mid < high - unchecked { - low = mid + 1; - } - } else { - high = mid; - } - } - - return low; - } - - /** - * @dev Same as {upperBound}, but with an array in memory. - */ - function upperBoundMemory(uint256[] memory array, uint256 element) internal pure returns (uint256) { - uint256 low = 0; - uint256 high = array.length; - - if (high == 0) { - return 0; - } - - while (low < high) { - uint256 mid = Math.average(low, high); - - // Note that mid will always be strictly less than high (i.e. it will be a valid array index) - // because Math.average rounds towards zero (it does integer division with truncation). - if (unsafeMemoryAccess(array, mid) > element) { - high = mid; - } else { - // this cannot overflow because mid < high - unchecked { - low = mid + 1; - } - } - } - - return low; - } - - /** - * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check. - * - * WARNING: Only use if you are certain `pos` is lower than the array length. - */ - function unsafeAccess(address[] storage arr, uint256 pos) internal pure returns (StorageSlot.AddressSlot storage) { - bytes32 slot; - /// @solidity memory-safe-assembly - assembly { - slot := arr.slot - } - return slot.deriveArray().offset(pos).getAddressSlot(); - } - - /** - * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check. - * - * WARNING: Only use if you are certain `pos` is lower than the array length. - */ - function unsafeAccess(bytes32[] storage arr, uint256 pos) internal pure returns (StorageSlot.Bytes32Slot storage) { - bytes32 slot; - /// @solidity memory-safe-assembly - assembly { - slot := arr.slot - } - return slot.deriveArray().offset(pos).getBytes32Slot(); - } - - /** - * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check. - * - * WARNING: Only use if you are certain `pos` is lower than the array length. - */ - function unsafeAccess(uint256[] storage arr, uint256 pos) internal pure returns (StorageSlot.Uint256Slot storage) { - bytes32 slot; - /// @solidity memory-safe-assembly - assembly { - slot := arr.slot - } - return slot.deriveArray().offset(pos).getUint256Slot(); - } - - /** - * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check. - * - * WARNING: Only use if you are certain `pos` is lower than the array length. - */ - function unsafeMemoryAccess(address[] memory arr, uint256 pos) internal pure returns (address res) { - assembly { - res := mload(add(add(arr, 0x20), mul(pos, 0x20))) - } - } - - /** - * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check. - * - * WARNING: Only use if you are certain `pos` is lower than the array length. - */ - function unsafeMemoryAccess(bytes32[] memory arr, uint256 pos) internal pure returns (bytes32 res) { - assembly { - res := mload(add(add(arr, 0x20), mul(pos, 0x20))) - } - } - - /** - * @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check. - * - * WARNING: Only use if you are certain `pos` is lower than the array length. - */ - function unsafeMemoryAccess(uint256[] memory arr, uint256 pos) internal pure returns (uint256 res) { - assembly { - res := mload(add(add(arr, 0x20), mul(pos, 0x20))) - } - } - - /** - * @dev Helper to set the length of an dynamic array. Directly writing to `.length` is forbidden. - * - * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased. - */ - function unsafeSetLength(address[] storage array, uint256 len) internal { - /// @solidity memory-safe-assembly - assembly { - sstore(array.slot, len) - } - } - - /** - * @dev Helper to set the length of an dynamic array. Directly writing to `.length` is forbidden. - * - * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased. - */ - function unsafeSetLength(bytes32[] storage array, uint256 len) internal { - /// @solidity memory-safe-assembly - assembly { - sstore(array.slot, len) - } - } - - /** - * @dev Helper to set the length of an dynamic array. Directly writing to `.length` is forbidden. - * - * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased. - */ - function unsafeSetLength(uint256[] storage array, uint256 len) internal { - /// @solidity memory-safe-assembly - assembly { - sstore(array.slot, len) - } - } -} diff --git a/l1-contracts/contracts/common/libraries/openzeppelin/Hashes.sol b/l1-contracts/contracts/common/libraries/openzeppelin/Hashes.sol deleted file mode 100644 index a2fb86d81..000000000 --- a/l1-contracts/contracts/common/libraries/openzeppelin/Hashes.sol +++ /dev/null @@ -1,38 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.8.0; - -/** - * @dev Library of standard hash functions. - */ -library Hashes { - /** - * @dev Commutative Keccak256 hash of a sorted pair of bytes32. Frequently used when working with merkle proofs. - * - * NOTE: Equivalent to the `standardNodeHash` in our https://github.com/OpenZeppelin/merkle-tree[JavaScript library]. - */ - function commutativeKeccak256(bytes32 a, bytes32 b) internal pure returns (bytes32) { - return a < b ? _efficientKeccak256(a, b) : _efficientKeccak256(b, a); - } - - /** - * @dev Keccak256 hash of a sorted pair of bytes32. Frequently used when working with merkle proofs. - * - * NOTE: - */ - function Keccak256(bytes32 a, bytes32 b) internal pure returns (bytes32) { - return _efficientKeccak256(a, b); - } - - /** - * @dev Implementation of keccak256(abi.encode(a, b)) that doesn't allocate or expand memory. - */ - function _efficientKeccak256(bytes32 a, bytes32 b) private pure returns (bytes32 value) { - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, a) - mstore(0x20, b) - value := keccak256(0x00, 0x40) - } - } -} diff --git a/l1-contracts/contracts/common/libraries/openzeppelin/SlotDerivation.sol b/l1-contracts/contracts/common/libraries/openzeppelin/SlotDerivation.sol deleted file mode 100644 index c75941b58..000000000 --- a/l1-contracts/contracts/common/libraries/openzeppelin/SlotDerivation.sol +++ /dev/null @@ -1,161 +0,0 @@ -// SPDX-License-Identifier: MIT -// This file was procedurally generated from scripts/generate/templates/SlotDerivation.js. - -pragma solidity ^0.8.20; - -/** - * @dev Library for computing storage (and transient storage) locations from namespaces and deriving slots - * corresponding to standard patterns. The derivation method for array and mapping matches the storage layout used by - * the solidity language / compiler. - * - * See https://docs.soliditylang.org/en/v0.8.20/internals/layout_in_storage.html#mappings-and-dynamic-arrays[Solidity docs for mappings and dynamic arrays.]. - * - * Example usage: - * ```solidity - * contract Example { - * // Add the library methods - * using StorageSlot for bytes32; - * using SlotDerivation for bytes32; - * - * // Declare a namespace - * string private constant _NAMESPACE = "" // eg. OpenZeppelin.Slot - * - * function setValueInNamespace(uint256 key, address newValue) internal { - * _NAMESPACE.erc7201Slot().deriveMapping(key).getAddressSlot().value = newValue; - * } - * - * function getValueInNamespace(uint256 key) internal view returns (address) { - * return _NAMESPACE.erc7201Slot().deriveMapping(key).getAddressSlot().value; - * } - * } - * ``` - * - * TIP: Consider using this library along with {StorageSlot}. - * - * NOTE: This library provides a way to manipulate storage locations in a non-standard way. Tooling for checking - * upgrade safety will ignore the slots accessed through this library. - */ -library SlotDerivation { - /** - * @dev Derive an ERC-7201 slot from a string (namespace). - */ - function erc7201Slot(string memory namespace) internal pure returns (bytes32 slot) { - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, sub(keccak256(add(namespace, 0x20), mload(namespace)), 1)) - slot := and(keccak256(0x00, 0x20), not(0xff)) - } - } - - /** - * @dev Add an offset to a slot to get the n-th element of a structure or an array. - */ - function offset(bytes32 slot, uint256 pos) internal pure returns (bytes32 result) { - unchecked { - return bytes32(uint256(slot) + pos); - } - } - - /** - * @dev Derive the location of the first element in an array from the slot where the length is stored. - */ - function deriveArray(bytes32 slot) internal pure returns (bytes32 result) { - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, slot) - result := keccak256(0x00, 0x20) - } - } - - /** - * @dev Derive the location of a mapping element from the key. - */ - function deriveMapping(bytes32 slot, address key) internal pure returns (bytes32 result) { - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, key) - mstore(0x20, slot) - result := keccak256(0x00, 0x40) - } - } - - /** - * @dev Derive the location of a mapping element from the key. - */ - function deriveMapping(bytes32 slot, bool key) internal pure returns (bytes32 result) { - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, key) - mstore(0x20, slot) - result := keccak256(0x00, 0x40) - } - } - - /** - * @dev Derive the location of a mapping element from the key. - */ - function deriveMapping(bytes32 slot, bytes32 key) internal pure returns (bytes32 result) { - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, key) - mstore(0x20, slot) - result := keccak256(0x00, 0x40) - } - } - - /** - * @dev Derive the location of a mapping element from the key. - */ - function deriveMapping(bytes32 slot, uint256 key) internal pure returns (bytes32 result) { - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, key) - mstore(0x20, slot) - result := keccak256(0x00, 0x40) - } - } - - /** - * @dev Derive the location of a mapping element from the key. - */ - function deriveMapping(bytes32 slot, int256 key) internal pure returns (bytes32 result) { - /// @solidity memory-safe-assembly - assembly { - mstore(0x00, key) - mstore(0x20, slot) - result := keccak256(0x00, 0x40) - } - } - - /** - * @dev Derive the location of a mapping element from the key. - */ - function deriveMapping(bytes32 slot, string memory key) internal pure returns (bytes32 result) { - /// @solidity memory-safe-assembly - assembly { - let length := mload(key) - let begin := add(key, 0x20) - let end := add(begin, length) - let cache := mload(end) - mstore(end, slot) - result := keccak256(begin, add(length, 0x20)) - mstore(end, cache) - } - } - - /** - * @dev Derive the location of a mapping element from the key. - */ - function deriveMapping(bytes32 slot, bytes memory key) internal pure returns (bytes32 result) { - /// @solidity memory-safe-assembly - assembly { - let length := mload(key) - let begin := add(key, 0x20) - let end := add(begin, length) - let cache := mload(end) - mstore(end, slot) - result := keccak256(begin, add(length, 0x20)) - mstore(end, cache) - } - } -} diff --git a/l1-contracts/contracts/dev-contracts/test/DummyExecutor.sol b/l1-contracts/contracts/dev-contracts/test/DummyExecutor.sol index 7da7113b2..1126dc89f 100644 --- a/l1-contracts/contracts/dev-contracts/test/DummyExecutor.sol +++ b/l1-contracts/contracts/dev-contracts/test/DummyExecutor.sol @@ -3,6 +3,7 @@ pragma solidity 0.8.24; import {IExecutor} from "../../state-transition/chain-interfaces/IExecutor.sol"; +import {PriorityOpsBatchInfo} from "../../state-transition/libraries/PriorityTree.sol"; /// @title DummyExecutor /// @notice A test smart contract implementing the IExecutor interface to simulate Executor behavior for testing purposes. @@ -125,10 +126,22 @@ contract DummyExecutor is IExecutor { ); } + function executeBatches(StoredBatchInfo[] calldata _batchesData, PriorityOpsBatchInfo[] calldata) external { + executeBatches(_batchesData); + } + function executeBatchesSharedBridge(uint256, StoredBatchInfo[] calldata _batchesData) external { executeBatches(_batchesData); } + function executeBatchesSharedBridge( + uint256, + StoredBatchInfo[] calldata _batchesData, + PriorityOpsBatchInfo[] calldata + ) external { + executeBatches(_batchesData); + } + function revertBatches(uint256 _newLastBatch) public { require( getTotalBatchesCommitted > _newLastBatch, diff --git a/l1-contracts/contracts/dev-contracts/test/FullMerkleTest.sol b/l1-contracts/contracts/dev-contracts/test/FullMerkleTest.sol index 121de17d2..78f5160d5 100644 --- a/l1-contracts/contracts/dev-contracts/test/FullMerkleTest.sol +++ b/l1-contracts/contracts/dev-contracts/test/FullMerkleTest.sol @@ -3,7 +3,6 @@ pragma solidity 0.8.24; import {FullMerkle} from "../../common/libraries/FullMerkle.sol"; -import {Arrays} from "../../common/libraries/openzeppelin/Arrays.sol"; contract FullMerkleTest { using FullMerkle for FullMerkle.FullTree; @@ -47,6 +46,6 @@ contract FullMerkleTest { } function zeros(uint256 _index) external view returns (bytes32) { - return Arrays.unsafeAccess(tree._zeros, _index).value; + return tree._zeros[_index]; } } diff --git a/l1-contracts/contracts/dev-contracts/test/IncrementalMerkleTest.sol b/l1-contracts/contracts/dev-contracts/test/IncrementalMerkleTest.sol index 086e1e0ea..b5850bb42 100644 --- a/l1-contracts/contracts/dev-contracts/test/IncrementalMerkleTest.sol +++ b/l1-contracts/contracts/dev-contracts/test/IncrementalMerkleTest.sol @@ -2,8 +2,7 @@ pragma solidity 0.8.24; -import {DynamicIncrementalMerkle} from "../../common/libraries/openzeppelin/IncrementalMerkle.sol"; -import {Arrays} from "../../common/libraries/openzeppelin/Arrays.sol"; +import {DynamicIncrementalMerkle} from "../../common/libraries/DynamicIncrementalMerkle.sol"; contract IncrementalMerkleTest { using DynamicIncrementalMerkle for DynamicIncrementalMerkle.Bytes32PushTree; @@ -23,7 +22,7 @@ contract IncrementalMerkleTest { } function height() external view returns (uint256) { - return tree._height; + return tree.height(); } function index() external view returns (uint256) { @@ -31,10 +30,10 @@ contract IncrementalMerkleTest { } function side(uint256 _index) external view returns (bytes32) { - return Arrays.unsafeAccess(tree._sides, _index).value; + return tree._sides[_index]; } function zeros(uint256 _index) external view returns (bytes32) { - return Arrays.unsafeAccess(tree._zeros, _index).value; + return tree._zeros[_index]; } } diff --git a/l1-contracts/contracts/dev-contracts/test/MerkleTest.sol b/l1-contracts/contracts/dev-contracts/test/MerkleTest.sol index d7c14d5a7..dbe0690f9 100644 --- a/l1-contracts/contracts/dev-contracts/test/MerkleTest.sol +++ b/l1-contracts/contracts/dev-contracts/test/MerkleTest.sol @@ -12,4 +12,13 @@ contract MerkleTest { ) external pure returns (bytes32) { return Merkle.calculateRoot(_path, _index, _itemHash); } + + function calculateRoot( + bytes32[] calldata _startPath, + bytes32[] calldata _endPath, + uint256 _startIndex, + bytes32[] calldata _itemHashes + ) external pure returns (bytes32) { + return Merkle.calculateRoot(_startPath, _endPath, _startIndex, _itemHashes); + } } diff --git a/l1-contracts/contracts/dev-contracts/test/PriorityTreeTest.sol b/l1-contracts/contracts/dev-contracts/test/PriorityTreeTest.sol new file mode 100644 index 000000000..0409c1a4c --- /dev/null +++ b/l1-contracts/contracts/dev-contracts/test/PriorityTreeTest.sol @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.24; + +import {PriorityTree, PriorityOpsBatchInfo, PriorityTreeCommitment} from "../../state-transition/libraries/PriorityTree.sol"; + +contract PriorityTreeTest { + PriorityTree.Tree priorityTree; + + constructor() { + PriorityTree.setup(priorityTree, 0); + } + + function getFirstUnprocessedPriorityTx() external view returns (uint256) { + return PriorityTree.getFirstUnprocessedPriorityTx(priorityTree); + } + + function getTotalPriorityTxs() external view returns (uint256) { + return PriorityTree.getTotalPriorityTxs(priorityTree); + } + + function getSize() external view returns (uint256) { + return PriorityTree.getSize(priorityTree); + } + + function push(bytes32 _hash) external { + return PriorityTree.push(priorityTree, _hash); + } + + function getRoot() external view returns (bytes32) { + return PriorityTree.getRoot(priorityTree); + } + + function processBatch(PriorityOpsBatchInfo calldata _priorityOpsData) external { + PriorityTree.processBatch(priorityTree, _priorityOpsData); + } + + function getCommitment() external view returns (PriorityTreeCommitment memory) { + return PriorityTree.getCommitment(priorityTree); + } + + function initFromCommitment(PriorityTreeCommitment calldata _commitment) external { + PriorityTree.initFromCommitment(priorityTree, _commitment); + } + + function getZero() external view returns (bytes32) { + return priorityTree.tree._zeros[0]; + } +} diff --git a/l1-contracts/contracts/dev-contracts/test/TestExecutor.sol b/l1-contracts/contracts/dev-contracts/test/TestExecutor.sol index 2b41daecc..10b907aec 100644 --- a/l1-contracts/contracts/dev-contracts/test/TestExecutor.sol +++ b/l1-contracts/contracts/dev-contracts/test/TestExecutor.sol @@ -5,6 +5,10 @@ import {ExecutorFacet} from "../../state-transition/chain-deps/facets/Executor.s pragma solidity 0.8.24; contract TestExecutor is ExecutorFacet { + function setPriorityTreeStartIndex(uint256 _startIndex) external { + s.priorityTree.startIndex = _startIndex; + } + // /// @dev Since we want to test the blob functionality we want mock the calls to the blobhash opcode. // function _getBlobVersionedHash(uint256 _index) internal view virtual override returns (bytes32 versionedHash) { // (bool success, bytes memory data) = s.blobVersionedHashRetriever.staticcall(abi.encode(_index)); diff --git a/l1-contracts/contracts/state-transition/ValidatorTimelock.sol b/l1-contracts/contracts/state-transition/ValidatorTimelock.sol index 396276306..acba1f53a 100644 --- a/l1-contracts/contracts/state-transition/ValidatorTimelock.sol +++ b/l1-contracts/contracts/state-transition/ValidatorTimelock.sol @@ -8,6 +8,7 @@ import {Ownable2Step} from "@openzeppelin/contracts/access/Ownable2Step.sol"; import {LibMap} from "./libraries/LibMap.sol"; import {IExecutor} from "./chain-interfaces/IExecutor.sol"; import {IStateTransitionManager} from "./IStateTransitionManager.sol"; +import {PriorityOpsBatchInfo} from "./libraries/PriorityTree.sol"; /// @author Matter Labs /// @custom:security-contact security@matterlabs.dev @@ -180,15 +181,19 @@ contract ValidatorTimelock is IExecutor, Ownable2Step { /// @dev Check that batches were committed at least X time ago and /// make a call to the hyperchain diamond contract with the same calldata. - function executeBatches(StoredBatchInfo[] calldata _newBatchesData) external onlyValidator(ERA_CHAIN_ID) { - _executeBatchesInner(ERA_CHAIN_ID, _newBatchesData); + function executeBatches( + StoredBatchInfo[] calldata _batchesData, + PriorityOpsBatchInfo[] calldata + ) external onlyValidator(ERA_CHAIN_ID) { + _executeBatchesInner(ERA_CHAIN_ID, _batchesData); } /// @dev Check that batches were committed at least X time ago and /// make a call to the hyperchain diamond contract with the same calldata. function executeBatchesSharedBridge( uint256 _chainId, - StoredBatchInfo[] calldata _newBatchesData + StoredBatchInfo[] calldata _newBatchesData, + PriorityOpsBatchInfo[] calldata ) external onlyValidator(_chainId) { _executeBatchesInner(_chainId, _newBatchesData); } diff --git a/l1-contracts/contracts/state-transition/chain-deps/DiamondInit.sol b/l1-contracts/contracts/state-transition/chain-deps/DiamondInit.sol index 7c3e4d9eb..9181a7673 100644 --- a/l1-contracts/contracts/state-transition/chain-deps/DiamondInit.sol +++ b/l1-contracts/contracts/state-transition/chain-deps/DiamondInit.sol @@ -9,11 +9,16 @@ import {ZkSyncHyperchainBase} from "./facets/ZkSyncHyperchainBase.sol"; import {L2_TO_L1_LOG_SERIALIZE_SIZE, MAX_GAS_PER_TRANSACTION} from "../../common/Config.sol"; import {InitializeData, IDiamondInit} from "../chain-interfaces/IDiamondInit.sol"; import {IBridgehub} from "../../bridgehub/IBridgehub.sol"; +import {PriorityQueue} from "../libraries/PriorityQueue.sol"; +import {PriorityTree} from "../libraries/PriorityTree.sol"; /// @author Matter Labs /// @dev The contract is used only once to initialize the diamond proxy. /// @dev The deployment process takes care of this contract's initialization. contract DiamondInit is ZkSyncHyperchainBase, IDiamondInit { + using PriorityQueue for PriorityQueue.Queue; + using PriorityTree for PriorityTree.Tree; + /// @dev Initialize the implementation to prevent any possibility of a Parity hack. constructor() reentrancyGuardInitializer {} @@ -49,6 +54,7 @@ contract DiamondInit is ZkSyncHyperchainBase, IDiamondInit { s.priorityTxMaxGasLimit = _initializeData.priorityTxMaxGasLimit; s.feeParams = _initializeData.feeParams; s.blobVersionedHashRetriever = _initializeData.blobVersionedHashRetriever; + s.priorityTree.setup(s.priorityQueue.getTotalPriorityTxs()); s.baseTokenAssetId = IBridgehub(_initializeData.bridgehub).baseTokenAssetId(_initializeData.chainId); diff --git a/l1-contracts/contracts/state-transition/chain-deps/ZkSyncHyperchainStorage.sol b/l1-contracts/contracts/state-transition/chain-deps/ZkSyncHyperchainStorage.sol index bc3a35852..45540177e 100644 --- a/l1-contracts/contracts/state-transition/chain-deps/ZkSyncHyperchainStorage.sol +++ b/l1-contracts/contracts/state-transition/chain-deps/ZkSyncHyperchainStorage.sol @@ -5,6 +5,7 @@ pragma solidity 0.8.24; import {IVerifier, VerifierParams} from "../chain-interfaces/IVerifier.sol"; // import {IStateTransitionManager} from "../IStateTransitionManager.sol"; import {PriorityQueue} from "../../state-transition/libraries/PriorityQueue.sol"; +import {PriorityTree} from "../../state-transition/libraries/PriorityTree.sol"; /// @notice Indicates whether an upgrade is initiated and if yes what type /// @param None Upgrade is NOT initiated @@ -162,4 +163,6 @@ struct ZkSyncHyperchainStorage { bytes32 baseTokenAssetId; /// @dev address of the synclayer, only set on L1 if settling on it address syncLayer; + /// @dev Priority tree, the new data structure for priority queue + PriorityTree.Tree priorityTree; } diff --git a/l1-contracts/contracts/state-transition/chain-deps/facets/Admin.sol b/l1-contracts/contracts/state-transition/chain-deps/facets/Admin.sol index 95dde298e..401c4fe74 100644 --- a/l1-contracts/contracts/state-transition/chain-deps/facets/Admin.sol +++ b/l1-contracts/contracts/state-transition/chain-deps/facets/Admin.sol @@ -8,10 +8,10 @@ import {IAdmin} from "../../chain-interfaces/IAdmin.sol"; import {Diamond} from "../../libraries/Diamond.sol"; import {MAX_GAS_PER_TRANSACTION, HyperchainCommitment} from "../../../common/Config.sol"; import {FeeParams, PubdataPricingMode} from "../ZkSyncHyperchainStorage.sol"; -// import {PriorityQueue} from "../../../state-transition/libraries/PriorityQueue.sol"; +import {PriorityTree} from "../../../state-transition/libraries/PriorityTree.sol"; +import {PriorityQueue} from "../../../state-transition/libraries/PriorityQueue.sol"; import {ZkSyncHyperchainBase} from "./ZkSyncHyperchainBase.sol"; import {IStateTransitionManager} from "../../IStateTransitionManager.sol"; -import {PriorityOperation} from "../../libraries/PriorityQueue.sol"; import {IL1GenesisUpgrade} from "../../../upgrades/IL1GenesisUpgrade.sol"; // While formally the following import is not used, it is needed to inherit documentation from it @@ -21,7 +21,8 @@ import {IZkSyncHyperchainBase} from "../../chain-interfaces/IZkSyncHyperchainBas /// @author Matter Labs /// @custom:security-contact security@matterlabs.dev contract AdminFacet is ZkSyncHyperchainBase, IAdmin { - // using PriorityQueue for PriorityQueue.Queue; + using PriorityTree for PriorityTree.Tree; + using PriorityQueue for PriorityQueue.Queue; /// @inheritdoc IZkSyncHyperchainBase string public constant override getName = "AdminFacet"; @@ -262,15 +263,7 @@ contract AdminFacet is ZkSyncHyperchainBase, IAdmin { s.storedBatchHashes[batchesExecuted + i] = _commitment.batchHashes[i]; } - // Currently only zero length is allowed. - uint256 pqHead = _commitment.priorityQueueHead; - s.priorityQueue.head = pqHead; - s.priorityQueue.tail = pqHead + _commitment.priorityQueueTxs.length; - - length = _commitment.priorityQueueTxs.length; - for (uint256 i = 0; i < length; ++i) { - s.priorityQueue.data[pqHead + i] = _commitment.priorityQueueTxs[i]; - } + s.priorityTree.initFromCommitment(_commitment.priorityTree); s.l2SystemContractsUpgradeTxHash = _commitment.l2SystemContractsUpgradeTxHash; s.l2SystemContractsUpgradeBatchNumber = _commitment.l2SystemContractsUpgradeBatchNumber; @@ -289,26 +282,14 @@ contract AdminFacet is ZkSyncHyperchainBase, IAdmin { // todo make internal. For now useful for testing function _prepareChainCommitment() public view returns (HyperchainCommitment memory commitment) { + require(s.priorityQueue.getFirstUnprocessedPriorityTx() >= s.priorityTree.startIndex, "PQ not ready"); + commitment.totalBatchesCommitted = s.totalBatchesCommitted; commitment.totalBatchesVerified = s.totalBatchesVerified; commitment.totalBatchesExecuted = s.totalBatchesExecuted; - - uint256 pqHead = s.priorityQueue.head; - commitment.priorityQueueHead = pqHead; - - uint256 pqLength = s.priorityQueue.tail - pqHead; - // FIXME: this will be removed once we support the migration of any priority queue size. - require(pqLength <= 50, "Migration is only allowed with empty priority queue 2"); - - PriorityOperation[] memory priorityQueueTxs = new PriorityOperation[](pqLength); - - for (uint256 i = pqHead; i < s.priorityQueue.tail; ++i) { - priorityQueueTxs[i] = s.priorityQueue.data[i]; - } - commitment.priorityQueueTxs = priorityQueueTxs; - commitment.l2SystemContractsUpgradeBatchNumber = s.l2SystemContractsUpgradeBatchNumber; commitment.l2SystemContractsUpgradeTxHash = s.l2SystemContractsUpgradeTxHash; + commitment.priorityTree = s.priorityTree.getCommitment(); // just in case require( diff --git a/l1-contracts/contracts/state-transition/chain-deps/facets/Executor.sol b/l1-contracts/contracts/state-transition/chain-deps/facets/Executor.sol index 42c49f13a..dd0eec64a 100644 --- a/l1-contracts/contracts/state-transition/chain-deps/facets/Executor.sol +++ b/l1-contracts/contracts/state-transition/chain-deps/facets/Executor.sol @@ -13,6 +13,7 @@ import {UncheckedMath} from "../../../common/libraries/UncheckedMath.sol"; import {UnsafeBytes} from "../../../common/libraries/UnsafeBytes.sol"; import {L2_BOOTLOADER_ADDRESS, L2_TO_L1_MESSENGER_SYSTEM_CONTRACT_ADDR, L2_SYSTEM_CONTEXT_SYSTEM_CONTRACT_ADDR} from "../../../common/L2ContractAddresses.sol"; import {IStateTransitionManager} from "../../IStateTransitionManager.sol"; +import {PriorityTree, PriorityOpsBatchInfo} from "../../libraries/PriorityTree.sol"; import {IL1DAValidator, L1DAValidatorOutput} from "../../chain-interfaces/IL1DAValidator.sol"; // While formally the following import is not used, it is needed to inherit documentation from it @@ -24,6 +25,7 @@ import {IZkSyncHyperchainBase} from "../../chain-interfaces/IZkSyncHyperchainBas contract ExecutorFacet is ZkSyncHyperchainBase, IExecutor { using UncheckedMath for uint256; using PriorityQueue for PriorityQueue.Queue; + using PriorityTree for PriorityTree.Tree; /// @inheritdoc IZkSyncHyperchainBase string public constant override getName = "ExecutorFacet"; @@ -300,23 +302,47 @@ contract ExecutorFacet is ZkSyncHyperchainBase, IExecutor { } } - /// @dev Executes one batch - /// @dev 1. Processes all pending operations (Complete priority requests) - /// @dev 2. Finalizes batch on Ethereum - /// @dev _executedBatchIdx is an index in the array of the batches that we want to execute together - function _executeOneBatch(StoredBatchInfo memory _storedBatch, uint256 _executedBatchIdx) internal { + function _rollingHash(bytes32[] calldata _hashes) internal pure returns (bytes32) { + bytes32 hash = EMPTY_STRING_KECCAK; + uint256 nHashes = _hashes.length; + for (uint256 i = 0; i < nHashes; i = i.uncheckedInc()) { + hash = keccak256(abi.encode(hash, _hashes[i])); + } + return hash; + } + + /// @dev Checks that the data of the batch is correct and can be executed + /// @dev Verifies that batch number, batch hash and priority operations hash are correct + function _checkBatchData( + StoredBatchInfo memory _storedBatch, + uint256 _executedBatchIdx, + bytes32 _priorityOperationsHash + ) internal view { uint256 currentBatchNumber = _storedBatch.batchNumber; require(currentBatchNumber == s.totalBatchesExecuted + _executedBatchIdx + 1, "k"); // Execute batches in order require( _hashStoredBatchInfo(_storedBatch) == s.storedBatchHashes[currentBatchNumber], "exe10" // executing batch should be committed ); + require(_priorityOperationsHash == _storedBatch.priorityOperationsHash, "x"); // priority operations hash does not match with expected + } + /// @dev Executes one batch + /// @dev 1. Processes all pending operations (Complete priority requests) + /// @dev 2. Finalizes batch on Ethereum + /// @dev _executedBatchIdx is an index in the array of the batches that we want to execute together + function _executeOneBatch(StoredBatchInfo memory _storedBatch, uint256 _executedBatchIdx) internal { bytes32 priorityOperationsHash = _collectOperationsFromPriorityQueue(_storedBatch.numberOfLayer1Txs); - require(priorityOperationsHash == _storedBatch.priorityOperationsHash, "x"); // priority operations hash does not match to expected + _checkBatchData(_storedBatch, _executedBatchIdx, priorityOperationsHash); + + uint256 firstUnprocessed = s.priorityQueue.getFirstUnprocessedPriorityTx(); + uint256 treeStartIndex = s.priorityTree.startIndex; + if (firstUnprocessed > treeStartIndex) { + s.priorityTree.unprocessedIndex = firstUnprocessed - treeStartIndex; + } // Save root hash of L2 -> L1 logs tree - s.l2LogsRootHashes[currentBatchNumber] = _storedBatch.l2LogsTreeRoot; + s.l2LogsRootHashes[_storedBatch.batchNumber] = _storedBatch.l2LogsTreeRoot; // IBridgehub bridgehub = IBridgehub(s.bridgehub); // bridgehub.messageRoot().addChainBatchRoot( // s.chainId, @@ -325,23 +351,49 @@ contract ExecutorFacet is ZkSyncHyperchainBase, IExecutor { // ); } - /// @inheritdoc IExecutor + function _executeOneBatch( + StoredBatchInfo memory _storedBatch, + PriorityOpsBatchInfo calldata _priorityOpsData, + uint256 _executedBatchIdx + ) internal { + require(_priorityOpsData.itemHashes.length == _storedBatch.numberOfLayer1Txs, "zxc"); + bytes32 priorityOperationsHash = _rollingHash(_priorityOpsData.itemHashes); + _checkBatchData(_storedBatch, _executedBatchIdx, priorityOperationsHash); + s.priorityTree.processBatch(_priorityOpsData); + + // Save root hash of L2 -> L1 logs tree + s.l2LogsRootHashes[_storedBatch.batchNumber] = _storedBatch.l2LogsTreeRoot; + } + function executeBatchesSharedBridge( uint256, - StoredBatchInfo[] calldata _batchesData + StoredBatchInfo[] calldata _batchesData, + PriorityOpsBatchInfo[] calldata _priorityOpsData ) external nonReentrant onlyValidator { - _executeBatches(_batchesData); + _executeBatches(_batchesData, _priorityOpsData); } - /// @inheritdoc IExecutor - function executeBatches(StoredBatchInfo[] calldata _batchesData) external nonReentrant onlyValidator { - _executeBatches(_batchesData); + function executeBatches( + StoredBatchInfo[] calldata _batchesData, + PriorityOpsBatchInfo[] calldata _priorityOpsData + ) external nonReentrant onlyValidator { + _executeBatches(_batchesData, _priorityOpsData); } - function _executeBatches(StoredBatchInfo[] calldata _batchesData) internal { + function _executeBatches( + StoredBatchInfo[] calldata _batchesData, + PriorityOpsBatchInfo[] calldata _priorityOpsData + ) internal { uint256 nBatches = _batchesData.length; + uint256 dataIndex = 0; + for (uint256 i = 0; i < nBatches; i = i.uncheckedInc()) { - _executeOneBatch(_batchesData[i], i); + if (s.priorityTree.startIndex <= s.priorityQueue.getFirstUnprocessedPriorityTx()) { + // solhint-disable-next-line gas-increment-by-one + _executeOneBatch(_batchesData[i], _priorityOpsData[dataIndex++], i); + } else { + _executeOneBatch(_batchesData[i], i); + } emit BlockExecution(_batchesData[i].batchNumber, _batchesData[i].batchHash, _batchesData[i].commitment); } diff --git a/l1-contracts/contracts/state-transition/chain-deps/facets/Getters.sol b/l1-contracts/contracts/state-transition/chain-deps/facets/Getters.sol index 78361ecff..06dde902e 100644 --- a/l1-contracts/contracts/state-transition/chain-deps/facets/Getters.sol +++ b/l1-contracts/contracts/state-transition/chain-deps/facets/Getters.sol @@ -10,6 +10,7 @@ import {PubdataPricingMode} from "../ZkSyncHyperchainStorage.sol"; import {VerifierParams} from "../../../state-transition/chain-interfaces/IVerifier.sol"; import {Diamond} from "../../libraries/Diamond.sol"; import {PriorityQueue, PriorityOperation} from "../../../state-transition/libraries/PriorityQueue.sol"; +import {PriorityTree} from "../../../state-transition/libraries/PriorityTree.sol"; import {UncheckedMath} from "../../../common/libraries/UncheckedMath.sol"; import {IGetters} from "../../chain-interfaces/IGetters.sol"; import {ILegacyGetters} from "../../chain-interfaces/ILegacyGetters.sol"; @@ -24,6 +25,7 @@ import {IZkSyncHyperchainBase} from "../../chain-interfaces/IZkSyncHyperchainBas contract GettersFacet is ZkSyncHyperchainBase, IGetters, ILegacyGetters { using UncheckedMath for uint256; using PriorityQueue for PriorityQueue.Queue; + using PriorityTree for PriorityTree.Tree; /// @inheritdoc IZkSyncHyperchainBase string public constant override getName = "GettersFacet"; @@ -99,24 +101,39 @@ contract GettersFacet is ZkSyncHyperchainBase, IGetters, ILegacyGetters { /// @inheritdoc IGetters function getTotalPriorityTxs() external view returns (uint256) { - return s.priorityQueue.getTotalPriorityTxs(); + if (s.priorityQueue.getFirstUnprocessedPriorityTx() >= s.priorityTree.startIndex) { + return s.priorityTree.getTotalPriorityTxs(); + } else { + return s.priorityQueue.getTotalPriorityTxs(); + } } /// @inheritdoc IGetters function getFirstUnprocessedPriorityTx() external view returns (uint256) { - return s.priorityQueue.getFirstUnprocessedPriorityTx(); + if (s.priorityQueue.getFirstUnprocessedPriorityTx() >= s.priorityTree.startIndex) { + return s.priorityTree.getFirstUnprocessedPriorityTx(); + } else { + return s.priorityQueue.getFirstUnprocessedPriorityTx(); + } } /// @inheritdoc IGetters - function getPriorityQueueSize() external view returns (uint256) { - return s.priorityQueue.getSize(); + function getPriorityTreeRoot() external view returns (bytes32) { + return s.priorityTree.getRoot(); } /// @inheritdoc IGetters - function priorityQueueFrontOperation() external view returns (PriorityOperation memory) { - return s.priorityQueue.front(); + function getPriorityQueueSize() external view returns (uint256) { + if (s.priorityQueue.getFirstUnprocessedPriorityTx() >= s.priorityTree.startIndex) { + return s.priorityTree.getSize(); + } else { + return s.priorityQueue.getSize(); + } } + /// @inheritdoc IGetters + function priorityQueueFrontOperation() external view returns (PriorityOperation memory op) {} + /// @inheritdoc IGetters function isValidator(address _address) external view returns (bool) { return s.validators[_address]; diff --git a/l1-contracts/contracts/state-transition/chain-deps/facets/Mailbox.sol b/l1-contracts/contracts/state-transition/chain-deps/facets/Mailbox.sol index 2c3e69c35..da241235f 100644 --- a/l1-contracts/contracts/state-transition/chain-deps/facets/Mailbox.sol +++ b/l1-contracts/contracts/state-transition/chain-deps/facets/Mailbox.sol @@ -13,6 +13,7 @@ import {IBridgehub} from "../../../bridgehub/IBridgehub.sol"; import {ITransactionFilterer} from "../../chain-interfaces/ITransactionFilterer.sol"; import {Merkle} from "../../../common/libraries/Merkle.sol"; import {PriorityQueue, PriorityOperation} from "../../libraries/PriorityQueue.sol"; +import {PriorityTree} from "../../libraries/PriorityTree.sol"; import {TransactionValidator} from "../../libraries/TransactionValidator.sol"; import {WritePriorityOpParams, L2CanonicalTransaction, L2Message, L2Log, TxStatus, BridgehubL2TransactionRequest} from "../../../common/Messaging.sol"; import {FeeParams, PubdataPricingMode} from "../ZkSyncHyperchainStorage.sol"; @@ -39,6 +40,7 @@ import {IZkSyncHyperchainBase} from "../../chain-interfaces/IZkSyncHyperchainBas contract MailboxFacet is ZkSyncHyperchainBase, IMailbox { using UncheckedMath for uint256; using PriorityQueue for PriorityQueue.Queue; + using PriorityTree for PriorityTree.Tree; /// @inheritdoc IZkSyncHyperchainBase string public constant override getName = "MailboxFacet"; @@ -296,7 +298,7 @@ contract MailboxFacet is ZkSyncHyperchainBase, IMailbox { BridgehubL2TransactionRequest memory request = _params.request; require(request.factoryDeps.length <= MAX_NEW_FACTORY_DEPS, "uj"); - _params.txId = s.priorityQueue.getTotalPriorityTxs(); + _params.txId = _nextPriorityTxId(); // Checking that the user provided enough ether to pay for the transaction. _params.l2GasPrice = _deriveL2GasPrice(tx.gasprice, request.l2GasPerPubdataByteLimit); @@ -330,12 +332,20 @@ contract MailboxFacet is ZkSyncHyperchainBase, IMailbox { } } + function _nextPriorityTxId() internal view returns (uint256) { + if (s.priorityQueue.getFirstUnprocessedPriorityTx() >= s.priorityTree.startIndex) { + return s.priorityTree.getTotalPriorityTxs(); + } else { + return s.priorityQueue.getTotalPriorityTxs(); + } + } + function _requestL2TransactionToSyncLayerFree( BridgehubL2TransactionRequest memory _request ) internal nonReentrant returns (bytes32 canonicalTxHash) { WritePriorityOpParams memory params = WritePriorityOpParams({ request: _request, - txId: s.priorityQueue.getTotalPriorityTxs(), + txId: _nextPriorityTxId(), l2GasPrice: 0, expirationTimestamp: uint64(block.timestamp + PRIORITY_EXPIRATION) }); @@ -391,14 +401,16 @@ contract MailboxFacet is ZkSyncHyperchainBase, IMailbox { bytes32 _canonicalTxHash, uint64 _expirationTimestamp ) internal { - s.priorityQueue.pushBack( - PriorityOperation({ - canonicalTxHash: _canonicalTxHash, - // FIXME: safe downcast - expirationTimestamp: _expirationTimestamp, - layer2Tip: uint192(0) // TODO: Restore after fee modeling will be stable. (SMA-1230) - }) - ); + if (s.priorityTree.startIndex > s.priorityQueue.getFirstUnprocessedPriorityTx()) { + s.priorityQueue.pushBack( + PriorityOperation({ + canonicalTxHash: _canonicalTxHash, + expirationTimestamp: _expirationTimestamp, + layer2Tip: uint192(0) // TODO: Restore after fee modeling will be stable. (SMA-1230) + }) + ); + } + s.priorityTree.push(_canonicalTxHash); // Data that is needed for the operator to simulate priority queue offchain // solhint-disable-next-line func-named-parameters diff --git a/l1-contracts/contracts/state-transition/chain-interfaces/IExecutor.sol b/l1-contracts/contracts/state-transition/chain-interfaces/IExecutor.sol index f08acf7be..c50e900f9 100644 --- a/l1-contracts/contracts/state-transition/chain-interfaces/IExecutor.sol +++ b/l1-contracts/contracts/state-transition/chain-interfaces/IExecutor.sol @@ -3,6 +3,7 @@ pragma solidity 0.8.24; import {IZkSyncHyperchainBase} from "./IZkSyncHyperchainBase.sol"; +import {PriorityOpsBatchInfo} from "../libraries/PriorityTree.sol"; /// @dev Enum used by L2 System Contracts to differentiate logs. enum SystemLogKey { @@ -183,10 +184,18 @@ interface IExecutor is IZkSyncHyperchainBase { /// - Processing all pending operations (commpleting priority requests). /// - Finalizing this batch (i.e. allowing to withdraw funds from the system) /// @param _batchesData Data of the batches to be executed. - function executeBatches(StoredBatchInfo[] calldata _batchesData) external; + /// @param _priorityOpsData Merkle proofs of the priority operations for each batch. + function executeBatches( + StoredBatchInfo[] calldata _batchesData, + PriorityOpsBatchInfo[] calldata _priorityOpsData + ) external; /// @notice same as `executeBatches` but with the chainId so ValidatorTimelock can sort the inputs. - function executeBatchesSharedBridge(uint256 _chainId, StoredBatchInfo[] calldata _batchesData) external; + function executeBatchesSharedBridge( + uint256 _chainId, + StoredBatchInfo[] calldata _batchesData, + PriorityOpsBatchInfo[] calldata _priorityOpsData + ) external; /// @notice Reverts unexecuted batches /// @param _newLastBatch batch number after which batches should be reverted diff --git a/l1-contracts/contracts/state-transition/chain-interfaces/IGetters.sol b/l1-contracts/contracts/state-transition/chain-interfaces/IGetters.sol index ad19761db..38b328452 100644 --- a/l1-contracts/contracts/state-transition/chain-interfaces/IGetters.sol +++ b/l1-contracts/contracts/state-transition/chain-interfaces/IGetters.sol @@ -51,6 +51,9 @@ interface IGetters is IZkSyncHyperchainBase { /// @return The total number of priority operations that were added to the priority queue, including all processed ones function getTotalPriorityTxs() external view returns (uint256); + /// @return The root hash of the priority tree + function getPriorityTreeRoot() external view returns (bytes32); + /// @notice The function that returns the first unprocessed priority transaction. /// @dev Returns zero if and only if no operations were processed from the queue. /// @dev If all the transactions were processed, it will return the last processed index, so @@ -61,7 +64,8 @@ interface IGetters is IZkSyncHyperchainBase { /// @return The number of priority operations currently in the queue function getPriorityQueueSize() external view returns (uint256); - /// @return The first unprocessed priority operation from the queue + /// @notice This function is deprecated and will return an empty priority operation. + /// @return Empty priority operation function priorityQueueFrontOperation() external view returns (PriorityOperation memory); /// @return Whether the address has a validator access diff --git a/l1-contracts/contracts/state-transition/libraries/PriorityTree.sol b/l1-contracts/contracts/state-transition/libraries/PriorityTree.sol new file mode 100644 index 000000000..3b29b7bb1 --- /dev/null +++ b/l1-contracts/contracts/state-transition/libraries/PriorityTree.sol @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.24; + +// solhint-disable gas-custom-errors + +import {DynamicIncrementalMerkle} from "../../common/libraries/DynamicIncrementalMerkle.sol"; +import {Merkle} from "../../common/libraries/Merkle.sol"; +import {PriorityTreeCommitment} from "../../common/Config.sol"; + +struct PriorityOpsBatchInfo { + bytes32[] leftPath; + bytes32[] rightPath; + bytes32[] itemHashes; +} + +bytes32 constant ZERO_LEAF_HASH = keccak256(""); + +library PriorityTree { + using PriorityTree for Tree; + using DynamicIncrementalMerkle for DynamicIncrementalMerkle.Bytes32PushTree; + + struct Tree { + uint256 startIndex; // priority tree started accepting priority ops from this index + uint256 unprocessedIndex; // relative to `startIndex` + mapping(bytes32 => bool) historicalRoots; + DynamicIncrementalMerkle.Bytes32PushTree tree; + } + + /// @notice Returns zero if and only if no operations were processed from the queue + /// @return Index of the oldest priority operation that wasn't processed yet + function getFirstUnprocessedPriorityTx(Tree storage _tree) internal view returns (uint256) { + return _tree.startIndex + _tree.unprocessedIndex; + } + + /// @return The total number of priority operations that were added to the priority queue, including all processed ones + function getTotalPriorityTxs(Tree storage _tree) internal view returns (uint256) { + return _tree.startIndex + _tree.tree._nextLeafIndex; + } + + /// @return The total number of unprocessed priority operations in a priority queue + function getSize(Tree storage _tree) internal view returns (uint256) { + return uint256(_tree.tree._nextLeafIndex - _tree.unprocessedIndex); + } + + /// @notice Add the priority operation to the end of the priority queue + function push(Tree storage _tree, bytes32 _hash) internal { + (, bytes32 newRoot) = _tree.tree.push(_hash); + _tree.historicalRoots[newRoot] = true; + } + + function setup(Tree storage _tree, uint256 _startIndex) internal { + _tree.tree.setup(ZERO_LEAF_HASH); + _tree.startIndex = _startIndex; + } + + function getRoot(Tree storage _tree) internal view returns (bytes32) { + return _tree.tree.root(); + } + + function processBatch(Tree storage _tree, PriorityOpsBatchInfo calldata _priorityOpsData) internal { + if (_priorityOpsData.itemHashes.length > 0) { + bytes32 expectedRoot = Merkle.calculateRoot( + _priorityOpsData.leftPath, + _priorityOpsData.rightPath, + _tree.unprocessedIndex, + _priorityOpsData.itemHashes + ); + require(_tree.historicalRoots[expectedRoot], "PT: root mismatch"); + _tree.unprocessedIndex += _priorityOpsData.itemHashes.length; + } + } + + function initFromCommitment(Tree storage _tree, PriorityTreeCommitment memory _commitment) internal { + uint256 height = _commitment.sides.length; // Height, including the root node. + require(height > 0, "PT: invalid commitment"); + _tree.startIndex = _commitment.startIndex; + _tree.unprocessedIndex = _commitment.unprocessedIndex; + _tree.tree._nextLeafIndex = _commitment.nextLeafIndex; + _tree.tree._sides = _commitment.sides; + bytes32 zero = ZERO_LEAF_HASH; + _tree.tree._zeros = new bytes32[](height); + for (uint256 i; i < height; ++i) { + _tree.tree._zeros[i] = zero; + zero = Merkle.efficientHash(zero, zero); + } + _tree.historicalRoots[_tree.tree.root()] = true; + } + + function getCommitment(Tree storage _tree) internal view returns (PriorityTreeCommitment memory commitment) { + commitment.nextLeafIndex = _tree.tree._nextLeafIndex; + commitment.startIndex = _tree.startIndex; + commitment.unprocessedIndex = _tree.unprocessedIndex; + commitment.sides = _tree.tree._sides; + } +} diff --git a/l1-contracts/scripts/revert-reason.ts b/l1-contracts/scripts/revert-reason.ts index 2816f282b..713587bc0 100644 --- a/l1-contracts/scripts/revert-reason.ts +++ b/l1-contracts/scripts/revert-reason.ts @@ -7,10 +7,18 @@ import { Interface } from "ethers/lib/utils"; import { web3Url } from "./utils"; const erc20BridgeInterface = new Interface(hardhat.artifacts.readArtifactSync("L1ERC20Bridge").abi); -const zkSyncInterface = new Interface(hardhat.artifacts.readArtifactSync("IZkSync").abi); +const zkSyncInterface = new Interface(hardhat.artifacts.readArtifactSync("IZkSyncHyperchain").abi); const verifierInterface = new Interface(hardhat.artifacts.readArtifactSync("Verifier").abi); - -const interfaces = [erc20BridgeInterface, zkSyncInterface, verifierInterface]; +const bridgehubInterface = new Interface(hardhat.artifacts.readArtifactSync("Bridgehub").abi); +const sharedBridgeInterface = new Interface(hardhat.artifacts.readArtifactSync("L1SharedBridge").abi); + +const interfaces = [ + erc20BridgeInterface, + zkSyncInterface, + verifierInterface, + bridgehubInterface, + sharedBridgeInterface, +]; function decodeTransaction(contractInterface, tx) { try { diff --git a/l1-contracts/src.ts/utils.ts b/l1-contracts/src.ts/utils.ts index b43b478b4..06b4d8b93 100644 --- a/l1-contracts/src.ts/utils.ts +++ b/l1-contracts/src.ts/utils.ts @@ -39,7 +39,7 @@ export const DIAMOND_CUT_DATA_ABI_STRING = export const FORCE_DEPLOYMENT_ABI_STRING = "tuple(bytes32 bytecodeHash, address newAddress, bool callConstructor, uint256 value, bytes input)[]"; export const HYPERCHAIN_COMMITMENT_ABI_STRING = - "tuple(uint256 totalBatchesExecuted, uint256 totalBatchesVerified, uint256 totalBatchesCommitted, uint256 priorityQueueHead, tuple(bytes32 canonicalTxHash, uint64 expirationTimestamp, uint192 layer2Tip)[] priorityQueueTxs, bytes32 l2SystemContractsUpgradeTxHash, uint256 l2SystemContractsUpgradeBatchNumber, bytes32[] batchHashes)"; + "tuple(uint256 totalBatchesExecuted, uint256 totalBatchesVerified, uint256 totalBatchesCommitted, bytes32 l2SystemContractsUpgradeTxHash, uint256 l2SystemContractsUpgradeBatchNumber, bytes32[] batchHashes, tuple(uint256 nextLeafIndex, uint256 startIndex, uint256 unprocessedIndex, bytes32[] sides) priorityTree)"; export function applyL1ToL2Alias(address: string): string { return ethers.utils.hexlify(ethers.BigNumber.from(address).add(L1_TO_L2_ALIAS_OFFSET).mod(ADDRESS_MODULO)); diff --git a/l1-contracts/test/foundry/unit/concrete/Executor/Authorization.t.sol b/l1-contracts/test/foundry/unit/concrete/Executor/Authorization.t.sol index c711a9527..6d2b59c75 100644 --- a/l1-contracts/test/foundry/unit/concrete/Executor/Authorization.t.sol +++ b/l1-contracts/test/foundry/unit/concrete/Executor/Authorization.t.sol @@ -64,6 +64,6 @@ contract AuthorizationTest is ExecutorTest { vm.prank(randomSigner); vm.expectRevert(bytes.concat("Hyperchain: not validator")); - executor.executeBatches(storedBatchInfoArray); + executor.executeBatches(storedBatchInfoArray, Utils.emptyData()); } } diff --git a/l1-contracts/test/foundry/unit/concrete/Executor/Executing.t.sol b/l1-contracts/test/foundry/unit/concrete/Executor/Executing.t.sol index 3360150d5..cc7c14565 100644 --- a/l1-contracts/test/foundry/unit/concrete/Executor/Executing.t.sol +++ b/l1-contracts/test/foundry/unit/concrete/Executor/Executing.t.sol @@ -12,6 +12,8 @@ import {IExecutor, SystemLogKey} from "contracts/state-transition/chain-interfac contract ExecutingTest is ExecutorTest { function setUp() public { + // This currently only uses the legacy priority queue, not the priority tree. + executor.setPriorityTreeStartIndex(100); vm.warp(COMMIT_TIMESTAMP_NOT_OLDER + 1); currentTimestamp = block.timestamp; @@ -63,7 +65,7 @@ contract ExecutingTest is ExecutorTest { vm.prank(validator); vm.expectRevert(bytes.concat("k")); - executor.executeBatches(storedBatchInfoArray); + executor.executeBatches(storedBatchInfoArray, Utils.emptyData()); } function test_RevertWhen_ExecutingBlockWithWrongData() public { @@ -75,7 +77,7 @@ contract ExecutingTest is ExecutorTest { vm.prank(validator); vm.expectRevert(bytes.concat("exe10")); - executor.executeBatches(storedBatchInfoArray); + executor.executeBatches(storedBatchInfoArray, Utils.emptyData()); } function test_RevertWhen_ExecutingRevertedBlockWithoutCommittingAndProvingAgain() public { @@ -87,7 +89,7 @@ contract ExecutingTest is ExecutorTest { vm.prank(validator); vm.expectRevert(bytes.concat("n")); - executor.executeBatches(storedBatchInfoArray); + executor.executeBatches(storedBatchInfoArray, Utils.emptyData()); } function test_RevertWhen_ExecutingUnavailablePriorityOperationHash() public { @@ -144,7 +146,7 @@ contract ExecutingTest is ExecutorTest { vm.prank(validator); vm.expectRevert(bytes.concat("s")); - executor.executeBatches(correctNewStoredBatchInfoArray); + executor.executeBatches(correctNewStoredBatchInfoArray, Utils.emptyData()); } function test_RevertWhen_ExecutingWithUnmatchedPriorityOperationHash() public { @@ -221,7 +223,7 @@ contract ExecutingTest is ExecutorTest { vm.prank(validator); vm.expectRevert(bytes.concat("x")); - executor.executeBatches(correctNewStoredBatchInfoArray); + executor.executeBatches(correctNewStoredBatchInfoArray, Utils.emptyData()); } function test_RevertWhen_CommittingBlockWithWrongPreviousBatchHash() public { @@ -255,7 +257,7 @@ contract ExecutingTest is ExecutorTest { storedBatchInfoArray[0] = newStoredBatchInfo; vm.prank(validator); - executor.executeBatches(storedBatchInfoArray); + executor.executeBatches(storedBatchInfoArray, Utils.emptyData()); uint256 totalBlocksExecuted = getters.getTotalBlocksExecuted(); assertEq(totalBlocksExecuted, 1); diff --git a/l1-contracts/test/foundry/unit/concrete/Executor/_Executor_Shared.t.sol b/l1-contracts/test/foundry/unit/concrete/Executor/_Executor_Shared.t.sol index b345c1fd3..310377a16 100644 --- a/l1-contracts/test/foundry/unit/concrete/Executor/_Executor_Shared.t.sol +++ b/l1-contracts/test/foundry/unit/concrete/Executor/_Executor_Shared.t.sol @@ -65,11 +65,12 @@ contract ExecutorTest is Test { } function getExecutorSelectors() private view returns (bytes4[] memory) { - bytes4[] memory selectors = new bytes4[](4); + bytes4[] memory selectors = new bytes4[](5); selectors[0] = executor.commitBatches.selector; selectors[1] = executor.proveBatches.selector; selectors[2] = executor.executeBatches.selector; selectors[3] = executor.revertBatches.selector; + selectors[4] = executor.setPriorityTreeStartIndex.selector; return selectors; } diff --git a/l1-contracts/test/foundry/unit/concrete/Utils/Utils.sol b/l1-contracts/test/foundry/unit/concrete/Utils/Utils.sol index 56175da6f..7dfd66f18 100644 --- a/l1-contracts/test/foundry/unit/concrete/Utils/Utils.sol +++ b/l1-contracts/test/foundry/unit/concrete/Utils/Utils.sol @@ -17,6 +17,7 @@ import {InitializeData, InitializeDataNewChain} from "contracts/state-transition import {IExecutor, SystemLogKey} from "contracts/state-transition/chain-interfaces/IExecutor.sol"; import {L2CanonicalTransaction} from "contracts/common/Messaging.sol"; import {DummyBridgehub} from "contracts/dev-contracts/test/DummyBridgehub.sol"; +import {PriorityOpsBatchInfo} from "contracts/state-transition/libraries/PriorityTree.sol"; bytes32 constant DEFAULT_L2_LOGS_TREE_ROOT_HASH = 0x0000000000000000000000000000000000000000000000000000000000000000; address constant L2_SYSTEM_CONTEXT_ADDRESS = 0x000000000000000000000000000000000000800B; @@ -482,6 +483,13 @@ library Utils { } } + function emptyData() internal pure returns (PriorityOpsBatchInfo[] calldata _empty) { + assembly { + _empty.offset := 0 + _empty.length := 0 + } + } + // add this to be excluded from coverage report function test() internal {} } diff --git a/l1-contracts/test/foundry/unit/concrete/ValidatorTimelock/ValidatorTimelock.t.sol b/l1-contracts/test/foundry/unit/concrete/ValidatorTimelock/ValidatorTimelock.t.sol index dacc45160..8cfce5dcb 100644 --- a/l1-contracts/test/foundry/unit/concrete/ValidatorTimelock/ValidatorTimelock.t.sol +++ b/l1-contracts/test/foundry/unit/concrete/ValidatorTimelock/ValidatorTimelock.t.sol @@ -228,7 +228,7 @@ contract ValidatorTimelockTest is Test { vm.prank(dan); vm.warp(timestamp + executionDelay + 1); - validator.executeBatches(storedBatches); + validator.executeBatches(storedBatches, Utils.emptyData()); } function test_executeBatchesSharedBridge() public { @@ -258,7 +258,7 @@ contract ValidatorTimelockTest is Test { vm.prank(alice); vm.warp(timestamp + executionDelay + 1); - validator.executeBatchesSharedBridge(chainId, storedBatches); + validator.executeBatchesSharedBridge(chainId, storedBatches, Utils.emptyData()); } function test_RevertWhen_setExecutionDelayNotOwner() public { @@ -361,7 +361,7 @@ contract ValidatorTimelockTest is Test { vm.prank(bob); vm.expectRevert("ValidatorTimelock: only validator"); - validator.executeBatches(storedBatches); + validator.executeBatches(storedBatches, Utils.emptyData()); } function test_RevertWhen_executeBatchesSharedBridgeNotValidator() public { @@ -372,7 +372,7 @@ contract ValidatorTimelockTest is Test { vm.prank(bob); vm.expectRevert("ValidatorTimelock: only validator"); - validator.executeBatchesSharedBridge(chainId, storedBatches); + validator.executeBatchesSharedBridge(chainId, storedBatches, Utils.emptyData()); } function test_RevertWhen_executeBatchesTooEarly() public { @@ -401,7 +401,7 @@ contract ValidatorTimelockTest is Test { vm.prank(dan); vm.warp(timestamp + executionDelay - 1); vm.expectRevert(bytes("5c")); - validator.executeBatches(storedBatches); + validator.executeBatches(storedBatches, Utils.emptyData()); } function test_RevertWhen_executeBatchesSharedBridgeTooEarly() public { @@ -430,6 +430,6 @@ contract ValidatorTimelockTest is Test { vm.prank(alice); vm.warp(timestamp + executionDelay - 1); vm.expectRevert(bytes("5c")); - validator.executeBatchesSharedBridge(chainId, storedBatches); + validator.executeBatchesSharedBridge(chainId, storedBatches, Utils.emptyData()); } } diff --git a/l1-contracts/test/foundry/unit/concrete/common/libraries/Merkle/Merkle.t.sol b/l1-contracts/test/foundry/unit/concrete/common/libraries/Merkle/Merkle.t.sol index 492d489c2..b6e6f3f84 100644 --- a/l1-contracts/test/foundry/unit/concrete/common/libraries/Merkle/Merkle.t.sol +++ b/l1-contracts/test/foundry/unit/concrete/common/libraries/Merkle/Merkle.t.sol @@ -7,12 +7,14 @@ import {MerkleTreeNoSort} from "./MerkleTreeNoSort.sol"; contract MerkleTestTest is Test { MerkleTreeNoSort merkleTree; + MerkleTreeNoSort smallMerkleTree; MerkleTest merkleTest; bytes32[] elements; bytes32 root; function setUp() public { merkleTree = new MerkleTreeNoSort(); + smallMerkleTree = new MerkleTreeNoSort(); merkleTest = new MerkleTest(); for (uint256 i = 0; i < 65; i++) { @@ -32,6 +34,20 @@ contract MerkleTestTest is Test { assertEq(rootFromContract, root); } + function prepareRangeProof( + uint256 start, + uint256 end + ) public returns (bytes32[] memory, bytes32[] memory, bytes32[] memory) { + bytes32[] memory left = merkleTree.getProof(elements, start); + bytes32[] memory right = merkleTree.getProof(elements, end); + bytes32[] memory leaves = new bytes32[](end - start + 1); + for (uint256 i = start; i <= end; ++i) { + leaves[i - start] = elements[i]; + } + + return (left, right, leaves); + } + function testFirstElement() public { testElements(0); } @@ -63,4 +79,62 @@ contract MerkleTestTest is Test { vm.expectRevert(bytes("bt")); merkleTest.calculateRoot(proof, 0, leaf); } + + function testRangeProof() public { + (bytes32[] memory left, bytes32[] memory right, bytes32[] memory leaves) = prepareRangeProof(10, 13); + bytes32 rootFromContract = merkleTest.calculateRoot(left, right, 10, leaves); + assertEq(rootFromContract, root); + } + + function testRangeProofIncorrect() public { + (bytes32[] memory left, bytes32[] memory right, bytes32[] memory leaves) = prepareRangeProof(10, 13); + bytes32 rootFromContract = merkleTest.calculateRoot(left, right, 9, leaves); + assertNotEq(rootFromContract, root); + } + + function testRangeProofLengthMismatch_shouldRevert() public { + (, bytes32[] memory right, bytes32[] memory leaves) = prepareRangeProof(10, 13); + bytes32[] memory leftShortened = new bytes32[](right.length - 1); + + vm.expectRevert(bytes("Merkle: path length mismatch")); + merkleTest.calculateRoot(leftShortened, right, 10, leaves); + } + + function testRangeProofEmptyPaths_shouldRevert() public { + (, , bytes32[] memory leaves) = prepareRangeProof(10, 13); + bytes32[] memory left; + bytes32[] memory right; + + vm.expectRevert(bytes("Merkle: empty paths")); + merkleTest.calculateRoot(left, right, 10, leaves); + } + + function testRangeProofWrongIndex_shouldRevert() public { + (bytes32[] memory left, bytes32[] memory right, bytes32[] memory leaves) = prepareRangeProof(10, 13); + vm.expectRevert(bytes("Merkle: index/height mismatch")); + merkleTest.calculateRoot(left, right, 128, leaves); + } + + function testRangeProofSingleLeaf() public { + (bytes32[] memory left, bytes32[] memory right, bytes32[] memory leaves) = prepareRangeProof(10, 10); + bytes32 rootFromContract = merkleTest.calculateRoot(left, right, 10, leaves); + assertEq(rootFromContract, root); + } + + function testRangeProofEmpty_shouldRevert() public { + bytes32[] memory left = merkleTree.getProof(elements, 10); + bytes32[] memory right = merkleTree.getProof(elements, 10); + bytes32[] memory leaves; + vm.expectRevert(bytes("Merkle: nothing to prove")); + merkleTest.calculateRoot(left, right, 10, leaves); + } + + function testRangeProofSingleElementTree() public { + bytes32[] memory leaves = new bytes32[](1); + leaves[0] = elements[10]; + bytes32[] memory left = new bytes32[](0); + bytes32[] memory right = new bytes32[](0); + bytes32 rootFromContract = merkleTest.calculateRoot(left, right, 0, leaves); + assertEq(rootFromContract, leaves[0]); + } } diff --git a/l1-contracts/test/foundry/unit/concrete/state-transition/chain-deps/facets/Getters/PriorityQueueFrontOperation.t.sol b/l1-contracts/test/foundry/unit/concrete/state-transition/chain-deps/facets/Getters/PriorityQueueFrontOperation.t.sol index d17577afc..91e23f2f3 100644 --- a/l1-contracts/test/foundry/unit/concrete/state-transition/chain-deps/facets/Getters/PriorityQueueFrontOperation.t.sol +++ b/l1-contracts/test/foundry/unit/concrete/state-transition/chain-deps/facets/Getters/PriorityQueueFrontOperation.t.sol @@ -6,24 +6,11 @@ import {GettersFacetTest} from "./_Getters_Shared.t.sol"; import {PriorityOperation} from "contracts/state-transition/libraries/PriorityQueue.sol"; contract GetPriorityQueueFrontOperationTest is GettersFacetTest { - function test_revertWhen_queueIsEmpty() public { - vm.expectRevert(bytes.concat("D")); - gettersFacet.priorityQueueFrontOperation(); - } - - function test() public { - PriorityOperation memory expected = PriorityOperation({ - canonicalTxHash: bytes32(uint256(1)), - expirationTimestamp: uint64(2), - layer2Tip: uint192(3) - }); - - gettersFacetWrapper.util_setPriorityQueueFrontOperation(expected); - + function test_empty() public { PriorityOperation memory received = gettersFacet.priorityQueueFrontOperation(); - bytes32 expectedHash = keccak256(abi.encode(expected)); - bytes32 receivedHash = keccak256(abi.encode(received)); - assertEq(expectedHash, receivedHash, "Priority queue front operation is incorrect"); + assertEq(received.canonicalTxHash, bytes32(0), "Priority queue front operation is incorrect"); + assertEq(received.layer2Tip, 0, "Priority queue front operation is incorrect"); + assertEq(received.expirationTimestamp, 0, "Priority queue front operation is incorrect"); } } diff --git a/l1-contracts/test/foundry/unit/concrete/state-transition/chain-deps/facets/Getters/_Getters_Shared.t.sol b/l1-contracts/test/foundry/unit/concrete/state-transition/chain-deps/facets/Getters/_Getters_Shared.t.sol index 1d64711fe..d06088b5f 100644 --- a/l1-contracts/test/foundry/unit/concrete/state-transition/chain-deps/facets/Getters/_Getters_Shared.t.sol +++ b/l1-contracts/test/foundry/unit/concrete/state-transition/chain-deps/facets/Getters/_Getters_Shared.t.sol @@ -53,21 +53,18 @@ contract GettersFacetWrapper is GettersFacet { } function util_setTotalPriorityTxs(uint256 _totalPriorityTxs) external { - s.priorityQueue.tail = _totalPriorityTxs; + s.priorityTree.startIndex = 0; + s.priorityTree.tree._nextLeafIndex = _totalPriorityTxs; } function util_setFirstUnprocessedPriorityTx(uint256 _firstUnprocessedPriorityTx) external { - s.priorityQueue.head = _firstUnprocessedPriorityTx; + s.priorityTree.startIndex = 0; + s.priorityTree.unprocessedIndex = _firstUnprocessedPriorityTx; } function util_setPriorityQueueSize(uint256 _priorityQueueSize) external { - s.priorityQueue.head = 0; - s.priorityQueue.tail = _priorityQueueSize; - } - - function util_setPriorityQueueFrontOperation(PriorityOperation memory _priorityQueueFrontOperation) external { - s.priorityQueue.data[s.priorityQueue.head] = _priorityQueueFrontOperation; - s.priorityQueue.tail = s.priorityQueue.head + 1; + s.priorityTree.unprocessedIndex = 1; + s.priorityTree.tree._nextLeafIndex = _priorityQueueSize + 1; } function util_setValidator(address _validator, bool _status) external { diff --git a/l1-contracts/test/foundry/unit/concrete/state-transition/chain-deps/facets/Mailbox/BridgehubRequestL2Transaction.t.sol b/l1-contracts/test/foundry/unit/concrete/state-transition/chain-deps/facets/Mailbox/BridgehubRequestL2Transaction.t.sol index d34a6bd7d..d249918f3 100644 --- a/l1-contracts/test/foundry/unit/concrete/state-transition/chain-deps/facets/Mailbox/BridgehubRequestL2Transaction.t.sol +++ b/l1-contracts/test/foundry/unit/concrete/state-transition/chain-deps/facets/Mailbox/BridgehubRequestL2Transaction.t.sol @@ -74,4 +74,25 @@ contract BridgehubRequestL2TransactionTest is MailboxTest { refundRecipient: sender }); } + + function test_priorityTreeRootChange() public { + bytes32 oldRootHash = gettersFacet.getPriorityTreeRoot(); + assertEq(oldRootHash, bytes32(0), "root hash should be 0"); + + address bridgehub = makeAddr("bridgehub"); + + utilsFacet.util_setBridgehub(bridgehub); + utilsFacet.util_setBaseTokenGasPriceMultiplierDenominator(1); + utilsFacet.util_setPriorityTxMaxGasLimit(100000000); + + BridgehubL2TransactionRequest memory req = getBridgehubRequestL2TransactionRequest(); + + vm.deal(bridgehub, 100 ether); + vm.prank(address(bridgehub)); + bytes32 canonicalTxHash = mailboxFacet.bridgehubRequestL2Transaction(req); + assertTrue(canonicalTxHash != bytes32(0), "canonicalTxHash should not be 0"); + + bytes32 newRootHash = gettersFacet.getPriorityTreeRoot(); + assertEq(canonicalTxHash, newRootHash, "root hash should have changed"); + } } diff --git a/l1-contracts/test/foundry/unit/concrete/state-transition/chain-deps/facets/Mailbox/_Mailbox_Shared.t.sol b/l1-contracts/test/foundry/unit/concrete/state-transition/chain-deps/facets/Mailbox/_Mailbox_Shared.t.sol index 03ab74a8d..00e558495 100644 --- a/l1-contracts/test/foundry/unit/concrete/state-transition/chain-deps/facets/Mailbox/_Mailbox_Shared.t.sol +++ b/l1-contracts/test/foundry/unit/concrete/state-transition/chain-deps/facets/Mailbox/_Mailbox_Shared.t.sol @@ -7,12 +7,15 @@ import {Utils} from "foundry-test/unit/concrete/Utils/Utils.sol"; import {UtilsFacet} from "foundry-test/unit/concrete/Utils/UtilsFacet.sol"; import {MailboxFacet} from "contracts/state-transition/chain-deps/facets/Mailbox.sol"; +import {GettersFacet} from "contracts/state-transition/chain-deps/facets/Getters.sol"; import {Diamond} from "contracts/state-transition/libraries/Diamond.sol"; import {IMailbox} from "contracts/state-transition/chain-interfaces/IMailbox.sol"; +import {IGetters} from "contracts/state-transition/chain-interfaces/IGetters.sol"; import {TestnetVerifier} from "contracts/state-transition/TestnetVerifier.sol"; contract MailboxTest is Test { IMailbox internal mailboxFacet; + IGetters internal gettersFacet; UtilsFacet internal utilsFacet; address sender; uint256 eraChainId = 9; @@ -24,11 +27,17 @@ contract MailboxTest is Test { return selectors; } + function getGettersSelectors() public pure returns (bytes4[] memory) { + bytes4[] memory selectors = new bytes4[](1); + selectors[0] = IGetters.getPriorityTreeRoot.selector; + return selectors; + } + function setUp() public virtual { sender = makeAddr("sender"); vm.deal(sender, 100 ether); - Diamond.FacetCut[] memory facetCuts = new Diamond.FacetCut[](2); + Diamond.FacetCut[] memory facetCuts = new Diamond.FacetCut[](3); facetCuts[0] = Diamond.FacetCut({ facet: address(new MailboxFacet(eraChainId)), action: Diamond.Action.Add, @@ -41,10 +50,17 @@ contract MailboxTest is Test { isFreezable: true, selectors: Utils.getUtilsFacetSelectors() }); + facetCuts[2] = Diamond.FacetCut({ + facet: address(new GettersFacet()), + action: Diamond.Action.Add, + isFreezable: true, + selectors: getGettersSelectors() + }); address diamondProxy = Utils.makeDiamondProxy(facetCuts, testnetVerifier); mailboxFacet = IMailbox(diamondProxy); utilsFacet = UtilsFacet(diamondProxy); + gettersFacet = IGetters(diamondProxy); } // add this to be excluded from coverage report diff --git a/l1-contracts/test/foundry/unit/concrete/state-transition/libraries/PriorityTree/PriorityTree.t.sol b/l1-contracts/test/foundry/unit/concrete/state-transition/libraries/PriorityTree/PriorityTree.t.sol new file mode 100644 index 000000000..447e4e47d --- /dev/null +++ b/l1-contracts/test/foundry/unit/concrete/state-transition/libraries/PriorityTree/PriorityTree.t.sol @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.24; + +import {PriorityTreeSharedTest, PriorityOpsBatchInfo} from "./_PriorityTree_Shared.t.sol"; +import {PriorityTreeCommitment} from "contracts/common/Config.sol"; + +bytes32 constant ZERO_LEAF_HASH = keccak256(""); + +contract PriorityTreeTest is PriorityTreeSharedTest { + function test_gets() public { + assertEq(0, priorityTree.getSize()); + assertEq(0, priorityTree.getFirstUnprocessedPriorityTx()); + assertEq(0, priorityTree.getTotalPriorityTxs()); + assertEq(bytes32(0), priorityTree.getRoot()); + } + + function test_push() public { + bytes32 leaf1 = keccak256(abi.encode(1)); + bytes32 leaf2 = keccak256(abi.encode(2)); + + priorityTree.push(leaf1); + + assertEq(1, priorityTree.getSize()); + assertEq(0, priorityTree.getFirstUnprocessedPriorityTx()); + assertEq(1, priorityTree.getTotalPriorityTxs()); + assertEq(leaf1, priorityTree.getRoot()); + + priorityTree.push(leaf2); + + assertEq(2, priorityTree.getSize()); + assertEq(0, priorityTree.getFirstUnprocessedPriorityTx()); + assertEq(2, priorityTree.getTotalPriorityTxs()); + + bytes32 expectedRoot = keccak256(abi.encode(leaf1, leaf2)); + assertEq(expectedRoot, priorityTree.getRoot()); + } + + function test_processEmptyBatch() public { + pushMockEntries(3); + + assertEq(0, priorityTree.getFirstUnprocessedPriorityTx()); + priorityTree.processBatch( + PriorityOpsBatchInfo({ + leftPath: new bytes32[](0), + rightPath: new bytes32[](0), + itemHashes: new bytes32[](0) + }) + ); + + assertEq(0, priorityTree.getFirstUnprocessedPriorityTx()); + } + + function test_processBatch() public { + bytes32[] memory leaves = pushMockEntries(3); + assertEq(0, priorityTree.getFirstUnprocessedPriorityTx()); + + // 2 batches with: 1 tx, 2 txs. + + bytes32[] memory leftPath = new bytes32[](2); + bytes32[] memory rightPath = new bytes32[](2); + rightPath[0] = leaves[1]; + rightPath[1] = keccak256(abi.encode(leaves[2], ZERO_LEAF_HASH)); + bytes32[] memory batch1 = new bytes32[](1); + batch1[0] = leaves[0]; + + priorityTree.processBatch(PriorityOpsBatchInfo({leftPath: leftPath, rightPath: rightPath, itemHashes: batch1})); + + assertEq(1, priorityTree.getFirstUnprocessedPriorityTx()); + + leftPath[0] = leaves[0]; + rightPath[0] = ZERO_LEAF_HASH; + rightPath[1] = bytes32(0); + bytes32[] memory batch2 = new bytes32[](2); + batch2[0] = leaves[1]; + batch2[1] = leaves[2]; + + priorityTree.processBatch(PriorityOpsBatchInfo({leftPath: leftPath, rightPath: rightPath, itemHashes: batch2})); + + assertEq(3, priorityTree.getFirstUnprocessedPriorityTx()); + } + + function test_processBatch_shouldRevert() public { + bytes32[] memory itemHashes = pushMockEntries(3); + + vm.expectRevert("PT: root mismatch"); + priorityTree.processBatch( + PriorityOpsBatchInfo({leftPath: new bytes32[](2), rightPath: new bytes32[](2), itemHashes: itemHashes}) + ); + } + + function test_commitDecommit() public { + pushMockEntries(3); + bytes32 root = priorityTree.getRoot(); + + PriorityTreeCommitment memory commitment = priorityTree.getCommitment(); + priorityTree.initFromCommitment(commitment); + + assertEq(0, priorityTree.getFirstUnprocessedPriorityTx()); + assertEq(3, priorityTree.getTotalPriorityTxs()); + assertEq(root, priorityTree.getRoot()); + assertEq(ZERO_LEAF_HASH, priorityTree.getZero()); + } +} diff --git a/l1-contracts/test/foundry/unit/concrete/state-transition/libraries/PriorityTree/_PriorityTree_Shared.t.sol b/l1-contracts/test/foundry/unit/concrete/state-transition/libraries/PriorityTree/_PriorityTree_Shared.t.sol new file mode 100644 index 000000000..0a39e74d1 --- /dev/null +++ b/l1-contracts/test/foundry/unit/concrete/state-transition/libraries/PriorityTree/_PriorityTree_Shared.t.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.24; + +import {Test} from "forge-std/Test.sol"; +import {PriorityTreeTest, PriorityOpsBatchInfo} from "contracts/dev-contracts/test/PriorityTreeTest.sol"; + +contract PriorityTreeSharedTest is Test { + PriorityTreeTest internal priorityTree; + + constructor() { + priorityTree = new PriorityTreeTest(); + } + + // Pushes 'count' entries into the priority tree. + function pushMockEntries(uint256 count) public returns (bytes32[] memory) { + bytes32[] memory hashes = new bytes32[](count); + for (uint256 i = 0; i < count; ++i) { + bytes32 hash = keccak256(abi.encode(i)); + hashes[i] = hash; + priorityTree.push(hash); + } + return hashes; + } + + // add this to be excluded from coverage report + function test() internal virtual {} +} diff --git a/l1-contracts/test/unit_tests/utils.ts b/l1-contracts/test/unit_tests/utils.ts index 8fa3abe41..687e49222 100644 --- a/l1-contracts/test/unit_tests/utils.ts +++ b/l1-contracts/test/unit_tests/utils.ts @@ -548,7 +548,8 @@ export async function makeExecutedEqualCommitted( }) ).wait(); - await (await proxyExecutor.executeBatches(batchesToExecute)).wait(); + const dummyMerkleProofs = batchesToExecute.map(() => ({ leftPath: [], rightPath: [], itemHashes: [] })); + await (await proxyExecutor.executeBatches(batchesToExecute, dummyMerkleProofs)).wait(); } export function getBatchStoredInfo(commitInfo: CommitBatchInfo, commitment: string): StoredBatchInfo { diff --git a/l1-contracts/test/unit_tests/validator_timelock_test.spec.ts b/l1-contracts/test/unit_tests/validator_timelock_test.spec.ts index 5ef3cb491..3b66c0f2c 100644 --- a/l1-contracts/test/unit_tests/validator_timelock_test.spec.ts +++ b/l1-contracts/test/unit_tests/validator_timelock_test.spec.ts @@ -111,7 +111,7 @@ describe("ValidatorTimelock tests", function () { it("Should revert if non-validator executes batches", async () => { const revertReason = await getCallRevertReason( - validatorTimelock.connect(randomSigner).executeBatches([getMockStoredBatchInfo(1)]) + validatorTimelock.connect(randomSigner).executeBatches([getMockStoredBatchInfo(1)], []) ); expect(revertReason).equal("ValidatorTimelock: only validator"); @@ -162,7 +162,7 @@ describe("ValidatorTimelock tests", function () { it("Should revert on executing earlier than the delay", async () => { const revertReason = await getCallRevertReason( - validatorTimelock.connect(validator).executeBatchesSharedBridge(chainId, [getMockStoredBatchInfo(1)]) + validatorTimelock.connect(validator).executeBatchesSharedBridge(chainId, [getMockStoredBatchInfo(1)], []) ); expect(revertReason).equal("5c"); @@ -193,7 +193,7 @@ describe("ValidatorTimelock tests", function () { it("Should successfully execute batches after the delay", async () => { await hardhat.network.provider.send("hardhat_mine", ["0x2", "0xc"]); //mine 2 batches with intervals of 12 seconds - await validatorTimelock.connect(validator).executeBatchesSharedBridge(chainId, [getMockStoredBatchInfo(1)]); + await validatorTimelock.connect(validator).executeBatchesSharedBridge(chainId, [getMockStoredBatchInfo(1)], []); expect(await dummyExecutor.getTotalBatchesExecuted()).equal(1); }); @@ -222,7 +222,7 @@ describe("ValidatorTimelock tests", function () { it("Should revert if validator tries to execute more batches than were proven", async () => { await hardhat.network.provider.send("hardhat_mine", ["0x2", "0xc"]); //mine 2 batches with intervals of 12 seconds const revertReason = await getCallRevertReason( - validatorTimelock.connect(validator).executeBatchesSharedBridge(chainId, [getMockStoredBatchInfo(2)]) + validatorTimelock.connect(validator).executeBatchesSharedBridge(chainId, [getMockStoredBatchInfo(2)], []) ); expect(revertReason).equal("DummyExecutor 2: Can"); @@ -265,15 +265,19 @@ describe("ValidatorTimelock tests", function () { await hardhat.network.provider.send("hardhat_mine", ["0x2", "0xc"]); //mine 2 batches with intervals of 12 seconds await validatorTimelock .connect(validator) - .executeBatchesSharedBridge(chainId, [ - getMockStoredBatchInfo(2), - getMockStoredBatchInfo(3), - getMockStoredBatchInfo(4), - getMockStoredBatchInfo(5), - getMockStoredBatchInfo(6), - getMockStoredBatchInfo(7), - getMockStoredBatchInfo(8), - ]); + .executeBatchesSharedBridge( + chainId, + [ + getMockStoredBatchInfo(2), + getMockStoredBatchInfo(3), + getMockStoredBatchInfo(4), + getMockStoredBatchInfo(5), + getMockStoredBatchInfo(6), + getMockStoredBatchInfo(7), + getMockStoredBatchInfo(8), + ], + [] + ); expect(await dummyExecutor.getTotalBatchesExecuted()).equal(8); }); diff --git a/l2-contracts/test/systems-typechain/ContractDeployer.d.ts b/l2-contracts/test/systems-typechain/ContractDeployer.d.ts new file mode 100644 index 000000000..5292a0768 --- /dev/null +++ b/l2-contracts/test/systems-typechain/ContractDeployer.d.ts @@ -0,0 +1,942 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ + +import { ethers, EventFilter, Signer, BigNumber, BigNumberish, PopulatedTransaction } from "ethers"; +import { Contract, ContractTransaction, Overrides, PayableOverrides, CallOverrides } from "@ethersproject/contracts"; +import { BytesLike } from "@ethersproject/bytes"; +import { Listener, Provider } from "@ethersproject/providers"; +import { FunctionFragment, EventFragment, Result } from "@ethersproject/abi"; + +interface ContractDeployerInterface extends ethers.utils.Interface { + functions: { + "create(bytes32,bytes32,bytes)": FunctionFragment; + "create2(bytes32,bytes32,bytes)": FunctionFragment; + "create2Account(bytes32,bytes32,bytes,uint8)": FunctionFragment; + "createAccount(bytes32,bytes32,bytes,uint8)": FunctionFragment; + "extendedAccountVersion(address)": FunctionFragment; + "forceDeployOnAddress(tuple,address)": FunctionFragment; + "forceDeployOnAddresses(tuple[])": FunctionFragment; + "getAccountInfo(address)": FunctionFragment; + "getNewAddressCreate(address,uint256)": FunctionFragment; + "getNewAddressCreate2(address,bytes32,bytes32,bytes)": FunctionFragment; + "updateAccountVersion(uint8)": FunctionFragment; + "updateNonceOrdering(uint8)": FunctionFragment; + }; + + encodeFunctionData(functionFragment: "create", values: [BytesLike, BytesLike, BytesLike]): string; + encodeFunctionData(functionFragment: "create2", values: [BytesLike, BytesLike, BytesLike]): string; + encodeFunctionData( + functionFragment: "create2Account", + values: [BytesLike, BytesLike, BytesLike, BigNumberish] + ): string; + encodeFunctionData( + functionFragment: "createAccount", + values: [BytesLike, BytesLike, BytesLike, BigNumberish] + ): string; + encodeFunctionData(functionFragment: "extendedAccountVersion", values: [string]): string; + encodeFunctionData( + functionFragment: "forceDeployOnAddress", + values: [ + { + bytecodeHash: BytesLike; + newAddress: string; + callConstructor: boolean; + value: BigNumberish; + input: BytesLike; + }, + string, + ] + ): string; + encodeFunctionData( + functionFragment: "forceDeployOnAddresses", + values: [ + { + bytecodeHash: BytesLike; + newAddress: string; + callConstructor: boolean; + value: BigNumberish; + input: BytesLike; + }[], + ] + ): string; + encodeFunctionData(functionFragment: "getAccountInfo", values: [string]): string; + encodeFunctionData(functionFragment: "getNewAddressCreate", values: [string, BigNumberish]): string; + encodeFunctionData( + functionFragment: "getNewAddressCreate2", + values: [string, BytesLike, BytesLike, BytesLike] + ): string; + encodeFunctionData(functionFragment: "updateAccountVersion", values: [BigNumberish]): string; + encodeFunctionData(functionFragment: "updateNonceOrdering", values: [BigNumberish]): string; + + decodeFunctionResult(functionFragment: "create", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "create2", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "create2Account", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "createAccount", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "extendedAccountVersion", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "forceDeployOnAddress", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "forceDeployOnAddresses", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "getAccountInfo", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "getNewAddressCreate", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "getNewAddressCreate2", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "updateAccountVersion", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "updateNonceOrdering", data: BytesLike): Result; + + events: { + "AccountNonceOrderingUpdated(address,uint8)": EventFragment; + "AccountVersionUpdated(address,uint8)": EventFragment; + "ContractDeployed(address,bytes32,address)": EventFragment; + }; + + getEvent(nameOrSignatureOrTopic: "AccountNonceOrderingUpdated"): EventFragment; + getEvent(nameOrSignatureOrTopic: "AccountVersionUpdated"): EventFragment; + getEvent(nameOrSignatureOrTopic: "ContractDeployed"): EventFragment; +} + +export class ContractDeployer extends Contract { + connect(signerOrProvider: Signer | Provider | string): this; + attach(addressOrName: string): this; + deployed(): Promise; + + on(event: EventFilter | string, listener: Listener): this; + once(event: EventFilter | string, listener: Listener): this; + addListener(eventName: EventFilter | string, listener: Listener): this; + removeAllListeners(eventName: EventFilter | string): this; + removeListener(eventName: any, listener: Listener): this; + + interface: ContractDeployerInterface; + + functions: { + create( + _salt: BytesLike, + _bytecodeHash: BytesLike, + _input: BytesLike, + overrides?: PayableOverrides + ): Promise; + + "create(bytes32,bytes32,bytes)"( + _salt: BytesLike, + _bytecodeHash: BytesLike, + _input: BytesLike, + overrides?: PayableOverrides + ): Promise; + + create2( + _salt: BytesLike, + _bytecodeHash: BytesLike, + _input: BytesLike, + overrides?: PayableOverrides + ): Promise; + + "create2(bytes32,bytes32,bytes)"( + _salt: BytesLike, + _bytecodeHash: BytesLike, + _input: BytesLike, + overrides?: PayableOverrides + ): Promise; + + create2Account( + _salt: BytesLike, + _bytecodeHash: BytesLike, + _input: BytesLike, + _aaVersion: BigNumberish, + overrides?: PayableOverrides + ): Promise; + + "create2Account(bytes32,bytes32,bytes,uint8)"( + _salt: BytesLike, + _bytecodeHash: BytesLike, + _input: BytesLike, + _aaVersion: BigNumberish, + overrides?: PayableOverrides + ): Promise; + + createAccount( + arg0: BytesLike, + _bytecodeHash: BytesLike, + _input: BytesLike, + _aaVersion: BigNumberish, + overrides?: PayableOverrides + ): Promise; + + "createAccount(bytes32,bytes32,bytes,uint8)"( + arg0: BytesLike, + _bytecodeHash: BytesLike, + _input: BytesLike, + _aaVersion: BigNumberish, + overrides?: PayableOverrides + ): Promise; + + extendedAccountVersion( + _address: string, + overrides?: CallOverrides + ): Promise<{ + 0: number; + }>; + + "extendedAccountVersion(address)"( + _address: string, + overrides?: CallOverrides + ): Promise<{ + 0: number; + }>; + + forceDeployOnAddress( + _deployment: { + bytecodeHash: BytesLike; + newAddress: string; + callConstructor: boolean; + value: BigNumberish; + input: BytesLike; + }, + _sender: string, + overrides?: PayableOverrides + ): Promise; + + "forceDeployOnAddress((bytes32,address,bool,uint256,bytes),address)"( + _deployment: { + bytecodeHash: BytesLike; + newAddress: string; + callConstructor: boolean; + value: BigNumberish; + input: BytesLike; + }, + _sender: string, + overrides?: PayableOverrides + ): Promise; + + forceDeployOnAddresses( + _deployments: { + bytecodeHash: BytesLike; + newAddress: string; + callConstructor: boolean; + value: BigNumberish; + input: BytesLike; + }[], + overrides?: PayableOverrides + ): Promise; + + "forceDeployOnAddresses(tuple[])"( + _deployments: { + bytecodeHash: BytesLike; + newAddress: string; + callConstructor: boolean; + value: BigNumberish; + input: BytesLike; + }[], + overrides?: PayableOverrides + ): Promise; + + getAccountInfo( + _address: string, + overrides?: CallOverrides + ): Promise<{ + info: { + supportedAAVersion: number; + nonceOrdering: number; + 0: number; + 1: number; + }; + 0: { + supportedAAVersion: number; + nonceOrdering: number; + 0: number; + 1: number; + }; + }>; + + "getAccountInfo(address)"( + _address: string, + overrides?: CallOverrides + ): Promise<{ + info: { + supportedAAVersion: number; + nonceOrdering: number; + 0: number; + 1: number; + }; + 0: { + supportedAAVersion: number; + nonceOrdering: number; + 0: number; + 1: number; + }; + }>; + + getNewAddressCreate( + _sender: string, + _senderNonce: BigNumberish, + overrides?: CallOverrides + ): Promise<{ + newAddress: string; + 0: string; + }>; + + "getNewAddressCreate(address,uint256)"( + _sender: string, + _senderNonce: BigNumberish, + overrides?: CallOverrides + ): Promise<{ + newAddress: string; + 0: string; + }>; + + getNewAddressCreate2( + _sender: string, + _bytecodeHash: BytesLike, + _salt: BytesLike, + _input: BytesLike, + overrides?: CallOverrides + ): Promise<{ + newAddress: string; + 0: string; + }>; + + "getNewAddressCreate2(address,bytes32,bytes32,bytes)"( + _sender: string, + _bytecodeHash: BytesLike, + _salt: BytesLike, + _input: BytesLike, + overrides?: CallOverrides + ): Promise<{ + newAddress: string; + 0: string; + }>; + + updateAccountVersion(_version: BigNumberish, overrides?: Overrides): Promise; + + "updateAccountVersion(uint8)"(_version: BigNumberish, overrides?: Overrides): Promise; + + updateNonceOrdering(_nonceOrdering: BigNumberish, overrides?: Overrides): Promise; + + "updateNonceOrdering(uint8)"(_nonceOrdering: BigNumberish, overrides?: Overrides): Promise; + }; + + create( + _salt: BytesLike, + _bytecodeHash: BytesLike, + _input: BytesLike, + overrides?: PayableOverrides + ): Promise; + + "create(bytes32,bytes32,bytes)"( + _salt: BytesLike, + _bytecodeHash: BytesLike, + _input: BytesLike, + overrides?: PayableOverrides + ): Promise; + + create2( + _salt: BytesLike, + _bytecodeHash: BytesLike, + _input: BytesLike, + overrides?: PayableOverrides + ): Promise; + + "create2(bytes32,bytes32,bytes)"( + _salt: BytesLike, + _bytecodeHash: BytesLike, + _input: BytesLike, + overrides?: PayableOverrides + ): Promise; + + create2Account( + _salt: BytesLike, + _bytecodeHash: BytesLike, + _input: BytesLike, + _aaVersion: BigNumberish, + overrides?: PayableOverrides + ): Promise; + + "create2Account(bytes32,bytes32,bytes,uint8)"( + _salt: BytesLike, + _bytecodeHash: BytesLike, + _input: BytesLike, + _aaVersion: BigNumberish, + overrides?: PayableOverrides + ): Promise; + + createAccount( + arg0: BytesLike, + _bytecodeHash: BytesLike, + _input: BytesLike, + _aaVersion: BigNumberish, + overrides?: PayableOverrides + ): Promise; + + "createAccount(bytes32,bytes32,bytes,uint8)"( + arg0: BytesLike, + _bytecodeHash: BytesLike, + _input: BytesLike, + _aaVersion: BigNumberish, + overrides?: PayableOverrides + ): Promise; + + extendedAccountVersion(_address: string, overrides?: CallOverrides): Promise; + + "extendedAccountVersion(address)"(_address: string, overrides?: CallOverrides): Promise; + + forceDeployOnAddress( + _deployment: { + bytecodeHash: BytesLike; + newAddress: string; + callConstructor: boolean; + value: BigNumberish; + input: BytesLike; + }, + _sender: string, + overrides?: PayableOverrides + ): Promise; + + "forceDeployOnAddress((bytes32,address,bool,uint256,bytes),address)"( + _deployment: { + bytecodeHash: BytesLike; + newAddress: string; + callConstructor: boolean; + value: BigNumberish; + input: BytesLike; + }, + _sender: string, + overrides?: PayableOverrides + ): Promise; + + forceDeployOnAddresses( + _deployments: { + bytecodeHash: BytesLike; + newAddress: string; + callConstructor: boolean; + value: BigNumberish; + input: BytesLike; + }[], + overrides?: PayableOverrides + ): Promise; + + "forceDeployOnAddresses(tuple[])"( + _deployments: { + bytecodeHash: BytesLike; + newAddress: string; + callConstructor: boolean; + value: BigNumberish; + input: BytesLike; + }[], + overrides?: PayableOverrides + ): Promise; + + getAccountInfo( + _address: string, + overrides?: CallOverrides + ): Promise<{ + supportedAAVersion: number; + nonceOrdering: number; + 0: number; + 1: number; + }>; + + "getAccountInfo(address)"( + _address: string, + overrides?: CallOverrides + ): Promise<{ + supportedAAVersion: number; + nonceOrdering: number; + 0: number; + 1: number; + }>; + + getNewAddressCreate(_sender: string, _senderNonce: BigNumberish, overrides?: CallOverrides): Promise; + + "getNewAddressCreate(address,uint256)"( + _sender: string, + _senderNonce: BigNumberish, + overrides?: CallOverrides + ): Promise; + + getNewAddressCreate2( + _sender: string, + _bytecodeHash: BytesLike, + _salt: BytesLike, + _input: BytesLike, + overrides?: CallOverrides + ): Promise; + + "getNewAddressCreate2(address,bytes32,bytes32,bytes)"( + _sender: string, + _bytecodeHash: BytesLike, + _salt: BytesLike, + _input: BytesLike, + overrides?: CallOverrides + ): Promise; + + updateAccountVersion(_version: BigNumberish, overrides?: Overrides): Promise; + + "updateAccountVersion(uint8)"(_version: BigNumberish, overrides?: Overrides): Promise; + + updateNonceOrdering(_nonceOrdering: BigNumberish, overrides?: Overrides): Promise; + + "updateNonceOrdering(uint8)"(_nonceOrdering: BigNumberish, overrides?: Overrides): Promise; + + callStatic: { + create(_salt: BytesLike, _bytecodeHash: BytesLike, _input: BytesLike, overrides?: CallOverrides): Promise; + + "create(bytes32,bytes32,bytes)"( + _salt: BytesLike, + _bytecodeHash: BytesLike, + _input: BytesLike, + overrides?: CallOverrides + ): Promise; + + create2(_salt: BytesLike, _bytecodeHash: BytesLike, _input: BytesLike, overrides?: CallOverrides): Promise; + + "create2(bytes32,bytes32,bytes)"( + _salt: BytesLike, + _bytecodeHash: BytesLike, + _input: BytesLike, + overrides?: CallOverrides + ): Promise; + + create2Account( + _salt: BytesLike, + _bytecodeHash: BytesLike, + _input: BytesLike, + _aaVersion: BigNumberish, + overrides?: CallOverrides + ): Promise; + + "create2Account(bytes32,bytes32,bytes,uint8)"( + _salt: BytesLike, + _bytecodeHash: BytesLike, + _input: BytesLike, + _aaVersion: BigNumberish, + overrides?: CallOverrides + ): Promise; + + createAccount( + arg0: BytesLike, + _bytecodeHash: BytesLike, + _input: BytesLike, + _aaVersion: BigNumberish, + overrides?: CallOverrides + ): Promise; + + "createAccount(bytes32,bytes32,bytes,uint8)"( + arg0: BytesLike, + _bytecodeHash: BytesLike, + _input: BytesLike, + _aaVersion: BigNumberish, + overrides?: CallOverrides + ): Promise; + + extendedAccountVersion(_address: string, overrides?: CallOverrides): Promise; + + "extendedAccountVersion(address)"(_address: string, overrides?: CallOverrides): Promise; + + forceDeployOnAddress( + _deployment: { + bytecodeHash: BytesLike; + newAddress: string; + callConstructor: boolean; + value: BigNumberish; + input: BytesLike; + }, + _sender: string, + overrides?: CallOverrides + ): Promise; + + "forceDeployOnAddress((bytes32,address,bool,uint256,bytes),address)"( + _deployment: { + bytecodeHash: BytesLike; + newAddress: string; + callConstructor: boolean; + value: BigNumberish; + input: BytesLike; + }, + _sender: string, + overrides?: CallOverrides + ): Promise; + + forceDeployOnAddresses( + _deployments: { + bytecodeHash: BytesLike; + newAddress: string; + callConstructor: boolean; + value: BigNumberish; + input: BytesLike; + }[], + overrides?: CallOverrides + ): Promise; + + "forceDeployOnAddresses(tuple[])"( + _deployments: { + bytecodeHash: BytesLike; + newAddress: string; + callConstructor: boolean; + value: BigNumberish; + input: BytesLike; + }[], + overrides?: CallOverrides + ): Promise; + + getAccountInfo( + _address: string, + overrides?: CallOverrides + ): Promise<{ + supportedAAVersion: number; + nonceOrdering: number; + 0: number; + 1: number; + }>; + + "getAccountInfo(address)"( + _address: string, + overrides?: CallOverrides + ): Promise<{ + supportedAAVersion: number; + nonceOrdering: number; + 0: number; + 1: number; + }>; + + getNewAddressCreate(_sender: string, _senderNonce: BigNumberish, overrides?: CallOverrides): Promise; + + "getNewAddressCreate(address,uint256)"( + _sender: string, + _senderNonce: BigNumberish, + overrides?: CallOverrides + ): Promise; + + getNewAddressCreate2( + _sender: string, + _bytecodeHash: BytesLike, + _salt: BytesLike, + _input: BytesLike, + overrides?: CallOverrides + ): Promise; + + "getNewAddressCreate2(address,bytes32,bytes32,bytes)"( + _sender: string, + _bytecodeHash: BytesLike, + _salt: BytesLike, + _input: BytesLike, + overrides?: CallOverrides + ): Promise; + + updateAccountVersion(_version: BigNumberish, overrides?: CallOverrides): Promise; + + "updateAccountVersion(uint8)"(_version: BigNumberish, overrides?: CallOverrides): Promise; + + updateNonceOrdering(_nonceOrdering: BigNumberish, overrides?: CallOverrides): Promise; + + "updateNonceOrdering(uint8)"(_nonceOrdering: BigNumberish, overrides?: CallOverrides): Promise; + }; + + filters: { + AccountNonceOrderingUpdated(accountAddress: string | null, nonceOrdering: null): EventFilter; + + AccountVersionUpdated(accountAddress: string | null, aaVersion: null): EventFilter; + + ContractDeployed( + deployerAddress: string | null, + bytecodeHash: BytesLike | null, + contractAddress: string | null + ): EventFilter; + }; + + estimateGas: { + create( + _salt: BytesLike, + _bytecodeHash: BytesLike, + _input: BytesLike, + overrides?: PayableOverrides + ): Promise; + + "create(bytes32,bytes32,bytes)"( + _salt: BytesLike, + _bytecodeHash: BytesLike, + _input: BytesLike, + overrides?: PayableOverrides + ): Promise; + + create2( + _salt: BytesLike, + _bytecodeHash: BytesLike, + _input: BytesLike, + overrides?: PayableOverrides + ): Promise; + + "create2(bytes32,bytes32,bytes)"( + _salt: BytesLike, + _bytecodeHash: BytesLike, + _input: BytesLike, + overrides?: PayableOverrides + ): Promise; + + create2Account( + _salt: BytesLike, + _bytecodeHash: BytesLike, + _input: BytesLike, + _aaVersion: BigNumberish, + overrides?: PayableOverrides + ): Promise; + + "create2Account(bytes32,bytes32,bytes,uint8)"( + _salt: BytesLike, + _bytecodeHash: BytesLike, + _input: BytesLike, + _aaVersion: BigNumberish, + overrides?: PayableOverrides + ): Promise; + + createAccount( + arg0: BytesLike, + _bytecodeHash: BytesLike, + _input: BytesLike, + _aaVersion: BigNumberish, + overrides?: PayableOverrides + ): Promise; + + "createAccount(bytes32,bytes32,bytes,uint8)"( + arg0: BytesLike, + _bytecodeHash: BytesLike, + _input: BytesLike, + _aaVersion: BigNumberish, + overrides?: PayableOverrides + ): Promise; + + extendedAccountVersion(_address: string, overrides?: CallOverrides): Promise; + + "extendedAccountVersion(address)"(_address: string, overrides?: CallOverrides): Promise; + + forceDeployOnAddress( + _deployment: { + bytecodeHash: BytesLike; + newAddress: string; + callConstructor: boolean; + value: BigNumberish; + input: BytesLike; + }, + _sender: string, + overrides?: PayableOverrides + ): Promise; + + "forceDeployOnAddress((bytes32,address,bool,uint256,bytes),address)"( + _deployment: { + bytecodeHash: BytesLike; + newAddress: string; + callConstructor: boolean; + value: BigNumberish; + input: BytesLike; + }, + _sender: string, + overrides?: PayableOverrides + ): Promise; + + forceDeployOnAddresses( + _deployments: { + bytecodeHash: BytesLike; + newAddress: string; + callConstructor: boolean; + value: BigNumberish; + input: BytesLike; + }[], + overrides?: PayableOverrides + ): Promise; + + "forceDeployOnAddresses(tuple[])"( + _deployments: { + bytecodeHash: BytesLike; + newAddress: string; + callConstructor: boolean; + value: BigNumberish; + input: BytesLike; + }[], + overrides?: PayableOverrides + ): Promise; + + getAccountInfo(_address: string, overrides?: CallOverrides): Promise; + + "getAccountInfo(address)"(_address: string, overrides?: CallOverrides): Promise; + + getNewAddressCreate(_sender: string, _senderNonce: BigNumberish, overrides?: CallOverrides): Promise; + + "getNewAddressCreate(address,uint256)"( + _sender: string, + _senderNonce: BigNumberish, + overrides?: CallOverrides + ): Promise; + + getNewAddressCreate2( + _sender: string, + _bytecodeHash: BytesLike, + _salt: BytesLike, + _input: BytesLike, + overrides?: CallOverrides + ): Promise; + + "getNewAddressCreate2(address,bytes32,bytes32,bytes)"( + _sender: string, + _bytecodeHash: BytesLike, + _salt: BytesLike, + _input: BytesLike, + overrides?: CallOverrides + ): Promise; + + updateAccountVersion(_version: BigNumberish, overrides?: Overrides): Promise; + + "updateAccountVersion(uint8)"(_version: BigNumberish, overrides?: Overrides): Promise; + + updateNonceOrdering(_nonceOrdering: BigNumberish, overrides?: Overrides): Promise; + + "updateNonceOrdering(uint8)"(_nonceOrdering: BigNumberish, overrides?: Overrides): Promise; + }; + + populateTransaction: { + create( + _salt: BytesLike, + _bytecodeHash: BytesLike, + _input: BytesLike, + overrides?: PayableOverrides + ): Promise; + + "create(bytes32,bytes32,bytes)"( + _salt: BytesLike, + _bytecodeHash: BytesLike, + _input: BytesLike, + overrides?: PayableOverrides + ): Promise; + + create2( + _salt: BytesLike, + _bytecodeHash: BytesLike, + _input: BytesLike, + overrides?: PayableOverrides + ): Promise; + + "create2(bytes32,bytes32,bytes)"( + _salt: BytesLike, + _bytecodeHash: BytesLike, + _input: BytesLike, + overrides?: PayableOverrides + ): Promise; + + create2Account( + _salt: BytesLike, + _bytecodeHash: BytesLike, + _input: BytesLike, + _aaVersion: BigNumberish, + overrides?: PayableOverrides + ): Promise; + + "create2Account(bytes32,bytes32,bytes,uint8)"( + _salt: BytesLike, + _bytecodeHash: BytesLike, + _input: BytesLike, + _aaVersion: BigNumberish, + overrides?: PayableOverrides + ): Promise; + + createAccount( + arg0: BytesLike, + _bytecodeHash: BytesLike, + _input: BytesLike, + _aaVersion: BigNumberish, + overrides?: PayableOverrides + ): Promise; + + "createAccount(bytes32,bytes32,bytes,uint8)"( + arg0: BytesLike, + _bytecodeHash: BytesLike, + _input: BytesLike, + _aaVersion: BigNumberish, + overrides?: PayableOverrides + ): Promise; + + extendedAccountVersion(_address: string, overrides?: CallOverrides): Promise; + + "extendedAccountVersion(address)"(_address: string, overrides?: CallOverrides): Promise; + + forceDeployOnAddress( + _deployment: { + bytecodeHash: BytesLike; + newAddress: string; + callConstructor: boolean; + value: BigNumberish; + input: BytesLike; + }, + _sender: string, + overrides?: PayableOverrides + ): Promise; + + "forceDeployOnAddress((bytes32,address,bool,uint256,bytes),address)"( + _deployment: { + bytecodeHash: BytesLike; + newAddress: string; + callConstructor: boolean; + value: BigNumberish; + input: BytesLike; + }, + _sender: string, + overrides?: PayableOverrides + ): Promise; + + forceDeployOnAddresses( + _deployments: { + bytecodeHash: BytesLike; + newAddress: string; + callConstructor: boolean; + value: BigNumberish; + input: BytesLike; + }[], + overrides?: PayableOverrides + ): Promise; + + "forceDeployOnAddresses(tuple[])"( + _deployments: { + bytecodeHash: BytesLike; + newAddress: string; + callConstructor: boolean; + value: BigNumberish; + input: BytesLike; + }[], + overrides?: PayableOverrides + ): Promise; + + getAccountInfo(_address: string, overrides?: CallOverrides): Promise; + + "getAccountInfo(address)"(_address: string, overrides?: CallOverrides): Promise; + + getNewAddressCreate( + _sender: string, + _senderNonce: BigNumberish, + overrides?: CallOverrides + ): Promise; + + "getNewAddressCreate(address,uint256)"( + _sender: string, + _senderNonce: BigNumberish, + overrides?: CallOverrides + ): Promise; + + getNewAddressCreate2( + _sender: string, + _bytecodeHash: BytesLike, + _salt: BytesLike, + _input: BytesLike, + overrides?: CallOverrides + ): Promise; + + "getNewAddressCreate2(address,bytes32,bytes32,bytes)"( + _sender: string, + _bytecodeHash: BytesLike, + _salt: BytesLike, + _input: BytesLike, + overrides?: CallOverrides + ): Promise; + + updateAccountVersion(_version: BigNumberish, overrides?: Overrides): Promise; + + "updateAccountVersion(uint8)"(_version: BigNumberish, overrides?: Overrides): Promise; + + updateNonceOrdering(_nonceOrdering: BigNumberish, overrides?: Overrides): Promise; + + "updateNonceOrdering(uint8)"(_nonceOrdering: BigNumberish, overrides?: Overrides): Promise; + }; +} diff --git a/l2-contracts/test/systems-typechain/ContractDeployerFactory.ts b/l2-contracts/test/systems-typechain/ContractDeployerFactory.ts new file mode 100644 index 000000000..788b3b65b --- /dev/null +++ b/l2-contracts/test/systems-typechain/ContractDeployerFactory.ts @@ -0,0 +1,534 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ + +import { Signer } from "ethers"; +import { Provider, TransactionRequest } from "@ethersproject/providers"; +import { Contract, ContractFactory, Overrides } from "@ethersproject/contracts"; + +import type { ContractDeployer } from "./ContractDeployer"; + +export class ContractDeployerFactory extends ContractFactory { + constructor(signer?: Signer) { + super(_abi, _bytecode, signer); + } + + deploy(overrides?: Overrides): Promise { + return super.deploy(overrides || {}) as Promise; + } + getDeployTransaction(overrides?: Overrides): TransactionRequest { + return super.getDeployTransaction(overrides || {}); + } + attach(address: string): ContractDeployer { + return super.attach(address) as ContractDeployer; + } + connect(signer: Signer): ContractDeployerFactory { + return super.connect(signer) as ContractDeployerFactory; + } + static connect(address: string, signerOrProvider: Signer | Provider): ContractDeployer { + return new Contract(address, _abi, signerOrProvider) as ContractDeployer; + } +} + +const _abi = [ + { + inputs: [], + name: "EmptyBytes32", + type: "error", + }, + { + inputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + name: "HashIsNonZero", + type: "error", + }, + { + inputs: [], + name: "InvalidData", + type: "error", + }, + { + inputs: [], + name: "InvalidNonceOrderingChange", + type: "error", + }, + { + inputs: [], + name: "NonEmptyAccount", + type: "error", + }, + { + inputs: [], + name: "NonEmptyMsgValue", + type: "error", + }, + { + inputs: [], + name: "NotAllowedToDeployInKernelSpace", + type: "error", + }, + { + inputs: [], + name: "Overflow", + type: "error", + }, + { + inputs: [], + name: "SystemCallFlagRequired", + type: "error", + }, + { + inputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + name: "Unauthorized", + type: "error", + }, + { + inputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + ], + name: "UnknownCodeHash", + type: "error", + }, + { + inputs: [ + { + internalType: "uint256", + name: "expected", + type: "uint256", + }, + { + internalType: "uint256", + name: "actual", + type: "uint256", + }, + ], + name: "ValuesNotEqual", + type: "error", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "accountAddress", + type: "address", + }, + { + indexed: false, + internalType: "enum IContractDeployer.AccountNonceOrdering", + name: "nonceOrdering", + type: "uint8", + }, + ], + name: "AccountNonceOrderingUpdated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "accountAddress", + type: "address", + }, + { + indexed: false, + internalType: "enum IContractDeployer.AccountAbstractionVersion", + name: "aaVersion", + type: "uint8", + }, + ], + name: "AccountVersionUpdated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: "address", + name: "deployerAddress", + type: "address", + }, + { + indexed: true, + internalType: "bytes32", + name: "bytecodeHash", + type: "bytes32", + }, + { + indexed: true, + internalType: "address", + name: "contractAddress", + type: "address", + }, + ], + name: "ContractDeployed", + type: "event", + }, + { + inputs: [ + { + internalType: "bytes32", + name: "_salt", + type: "bytes32", + }, + { + internalType: "bytes32", + name: "_bytecodeHash", + type: "bytes32", + }, + { + internalType: "bytes", + name: "_input", + type: "bytes", + }, + ], + name: "create", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "payable", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes32", + name: "_salt", + type: "bytes32", + }, + { + internalType: "bytes32", + name: "_bytecodeHash", + type: "bytes32", + }, + { + internalType: "bytes", + name: "_input", + type: "bytes", + }, + ], + name: "create2", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "payable", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes32", + name: "_salt", + type: "bytes32", + }, + { + internalType: "bytes32", + name: "_bytecodeHash", + type: "bytes32", + }, + { + internalType: "bytes", + name: "_input", + type: "bytes", + }, + { + internalType: "enum IContractDeployer.AccountAbstractionVersion", + name: "_aaVersion", + type: "uint8", + }, + ], + name: "create2Account", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "payable", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes32", + name: "", + type: "bytes32", + }, + { + internalType: "bytes32", + name: "_bytecodeHash", + type: "bytes32", + }, + { + internalType: "bytes", + name: "_input", + type: "bytes", + }, + { + internalType: "enum IContractDeployer.AccountAbstractionVersion", + name: "_aaVersion", + type: "uint8", + }, + ], + name: "createAccount", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "payable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "_address", + type: "address", + }, + ], + name: "extendedAccountVersion", + outputs: [ + { + internalType: "enum IContractDeployer.AccountAbstractionVersion", + name: "", + type: "uint8", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + components: [ + { + internalType: "bytes32", + name: "bytecodeHash", + type: "bytes32", + }, + { + internalType: "address", + name: "newAddress", + type: "address", + }, + { + internalType: "bool", + name: "callConstructor", + type: "bool", + }, + { + internalType: "uint256", + name: "value", + type: "uint256", + }, + { + internalType: "bytes", + name: "input", + type: "bytes", + }, + ], + internalType: "struct ForceDeployment", + name: "_deployment", + type: "tuple", + }, + { + internalType: "address", + name: "_sender", + type: "address", + }, + ], + name: "forceDeployOnAddress", + outputs: [], + stateMutability: "payable", + type: "function", + }, + { + inputs: [ + { + components: [ + { + internalType: "bytes32", + name: "bytecodeHash", + type: "bytes32", + }, + { + internalType: "address", + name: "newAddress", + type: "address", + }, + { + internalType: "bool", + name: "callConstructor", + type: "bool", + }, + { + internalType: "uint256", + name: "value", + type: "uint256", + }, + { + internalType: "bytes", + name: "input", + type: "bytes", + }, + ], + internalType: "struct ForceDeployment[]", + name: "_deployments", + type: "tuple[]", + }, + ], + name: "forceDeployOnAddresses", + outputs: [], + stateMutability: "payable", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "_address", + type: "address", + }, + ], + name: "getAccountInfo", + outputs: [ + { + components: [ + { + internalType: "enum IContractDeployer.AccountAbstractionVersion", + name: "supportedAAVersion", + type: "uint8", + }, + { + internalType: "enum IContractDeployer.AccountNonceOrdering", + name: "nonceOrdering", + type: "uint8", + }, + ], + internalType: "struct IContractDeployer.AccountInfo", + name: "info", + type: "tuple", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "_sender", + type: "address", + }, + { + internalType: "uint256", + name: "_senderNonce", + type: "uint256", + }, + ], + name: "getNewAddressCreate", + outputs: [ + { + internalType: "address", + name: "newAddress", + type: "address", + }, + ], + stateMutability: "pure", + type: "function", + }, + { + inputs: [ + { + internalType: "address", + name: "_sender", + type: "address", + }, + { + internalType: "bytes32", + name: "_bytecodeHash", + type: "bytes32", + }, + { + internalType: "bytes32", + name: "_salt", + type: "bytes32", + }, + { + internalType: "bytes", + name: "_input", + type: "bytes", + }, + ], + name: "getNewAddressCreate2", + outputs: [ + { + internalType: "address", + name: "newAddress", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "enum IContractDeployer.AccountAbstractionVersion", + name: "_version", + type: "uint8", + }, + ], + name: "updateAccountVersion", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "enum IContractDeployer.AccountNonceOrdering", + name: "_nonceOrdering", + type: "uint8", + }, + ], + name: "updateNonceOrdering", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, +]; + +const _bytecode = + "0x001200000000000200090000000000020000000003020019000000000201001900000060042002700000049502400197000100000021035500020000002103550003000000210355000400000021035500050000002103550006000000210355000700000021035500080000002103550009000000210355000a000000210355000b000000210355000c000000210355000d000000210355000e000000210355000f00000021035500100000002103550011000000010355000004950040019d0000008004000039000000400040043f0000000104300190000000690000c13d000000040420008c0000033b0000413d000000000401043b000000e004400270000004970540009c000000710000213d0000049f0540009c000000a60000213d000004a30540009c000001350000613d000004a40540009c000002710000613d000004a50440009c0000033b0000c13d0000000004000416000000000404004b0000033b0000c13d000000040220008a000000200220008c0000033b0000413d0000000401100370000000000101043b000900000001001d000000010110008c0000033b0000213d00000002013001900000000101100270000000010110015f0000003d0000c13d00000000010004110000ffff0110008c00000000010000190000000101002039000000000101004b000003ac0000c13d0000000001000411000800000001001d0000000000100435000000200000043f00000495030000410000000001000414000004950210009c0000000001038019000000c001100210000004ac011001c70000801002000039124e123e0000040f00000001022001900000033b0000613d000000000101043b000000000201041a000001000300008a000000000232016f0000000903000029000000000232019f000000000021041b000000400100043d00000000003104350000000002000414000004950320009c00000495040000410000000002048019000004950310009c00000000010480190000004001100210000000c002200210000000000112019f000004c9011001c70000800d020000390000000203000039000004d5040000410000000805000029124e12390000040f00000001012001900000033b0000613d00000000010000190000124f0001042e0000000001000416000000000101004b0000033b0000c13d00000020010000390000010000100443000001200000044300000496010000410000124f0001042e000004980540009c000000ca0000213d0000049c0540009c0000014c0000613d0000049d0340009c000002e30000613d0000049e0340009c0000033b0000c13d000000040320008a000000200330008c0000033b0000413d0000000403100370000000000303043b000300000003001d000004a60330009c0000033b0000213d00000003030000290000002303300039000004a704000041000000000523004b00000000050000190000000005048019000004a703300197000000000603004b0000000004008019000004a70330009c000000000405c019000000000304004b0000033b0000c13d00000003030000290000000403300039000000000331034f000000000d03043b000004a603d0009c0000033b0000213d0000000303000029000000240e3000390000000503d002100000000003e30019000000000323004b0000033b0000213d000000090400008a0000000003000411000000000443016f000080070440008c000003d00000c13d00000000040d004b000003f30000c13d0000000001000416000000000201004b0000000002000019000000670000613d000005270000013d000004a00540009c000001b80000613d000004a10340009c000003170000613d000004a20340009c0000033b0000c13d0000000003000416000000000303004b0000033b0000c13d000000040320008a000000800330008c0000033b0000413d0000000403100370000000000303043b000900000003001d000004a80330009c0000033b0000213d0000006401100370000000000101043b000004a60310009c0000033b0000213d0000000401100039124e09220000040f00000011040003670000004403400370000000000303043b0000002404400370000000000404043b000000000501001900000000060200190000000901000029000000000204001900000000040500190000000005060019124e093c0000040f000001430000013d000004990540009c0000022f0000613d0000049a0540009c000003380000613d0000049b0340009c0000033b0000c13d000000040320008a000000400330008c0000033b0000413d0000000403100370000000000303043b000900000003001d000004a60330009c0000033b0000213d000000090420006a000004a702000041000000a40340008c00000000030000190000000003024019000800000004001d000004a704400197000000000504004b000000000200a019000004a70440009c000000000203c019000000000202004b0000033b0000c13d0000002402100370000000000202043b000700000002001d000004a80220009c0000033b0000213d00000000020004110000000004000410000000000342004b000003cb0000c13d000400000004001d0000000902000029000500040020003d0000000501100360000000000201043b000004ab01000041000000800010043f000600000002001d000000840020043f00000495010000410000000002000414000004950320009c0000000002018019000000c001200210000004aa011001c70000800402000039124e123e0000040f000000000301001900000060033002700000049503300197000000200430008c000000000403001900000020040080390000001f0540018f0000000506400272000001110000613d00000000070000190000000508700210000000000981034f000000000909043b000000800880003900000000009804350000000107700039000000000867004b000001090000413d000000000705004b000001200000613d0000000506600210000000000761034f00000003055002100000008006600039000000000806043300000000085801cf000000000858022f000000000707043b0000010005500089000000000757022f00000000055701cf000000000585019f00000000005604350000000102200190000003d60000613d0000001f01400039000000600110018f00000080021001bf000300000002001d000000400020043f000000200230008c0000033b0000413d000000800200043d000000000202004b0000056d0000c13d000004c5020000410000000303000029000000000023043500000084011001bf000000060200002900000000002104350000004001300210000004bc011001c700001250000104300000000003000416000000000303004b0000033b0000c13d000000040220008a000000400220008c0000033b0000413d0000000402100370000000000302043b000004a80230009c0000033b0000213d0000002401100370000000000201043b0000000001030019124e09fa0000040f000004a801100197000000400200043d00000000001204350000049501000041000004950320009c00000000020180190000004001200210000004c7011001c70000124f0001042e000000040420008a000000600440008c0000033b0000413d0000002404100370000000000404043b000900000004001d0000004404100370000000000404043b000004a60540009c0000033b0000213d0000002305400039000004a706000041000000000725004b00000000070000190000000007068019000004a705500197000000000805004b0000000006008019000004a70550009c000000000607c019000000000506004b0000033b0000c13d0000000405400039000000000151034f000000000101043b000800000001001d000004a60110009c0000033b0000213d0000002404400039000700000004001d0000000801400029000000000121004b0000033b0000213d00000002013001900000000101100270000000010110015f000001750000c13d00000000010004110000ffff0110008c00000000010000190000000101002039000000000101004b000003ac0000c13d000004c601000041000000800010043f0000000001000411000600000001001d000000840010043f00000495010000410000000002000414000004950320009c0000000002018019000000c001200210000004aa011001c70000800302000039124e12390000040f000000000301001900000060033002700000049503300197000000200430008c000000000403001900000020040080390000001f0540018f0000000506400272000001960000613d00000000070000190000000508700210000000000981034f000000000909043b000000800880003900000000009804350000000107700039000000000867004b0000018e0000413d000000000705004b000001a50000613d0000000506600210000000000761034f00000003055002100000008006600039000000000806043300000000085801cf000000000858022f000000000707043b0000010005500089000000000757022f00000000055701cf000000000585019f00000000005604350000000102200190000004ed0000613d0000001f01400039000000600110018f00000080011001bf000000400010043f000000200130008c0000033b0000413d000000800200043d0000000601000029124e09fa0000040f0000000002010019000600000002001d000000090100002900000007030000290000000804000029124e0a260000040f0000000601000029000001430000013d000000040420008a000000800440008c0000033b0000413d0000002404100370000000000404043b000900000004001d0000000404100370000000000404043b000800000004001d0000004404100370000000000404043b000004a60540009c0000033b0000213d0000002305400039000004a706000041000000000725004b00000000070000190000000007068019000004a705500197000000000805004b0000000006008019000004a70550009c000000000607c019000000000506004b0000033b0000c13d0000000405400039000000000551034f000000000505043b000700000005001d000004a60550009c0000033b0000213d0000002405400039000600000005001d0000000704500029000000000224004b0000033b0000213d0000006401100370000000000101043b000500000001001d000000010110008c0000033b0000213d00000002013001900000000101100270000000010110015f000001e90000c13d00000000010004110000ffff0110008c00000000010000190000000101002039000000000101004b000003ac0000c13d000004c601000041000000800010043f0000000001000411000400000001001d000000840010043f00000495010000410000000002000414000004950320009c0000000002018019000000c001200210000004aa011001c70000800302000039124e12390000040f000000000301001900000060033002700000049503300197000000200430008c000000000403001900000020040080390000001f0540018f00000005064002720000020a0000613d00000000070000190000000508700210000000000981034f000000000909043b000000800880003900000000009804350000000107700039000000000867004b000002020000413d000000000705004b000002190000613d0000000506600210000000000761034f00000003055002100000008006600039000000000806043300000000085801cf000000000858022f000000000707043b0000010005500089000000000757022f00000000055701cf000000000585019f000000000056043500000001022001900000052d0000613d0000001f01400039000000600110018f00000080011001bf000000400010043f000000200130008c0000033b0000413d00000004010000290000000902000029000000080300002900000006040000290000000705000029124e093c0000040f0000000002010019000800000002001d0000000901000029000000050300002900000006040000290000000705000029124e0e2c0000040f000002e10000013d0000000004000416000000000404004b0000033b0000c13d000000040220008a000000200220008c0000033b0000413d0000000401100370000000000101043b000900000001001d000000010110008c0000033b0000213d00000002013001900000000101100270000000010110015f000002420000c13d00000000010004110000ffff0110008c00000000010000190000000101002039000000000101004b000003ac0000c13d0000000001000411000800000001001d0000000000100435000000200000043f00000495010000410000000002000414000004950320009c0000000002018019000000c001200210000004ac011001c70000801002000039124e123e0000040f00000001022001900000033b0000613d000000400400043d000004bd0240009c000003340000213d000000000101043b0000004002400039000000400020043f000000000101041a000000ff0210018f000000010320008c000003c50000213d00000000032404360000000801100270000000ff0110018f000000010210008c000003c50000213d000700000004001d00000000001304350000000902000029000000010220008c000006100000613d000000000101004b000006100000613d000000400100043d000004c80200004100000000002104350000049502000041000004950310009c00000000010280190000004001100210000004c0011001c70000125000010430000000040420008a000000600440008c0000033b0000413d0000002404100370000000000404043b000900000004001d0000000404100370000000000404043b000800000004001d0000004404100370000000000404043b000004a60540009c0000033b0000213d0000002305400039000004a706000041000000000725004b00000000070000190000000007068019000004a705500197000000000805004b0000000006008019000004a70550009c000000000607c019000000000506004b0000033b0000c13d0000000405400039000000000151034f000000000101043b000700000001001d000004a60110009c0000033b0000213d0000002404400039000600000004001d0000000701400029000000000121004b0000033b0000213d00000002013001900000000101100270000000010110015f0000029d0000c13d00000000010004110000ffff0110008c00000000010000190000000101002039000000000101004b000003ac0000c13d000004c601000041000000800010043f0000000001000411000500000001001d000000840010043f00000495010000410000000002000414000004950320009c0000000002018019000000c001200210000004aa011001c70000800302000039124e12390000040f000000000301001900000060033002700000049503300197000000200430008c000000000403001900000020040080390000001f0540018f0000000506400272000002be0000613d00000000070000190000000508700210000000000981034f000000000909043b000000800880003900000000009804350000000107700039000000000867004b000002b60000413d000000000705004b000002cd0000613d0000000506600210000000000761034f00000003055002100000008006600039000000000806043300000000085801cf000000000858022f000000000707043b0000010005500089000000000757022f00000000055701cf000000000585019f000000000056043500000001022001900000050a0000613d0000001f01400039000000600110018f00000080011001bf000000400010043f000000200130008c0000033b0000413d00000005010000290000000902000029000000080300002900000006040000290000000705000029124e093c0000040f0000000002010019000800000002001d000000090100002900000006030000290000000704000029124e0a260000040f0000000801000029000001430000013d0000000003000416000000000303004b0000033b0000c13d000000040220008a000000200220008c0000033b0000413d0000000401100370000000000101043b000900000001001d000004a80110009c0000033b0000213d00000009010000290000000000100435000000200000043f00000495010000410000000002000414000004950320009c0000000002018019000000c001200210000004ac011001c70000801002000039124e123e0000040f00000001022001900000033b0000613d000000400200043d000004bd0320009c000003340000213d000000000101043b0000004003200039000000400030043f000000000101041a000000ff0310018f000000010430008c000003c50000213d00000000033204360000000801100270000000ff0110018f000000010410008c000003c50000213d00000000001304350000000002020433000000010120008c000003c50000213d0000000101000039000000000202004b000001440000c13d0000000901000029000004d10110019800000000010000190000064c0000c13d000000010110018f000001440000013d0000000003000416000000000303004b0000033b0000c13d000000040220008a000000200220008c0000033b0000413d0000000401100370000000000101043b000004a80210009c0000033b0000213d000000c002000039000000400020043f000000800000043f000000a00000043f0000000000100435000000200000043f00000495010000410000000002000414000004950320009c0000000002018019000000c001200210000004ac011001c70000801002000039124e123e0000040f00000001022001900000033b0000613d000000400200043d000004d30320009c000003b00000413d000004ce0100004100000000001004350000004101000039000003c80000013d000000040420008a000000800440008c0000033d0000813d000000000100001900001250000104300000002404100370000000000404043b000900000004001d0000004404100370000000000404043b000004a60540009c0000033b0000213d0000002305400039000004a706000041000000000725004b00000000070000190000000007068019000004a705500197000000000805004b0000000006008019000004a70550009c000000000607c019000000000506004b0000033b0000c13d0000000405400039000000000551034f000000000505043b000800000005001d000004a60550009c0000033b0000213d0000002405400039000700000005001d0000000804500029000000000224004b0000033b0000213d0000006401100370000000000101043b000600000001001d000000010110008c0000033b0000213d00000002013001900000000101100270000000010110015f000003680000c13d00000000010004110000ffff0110008c00000000010000190000000101002039000000000101004b000003ac0000c13d000004c601000041000000800010043f0000000001000411000500000001001d000000840010043f00000495010000410000000002000414000004950320009c0000000002018019000000c001200210000004aa011001c70000800302000039124e12390000040f000000000301001900000060033002700000049503300197000000200430008c000000000403001900000020040080390000001f0540018f0000000506400272000003890000613d00000000070000190000000508700210000000000981034f000000000909043b000000800880003900000000009804350000000107700039000000000867004b000003810000413d000000000705004b000003980000613d0000000506600210000000000761034f00000003055002100000008006600039000000000806043300000000085801cf000000000858022f000000000707043b0000010005500089000000000757022f00000000055701cf000000000585019f000000000056043500000001022001900000054a0000613d0000001f01400039000000600110018f00000080011001bf000000400010043f000000200130008c0000033b0000413d000000800200043d0000000501000029124e09fa0000040f0000000002010019000500000002001d0000000901000029000000060300002900000007040000290000000805000029124e0e2c0000040f0000000501000029000001430000013d000004d601000041000000800010043f000004d7010000410000125000010430000000000101043b0000004003200039000000400030043f000000000301041a000000ff0130018f000000020410008c000003c50000813d00000000011204360000000803300270000000ff0330018f000000010430008c000003c50000213d00000000003104350000000003020433000000010230008c000003c50000213d000000400200043d00000000033204360000000001010433000000010410008c000006450000a13d000004ce0100004100000000001004350000002101000039000000040010043f000004bc010000410000125000010430000004a901000041000000800010043f000000840020043f000004aa010000410000125000010430000004a901000041000000800010043f000004a801300197000000840010043f000004aa010000410000125000010430000000400200043d0000001f0430018f0000000505300272000003e30000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000003db0000413d000000000604004b000003f20000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000005660000013d000000030400002900000000024200490000008404400039000000c30520008a000004a7060000410000000007000019000000000200001900000005087002100000000008e80019000000000881034f000000000808043b000000000958004b00000000090000190000000009068019000004a70a500197000004a70b800197000000000cab004b000000000c000019000000000c064019000000000aab013f000004a70aa0009c000000000c09c01900000000090c004b0000033b0000c13d0000000008840019000000000881034f000000000808043b0000000002280019000000000882004b000000000800001900000001080040390000000108800190000007180000c13d00000001077000390000000008d7004b000003fa0000413d0000000001000416000000000421004b000005270000c13d000204a80030019b000004a708000041000000000900001900060000000d001d00050000000e001d00000005019002100000000002e100190000001101000367000000000221034f000000000202043b00000003030000290000000003300079000000c30330008a000000000432004b00000000040000190000000004088019000004a703300197000004a705200197000000000635004b00000000060000190000000006084019000000000335013f000004a70330009c000000000604c019000000000306004b0000033b0000c13d000900000009001d0000000002e20019000800000002001d0000006002200039000000000121034f000000000101043b000400000001001d000004ae0100004100000000001004390000000001000410000700000001001d00000004001004430000000001000414000004950210009c0000049501008041000000c001100210000004af011001c70000800202000039124e123e0000040f0000000102200190000008c60000613d000000000101043b000000000101004b000000060d000029000000050e000029000004a7080000410000000909000029000000080b0000290000033b0000613d000000400a00043d000004cb0100004100000000001a04350000000401a000390000004002000039000000000021043500000011010003670000000002b1034f000000000202043b0000004403a0003900000000002304350000002002b00039000000000321034f000000000303043b000004a80430009c0000033b0000213d0000006404a0003900000000003404350000002002200039000000000321034f000000000303043b000000000403004b0000000004000019000000010400c039000000000443004b0000033b0000c13d0000008404a0003900000000003404350000002003200039000000000331034f000000000303043b000000a404a0003900000000003404350000004002200039000000000221034f000000000202043b00000000030000310000000004b300490000001f0440008a000000000542004b00000000050000190000000005088019000004a704400197000004a706200197000000000746004b00000000070000190000000007084019000000000446013f000004a70440009c000000000705c019000000000407004b0000033b0000c13d0000000004b20019000000000241034f000000000202043b000004a60520009c0000033b0000213d00000020044000390000000003230049000000000534004b00000000050000190000000005082019000004a703300197000004a706400197000000000736004b00000000070000190000000007084019000000000336013f000004a70330009c000000000705c019000000000307004b0000033b0000c13d000000c403a00039000000a0050000390000000000530435000000e403a000390000000000230435000000000341034f0000010401a000390000000504200272000004ab0000613d000000000500001900000005065002100000000007610019000000000663034f000000000606043b00000000006704350000000105500039000000000645004b000004a30000413d0000001f05200190000004ba0000613d0000000504400210000000000343034f00000000044100190000000305500210000000000604043300000000065601cf000000000656022f000000000303043b0000010005500089000000000353022f00000000035301cf000000000363019f0000000000340435000000000112001900000000000104350000002401a000390000000203000029000000000031043500000000010004140000000704000029000000040340008c000004e60000613d0000001f02200039000000200300008a000000000232016f000004cc0320009c000004cc020080410000049503a0009c000004950500004100080000000a001d000000000305001900000000030a401900000040033002100000006002200210000000000232019f000004950310009c0000000001058019000000c001100210000000000112019f000004cd011000410000000403000029000000000203004b000004dd0000613d000004c3011001c700008009020000390000000005000019124e12390000040f000004df0000013d0000000002040019124e12390000040f0000000102200190000000060d000029000000050e000029000004a7080000410000000909000029000000080a000029000006b30000613d000004a601a0009c000003340000213d0000004000a0043f00000001099000390000000001d9004b0000041f0000413d000000670000013d000000400200043d0000001f0430018f0000000505300272000004fa0000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000004f20000413d000000000604004b000005090000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000005660000013d000000400200043d0000001f0430018f0000000505300272000005170000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b0000050f0000413d000000000604004b000005660000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000005660000013d000004cf03000041000000800030043f000000840020043f000000a40010043f000004d0010000410000125000010430000000400200043d0000001f0430018f00000005053002720000053a0000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000005320000413d000000000604004b000005490000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000005660000013d000000400200043d0000001f0430018f0000000505300272000005570000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b0000054f0000413d000000000604004b000005660000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f00000000001504350000049501000041000004950420009c000000000201801900000040012002100000006002300210000000000121019f0000125000010430000000c002100039000000400020043f00000003020000290000000000020435000000a001100039000200000001001d000000000001043500000005010000290000002001100039000100000001001d0000001101100367000000000101043b000500000001001d000004a80110009c0000033b0000213d00000005010000290000000000100435000000200000043f00000495010000410000000002000414000004950320009c0000000002018019000000c001200210000004ac011001c70000801002000039124e123e0000040f00000001022001900000033b0000613d00000003020000290000000002020433000000010320008c000003c50000213d000000000101043b000000000301041a000001000400008a000000000343016f000000000223019f000000000021041b00000002030000290000000003030433000000010430008c000003c50000213d000004ad0220019700000008033002100000ff000330018f000000000223019f000000000021041b000000010100002900000060021000390000001101000367000000000321034f000000000303043b0000000804000029000000230440008a000004a705000041000000000643004b00000000060000190000000006058019000004a704400197000004a707300197000000000847004b0000000005008019000000000447013f000004a70440009c000000000506c019000000000405004b0000033b0000c13d00000009033000290000000404300039000000000441034f000000000404043b000900000004001d000004a60440009c0000033b0000213d000000090400002900000000044000790000002406300039000004a703000041000000000546004b00000000050000190000000005032019000004a704400197000800000006001d000004a706600197000000000746004b0000000003008019000000000446013f000004a70440009c000000000305c019000000000303004b0000033b0000c13d000000400220008a000000000121034f000000000101043b000000000201004b0000000002000019000000010200c039000000000221004b0000033b0000c13d0000000002000416000300000002001d000000000101004b000006d30000c13d000000030100006b0000071c0000c13d000004ae0100004100000000001004390000800202000039000000040020044300000495010000410000000003000414000004950430009c0000000003018019000000c001300210000004af011001c7124e123e0000040f0000000102200190000008c60000613d000000000101043b000000000101004b0000033b0000613d000000400400043d000000240140003900000006020000290000000000210435000004c201000041000000000014043500000004014000390000000502000029000000000021043500000495010000410000000002000414000004950320009c0000000002018019000004950340009c000900000004001d00000000010440190000004001100210000000c002200210000000000112019f000004b5011001c70000800202000039124e12390000040f0000000102200190000007720000613d0000000901000029000004a60110009c000003340000213d0000000901000029000000400010043f00000495010000410000000002000414000004950320009c0000000002018019000000c001200210000004c3011001c70000800d020000390000000403000039000004c404000041000000070500002900000006060000290000000507000029000000640000013d0000000901000029000600000003001d00000000001304350000000801000029000004a8011001970000000000100435000000200000043f00000495010000410000000002000414000004950320009c0000000002018019000000c001200210000004ac011001c70000801002000039124e123e0000040f00000001022001900000033b0000613d00000007020000290000000002020433000000010320008c0000000605000029000003c50000213d000000000101043b000000000301041a000001000400008a000000000343016f000000000223019f000000000021041b0000000003050433000000010430008c000003c50000213d000004ad0220019700000008033002100000ff000330018f000000000223019f000000000021041b000000400100043d0000000902000029000000000021043500000495020000410000000003000414000004950430009c0000000003028019000004950410009c00000000010280190000004001100210000000c002300210000000000112019f000004c9011001c70000800d020000390000000203000039000004ca04000041000000630000013d00000000001304350000049501000041000004950320009c00000000020180190000004001200210000004d4011001c70000124f0001042e000000400400043d000800000004001d000004d201000041000000000014043500000004014000390000000902000029000000000021043500000495010000410000000002000414000004950320009c0000000002018019000004950340009c00000000010440190000004001100210000000c002200210000000000112019f000004bc011001c70000800202000039124e123e0000040f000000080a000029000000000301001900000060033002700000049503300197000000200430008c000000000403001900000020040080390000001f0540018f0000000506400272000006720000613d0000000007000019000000050870021000000000098a0019000000000881034f000000000808043b00000000008904350000000107700039000000000867004b0000066a0000413d00000000090a0019000000000705004b000006820000613d0000000506600210000000000761034f00000000066900190000000305500210000000000806043300000000085801cf000000000858022f000000000707043b0000010005500089000000000757022f00000000055701cf000000000585019f00000000005604350000000102200190000006960000613d0000001f01400039000000600210018f0000000001920019000000000221004b00000000020000190000000102004039000004a60410009c000003340000213d0000000102200190000003340000c13d000000400010043f000000200130008c0000033b0000413d0000000001090433000000000101004b00000000010000190000000101006039000003150000013d000000400200043d0000001f0430018f0000000505300272000006a30000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b0000069b0000413d000000000604004b000006b20000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000005660000013d000000400200043d000000000301001900000060033002700000001f0430018f00000495033001970000000505300272000006c30000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000006bb0000413d000000000604004b000006d20000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000005660000013d000000030100006b0000071f0000c13d000004ae0100004100000000001004390000800202000039000000040020044300000495010000410000000003000414000004950430009c0000000003018019000000c001300210000004af011001c7124e123e0000040f0000000102200190000008c60000613d000000000101043b000000000101004b0000033b0000613d000000400400043d000004b20100004100000000001404350000000401400039000000050200002900000000002104350000000601000029000004b301100197000004b4011001c70000002402400039000000000012043500000495010000410000000002000414000004950320009c0000000002018019000004950340009c000400000004001d00000000010440190002004000100218000000c00120021000000002011001af000004b5011001c70000800202000039000100000002001d124e12390000040f0000000102200190000007520000613d0000000401000029000004a60110009c000003340000213d0000000401000029000000400010043f000000030100006b0000070a0000613d0000000301000029000004b6011001970000000000010417000000080400002900000495024001970000000001000414000000110300036700010000002303550000000904400029000000090540006c000000000500001900000001050040390000000105500190000007180000c13d0000000005000031000000000645004b000007b20000813d000004ce0100004100000000001004350000001101000039000003c80000013d000000400100043d000004c1020000410000026a0000013d000004ae0100004100000000001004390000800a01000039000000040010044300000495010000410000000002000414000004950320009c0000000002018019000000c001200210000004af011001c70000800202000039124e123e0000040f0000000102200190000008c60000613d000000000101043b000000000101004b0000033b0000613d000000400400043d000000440140003900000003020000290000000000210435000000240140003900000005020000290000000000210435000004b00100004100000000001404350000000401000029000004a8011001970000000402400039000000000012043500000495010000410000000002000414000004950320009c0000000002018019000004950340009c000400000004001d00000000010440190000004001100210000000c002200210000000000112019f000004b1011001c70000800a02000039124e12390000040f0000000102200190000007920000613d0000000401000029000004a60110009c000003340000213d0000000401000029000000400010043f000006d50000013d000000400200043d000000000301001900000060033002700000001f0430018f00000495033001970000000505300272000007620000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b0000075a0000413d000000000604004b000007710000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000005660000013d000000400200043d000000000301001900000060033002700000001f0430018f00000495033001970000000505300272000007820000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b0000077a0000413d000000000604004b000007910000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000005660000013d000000400200043d000000000301001900000060033002700000001f0430018f00000495033001970000000505300272000007a20000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b0000079a0000413d000000000604004b000007b10000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000005660000013d000000000223034f0000000003450049000004950330019700010000003203e5000004b70410009c000007be0000413d000004bf01000041000000040200002900000000001204350000000201000029000004c0011001c7000012500001043000000000023203df000000c001100210000004b801100197000004b9011001c700010000001203b500000000011203af0000000502000029000000070d000029124e12480000040f0000000003010019000000600330027000000495033001970000000102200190000008c70000613d0000003f02300039000004ba02200197000000400400043d0000000002240019000900000004001d000000000442004b00000000040000190000000104004039000004a60520009c000003340000213d0000000104400190000003340000c13d000000400020043f000000090200002900000000083204360000001f023000390000000502200272000007e90000613d00000000040000310000001104400367000000000500001900000005065002100000000007680019000000000664034f000000000606043b00000000006704350000000105500039000000000625004b000007e10000413d000400000008001d000000000200004b000007ec0000613d0000001f0230018f00000005033002720000000407000029000007f90000613d000000000400001900000005054002100000000006570019000000000551034f000000000505043b00000000005604350000000104400039000000000534004b000007f10000413d000000000402004b000008080000613d0000000503300210000000000131034f00000004033000290000000302200210000000000403043300000000042401cf000000000424022f000000000101043b0000010002200089000000000121022f00000000012101cf000000000141019f0000000000130435000004ae0100004100000000001004390000000102000029000000040020044300000495010000410000000004000414000004950340009c0000000004018019000000c001400210000004af011001c7124e123e0000040f0000000102200190000008c60000613d000000000101043b000000000101004b0000033b0000613d000000400400043d000004bb01000041000000000014043500000004014000390000000502000029000000000021043500000495010000410000000002000414000004950320009c0000000002018019000004950340009c000800000004001d00000000010440190000004001100210000000c002200210000000000112019f000004bc011001c70000800202000039124e12390000040f0000000102200190000008e20000613d0000000801000029000004a60110009c000003340000213d0000000801000029000000400010043f00000009010000290000000001010433000004a702000041000000200310008c00000000030000190000000003024019000004a704100197000000000504004b000000000200a019000004a70440009c000000000203c019000000000202004b0000033b0000c13d00000004020000290000000002020433000004a60320009c0000033b0000213d000000040110002900000004022000290000001f03200039000004a704000041000000000513004b00000000050000190000000005048019000004a703300197000004a706100197000000000763004b0000000004008019000000000363013f000004a70330009c000000000405c019000000000304004b0000033b0000c13d0000000023020434000004a60430009c000003340000213d00000005043002100000003f04400039000000200500008a000000000454016f0000000804400029000004a60540009c000003340000213d000000400040043f0000000804000029000000000034043500000006033002100000000003230019000000000413004b0000033b0000213d000000000432004b000008820000813d000004a70400004100000008050000290000000006210049000000400760008c00000000070000190000000007044019000004a706600197000000000806004b00000000080000190000000008042019000004a70660009c000000000807c019000000000608004b0000033b0000c13d000000400600043d000004bd0760009c000003340000213d00000020055000390000004007600039000000400070043f000000008702043400000000077604360000000008080433000000000087043500000000006504350000004002200039000000000632004b000008680000413d000004ae0100004100000000001004390000800501000039000000040010044300000495010000410000000002000414000004950320009c0000000002018019000000c001200210000004af011001c70000800202000039124e123e0000040f0000000102200190000008c60000613d000000000101043b000000000101004b0000033b0000613d000000400300043d000000240130003900000040020000390000000000210435000004be0100004100000000001304350000000401300039000000050200002900000000002104350000000801000029000000000101043300000044023000390000000000120435000900000003001d0000006402300039000000000301004b000008b10000613d000000000300001900000008040000290000002004400039000800000004001d0000000004040433000000005404043400000000044204360000000005050433000000000054043500000040022000390000000103300039000000000413004b000008a50000413d000000090400002900000000014200490000049502000041000004950340009c000000000302001900000000030440190000004003300210000004950410009c00000000010280190000006001100210000000000131019f0000000003000414000004950430009c0000000003028019000000c002300210000000000121019f0000800502000039124e12390000040f0000000102200190000009020000613d000005fe0000013d000000000001042f0000001f0430018f0000000502300272000008d20000613d00000000050000190000000506500210000000000761034f000000000707043b00000000007604350000000105500039000000000625004b000008cb0000413d000000000504004b000008e00000613d00000003044002100000000502200210000000000502043300000000054501cf000000000545022f000000000121034f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f000000000012043500000060013002100000125000010430000000400200043d000000000301001900000060033002700000001f0430018f00000495033001970000000505300272000008f20000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000008ea0000413d000000000604004b000009010000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000005660000013d000000400200043d000000000301001900000060033002700000001f0430018f00000495033001970000000505300272000009120000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b0000090a0000413d000000000604004b000009210000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000005660000013d0000001f03100039000004a704000041000000000523004b00000000050000190000000005044019000004a706200197000004a703300197000000000763004b000000000400a019000000000363013f000004a70330009c000000000405c019000000000304004b0000093a0000613d0000001103100367000000000303043b000004a60430009c0000093a0000213d00000020011000390000000004310019000000000224004b0000093a0000213d0000000002030019000000000001042d00000000010000190000125000010430000300000000000200000495094001970000000008000414000000110700036700010000009703550000000004450019000000000554004b000000000500001900000001050040390000000105500190000009c80000c13d0000000005000031000000000645004b000009c80000413d000100000002001d000200000001001d000300000003001d000000000297034f0000000003450049000004950330019700010000003203e5000004b70480009c000009d20000813d00000000023203df000000c001800210000004b801100197000004d8011001c700010000001203b500000000011203af0000801002000039124e12430000040f0000000003010019000000600330027000000495033001970000000102200190000009d50000613d0000003f02300039000004ba04200197000000400200043d0000000004420019000000000524004b00000000050000190000000105004039000004a60640009c000009cc0000213d0000000105500190000009cc0000c13d000000400040043f00000000043204360000001f0530003900000005055002720000097b0000613d00000000060000310000001106600367000000000700001900000005087002100000000009840019000000000886034f000000000808043b00000000008904350000000107700039000000000857004b000009730000413d000000000500004b0000097d0000613d0000001f0530018f000000050330027200000001090000290000098a0000613d000000000600001900000005076002100000000008740019000000000771034f000000000707043b00000000007804350000000106600039000000000736004b000009820000413d000000000605004b000009990000613d0000000503300210000000000131034f00000000033400190000000305500210000000000603043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000130435000000400100043d0000000002020433000000200220008c00000003050000290000000206000029000009f00000c13d0000000002040433000000a00310003900000000002304350000008002100039000000000092043500000060021000390000000000520435000004a802600197000000400310003900000000002304350000002002100039000004da030000410000000000320435000000a0030000390000000000310435000004db0310009c000009cc0000213d000000c003100039000000400030043f0000049503000041000004950420009c000000000203801900000040022002100000000001010433000004950410009c00000000010380190000006001100210000000000121019f0000000002000414000004950420009c0000000002038019000000c002200210000000000112019f000004c3011001c70000801002000039124e123e0000040f0000000102200190000009f80000613d000000000101043b000004a801100197000000000001042d000004ce0100004100000000001004350000001101000039000009cf0000013d000004ce0100004100000000001004350000004101000039000000040010043f000004bc010000410000125000010430000000400100043d000004bf02000041000009f10000013d0000001f0430018f0000000502300272000009e00000613d00000000050000190000000506500210000000000761034f000000000707043b00000000007604350000000105500039000000000625004b000009d90000413d000000000504004b000009ee0000613d00000003044002100000000502200210000000000502043300000000054501cf000000000545022f000000000121034f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f000000000012043500000060013002100000125000010430000004d90200004100000000002104350000049502000041000004950310009c00000000010280190000004001100210000004c0011001c7000012500001043000000000010000190000125000010430000000400300043d00000060043000390000000000240435000004a8011001970000004002300039000000000012043500000060010000390000000001130436000004dc020000410000000000210435000004dd0230009c00000a1e0000813d0000008002300039000000400020043f0000049502000041000004950410009c000000000102801900000040011002100000000003030433000004950430009c00000000030280190000006003300210000000000113019f0000000003000414000004950430009c0000000003028019000000c002300210000000000112019f000004c3011001c70000801002000039124e123e0000040f000000010220019000000a240000613d000000000101043b000004a801100197000000000001042d000004ce0100004100000000001004350000004101000039000000040010043f000004bc010000410000125000010430000000000100001900001250000104300009000000000002000500000004001d000400000003001d000000400400043d000800000001001d000000000101004b00000cf20000613d000300000002001d000004a8022001970000ffff0120008c00000cf40000a13d000004de0100004100000000001404350000000401400039000900000002001d000000000021043500000495010000410000000002000414000004950320009c0000000002018019000004950340009c00000000010440190000004001100210000000c002200210000000000112019f000004bc011001c70000800202000039000600000002001d000700000004001d124e123e0000040f000000070a000029000000000301001900000060033002700000049503300197000000200430008c000000000403001900000020040080390000001f0540018f000000050640027200000a570000613d0000000007000019000000050870021000000000098a0019000000000881034f000000000808043b00000000008904350000000107700039000000000867004b00000a4f0000413d000000000705004b00000a660000613d0000000506600210000000000761034f00000000066a00190000000305500210000000000806043300000000085801cf000000000858022f000000000707043b0000010005500089000000000757022f00000000055701cf000000000585019f0000000000560435000000010220019000000cf60000613d0000001f01400039000000600110018f0000000004a10019000000000114004b00000000010000190000000101004039000004a60240009c00000ce30000213d000000010110019000000ce30000c13d000000400040043f0000001f0130008c00000ce10000a13d000000040140003900000000020a0433000000000302004b00000d130000c13d000004e00200004100000000002404350000000902000029000000000021043500000495010000410000000002000414000004950320009c0000000002018019000004950340009c00000000010440190000004001100210000000c002200210000000000112019f000004bc011001c70000800302000039000700000004001d124e123e0000040f000000070a000029000000000301001900000060033002700000049503300197000000200430008c000000000403001900000020040080390000001f0540018f000000050640027200000a9d0000613d0000000007000019000000050870021000000000098a0019000000000881034f000000000808043b00000000008904350000000107700039000000000867004b00000a950000413d000000000705004b00000aac0000613d0000000506600210000000000761034f00000000066a00190000000305500210000000000806043300000000085801cf000000000858022f000000000707043b0000010005500089000000000757022f00000000055701cf000000000585019f0000000000560435000000010220019000000d160000613d0000001f01400039000000600110018f0000000004a10019000004a60140009c00000ce30000213d000000400040043f000000200130008c00000ce10000413d00000000010a0433000000000101004b00000d330000c13d000004ab01000041000000000014043500000004014000390000000802000029000000000021043500000495010000410000000002000414000004950320009c0000000002018019000004950340009c00000000010440190000004001100210000000c002200210000000000112019f000004bc011001c70000800402000039000700000004001d124e123e0000040f000000070a000029000000000301001900000060033002700000049503300197000000200430008c000000000403001900000020040080390000001f0540018f000000050640027200000ade0000613d0000000007000019000000050870021000000000098a0019000000000881034f000000000808043b00000000008904350000000107700039000000000867004b00000ad60000413d000000000705004b00000aed0000613d0000000506600210000000000761034f00000000066a00190000000305500210000000000806043300000000085801cf000000000858022f000000000707043b0000010005500089000000000757022f00000000055701cf000000000585019f0000000000560435000000010220019000000d3b0000613d0000001f01400039000000600110018f0000000004a10019000004a60140009c00000ce30000213d000000400040043f000000200130008c00000ce10000413d00000000010a0433000000000101004b00000d580000613d000004bd0140009c00000ce30000213d0000004001400039000000400010043f0000000001040436000200000001001d000000000001043500000009010000290000000000100435000000200000043f00000495010000410000000002000414000004950320009c0000000002018019000000c001200210000004ac011001c70000801002000039000700000004001d124e123e0000040f0000000703000029000000010220019000000ce10000613d0000000002030433000000020320008c00000cea0000813d000000000101043b000000000301041a000001000400008a000000000343016f000000000223019f000000000021041b00000002030000290000000003030433000000010430008c00000cea0000213d000004ad0220019700000008033002100000ff000330018f000000000223019f000000000021041b000004ae0100004100000000001004390000000001000416000700000001001d000000000101004b00000b8a0000613d0000800a01000039000000040010044300000495010000410000000002000414000004950320009c0000000002018019000000c001200210000004af011001c70000800202000039000200000002001d124e123e0000040f000000010220019000000ce90000613d000000000101043b000000000101004b00000ce10000613d000000400400043d000000440140003900000007020000290000000000210435000000240140003900000009020000290000000000210435000004b00100004100000000001404350000000001000410000004a8011001970000000402400039000000000012043500000495010000410000000002000414000004950320009c0000000002018019000004950340009c000100000004001d00000000010440190000004001100210000000c002200210000000000112019f000004b1011001c70000800a02000039124e12390000040f000000010220019000000dc60000613d0000000102000029000004a60120009c00000ce30000213d000000400020043f000004ae0100004100000000001004390000000202000029000000040020044300000495010000410000000004000414000004950340009c0000000004018019000000c001400210000004af011001c7124e123e0000040f000000010220019000000ce90000613d000000000101043b000000000101004b00000ce10000613d000000400400043d000004b20100004100000000001404350000000401400039000000090200002900000000002104350000000801000029000004b301100197000004b4011001c70000002402400039000000000012043500000495010000410000000002000414000004950320009c0000000002018019000004950340009c000200000004001d00000000010440190000004001100210000000c002200210000000000112019f000004b5011001c70000800202000039124e12390000040f000000010220019000000de60000613d0000000208000029000004a60180009c00000ce30000213d000000400080043f0000000701000029000004b601100197000000000001041700000bb60000013d0000000602000029000000040020044300000495010000410000000004000414000004950340009c0000000004018019000000c001400210000004af011001c7124e123e0000040f000000010220019000000ce90000613d000000000101043b000000000101004b00000ce10000613d000000400400043d000004b20100004100000000001404350000000401400039000000090200002900000000002104350000000801000029000004b301100197000004b4011001c70000002402400039000000000012043500000495010000410000000002000414000004950320009c0000000002018019000004950340009c000200000004001d00000000010440190000004001100210000000c002200210000000000112019f000004b5011001c70000800202000039124e12390000040f000000010220019000000e060000613d0000000208000029000004a60180009c00000ce30000213d000000400080043f0000000404000029000004950240019700000000010004140000001103000367000100000023035500000000070004110000000504400029000000050540006c00000000050000190000000105004039000000010550019000000cee0000c13d0000000005000031000000000645004b00000cee0000413d000000000223034f0000000003450049000004950330019700010000003203e5000004b70410009c00000d630000813d00000000023203df000000c001100210000004b801100197000004b9011001c700010000001203b500000000011203af000400000007001d000004a80d7001970000000302000029124e12480000040f000000000301001900000060033002700000049503300197000000010220019000000d6b0000613d0000003f02300039000004ba02200197000000400600043d0000000002260019000000000462004b00000000040000190000000104004039000004a60520009c00000ce30000213d000000010440019000000ce30000c13d000000400020043f000500000006001d00000000083604360000001f02300039000000050220027200000bf60000613d00000000040000310000001104400367000000000500001900000005065002100000000007680019000000000664034f000000000606043b00000000006704350000000105500039000000000625004b00000bee0000413d000000000200004b00000bf80000613d0000001f0230018f000000050330027200000c040000613d000000000400001900000005054002100000000006580019000000000551034f000000000505043b00000000005604350000000104400039000000000534004b00000bfc0000413d000000000402004b00000c130000613d0000000503300210000000000131034f00000000033800190000000302200210000000000403043300000000042401cf000000000424022f000000000101043b0000010002200089000000000121022f00000000012101cf000000000141019f0000000000130435000700000008001d000004ae0100004100000000001004390000000602000029000000040020044300000495010000410000000004000414000004950340009c0000000004018019000000c001400210000004af011001c7124e123e0000040f000000010220019000000ce90000613d000000000101043b000000000101004b00000ce10000613d000000400400043d000004bb01000041000000000014043500000004014000390000000902000029000000000021043500000495010000410000000002000414000004950320009c0000000002018019000004950340009c000600000004001d00000000010440190000004001100210000000c002200210000000000112019f000004bc011001c70000800202000039124e12390000040f000000010220019000000d860000613d0000000609000029000004a60190009c000000050100002900000ce30000213d000000400090043f0000000001010433000004a702000041000000200310008c00000000030000190000000003024019000004a704100197000000000504004b000000000200a019000004a70440009c000000000203c019000000000202004b00000ce10000c13d00000007020000290000000002020433000004a60320009c00000ce10000213d000000070110002900000007022000290000001f03200039000004a704000041000000000513004b00000000050000190000000005048019000004a703300197000004a706100197000000000763004b0000000004008019000000000363013f000004a70330009c000000000405c019000000000304004b00000ce10000c13d0000000023020434000004a60430009c00000ce30000213d00000005043002100000003f04400039000000200500008a000000000454016f0000000004940019000004a60540009c00000ce30000213d000000400040043f000000000039043500000006033002100000000003230019000000000413004b00000ce10000213d000000000432004b00000c8c0000813d000004a70400004100000000050900190000000006210049000000400760008c00000000070000190000000007044019000004a706600197000000000806004b00000000080000190000000008042019000004a70660009c000000000807c019000000000608004b00000ce10000c13d000000400600043d000004bd0760009c00000ce30000213d00000020055000390000004007600039000000400070043f000000008702043400000000077604360000000008080433000000000087043500000000006504350000004002200039000000000632004b00000c720000413d000004ae0100004100000000001004390000800501000039000000040010044300000495010000410000000002000414000004950320009c0000000002018019000000c001200210000004af011001c70000800202000039124e123e0000040f000000010220019000000ce90000613d000000000101043b000000000101004b000000060600002900000ce10000613d000000400700043d000000240170003900000040020000390000000000210435000004be0100004100000000001704350000000401700039000000090200002900000000002104350000000001060433000000440270003900000000001204350000006402700039000000000301004b00000cb80000613d000000000300001900000020066000390000000004060433000000005404043400000000044204360000000005050433000000000054043500000040022000390000000103300039000000000413004b00000cae0000413d00000000017200490000049502000041000004950370009c000000000302001900000000030740190000004003300210000004950410009c00000000010280190000006001100210000000000131019f0000000003000414000004950430009c0000000003028019000000c002300210000000000121019f0000800502000039000700000007001d124e12390000040f000000010220019000000da60000613d0000000702000029000004a60120009c000000000102001900000ce30000213d000000400010043f00000495010000410000000002000414000004950320009c0000000002018019000000c001200210000004c3011001c70000800d020000390000000403000039000004c404000041000000040500002900000008060000290000000907000029124e12390000040f000000010120019000000ce10000613d000000000001042d00000000010000190000125000010430000004ce0100004100000000001004350000004101000039000000040010043f000004bc010000410000125000010430000000000001042f000004ce010000410000000000100435000000210100003900000ce60000013d000004ce010000410000000000100435000000110100003900000ce60000013d000004e30100004100000d340000013d000004e20100004100000d340000013d000000400200043d0000001f0430018f000000050530027200000d030000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b00000cfb0000413d000000000604004b00000e250000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f000000000015043500000e250000013d000004df03000041000000000034043500000d5c0000013d000000400200043d0000001f0430018f000000050530027200000d230000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b00000d1b0000413d000000000604004b00000d320000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f000000000015043500000e250000013d000004e10100004100000000001404350000049501000041000004950240009c00000000040180190000004001400210000004c0011001c70000125000010430000000400200043d0000001f0430018f000000050530027200000d480000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b00000d400000413d000000000604004b00000d570000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f000000000015043500000e250000013d000004c50100004100000000001404350000000401400039000000080200002900000000002104350000049501000041000004950240009c00000000040180190000004001400210000004bc011001c70000125000010430000004bf0100004100000000001804350000049501000041000004950280009c00000000080180190000004001800210000004c0011001c700001250000104300000001f0430018f000000050230027200000d760000613d00000000050000190000000506500210000000000761034f000000000707043b00000000007604350000000105500039000000000625004b00000d6f0000413d000000000504004b00000d840000613d00000003044002100000000502200210000000000502043300000000054501cf000000000545022f000000000121034f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f000000000012043500000060013002100000125000010430000000400200043d000000000301001900000060033002700000001f0430018f0000049503300197000000050530027200000d960000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b00000d8e0000413d000000000604004b00000da50000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f000000000015043500000e250000013d000000400200043d000000000301001900000060033002700000001f0430018f0000049503300197000000050530027200000db60000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b00000dae0000413d000000000604004b00000dc50000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f000000000015043500000e250000013d000000400200043d000000000301001900000060033002700000001f0430018f0000049503300197000000050530027200000dd60000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b00000dce0000413d000000000604004b00000de50000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f000000000015043500000e250000013d000000400200043d000000000301001900000060033002700000001f0430018f0000049503300197000000050530027200000df60000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b00000dee0000413d000000000604004b00000e050000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f000000000015043500000e250000013d000000400200043d000000000301001900000060033002700000001f0430018f0000049503300197000000050530027200000e160000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b00000e0e0000413d000000000604004b00000e250000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f00000000001504350000049501000041000004950420009c000000000201801900000040012002100000006002300210000000000121019f00001250000104300009000000000002000400000005001d000300000004001d000000400400043d000800000001001d000000000101004b000010fe0000613d000500000003001d000200000002001d000004a8022001970000ffff0120008c000011000000a13d000004de0100004100000000001404350000000401400039000900000002001d000000000021043500000495010000410000000002000414000004950320009c0000000002018019000004950340009c00000000010440190000004001100210000000c002200210000000000112019f000004bc011001c70000800202000039000600000002001d000700000004001d124e123e0000040f000000070a000029000000000301001900000060033002700000049503300197000000200430008c000000000403001900000020040080390000001f0540018f000000050640027200000e5e0000613d0000000007000019000000050870021000000000098a0019000000000881034f000000000808043b00000000008904350000000107700039000000000867004b00000e560000413d000000000705004b00000e6d0000613d0000000506600210000000000761034f00000000066a00190000000305500210000000000806043300000000085801cf000000000858022f000000000707043b0000010005500089000000000757022f00000000055701cf000000000585019f00000000005604350000000102200190000011020000613d0000001f01400039000000600110018f0000000004a10019000000000114004b00000000010000190000000101004039000004a60240009c000010ef0000213d0000000101100190000010ef0000c13d000000400040043f0000001f0130008c000010ed0000a13d000000040140003900000000020a0433000000000302004b0000111f0000c13d000004e00200004100000000002404350000000902000029000000000021043500000495010000410000000002000414000004950320009c0000000002018019000004950340009c00000000010440190000004001100210000000c002200210000000000112019f000004bc011001c70000800302000039000700000004001d124e123e0000040f000000070a000029000000000301001900000060033002700000049503300197000000200430008c000000000403001900000020040080390000001f0540018f000000050640027200000ea40000613d0000000007000019000000050870021000000000098a0019000000000881034f000000000808043b00000000008904350000000107700039000000000867004b00000e9c0000413d000000000705004b00000eb30000613d0000000506600210000000000761034f00000000066a00190000000305500210000000000806043300000000085801cf000000000858022f000000000707043b0000010005500089000000000757022f00000000055701cf000000000585019f00000000005604350000000102200190000011220000613d0000001f01400039000000600110018f0000000004a10019000004a60140009c000010ef0000213d000000400040043f000000200130008c000010ed0000413d00000000010a0433000000000101004b0000113f0000c13d000004ab01000041000000000014043500000004014000390000000802000029000000000021043500000495010000410000000002000414000004950320009c0000000002018019000004950340009c00000000010440190000004001100210000000c002200210000000000112019f000004bc011001c70000800402000039000700000004001d124e123e0000040f000000070a000029000000000301001900000060033002700000049503300197000000200430008c000000000403001900000020040080390000001f0540018f000000050640027200000ee50000613d0000000007000019000000050870021000000000098a0019000000000881034f000000000808043b00000000008904350000000107700039000000000867004b00000edd0000413d000000000705004b00000ef40000613d0000000506600210000000000761034f00000000066a00190000000305500210000000000806043300000000085801cf000000000858022f000000000707043b0000010005500089000000000757022f00000000055701cf000000000585019f00000000005604350000000102200190000011470000613d0000001f01400039000000600110018f0000000004a10019000004a60140009c000010ef0000213d000000400040043f000000200130008c000010ed0000413d00000000010a0433000000000101004b000011640000613d000004bd0140009c000010ef0000213d0000004001400039000000400010043f000000000304043600000000000304350000000502000029000000020120008c000010f60000813d0000000000240435000500000003001d000000000003043500000009010000290000000000100435000000200000043f00000495010000410000000002000414000004950320009c0000000002018019000000c001200210000004ac011001c70000801002000039000700000004001d124e123e0000040f00000007030000290000000102200190000010ed0000613d0000000002030433000000010320008c0000000505000029000010f60000213d000000000101043b000000000301041a000001000400008a000000000343016f000000000223019f000000000021041b0000000003050433000000010430008c000010f60000213d000004ad0220019700000008033002100000ff000330018f000000000223019f000000000021041b000004ae0100004100000000001004390000000001000416000700000001001d000000000101004b00000f960000613d0000800a01000039000000040010044300000495010000410000000002000414000004950320009c0000000002018019000000c001200210000004af011001c70000800202000039000500000002001d124e123e0000040f0000000102200190000010f50000613d000000000101043b000000000101004b000010ed0000613d000000400400043d000000440140003900000007020000290000000000210435000000240140003900000009020000290000000000210435000004b00100004100000000001404350000000001000410000004a8011001970000000402400039000000000012043500000495010000410000000002000414000004950320009c0000000002018019000004950340009c000100000004001d00000000010440190000004001100210000000c002200210000000000112019f000004b1011001c70000800a02000039124e12390000040f0000000102200190000011d20000613d0000000102000029000004a60120009c000010ef0000213d000000400020043f000004ae0100004100000000001004390000000502000029000000040020044300000495010000410000000004000414000004950340009c0000000004018019000000c001400210000004af011001c7124e123e0000040f0000000102200190000010f50000613d000000000101043b000000000101004b000010ed0000613d000000400400043d000004b20100004100000000001404350000000401400039000000090200002900000000002104350000000801000029000004b301100197000004b4011001c70000002402400039000000000012043500000495010000410000000002000414000004950320009c0000000002018019000004950340009c000500000004001d00000000010440190000004001100210000000c002200210000000000112019f000004b5011001c70000800202000039124e12390000040f0000000102200190000011f20000613d0000000508000029000004a60180009c000010ef0000213d000000400080043f0000000701000029000004b601100197000000000001041700000fc20000013d0000000602000029000000040020044300000495010000410000000004000414000004950340009c0000000004018019000000c001400210000004af011001c7124e123e0000040f0000000102200190000010f50000613d000000000101043b000000000101004b000010ed0000613d000000400400043d000004b20100004100000000001404350000000401400039000000090200002900000000002104350000000801000029000004b301100197000004b4011001c70000002402400039000000000012043500000495010000410000000002000414000004950320009c0000000002018019000004950340009c000500000004001d00000000010440190000004001100210000000c002200210000000000112019f000004b5011001c70000800202000039124e12390000040f0000000102200190000012120000613d0000000508000029000004a60180009c000010ef0000213d000000400080043f0000000304000029000004950240019700000000010004140000001103000367000100000023035500000000070004110000000404400029000000040540006c000000000500001900000001050040390000000105500190000010fa0000c13d0000000005000031000000000645004b000010fa0000413d000000000223034f0000000003450049000004950330019700010000003203e5000004b70410009c0000116f0000813d00000000023203df000000c001100210000004b801100197000004b9011001c700010000001203b500000000011203af000400000007001d000004a80d7001970000000202000029124e12480000040f0000000003010019000000600330027000000495033001970000000102200190000011770000613d0000003f02300039000004ba02200197000000400600043d0000000002260019000000000462004b00000000040000190000000104004039000004a60520009c000010ef0000213d0000000104400190000010ef0000c13d000000400020043f000500000006001d00000000083604360000001f023000390000000502200272000010020000613d00000000040000310000001104400367000000000500001900000005065002100000000007680019000000000664034f000000000606043b00000000006704350000000105500039000000000625004b00000ffa0000413d000000000200004b000010040000613d0000001f0230018f0000000503300272000010100000613d000000000400001900000005054002100000000006580019000000000551034f000000000505043b00000000005604350000000104400039000000000534004b000010080000413d000000000402004b0000101f0000613d0000000503300210000000000131034f00000000033800190000000302200210000000000403043300000000042401cf000000000424022f000000000101043b0000010002200089000000000121022f00000000012101cf000000000141019f0000000000130435000700000008001d000004ae0100004100000000001004390000000602000029000000040020044300000495010000410000000004000414000004950340009c0000000004018019000000c001400210000004af011001c7124e123e0000040f0000000102200190000010f50000613d000000000101043b000000000101004b000010ed0000613d000000400400043d000004bb01000041000000000014043500000004014000390000000902000029000000000021043500000495010000410000000002000414000004950320009c0000000002018019000004950340009c000600000004001d00000000010440190000004001100210000000c002200210000000000112019f000004bc011001c70000800202000039124e12390000040f0000000102200190000011920000613d0000000609000029000004a60190009c0000000501000029000010ef0000213d000000400090043f0000000001010433000004a702000041000000200310008c00000000030000190000000003024019000004a704100197000000000504004b000000000200a019000004a70440009c000000000203c019000000000202004b000010ed0000c13d00000007020000290000000002020433000004a60320009c000010ed0000213d000000070110002900000007022000290000001f03200039000004a704000041000000000513004b00000000050000190000000005048019000004a703300197000004a706100197000000000763004b0000000004008019000000000363013f000004a70330009c000000000405c019000000000304004b000010ed0000c13d0000000023020434000004a60430009c000010ef0000213d00000005043002100000003f04400039000000200500008a000000000454016f0000000004940019000004a60540009c000010ef0000213d000000400040043f000000000039043500000006033002100000000003230019000000000413004b000010ed0000213d000000000432004b000010980000813d000004a70400004100000000050900190000000006210049000000400760008c00000000070000190000000007044019000004a706600197000000000806004b00000000080000190000000008042019000004a70660009c000000000807c019000000000608004b000010ed0000c13d000000400600043d000004bd0760009c000010ef0000213d00000020055000390000004007600039000000400070043f000000008702043400000000077604360000000008080433000000000087043500000000006504350000004002200039000000000632004b0000107e0000413d000004ae0100004100000000001004390000800501000039000000040010044300000495010000410000000002000414000004950320009c0000000002018019000000c001200210000004af011001c70000800202000039124e123e0000040f0000000102200190000010f50000613d000000000101043b000000000101004b0000000606000029000010ed0000613d000000400700043d000000240170003900000040020000390000000000210435000004be0100004100000000001704350000000401700039000000090200002900000000002104350000000001060433000000440270003900000000001204350000006402700039000000000301004b000010c40000613d000000000300001900000020066000390000000004060433000000005404043400000000044204360000000005050433000000000054043500000040022000390000000103300039000000000413004b000010ba0000413d00000000017200490000049502000041000004950370009c000000000302001900000000030740190000004003300210000004950410009c00000000010280190000006001100210000000000131019f0000000003000414000004950430009c0000000003028019000000c002300210000000000121019f0000800502000039000700000007001d124e12390000040f0000000102200190000011b20000613d0000000702000029000004a60120009c0000000001020019000010ef0000213d000000400010043f00000495010000410000000002000414000004950320009c0000000002018019000000c001200210000004c3011001c70000800d020000390000000403000039000004c404000041000000040500002900000008060000290000000907000029124e12390000040f0000000101200190000010ed0000613d000000000001042d00000000010000190000125000010430000004ce0100004100000000001004350000004101000039000000040010043f000004bc010000410000125000010430000000000001042f000004ce0100004100000000001004350000002101000039000010f20000013d000004ce0100004100000000001004350000001101000039000010f20000013d000004e301000041000011400000013d000004e201000041000011400000013d000000400200043d0000001f0430018f00000005053002720000110f0000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000011070000413d000000000604004b000012310000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000012310000013d000004df030000410000000000340435000011680000013d000000400200043d0000001f0430018f00000005053002720000112f0000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000011270000413d000000000604004b0000113e0000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000012310000013d000004e10100004100000000001404350000049501000041000004950240009c00000000040180190000004001400210000004c0011001c70000125000010430000000400200043d0000001f0430018f0000000505300272000011540000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b0000114c0000413d000000000604004b000011630000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000012310000013d000004c50100004100000000001404350000000401400039000000080200002900000000002104350000049501000041000004950240009c00000000040180190000004001400210000004bc011001c70000125000010430000004bf0100004100000000001804350000049501000041000004950280009c00000000080180190000004001800210000004c0011001c700001250000104300000001f0430018f0000000502300272000011820000613d00000000050000190000000506500210000000000761034f000000000707043b00000000007604350000000105500039000000000625004b0000117b0000413d000000000504004b000011900000613d00000003044002100000000502200210000000000502043300000000054501cf000000000545022f000000000121034f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f000000000012043500000060013002100000125000010430000000400200043d000000000301001900000060033002700000001f0430018f00000495033001970000000505300272000011a20000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b0000119a0000413d000000000604004b000011b10000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000012310000013d000000400200043d000000000301001900000060033002700000001f0430018f00000495033001970000000505300272000011c20000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000011ba0000413d000000000604004b000011d10000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000012310000013d000000400200043d000000000301001900000060033002700000001f0430018f00000495033001970000000505300272000011e20000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000011da0000413d000000000604004b000011f10000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000012310000013d000000400200043d000000000301001900000060033002700000001f0430018f00000495033001970000000505300272000012020000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b000011fa0000413d000000000604004b000012110000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f0000000000150435000012310000013d000000400200043d000000000301001900000060033002700000001f0430018f00000495033001970000000505300272000012220000613d000000000600001900000005076002100000000008720019000000000771034f000000000707043b00000000007804350000000106600039000000000756004b0000121a0000413d000000000604004b000012310000613d0000000505500210000000000151034f00000000055200190000000304400210000000000605043300000000064601cf000000000646022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000161019f00000000001504350000049501000041000004950420009c000000000201801900000040012002100000006002300210000000000121019f0000125000010430000000000001042f0000123c002104210000000102000039000000000001042d0000000002000019000000000001042d00001241002104230000000102000039000000000001042d0000000002000019000000000001042d00001246002104230000000102000039000000000001042d0000000002000019000000000001042d000000000f0d00190000124c002104290000000102000039000000000001042d0000000002000019000000000001042d0000124e000004320000124f0001042e000012500001043000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffff0000000200000000000000000000000000000040000001000000000000000000000000000000000000000000000000000000000000000000000000009c4d535a00000000000000000000000000000000000000000000000000000000ec8067c600000000000000000000000000000000000000000000000000000000ec8067c700000000000000000000000000000000000000000000000000000000ecf95b8a00000000000000000000000000000000000000000000000000000000f3385fb6000000000000000000000000000000000000000000000000000000009c4d535b00000000000000000000000000000000000000000000000000000000bb0fd61000000000000000000000000000000000000000000000000000000000e9f18c17000000000000000000000000000000000000000000000000000000005d3826ff000000000000000000000000000000000000000000000000000000005d382700000000000000000000000000000000000000000000000000000000007b510fe80000000000000000000000000000000000000000000000000000000084da1fb400000000000000000000000000000000000000000000000000000000187598a5000000000000000000000000000000000000000000000000000000003cda33510000000000000000000000000000000000000000000000000000000057180981000000000000000000000000000000000000000000000000ffffffffffffffff8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffff8e4a23d60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000240000008000000000000000004c6314f0000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000040000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff1806aa1896bbf26568e884a7374b41e002500962caba6a15023a8d90e8508b830200000200000000000000000000000000000024000000000000000000000000579952fc0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000640000000000000000000000004f1e1be000000000000000000000000000000000000000000000000000000000ff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004400000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000010000000000000000ffffffff000000000000000000000000000000000000000000000000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001ffffffe0c2e4ff97000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffbfad7e232e0000000000000000000000000000000000000000000000000000000035278d12000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000536ec84b000000000000000000000000000000000000000000000000000000000d4651aa000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000290afdae231a3fc0bbae8b1af63698b0a1d79b21ad17df0342dfb952fe74f8e53e5efef900000000000000000000000000000000000000000000000000000000306395c600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000060b85677000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000020000000000000000000000000c7544194dab38b1652f35439b9b4806d8b71e113f2cf5c1351cb2ecf7c83959af3385fb60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fffffefb00000000000000000000000000000000000001040000000000000000000000004e487b7100000000000000000000000000000000000000000000000000000000460b9939000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044000000800000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffff00004de2e46800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffc000000000000000000000000000000000000000400000000000000000000000003fb6f4f15ddd4a75588ca934894ad2cdcab25a5012e2515e1783433d0128611a71c3da0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000080000000000000000000000001000000000000000000000000000000000000000000000000000000005cb045db000000000000000000000000000000000000000000000000000000002020dba91b30cc0006188af794c2fb30dd8520db7e2c088b7fc7c103c00ca494000000000000000000000000000000000000000000000000ffffffffffffff3f63bae3a9951d38e8a3fbb7b70909afc1200610fc5bc55ade242f815974674f23000000000000000000000000000000000000000000000000ffffffffffffff80e03fe177000000000000000000000000000000000000000000000000000000009e4a3c8a000000000000000000000000000000000000000000000000000000005aa9b6b500000000000000000000000000000000000000000000000000000000760a15680000000000000000000000000000000000000000000000000000000050df6bc3000000000000000000000000000000000000000000000000000000001c25715b00000000000000000000000000000000000000000000000000000000f545bc1a33cf9a5fc79da6931445ede690a66fc7767ba66bf7a22f153dc4e8bc"; diff --git a/l2-contracts/test/systems-typechain/index.ts b/l2-contracts/test/systems-typechain/index.ts new file mode 100644 index 000000000..0052ea0eb --- /dev/null +++ b/l2-contracts/test/systems-typechain/index.ts @@ -0,0 +1,5 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ +export { ContractDeployerFactory } from "./ContractDeployerFactory"; +export type { ContractDeployer } from "./ContractDeployer"; diff --git a/l2-contracts/test/test-utils.ts b/l2-contracts/test/test-utils.ts index 152d01a51..241a32a49 100644 --- a/l2-contracts/test/test-utils.ts +++ b/l2-contracts/test/test-utils.ts @@ -2,7 +2,6 @@ import { ethers } from "ethers"; import * as hre from "hardhat"; import * as zksync from "zksync-ethers"; import type { BytesLike } from "ethers"; - import { ContractDeployerFactory } from "../typechain/ContractDeployerFactory"; const L1_TO_L2_ALIAS_OFFSET = "0x1111000000000000000000000000000000001111";