MerkleProof.sol 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. // SPDX-License-Identifier: MIT
  2. // OpenZeppelin Contracts (last updated v4.6.0) (utils/cryptography/MerkleProof.sol)
  3. pragma solidity ^0.8.0;
  4. /**
  5. * @dev These functions deal with verification of Merkle Trees proofs.
  6. *
  7. * The proofs can be generated using the JavaScript library
  8. * https://github.com/miguelmota/merkletreejs[merkletreejs].
  9. * Note: the hashing algorithm should be keccak256 and pair sorting should be enabled.
  10. *
  11. * See `test/utils/cryptography/MerkleProof.test.js` for some examples.
  12. *
  13. * WARNING: You should avoid using leaf values that are 64 bytes long prior to
  14. * hashing, or use a hash function other than keccak256 for hashing leaves.
  15. * This is because the concatenation of a sorted pair of internal nodes in
  16. * the merkle tree could be reinterpreted as a leaf value.
  17. */
  18. library MerkleProof {
  19. /**
  20. * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
  21. * defined by `root`. For this, a `proof` must be provided, containing
  22. * sibling hashes on the branch from the leaf to the root of the tree. Each
  23. * pair of leaves and each pair of pre-images are assumed to be sorted.
  24. */
  25. function verify(
  26. bytes32[] memory proof,
  27. bytes32 root,
  28. bytes32 leaf
  29. ) internal pure returns (bool) {
  30. return processProof(proof, leaf) == root;
  31. }
  32. /**
  33. * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up
  34. * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt
  35. * hash matches the root of the tree. When processing the proof, the pairs
  36. * of leafs & pre-images are assumed to be sorted.
  37. *
  38. * _Available since v4.4._
  39. */
  40. function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {
  41. bytes32 computedHash = leaf;
  42. for (uint256 i = 0; i < proof.length; i++) {
  43. bytes32 proofElement = proof[i];
  44. if (computedHash <= proofElement) {
  45. // Hash(current computed hash + current element of the proof)
  46. computedHash = _efficientHash(computedHash, proofElement);
  47. } else {
  48. // Hash(current element of the proof + current computed hash)
  49. computedHash = _efficientHash(proofElement, computedHash);
  50. }
  51. }
  52. return computedHash;
  53. }
  54. function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {
  55. /// @solidity memory-safe-assembly
  56. assembly {
  57. mstore(0x00, a)
  58. mstore(0x20, b)
  59. value := keccak256(0x00, 0x40)
  60. }
  61. }
  62. }