diff --git a/contracts/utils/cryptography/MerkleProof.sol b/contracts/utils/cryptography/MerkleProof.sol index 19b09e2af65..a98b8ea8a8c 100644 --- a/contracts/utils/cryptography/MerkleProof.sol +++ b/contracts/utils/cryptography/MerkleProof.sol @@ -217,26 +217,25 @@ library MerkleProof { revert MerkleProofInvalidMultiproof(); } - // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using - // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". - bytes32[] memory hashes = new bytes32[](proofFlagsLen); - uint256 leafPos = 0; - uint256 hashPos = 0; - uint256 proofPos = 0; - // At each step, we compute the next hash using two values: - // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we - // get the next hash. - // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the - // `proof` array. - for (uint256 i = 0; i < proofFlagsLen; i++) { - bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; - bytes32 b = proofFlags[i] - ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]) - : proof[proofPos++]; - hashes[i] = Hashes.commutativeKeccak256(a, b); - } - if (proofFlagsLen > 0) { + // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using + // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". + bytes32[] memory hashes = new bytes32[](proofFlagsLen); + uint256 leafPos = 0; + uint256 hashPos = 0; + uint256 proofPos = 0; + // At each step, we compute the next hash using two values: + // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we + // get the next hash. + // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the + // `proof` array. + for (uint256 i = 0; i < proofFlagsLen; i++) { + bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; + bytes32 b = proofFlags[i] + ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]) + : proof[proofPos++]; + hashes[i] = Hashes.commutativeKeccak256(a, b); + } if (proofPos != proof.length) { revert MerkleProofInvalidMultiproof(); } @@ -305,26 +304,25 @@ library MerkleProof { revert MerkleProofInvalidMultiproof(); } - // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using - // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". - bytes32[] memory hashes = new bytes32[](proofFlagsLen); - uint256 leafPos = 0; - uint256 hashPos = 0; - uint256 proofPos = 0; - // At each step, we compute the next hash using two values: - // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we - // get the next hash. - // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the - // `proof` array. - for (uint256 i = 0; i < proofFlagsLen; i++) { - bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; - bytes32 b = proofFlags[i] - ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]) - : proof[proofPos++]; - hashes[i] = hasher(a, b); - } - if (proofFlagsLen > 0) { + // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using + // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". + bytes32[] memory hashes = new bytes32[](proofFlagsLen); + uint256 leafPos = 0; + uint256 hashPos = 0; + uint256 proofPos = 0; + // At each step, we compute the next hash using two values: + // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we + // get the next hash. + // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the + // `proof` array. + for (uint256 i = 0; i < proofFlagsLen; i++) { + bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; + bytes32 b = proofFlags[i] + ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]) + : proof[proofPos++]; + hashes[i] = hasher(a, b); + } if (proofPos != proof.length) { revert MerkleProofInvalidMultiproof(); } @@ -391,26 +389,25 @@ library MerkleProof { revert MerkleProofInvalidMultiproof(); } - // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using - // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". - bytes32[] memory hashes = new bytes32[](proofFlagsLen); - uint256 leafPos = 0; - uint256 hashPos = 0; - uint256 proofPos = 0; - // At each step, we compute the next hash using two values: - // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we - // get the next hash. - // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the - // `proof` array. - for (uint256 i = 0; i < proofFlagsLen; i++) { - bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; - bytes32 b = proofFlags[i] - ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]) - : proof[proofPos++]; - hashes[i] = Hashes.commutativeKeccak256(a, b); - } - if (proofFlagsLen > 0) { + // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using + // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". + bytes32[] memory hashes = new bytes32[](proofFlagsLen); + uint256 leafPos = 0; + uint256 hashPos = 0; + uint256 proofPos = 0; + // At each step, we compute the next hash using two values: + // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we + // get the next hash. + // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the + // `proof` array. + for (uint256 i = 0; i < proofFlagsLen; i++) { + bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; + bytes32 b = proofFlags[i] + ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]) + : proof[proofPos++]; + hashes[i] = Hashes.commutativeKeccak256(a, b); + } if (proofPos != proof.length) { revert MerkleProofInvalidMultiproof(); } @@ -479,26 +476,25 @@ library MerkleProof { revert MerkleProofInvalidMultiproof(); } - // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using - // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". - bytes32[] memory hashes = new bytes32[](proofFlagsLen); - uint256 leafPos = 0; - uint256 hashPos = 0; - uint256 proofPos = 0; - // At each step, we compute the next hash using two values: - // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we - // get the next hash. - // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the - // `proof` array. - for (uint256 i = 0; i < proofFlagsLen; i++) { - bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; - bytes32 b = proofFlags[i] - ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]) - : proof[proofPos++]; - hashes[i] = hasher(a, b); - } - if (proofFlagsLen > 0) { + // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using + // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". + bytes32[] memory hashes = new bytes32[](proofFlagsLen); + uint256 leafPos = 0; + uint256 hashPos = 0; + uint256 proofPos = 0; + // At each step, we compute the next hash using two values: + // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we + // get the next hash. + // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the + // `proof` array. + for (uint256 i = 0; i < proofFlagsLen; i++) { + bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; + bytes32 b = proofFlags[i] + ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]) + : proof[proofPos++]; + hashes[i] = hasher(a, b); + } if (proofPos != proof.length) { revert MerkleProofInvalidMultiproof(); } diff --git a/scripts/generate/templates/MerkleProof.js b/scripts/generate/templates/MerkleProof.js index 890b2febac4..292fef34c7f 100644 --- a/scripts/generate/templates/MerkleProof.js +++ b/scripts/generate/templates/MerkleProof.js @@ -138,26 +138,25 @@ function processMultiProof${suffix}(${formatArgsMultiline( revert MerkleProofInvalidMultiproof(); } - // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using - // \`xxx[xxxPos++]\`, which return the current value and increment the pointer, thus mimicking a queue's "pop". - bytes32[] memory hashes = new bytes32[](proofFlagsLen); - uint256 leafPos = 0; - uint256 hashPos = 0; - uint256 proofPos = 0; - // At each step, we compute the next hash using two values: - // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we - // get the next hash. - // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the - // \`proof\` array. - for (uint256 i = 0; i < proofFlagsLen; i++) { - bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; - bytes32 b = proofFlags[i] - ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]) - : proof[proofPos++]; - hashes[i] = ${hash ?? DEFAULT_HASH}(a, b); - } - if (proofFlagsLen > 0) { + // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using + // \`xxx[xxxPos++]\`, which return the current value and increment the pointer, thus mimicking a queue's "pop". + bytes32[] memory hashes = new bytes32[](proofFlagsLen); + uint256 leafPos = 0; + uint256 hashPos = 0; + uint256 proofPos = 0; + // At each step, we compute the next hash using two values: + // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we + // get the next hash. + // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the + // \`proof\` array. + for (uint256 i = 0; i < proofFlagsLen; i++) { + bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; + bytes32 b = proofFlags[i] + ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]) + : proof[proofPos++]; + hashes[i] = ${hash ?? DEFAULT_HASH}(a, b); + } if (proofPos != proof.length) { revert MerkleProofInvalidMultiproof(); }