github-actions 5 hónapja
szülő
commit
da7fd0d3e5
100 módosított fájl, 2109 hozzáadás és 433 törlés
  1. 0 8
      .githooks/pre-push
  2. 6 5
      .github/actions/gas-compare/action.yml
  3. 1 1
      .github/actions/setup/action.yml
  4. 2 1
      .github/actions/storage-layout/action.yml
  5. 2 6
      .github/workflows/checks.yml
  6. 1 1
      .github/workflows/formal-verification.yml
  7. 1 0
      .gitignore
  8. 2 0
      .husky/pre-commit
  9. 62 3
      CHANGELOG.md
  10. 3 0
      FUNDING.json
  11. 1 1
      GUIDELINES.md
  12. 1 1
      LICENSE
  13. 2 2
      README.md
  14. 2 2
      RELEASING.md
  15. 1 1
      SECURITY.md
  16. 5 5
      audits/2017-03.md
  17. BIN
      audits/2024-12-v5.2.pdf
  18. 9 8
      audits/README.md
  19. 2 2
      certora/README.md
  20. 27 19
      certora/run.js
  21. 2 2
      certora/specs/AccessControlDefaultAdminRules.spec
  22. 3 3
      certora/specs/ERC20FlashMint.spec
  23. 2 2
      contracts/access/AccessControl.sol
  24. 2 2
      contracts/access/IAccessControl.sol
  25. 14 10
      contracts/access/manager/AuthorityUtils.sol
  26. 26 37
      contracts/account/utils/draft-ERC4337Utils.sol
  27. 5 3
      contracts/account/utils/draft-ERC7579Utils.sol
  28. 2 2
      contracts/finance/VestingWallet.sol
  29. 34 15
      contracts/governance/Governor.sol
  30. 20 7
      contracts/governance/IGovernor.sol
  31. 16 4
      contracts/governance/README.adoc
  32. 2 2
      contracts/governance/TimelockController.sol
  33. 4 4
      contracts/governance/extensions/GovernorCountingFractional.sol
  34. 18 18
      contracts/governance/extensions/GovernorCountingOverridable.sol
  35. 58 0
      contracts/governance/extensions/GovernorProposalGuardian.sol
  36. 77 0
      contracts/governance/extensions/GovernorSequentialProposalId.sol
  37. 2 2
      contracts/governance/extensions/GovernorStorage.sol
  38. 60 0
      contracts/governance/extensions/GovernorSuperQuorum.sol
  39. 2 2
      contracts/governance/extensions/GovernorTimelockAccess.sol
  40. 2 2
      contracts/governance/extensions/GovernorTimelockCompound.sol
  41. 2 2
      contracts/governance/extensions/GovernorTimelockControl.sol
  42. 17 14
      contracts/governance/extensions/GovernorVotesQuorumFraction.sol
  43. 134 0
      contracts/governance/extensions/GovernorVotesSuperQuorumFraction.sol
  44. 2 2
      contracts/interfaces/IERC1271.sol
  45. 2 2
      contracts/interfaces/IERC4626.sol
  46. 15 1
      contracts/interfaces/README.adoc
  47. 4 4
      contracts/interfaces/draft-IERC4337.sol
  48. 125 0
      contracts/interfaces/draft-IERC6909.sol
  49. 7 7
      contracts/interfaces/draft-IERC7579.sol
  50. 5 2
      contracts/metatx/ERC2771Forwarder.sol
  51. 5 5
      contracts/mocks/AuthorityMock.sol
  52. 8 0
      contracts/mocks/MerkleTreeMock.sol
  53. 2 2
      contracts/mocks/docs/access-control/AccessControlModified.sol
  54. 26 0
      contracts/mocks/docs/token/ERC6909/ERC6909GameItems.sol
  55. 27 0
      contracts/mocks/governance/GovernorProposalGuardianMock.sol
  56. 39 0
      contracts/mocks/governance/GovernorSequentialProposalIdMock.sol
  57. 95 0
      contracts/mocks/governance/GovernorSuperQuorumMock.sol
  58. 37 0
      contracts/mocks/governance/GovernorVotesSuperQuorumFractionMock.sol
  59. 1 1
      contracts/mocks/token/ERC20ForceApproveMock.sol
  60. 1 1
      contracts/package.json
  61. 4 4
      contracts/proxy/Clones.sol
  62. 13 3
      contracts/proxy/utils/Initializable.sol
  63. 1 2
      contracts/proxy/utils/UUPSUpgradeable.sol
  64. 3 3
      contracts/token/ERC1155/IERC1155.sol
  65. 3 3
      contracts/token/ERC1155/utils/ERC1155Utils.sol
  66. 4 5
      contracts/token/ERC20/ERC20.sol
  67. 5 5
      contracts/token/ERC20/README.adoc
  68. 7 7
      contracts/token/ERC20/extensions/ERC4626.sol
  69. 2 2
      contracts/token/ERC20/extensions/draft-ERC20TemporaryApproval.sol
  70. 15 1
      contracts/token/ERC20/utils/SafeERC20.sol
  71. 27 0
      contracts/token/ERC6909/README.adoc
  72. 224 0
      contracts/token/ERC6909/draft-ERC6909.sol
  73. 53 0
      contracts/token/ERC6909/extensions/draft-ERC6909ContentURI.sol
  74. 77 0
      contracts/token/ERC6909/extensions/draft-ERC6909Metadata.sol
  75. 35 0
      contracts/token/ERC6909/extensions/draft-ERC6909TokenSupply.sol
  76. 2 2
      contracts/token/ERC721/README.adoc
  77. 2 2
      contracts/token/ERC721/extensions/ERC721Consecutive.sol
  78. 2 2
      contracts/token/ERC721/extensions/ERC721URIStorage.sol
  79. 2 2
      contracts/token/ERC721/utils/ERC721Utils.sol
  80. 2 2
      contracts/token/common/ERC2981.sol
  81. 4 4
      contracts/utils/Arrays.sol
  82. 25 0
      contracts/utils/Calldata.sol
  83. 3 3
      contracts/utils/Multicall.sol
  84. 1 8
      contracts/utils/Pausable.sol
  85. 13 4
      contracts/utils/README.adoc
  86. 2 2
      contracts/utils/ReentrancyGuardTransient.sol
  87. 3 3
      contracts/utils/ShortStrings.sol
  88. 2 2
      contracts/utils/SlotDerivation.sol
  89. 59 10
      contracts/utils/Strings.sol
  90. 6 6
      contracts/utils/TransientSlot.sol
  91. 4 2
      contracts/utils/cryptography/EIP712.sol
  92. 3 3
      contracts/utils/cryptography/Hashes.sol
  93. 18 3
      contracts/utils/cryptography/MessageHashUtils.sol
  94. 41 3
      contracts/utils/cryptography/P256.sol
  95. 162 98
      contracts/utils/math/Math.sol
  96. 4 4
      contracts/utils/structs/Checkpoints.sol
  97. 2 2
      contracts/utils/structs/CircularBuffer.sol
  98. 96 1
      contracts/utils/structs/EnumerableMap.sol
  99. 48 1
      contracts/utils/structs/EnumerableSet.sol
  100. 95 3
      contracts/utils/structs/MerkleTree.sol

+ 0 - 8
.githooks/pre-push

@@ -1,8 +0,0 @@
-#!/usr/bin/env bash
-
-set -euo pipefail
-
-if [ "${CI:-"false"}" != "true" ]; then
-  npm run test:generation
-  npm run lint
-fi

+ 6 - 5
.github/actions/gas-compare/action.yml

@@ -2,18 +2,18 @@ name: Compare gas costs
 description: Compare gas costs between branches
 description: Compare gas costs between branches
 inputs:
 inputs:
   token:
   token:
-    description: github token
+    description: GitHub token, required to access GitHub API
     required: true
     required: true
   report:
   report:
-    description: report to read from
+    description: Path to the report to compare
     required: false
     required: false
     default: gasReporterOutput.json
     default: gasReporterOutput.json
   out_report:
   out_report:
-    description: report to read
+    description: Path to save the output report
     required: false
     required: false
     default: ${{ github.ref_name }}.gasreport.json
     default: ${{ github.ref_name }}.gasreport.json
   ref_report:
   ref_report:
-    description: report to read from
+    description: Path to the reference report for comparison
     required: false
     required: false
     default: ${{ github.base_ref }}.gasreport.json
     default: ${{ github.base_ref }}.gasreport.json
 
 
@@ -44,7 +44,8 @@ runs:
       shell: bash
       shell: bash
     - name: Save report
     - name: Save report
       if: github.event_name != 'pull_request'
       if: github.event_name != 'pull_request'
-      uses: actions/upload-artifact@v3
+      uses: actions/upload-artifact@v4
       with:
       with:
         name: gasreport
         name: gasreport
+        overwrite: true
         path: ${{ inputs.out_report }}
         path: ${{ inputs.out_report }}

+ 1 - 1
.github/actions/setup/action.yml

@@ -19,4 +19,4 @@ runs:
     - name: Install Foundry
     - name: Install Foundry
       uses: foundry-rs/foundry-toolchain@v1
       uses: foundry-rs/foundry-toolchain@v1
       with:
       with:
-        version: nightly
+        version: stable

+ 2 - 1
.github/actions/storage-layout/action.yml

@@ -50,7 +50,8 @@ runs:
       shell: bash
       shell: bash
     - name: Save artifacts
     - name: Save artifacts
       if: github.event_name != 'pull_request'
       if: github.event_name != 'pull_request'
-      uses: actions/upload-artifact@v3
+      uses: actions/upload-artifact@v4
       with:
       with:
         name: layout
         name: layout
+        overwrite: true
         path: ${{ inputs.out_layout }}
         path: ${{ inputs.out_layout }}

+ 2 - 6
.github/workflows/checks.yml

@@ -43,7 +43,7 @@ jobs:
         run: npm run test:inheritance
         run: npm run test:inheritance
       - name: Check pragma consistency between files
       - name: Check pragma consistency between files
         run: npm run test:pragma
         run: npm run test:pragma
-      - name: Check proceduraly generated contracts are up-to-date
+      - name: Check procedurally generated contracts are up-to-date
         run: npm run test:generation
         run: npm run test:generation
       - name: Compare gas costs
       - name: Compare gas costs
         uses: ./.github/actions/gas-compare
         uses: ./.github/actions/gas-compare
@@ -97,7 +97,7 @@ jobs:
         uses: ./.github/actions/setup
         uses: ./.github/actions/setup
       - name: Run coverage
       - name: Run coverage
         run: npm run coverage
         run: npm run coverage
-      - uses: codecov/codecov-action@v4
+      - uses: codecov/codecov-action@v5
         env:
         env:
           CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
           CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
 
 
@@ -118,11 +118,7 @@ jobs:
       - uses: actions/checkout@v4
       - uses: actions/checkout@v4
       - name: Set up environment
       - name: Set up environment
         uses: ./.github/actions/setup
         uses: ./.github/actions/setup
-      - run: rm foundry.toml
       - uses: crytic/slither-action@v0.4.0
       - uses: crytic/slither-action@v0.4.0
-        with:
-          node-version: 18.15
-          slither-version: 0.10.1
 
 
   codespell:
   codespell:
     runs-on: ubuntu-latest
     runs-on: ubuntu-latest

+ 1 - 1
.github/workflows/formal-verification.yml

@@ -52,7 +52,7 @@ jobs:
       - name: Install python packages
       - name: Install python packages
         run: pip install -r fv-requirements.txt
         run: pip install -r fv-requirements.txt
       - name: Install java
       - name: Install java
-        uses: actions/setup-java@v3
+        uses: actions/setup-java@v4
         with:
         with:
           distribution: temurin
           distribution: temurin
           java-version: ${{ env.JAVA_VERSION }}
           java-version: ${{ env.JAVA_VERSION }}

+ 1 - 0
.gitignore

@@ -37,6 +37,7 @@ npm-debug.log
 
 
 # docs artifacts
 # docs artifacts
 docs/modules/api
 docs/modules/api
+build/site
 
 
 # only used to package @openzeppelin/contracts
 # only used to package @openzeppelin/contracts
 contracts/build/
 contracts/build/

+ 2 - 0
.husky/pre-commit

@@ -0,0 +1,2 @@
+npm run test:generation
+npx lint-staged

+ 62 - 3
CHANGELOG.md

@@ -1,5 +1,64 @@
 # Changelog
 # Changelog
 
 
+## 5.3.0 (2025-04-09)
+
+### Breaking Changes
+
+- Replace `GovernorCountingOverridable.VoteReceipt` struct parameter member names `hasOverriden` and `overridenWeight` for `hasOverridden` and `overriddenWeight` respectively.
+
+#### Custom error changes
+
+- Replace `AccessControlNonRevokable` with `AccessControlNonRevocable`.
+- Replace `GovernorAlreadyOverridenVote` with `GovernorAlreadyOverriddenVote`.
+- Replace `GovernorOnlyProposer` with `GovernorUnableToCancel`.
+
+### Changes by category
+
+#### Account
+
+- `ERC4337Utils`: Update the `hash` function to call `getUserOpHash` on the specified entrypoint and add an `ENTRYPOINT_V08` constant. ([#5614](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5614))
+- `ERC7579Utils`: Add ABI decoding checks on calldata bounds within `decodeBatch`. ([#5371](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5371))
+- `ERC7579Utils`: Replace `address(0)` with `address(this)` during execution for calldata compression efficiency. ([#5614](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5614))
+
+#### Governance
+
+- `IGovernor`: Add the `getProposalId` function to the governor interface. ([#5290](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5290))
+- `GovernorProposalGuardian`: Add a governance extension that defines a proposal guardian who can cancel proposals at any stage in their lifecycle. ([#5303](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5303))
+- `GovernorSequentialProposalId`: Adds a `Governor` extension that sequentially numbers proposal ids instead of using the hash. ([#5290](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5290))
+- `GovernorSuperQuorum`: Add a governance extension to support a super quorum. Proposals that meet the super quorum (and have a majority of for votes) advance to the `Succeeded` state before the proposal deadline. ([#5526](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5526))
+- `GovernorVotesSuperQuorumFraction`: Add a variant of the `GovernorSuperQuorum` extensions where the super quorum is expressed as a fraction of the total supply. ([#5526](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5526))
+- `TimelockController`: Receive function is now virtual. ([#5509](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5509))
+
+#### Structures
+
+- `EnumerableSet`: Add `clear` function to EnumerableSets which deletes all values in the set. ([#5486](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5486))
+- `EnumerableMap`: Add `clear` function to EnumerableMaps which deletes all entries in the map. ([#5486](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5486))
+- `MerkleTree`: Add an update function that replaces a previously inserted leaf with a new value, updating the tree root along the way. ([#5526](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5526))
+
+#### Tokens
+
+- `ERC4626`: Use the `asset` getter in `totalAssets`, `_deposit` and `_withdraw`. ([#5322](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5322))
+- `IERC6909`: Add the interface for ERC-6909. ([#5343](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5343))
+- `ERC6909`: Add a standard implementation of ERC6909. ([#5394](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5394))
+- `ERC6909TokenSupply`: Add an extension of ERC6909 which tracks total supply for each token id. ([#5394](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5394))
+- `ERC6909Metadata`: Add an extension of ERC6909 which adds metadata functionality. ([#5394](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5394))
+- `ERC6909ContentURI`: Add an extension of ERC6909 which adds content URI functionality. ([#5394](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5394))
+- `SafeERC20`: Add `trySafeTransfer` and `trySafeTransferFrom` that do not revert and return false if the transfer is not successful. ([#5483](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5483))
+
+#### Other
+
+- `Address`: bubble up revert data on `sendValue` failed call. ([#5379](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5379))
+- `Calldata`: Library with `emptyBytes` and `emptyString` functions to generate empty `bytes` and `string` calldata types. ([#5422](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5422))
+- `ERC2771Forwarder`: Expose the `_isTrustedByTarget` internal function to check whether a target trusts the forwarder. ([#5416](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5416))
+- `Hashes`: Expose `efficientKeccak256` for hashing non-commutative pairs of bytes32 without allocating extra memory. ([#5442](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5442))
+- `Initializable`: Add `_initializableStorageSlot` function that returns a pointer to the storage struct. The function allows customizing with a custom storage slot with an `override`. ([#5526](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5526))
+- `Math`: Add `add512`, `mul512` and `mulShr`. ([#5526](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5526))
+- `Math`: Add saturating arithmetic operations `saturatingAdd`, `saturatingSub` and `saturatingMul`. ([#5526](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5526))
+- `MessageHashUtils`: Add `toDataWithIntendedValidatorHash(address, bytes32)`. ([#5526](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5526))
+- `P256`: Adjust precompile detection in `verifyNative` to consider empty `returndata` on invalid verification. Previously, invalid signatures would've reverted with a `MissingPrecompile` error in chains with RIP-7212 support. ([#5620](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5620))
+- `Pausable`: Stop explicitly setting `paused` to `false` during construction. ([#5448](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5448))
+- `Strings`: Add `espaceJSON` that escapes special characters in JSON strings. ([#5526](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5526))
+
 ## 5.2.0 (2025-01-08)
 ## 5.2.0 (2025-01-08)
 
 
 ### Breaking Changes
 ### Breaking Changes
@@ -37,7 +96,7 @@ This version comes with changes to the custom error identifiers. Contracts previ
 ### Utils
 ### Utils
 
 
 - `Address`: bubble up revert data on `sendValue` failed call ([#5418](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5418))
 - `Address`: bubble up revert data on `sendValue` failed call ([#5418](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5418))
-- `Bytes`: Add a library of common operation that operate on `bytes` objects. ([#5252](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5252))
+- `Bytes`: Add a library of common operations that operate on `bytes` objects. ([#5252](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5252))
 - `CAIP2` and `CAIP10`: Add libraries for formatting and parsing CAIP-2 and CAIP-10 identifiers. ([#5252](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5252))
 - `CAIP2` and `CAIP10`: Add libraries for formatting and parsing CAIP-2 and CAIP-10 identifiers. ([#5252](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5252))
 - `NoncesKeyed`: Add a variant of `Nonces` that implements the ERC-4337 entrypoint nonce system. ([#5272](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5272))
 - `NoncesKeyed`: Add a variant of `Nonces` that implements the ERC-4337 entrypoint nonce system. ([#5272](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5272))
 - `Packing`: Add variants for packing `bytes10` and `bytes22` ([#5274](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5274))
 - `Packing`: Add variants for packing `bytes10` and `bytes22` ([#5274](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5274))
@@ -48,7 +107,7 @@ This version comes with changes to the custom error identifiers. Contracts previ
 ### Breaking changes
 ### Breaking changes
 
 
 - `ERC1967Utils`: Removed duplicate declaration of the `Upgraded`, `AdminChanged` and `BeaconUpgraded` events. These events are still available through the `IERC1967` interface located under the `contracts/interfaces/` directory. Minimum pragma version is now 0.8.21.
 - `ERC1967Utils`: Removed duplicate declaration of the `Upgraded`, `AdminChanged` and `BeaconUpgraded` events. These events are still available through the `IERC1967` interface located under the `contracts/interfaces/` directory. Minimum pragma version is now 0.8.21.
-- `Governor`, `GovernorCountingSimple`: The `_countVote` virtual function now returns an `uint256` with the total votes casted. This change allows for more flexibility for partial and fractional voting. Upgrading users may get a compilation error that can be fixed by adding a return statement to the `_countVote` function.
+- `Governor`, `GovernorCountingSimple`: The `_countVote` virtual function now returns an `uint256` with the total votes cast. This change allows for more flexibility for partial and fractional voting. Upgrading users may get a compilation error that can be fixed by adding a return statement to the `_countVote` function.
 
 
 #### Custom error changes
 #### Custom error changes
 
 
@@ -419,7 +478,7 @@ Instead, contracts now revert with custom errors. Systems that interact with sma
 
 
 ##### Relying on storage locations for retrieving data
 ##### Relying on storage locations for retrieving data
 
 
-After 5.0, the storage location of some variables were changed. This is the case for `Initializable` and all the upgradeable contracts since they now use namespaced storaged locations. Any system relying on storage locations for retrieving data or detecting capabilities should be updated to support these new locations.
+After 5.0, the storage location of some variables was changed. This is the case for `Initializable` and all the upgradeable contracts since they now use namespaced storage locations. Any system relying on storage locations for retrieving data or detecting capabilities should be updated to support these new locations.
 
 
 ## 4.9.6 (2024-02-29)
 ## 4.9.6 (2024-02-29)
 
 

+ 3 - 0
FUNDING.json

@@ -3,5 +3,8 @@
     "ethereum": {
     "ethereum": {
       "ownedBy": "0xAeb37910f93486C85A1F8F994b67E8187554d664"
       "ownedBy": "0xAeb37910f93486C85A1F8F994b67E8187554d664"
     }
     }
+  },
+  "opRetro": {
+    "projectId": "0x939241afa4c4b9e1dda6b8250baa8f04fa8b0debce738cfd324c0b18f9926d25"
   }
   }
 }
 }

+ 1 - 1
GUIDELINES.md

@@ -6,7 +6,7 @@ Code must be thoroughly tested with quality unit tests.
 
 
 We defer to the [Moloch Testing Guide](https://github.com/MolochVentures/moloch/tree/master/test#readme) for specific recommendations, though not all of it is relevant here. Note the introduction:
 We defer to the [Moloch Testing Guide](https://github.com/MolochVentures/moloch/tree/master/test#readme) for specific recommendations, though not all of it is relevant here. Note the introduction:
 
 
-> Tests should be written, not only to verify correctness of the target code, but to be comprehensively reviewed by other programmers. Therefore, for mission critical Solidity code, the quality of the tests are just as important (if not more so) than the code itself, and should be written with the highest standards of clarity and elegance.
+> Tests should be written, not only to verify correctness of the target code, but to be comprehensively reviewed by other programmers. Therefore, for mission critical Solidity code, the quality of the tests is just as important (if not more so) than the code itself, and should be written to the highest standards of clarity and elegance.
 
 
 Every addition or change to the code must come with relevant and comprehensive tests.
 Every addition or change to the code must come with relevant and comprehensive tests.
 
 

+ 1 - 1
LICENSE

@@ -1,6 +1,6 @@
 The MIT License (MIT)
 The MIT License (MIT)
 
 
-Copyright (c) 2016-2024 Zeppelin Group Ltd
+Copyright (c) 2016-2025 Zeppelin Group Ltd
 
 
 Permission is hereby granted, free of charge, to any person obtaining
 Permission is hereby granted, free of charge, to any person obtaining
 a copy of this software and associated documentation files (the
 a copy of this software and associated documentation files (the

+ 2 - 2
README.md

@@ -4,7 +4,7 @@
 [![Coverage Status](https://codecov.io/gh/OpenZeppelin/openzeppelin-contracts/graph/badge.svg)](https://codecov.io/gh/OpenZeppelin/openzeppelin-contracts)
 [![Coverage Status](https://codecov.io/gh/OpenZeppelin/openzeppelin-contracts/graph/badge.svg)](https://codecov.io/gh/OpenZeppelin/openzeppelin-contracts)
 [![GitPOAPs](https://public-api.gitpoap.io/v1/repo/OpenZeppelin/openzeppelin-contracts/badge)](https://www.gitpoap.io/gh/OpenZeppelin/openzeppelin-contracts)
 [![GitPOAPs](https://public-api.gitpoap.io/v1/repo/OpenZeppelin/openzeppelin-contracts/badge)](https://www.gitpoap.io/gh/OpenZeppelin/openzeppelin-contracts)
 [![Docs](https://img.shields.io/badge/docs-%F0%9F%93%84-yellow)](https://docs.openzeppelin.com/contracts)
 [![Docs](https://img.shields.io/badge/docs-%F0%9F%93%84-yellow)](https://docs.openzeppelin.com/contracts)
-[![Forum](https://img.shields.io/badge/forum-%F0%9F%92%AC-yellow)](https://docs.openzeppelin.com/contracts)
+[![Forum](https://img.shields.io/badge/forum-%F0%9F%92%AC-yellow)](https://forum.openzeppelin.com/)
 
 
 **A library for secure smart contract development.** Build on a solid foundation of community-vetted code.
 **A library for secure smart contract development.** Build on a solid foundation of community-vetted code.
 
 
@@ -70,7 +70,7 @@ The guides in the [documentation site](https://docs.openzeppelin.com/contracts)
 * [Tokens](https://docs.openzeppelin.com/contracts/tokens): create tradeable assets or collectives, and distribute them via [Crowdsales](https://docs.openzeppelin.com/contracts/crowdsales).
 * [Tokens](https://docs.openzeppelin.com/contracts/tokens): create tradeable assets or collectives, and distribute them via [Crowdsales](https://docs.openzeppelin.com/contracts/crowdsales).
 * [Utilities](https://docs.openzeppelin.com/contracts/utilities): generic useful tools including non-overflowing math, signature verification, and trustless paying systems.
 * [Utilities](https://docs.openzeppelin.com/contracts/utilities): generic useful tools including non-overflowing math, signature verification, and trustless paying systems.
 
 
-The [full API](https://docs.openzeppelin.com/contracts/api/token/ERC20) is also thoroughly documented, and serves as a great reference when developing your smart contract application. You can also ask for help or follow Contracts's development in the [community forum](https://forum.openzeppelin.com).
+The [full API](https://docs.openzeppelin.com/contracts/api/token/ERC20) is also thoroughly documented, and serves as a great reference when developing your smart contract application. You can also ask for help or follow Contracts' development in the [community forum](https://forum.openzeppelin.com).
 
 
 Finally, you may want to take a look at the [guides on our blog](https://blog.openzeppelin.com/), which cover several common use cases and good practices. The following articles provide great background reading, though please note that some of the referenced tools have changed, as the tooling in the ecosystem continues to rapidly evolve.
 Finally, you may want to take a look at the [guides on our blog](https://blog.openzeppelin.com/), which cover several common use cases and good practices. The following articles provide great background reading, though please note that some of the referenced tools have changed, as the tooling in the ecosystem continues to rapidly evolve.
 
 

+ 2 - 2
RELEASING.md

@@ -1,10 +1,10 @@
 # Releasing
 # Releasing
 
 
-OpenZeppelin Contracts uses a fully automated release process that takes care of compiling, packaging, and publishing the library, all of which is carried out in a clean CI environment (GitHub Actions), implemented in the ([`release-cycle`](.github/workflows/release-cycle.yml)) workflow. This helps to reduce the potential for human error and inconsistencies, and ensures that the release process is ongoing and reliable.
+OpenZeppelin Contracts uses a fully automated release process that takes care of compiling, packaging, and publishing the library, all of which is carried out in a clean CI environment (GitHub Actions), implemented in the [`release-cycle`](.github/workflows/release-cycle.yml) workflow. This helps to reduce the potential for human error and inconsistencies, and ensures that the release process is consistent and reliable.
 
 
 ## Changesets
 ## Changesets
 
 
-[Changesets](https://github.com/changesets/changesets/) is used as part of our release process for `CHANGELOG.md` management. Each change that is relevant for the codebase is expected to include a changeset.
+[Changesets](https://github.com/changesets/changesets/) are used as part of our release process for `CHANGELOG.md` management. Each change that is relevant for the codebase is expected to include a changeset.
 
 
 ## Branching model
 ## Branching model
 
 

+ 1 - 1
SECURITY.md

@@ -40,4 +40,4 @@ Note as well that the Solidity language itself only guarantees security updates
 
 
 ## Legal
 ## Legal
 
 
-Smart contracts are a nascent technology and carry a high level of technical risk and uncertainty. OpenZeppelin Contracts is made available under the MIT License, which disclaims all warranties in relation to the project and which limits the liability of those that contribute and maintain the project, including OpenZeppelin. Your use of the project is also governed by the terms found at www.openzeppelin.com/tos (the "Terms"). As set out in the Terms, you are solely responsible for any use of OpenZeppelin Contracts and you assume all risks associated with any such use. This Security Policy in no way evidences or represents an on-going duty by any contributor, including OpenZeppelin, to correct any flaws or alert you to all or any of the potential risks of utilizing the project.
+Smart contracts are a nascent technology and carry a high level of technical risk and uncertainty. OpenZeppelin Contracts is made available under the MIT License, which disclaims all warranties in relation to the project and which limits the liability of those that contribute and maintain the project, including OpenZeppelin. Your use of the project is also governed by the terms found at www.openzeppelin.com/tos (the "Terms"). As set out in the Terms, you are solely responsible for any use of OpenZeppelin Contracts and you assume all risks associated with any such use. This Security Policy in no way evidences or represents an ongoing duty by any contributor, including OpenZeppelin, to correct any flaws or alert you to all or any of the potential risks of utilizing the project.

+ 5 - 5
audits/2017-03.md

@@ -20,7 +20,7 @@ The git commit hash we evaluated is:
 
 
 # Disclaimer
 # Disclaimer
 
 
-The audit makes no statements or warrantees about utility of the code, safety of the code, suitability of the business model, regulatory regime for the business model, or any other statements about fitness of the contracts to purpose, or their bugfree status. The audit documentation is for discussion purposes only.
+The audit makes no statements or warranties about utility of the code, safety of the code, suitability of the business model, regulatory regime for the business model, or any other statements about fitness of the contracts to purpose, or their bug free status. The audit documentation is for discussion purposes only.
 
 
 # Executive Summary
 # Executive Summary
 
 
@@ -90,7 +90,7 @@ We are still working through the confirmation protocol in `Shareable.sol`, but w
 This bug has a number of causes that need to be addressed:
 This bug has a number of causes that need to be addressed:
 
 
 1. `resetSpentToday` and `confirm` together do not limit the days on which the function can be called or (it appears) the number of times it can be called.
 1. `resetSpentToday` and `confirm` together do not limit the days on which the function can be called or (it appears) the number of times it can be called.
-1. Once a call has been confirmed and `execute`d it appears that it can be re-executed. This is not good.
+1. Once a call has been confirmed and executed it appears that it can be re-executed. This is not good.
 3. `confirmandCheck` doesn't seem to have logic about whether or not the function in question has been called.
 3. `confirmandCheck` doesn't seem to have logic about whether or not the function in question has been called.
 4. Even if it did, `revoke` would need updates and logic to deal with revocation requests after a function call had been completed.
 4. Even if it did, `revoke` would need updates and logic to deal with revocation requests after a function call had been completed.
 
 
@@ -109,7 +109,7 @@ It would be nice to see how many payments are pending. This would imply a bit of
 
 
 ## Shareable Contract
 ## Shareable Contract
 
 
-We do not believe the `Shareable.sol` contract is ready for primetime. It is missing functions, and as written may be vulnerable to a reordering attack -- an attack in which a miner or other party "racing" with a smart contract participant inserts their own information into a list or mapping.
+We do not believe the `Shareable.sol` contract is ready for prime time. It is missing functions, and as written may be vulnerable to a reordering attack -- an attack in which a miner or other party "racing" with a smart contract participant inserts their own information into a list or mapping.
 
 
 The confirmation and revocation code needs to be looked over with a very careful eye imagining extraordinarily bad behavior by shared owners before this contract can be called safe.
 The confirmation and revocation code needs to be looked over with a very careful eye imagining extraordinarily bad behavior by shared owners before this contract can be called safe.
 
 
@@ -159,7 +159,7 @@ Allows owner to set a public string of contract information. No issues.
 
 
 This needs some work. Doesn't check if `_required <= len(_owners)` for instance, that would be a bummer. What if _required were like `MAX - 1`?
 This needs some work. Doesn't check if `_required <= len(_owners)` for instance, that would be a bummer. What if _required were like `MAX - 1`?
 
 
-I have a general concern about the difference between `owners`, `_owners`, and `owner` in `Ownable.sol`. I recommend "Owners" be renamed. In general we do not recomment single character differences in variable names, although a preceding underscore is not uncommon in Solidity code.
+I have a general concern about the difference between `owners`, `_owners`, and `owner` in `Ownable.sol`. I recommend "Owners" be renamed. In general we do not recommend single character differences in variable names, although a preceding underscore is not uncommon in Solidity code.
 
 
 Line 34: "this contract only has six types of events"...actually only two.
 Line 34: "this contract only has six types of events"...actually only two.
 
 
@@ -224,7 +224,7 @@ Transfer() and transferFrom() use SafeMath functions, which will cause them to t
 
 
 ### SimpleToken
 ### SimpleToken
 
 
-Sample instantiation of StandardToken. Note that in this sample, decimals is 18 and supply only 10,000, so the supply is a small fraction of a single nominal token.
+Sample instantiation of StandardToken. Note that in this sample, decimals is 18 and supply is only 10,000, so the supply is a small fraction of a single nominal token.
 
 
 ### CrowdsaleToken
 ### CrowdsaleToken
 
 

BIN
audits/2024-12-v5.2.pdf


+ 9 - 8
audits/README.md

@@ -1,13 +1,14 @@
 # Audits
 # Audits
 
 
-| Date         | Version | Commit    | Auditor      | Scope                | Links                                                       |
-| ------------ | ------- | --------- | ------------ | -------------------- | ----------------------------------------------------------- |
-| October 2024 | v5.1.0  | TBD       | OpenZeppelin | v5.1 Changes         | [🔗](./2024-10-v5.1.pdf)                                    |
-| October 2023 | v5.0.0  | `b5a3e69` | OpenZeppelin | v5.0 Changes         | [🔗](./2023-10-v5.0.pdf)                                    |
-| May 2023     | v4.9.0  | `91df66c` | OpenZeppelin | v4.9 Changes         | [🔗](./2023-05-v4.9.pdf)                                    |
-| October 2022 | v4.8.0  | `14f98db` | OpenZeppelin | ERC4626, Checkpoints | [🔗](./2022-10-ERC4626.pdf) [🔗](./2022-10-Checkpoints.pdf) |
-| October 2018 | v2.0.0  | `dac5bcc` | LevelK       | Everything           | [🔗](./2018-10.pdf)                                         |
-| March 2017   | v1.0.4  | `9c5975a` | New Alchemy  | Everything           | [🔗](./2017-03.md)                                          |
+| Date          | Version | Commit                                                                           | Auditor      | Scope                | Links                                                       |
+| ------------- | ------- | -------------------------------------------------------------------------------- | ------------ | -------------------- | ----------------------------------------------------------- |
+| December 2024 | v5.2.0  | [`98d28f9`](https://github.com/openzeppelin/openzeppelin-contracts/tree/98d28f9) | OpenZeppelin | v5.2 Changes         | [🔗](./2024-12-v5.2.pdf)                                    |
+| October 2024  | v5.1.0  | [`aba9ff6`](https://github.com/openzeppelin/openzeppelin-contracts/tree/aba9ff6) | OpenZeppelin | v5.1 Changes         | [🔗](./2024-10-v5.1.pdf)                                    |
+| October 2023  | v5.0.0  | [`b5a3e69`](https://github.com/openzeppelin/openzeppelin-contracts/tree/b5a3e69) | OpenZeppelin | v5.0 Changes         | [🔗](./2023-10-v5.0.pdf)                                    |
+| May 2023      | v4.9.0  | [`91df66c`](https://github.com/openzeppelin/openzeppelin-contracts/tree/91df66c) | OpenZeppelin | v4.9 Changes         | [🔗](./2023-05-v4.9.pdf)                                    |
+| October 2022  | v4.8.0  | [`14f98db`](https://github.com/openzeppelin/openzeppelin-contracts/tree/14f98db) | OpenZeppelin | ERC4626, Checkpoints | [🔗](./2022-10-ERC4626.pdf) [🔗](./2022-10-Checkpoints.pdf) |
+| October 2018  | v2.0.0  | [`dac5bcc`](https://github.com/openzeppelin/openzeppelin-contracts/tree/dac5bcc) | LevelK       | Everything           | [🔗](./2018-10.pdf)                                         |
+| March 2017    | v1.0.4  | [`9c5975a`](https://github.com/openzeppelin/openzeppelin-contracts/tree/9c5975a) | New Alchemy  | Everything           | [🔗](./2017-03.md)                                          |
 
 
 # Formal Verification
 # Formal Verification
 
 

+ 2 - 2
certora/README.md

@@ -2,14 +2,14 @@
 
 
 These instructions detail the process for running Certora Verification Tool on OpenZeppelin Contracts.
 These instructions detail the process for running Certora Verification Tool on OpenZeppelin Contracts.
 
 
-Documentation for CVT and the specification language are available [here](https://certora.atlassian.net/wiki/spaces/CPD/overview).
+Documentation for CVT and the specification language is available [here](https://certora.atlassian.net/wiki/spaces/CPD/overview).
 
 
 ## Prerequisites
 ## Prerequisites
 
 
 Follow the [Certora installation guide](https://docs.certora.com/en/latest/docs/user-guide/getting-started/install.html) in order to get the Certora Prover Package and the `solc` executable folder in your path.
 Follow the [Certora installation guide](https://docs.certora.com/en/latest/docs/user-guide/getting-started/install.html) in order to get the Certora Prover Package and the `solc` executable folder in your path.
 
 
 > **Note**
 > **Note**
-> An API Key is required for local testing. Although the prover will run on a Github Actions' CI environment on selected Pull Requests.
+> An API Key is required for local testing. Although the prover will run on a GitHub Actions' CI environment on selected Pull Requests.
 
 
 ## Running the verification
 ## Running the verification
 
 

+ 27 - 19
certora/run.js

@@ -7,11 +7,16 @@
 //    node certora/run.js AccessControl
 //    node certora/run.js AccessControl
 //    node certora/run.js AccessControlHarness:AccessControl
 //    node certora/run.js AccessControlHarness:AccessControl
 
 
-const proc = require('child_process');
-const { PassThrough } = require('stream');
-const events = require('events');
-
-const argv = require('yargs')
+import { spawn } from 'child_process';
+import { PassThrough } from 'stream';
+import { once } from 'events';
+import path from 'path';
+import yargs from 'yargs';
+import { hideBin } from 'yargs/helpers';
+import pLimit from 'p-limit';
+import fs from 'fs/promises';
+
+const argv = yargs(hideBin(process.argv))
   .env('')
   .env('')
   .options({
   .options({
     all: {
     all: {
@@ -21,7 +26,7 @@ const argv = require('yargs')
     spec: {
     spec: {
       alias: 's',
       alias: 's',
       type: 'string',
       type: 'string',
-      default: __dirname + '/specs.json',
+      default: path.resolve(import.meta.dirname, 'specs.json'),
     },
     },
     parallel: {
     parallel: {
       alias: 'p',
       alias: 'p',
@@ -38,18 +43,20 @@ const argv = require('yargs')
       type: 'array',
       type: 'array',
       default: [],
       default: [],
     },
     },
-  }).argv;
+  })
+  .parse();
 
 
 function match(entry, request) {
 function match(entry, request) {
   const [reqSpec, reqContract] = request.split(':').reverse();
   const [reqSpec, reqContract] = request.split(':').reverse();
   return entry.spec == reqSpec && (!reqContract || entry.contract == reqContract);
   return entry.spec == reqSpec && (!reqContract || entry.contract == reqContract);
 }
 }
 
 
-const specs = require(argv.spec).filter(s => argv.all || argv._.some(r => match(s, r)));
-const limit = require('p-limit')(argv.parallel);
+const specs = JSON.parse(fs.readFileSync(argv.spec, 'utf8')).filter(s => argv.all || argv._.some(r => match(s, r)));
+
+const limit = pLimit(argv.parallel);
 
 
 if (argv._.length == 0 && !argv.all) {
 if (argv._.length == 0 && !argv.all) {
-  console.error(`Warning: No specs requested. Did you forgot to toggle '--all'?`);
+  console.error(`Warning: No specs requested. Did you forget to toggle '--all'?`);
 }
 }
 
 
 for (const r of argv._) {
 for (const r of argv._) {
@@ -64,12 +71,13 @@ if (process.exitCode) {
 }
 }
 
 
 for (const { spec, contract, files, options = [] } of specs) {
 for (const { spec, contract, files, options = [] } of specs) {
-  limit(
-    runCertora,
-    spec,
-    contract,
-    files,
-    [...options, ...argv.options].flatMap(opt => opt.split(' ')),
+  limit(() =>
+    runCertora(
+      spec,
+      contract,
+      files,
+      [...options, ...argv.options].flatMap(opt => opt.split(' ')),
+    ),
   );
   );
 }
 }
 
 
@@ -79,7 +87,7 @@ async function runCertora(spec, contract, files, options = []) {
   if (argv.verbose) {
   if (argv.verbose) {
     console.log('Running:', args.join(' '));
     console.log('Running:', args.join(' '));
   }
   }
-  const child = proc.spawn('certoraRun', args);
+  const child = spawn('certoraRun', args);
 
 
   const stream = new PassThrough();
   const stream = new PassThrough();
   const output = collect(stream);
   const output = collect(stream);
@@ -103,7 +111,7 @@ async function runCertora(spec, contract, files, options = []) {
   });
   });
 
 
   // wait for process end
   // wait for process end
-  const [code, signal] = await events.once(child, 'exit');
+  const [code, signal] = await once(child, 'exit');
 
 
   // error
   // error
   if (code || signal) {
   if (code || signal) {
@@ -152,7 +160,7 @@ function writeEntry(spec, contract, success, url) {
     formatRow(
     formatRow(
       spec,
       spec,
       contract,
       contract,
-      success ? ':x:' : ':heavy_check_mark:',
+      success ? ':heavy_check_mark:' : ':x:',
       url ? `[link](${url?.replace('/output/', '/jobStatus/')})` : 'error',
       url ? `[link](${url?.replace('/output/', '/jobStatus/')})` : 'error',
       url ? `[link](${url})` : 'error',
       url ? `[link](${url})` : 'error',
     ),
     ),

+ 2 - 2
certora/specs/AccessControlDefaultAdminRules.spec

@@ -176,7 +176,7 @@ rule renounceRoleEffect(env e, bytes32 role) {
 
 
 /*
 /*
 ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
 ┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
-│ Rule: defaultAdmin is only affected by accepting an admin transfer or renoucing 
+│ Rule: defaultAdmin is only affected by accepting an admin transfer or renouncing                                    │
 └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
 └─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
 */
 */
 rule noDefaultAdminChange(env e, method f, calldataarg args) {
 rule noDefaultAdminChange(env e, method f, calldataarg args) {
@@ -188,7 +188,7 @@ rule noDefaultAdminChange(env e, method f, calldataarg args) {
     f.selector == sig:acceptDefaultAdminTransfer().selector ||
     f.selector == sig:acceptDefaultAdminTransfer().selector ||
     f.selector == sig:renounceRole(bytes32,address).selector
     f.selector == sig:renounceRole(bytes32,address).selector
   ),
   ),
-    "default admin is only affected by accepting an admin transfer or renoucing";
+    "default admin is only affected by accepting an admin transfer or renouncing";
 }
 }
 
 
 /*
 /*

+ 3 - 3
certora/specs/ERC20FlashMint.spec

@@ -18,7 +18,7 @@ methods {
 */
 */
 ghost mapping(address => mathint)                     trackedMintAmount;
 ghost mapping(address => mathint)                     trackedMintAmount;
 ghost mapping(address => mathint)                     trackedBurnAmount;
 ghost mapping(address => mathint)                     trackedBurnAmount;
-ghost mapping(address => mapping(address => mathint)) trackedTransferedAmount;
+ghost mapping(address => mapping(address => mathint)) trackedTransferredAmount;
 
 
 function specUpdate(address from, address to, uint256 amount) {
 function specUpdate(address from, address to, uint256 amount) {
     if (from == 0 && to == 0) { assert(false); } // defensive
     if (from == 0 && to == 0) { assert(false); } // defensive
@@ -28,7 +28,7 @@ function specUpdate(address from, address to, uint256 amount) {
     } else if (to == 0) {
     } else if (to == 0) {
         trackedBurnAmount[from] = amount;
         trackedBurnAmount[from] = amount;
     } else {
     } else {
-        trackedTransferedAmount[from][to] = amount;
+        trackedTransferredAmount[from][to] = amount;
     }
     }
 }
 }
 
 
@@ -51,5 +51,5 @@ rule checkMintAndBurn(env e) {
 
 
     assert trackedMintAmount[receiver] == to_mathint(amount);
     assert trackedMintAmount[receiver] == to_mathint(amount);
     assert trackedBurnAmount[receiver] == amount + to_mathint(recipient == 0 ? fees : 0);
     assert trackedBurnAmount[receiver] == amount + to_mathint(recipient == 0 ? fees : 0);
-    assert (fees > 0 && recipient != 0) => trackedTransferedAmount[receiver][recipient] == to_mathint(fees);
+    assert (fees > 0 && recipient != 0) => trackedTransferredAmount[receiver][recipient] == to_mathint(fees);
 }
 }

+ 2 - 2
contracts/access/AccessControl.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (access/AccessControl.sol)
 
 
 pragma solidity ^0.8.20;
 pragma solidity ^0.8.20;
 
 
@@ -191,7 +191,7 @@ abstract contract AccessControl is Context, IAccessControl, ERC165 {
     }
     }
 
 
     /**
     /**
-     * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.
+     * @dev Attempts to revoke `role` from `account` and returns a boolean indicating if `role` was revoked.
      *
      *
      * Internal function without access restriction.
      * Internal function without access restriction.
      *
      *

+ 2 - 2
contracts/access/IAccessControl.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (access/IAccessControl.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (access/IAccessControl.sol)
 
 
 pragma solidity ^0.8.20;
 pragma solidity ^0.8.20;
 
 
@@ -23,7 +23,7 @@ interface IAccessControl {
      * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
      * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
      *
      *
      * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
      * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
-     * {RoleAdminChanged} not being emitted signaling this.
+     * {RoleAdminChanged} not being emitted to signal this.
      */
      */
     event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
     event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
 
 

+ 14 - 10
contracts/access/manager/AuthorityUtils.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.0.0) (access/manager/AuthorityUtils.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (access/manager/AuthorityUtils.sol)
 
 
 pragma solidity ^0.8.20;
 pragma solidity ^0.8.20;
 
 
@@ -17,16 +17,20 @@ library AuthorityUtils {
         address target,
         address target,
         bytes4 selector
         bytes4 selector
     ) internal view returns (bool immediate, uint32 delay) {
     ) internal view returns (bool immediate, uint32 delay) {
-        (bool success, bytes memory data) = authority.staticcall(
-            abi.encodeCall(IAuthority.canCall, (caller, target, selector))
-        );
-        if (success) {
-            if (data.length >= 0x40) {
-                (immediate, delay) = abi.decode(data, (bool, uint32));
-            } else if (data.length >= 0x20) {
-                immediate = abi.decode(data, (bool));
+        bytes memory data = abi.encodeCall(IAuthority.canCall, (caller, target, selector));
+
+        assembly ("memory-safe") {
+            mstore(0x00, 0x00)
+            mstore(0x20, 0x00)
+
+            if staticcall(gas(), authority, add(data, 0x20), mload(data), 0x00, 0x40) {
+                immediate := mload(0x00)
+                delay := mload(0x20)
+
+                // If delay does not fit in a uint32, return 0 (no delay)
+                // equivalent to: if gt(delay, 0xFFFFFFFF) { delay := 0 }
+                delay := mul(delay, iszero(shr(32, delay)))
             }
             }
         }
         }
-        return (immediate, delay);
     }
     }
 }
 }

+ 26 - 37
contracts/account/utils/draft-ERC4337Utils.sol

@@ -1,12 +1,18 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.2.0) (account/utils/draft-ERC4337Utils.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (account/utils/draft-ERC4337Utils.sol)
 
 
 pragma solidity ^0.8.20;
 pragma solidity ^0.8.20;
 
 
-import {PackedUserOperation} from "../../interfaces/draft-IERC4337.sol";
+import {IEntryPoint, PackedUserOperation} from "../../interfaces/draft-IERC4337.sol";
 import {Math} from "../../utils/math/Math.sol";
 import {Math} from "../../utils/math/Math.sol";
+import {Calldata} from "../../utils/Calldata.sol";
 import {Packing} from "../../utils/Packing.sol";
 import {Packing} from "../../utils/Packing.sol";
 
 
+/// @dev This is available on all entrypoint since v0.4.0, but is not formally part of the ERC.
+interface IEntryPointExtra {
+    function getUserOpHash(PackedUserOperation calldata userOp) external view returns (bytes32);
+}
+
 /**
 /**
  * @dev Library with common ERC-4337 utility functions.
  * @dev Library with common ERC-4337 utility functions.
  *
  *
@@ -15,6 +21,12 @@ import {Packing} from "../../utils/Packing.sol";
 library ERC4337Utils {
 library ERC4337Utils {
     using Packing for *;
     using Packing for *;
 
 
+    /// @dev Address of the entrypoint v0.7.0
+    IEntryPoint internal constant ENTRYPOINT_V07 = IEntryPoint(0x0000000071727De22E5E9d8BAf0edAc6f37da032);
+
+    /// @dev Address of the entrypoint v0.8.0
+    IEntryPoint internal constant ENTRYPOINT_V08 = IEntryPoint(0x4337084D9E255Ff0702461CF8895CE9E3b5Ff108);
+
     /// @dev For simulation purposes, validateUserOp (and validatePaymasterUserOp) return this value on success.
     /// @dev For simulation purposes, validateUserOp (and validatePaymasterUserOp) return this value on success.
     uint256 internal constant SIG_VALIDATION_SUCCESS = 0;
     uint256 internal constant SIG_VALIDATION_SUCCESS = 0;
 
 
@@ -73,31 +85,16 @@ library ERC4337Utils {
         return (aggregator_, block.timestamp < validAfter || validUntil < block.timestamp);
         return (aggregator_, block.timestamp < validAfter || validUntil < block.timestamp);
     }
     }
 
 
-    /// @dev Computes the hash of a user operation for a given entrypoint and chainid.
-    function hash(
-        PackedUserOperation calldata self,
-        address entrypoint,
-        uint256 chainid
-    ) internal pure returns (bytes32) {
-        bytes32 result = keccak256(
-            abi.encode(
-                keccak256(
-                    abi.encode(
-                        self.sender,
-                        self.nonce,
-                        keccak256(self.initCode),
-                        keccak256(self.callData),
-                        self.accountGasLimits,
-                        self.preVerificationGas,
-                        self.gasFees,
-                        keccak256(self.paymasterAndData)
-                    )
-                ),
-                entrypoint,
-                chainid
-            )
-        );
-        return result;
+    /// @dev Get the hash of a user operation for a given entrypoint
+    function hash(PackedUserOperation calldata self, address entrypoint) internal view returns (bytes32) {
+        // NOTE: getUserOpHash is available since v0.4.0
+        //
+        // Prior to v0.8.0, this was easy to replicate for any entrypoint and chainId. Since v0.8.0 of the
+        // entrypoint, this depends on the Entrypoint's domain separator, which cannot be hardcoded and is complex
+        // to recompute. Domain separator could be fetch using the `getDomainSeparatorV4` getter, or recomputed from
+        // the ERC-5267 getter, but both operation would require doing a view call to the entrypoint. Overall it feels
+        // simpler and less error prone to get that functionality from the entrypoint directly.
+        return IEntryPointExtra(entrypoint).getUserOpHash(self);
     }
     }
 
 
     /// @dev Returns `factory` from the {PackedUserOperation}, or address(0) if the initCode is empty or not properly formatted.
     /// @dev Returns `factory` from the {PackedUserOperation}, or address(0) if the initCode is empty or not properly formatted.
@@ -107,7 +104,7 @@ library ERC4337Utils {
 
 
     /// @dev Returns `factoryData` from the {PackedUserOperation}, or empty bytes if the initCode is empty or not properly formatted.
     /// @dev Returns `factoryData` from the {PackedUserOperation}, or empty bytes if the initCode is empty or not properly formatted.
     function factoryData(PackedUserOperation calldata self) internal pure returns (bytes calldata) {
     function factoryData(PackedUserOperation calldata self) internal pure returns (bytes calldata) {
-        return self.initCode.length < 20 ? _emptyCalldataBytes() : self.initCode[20:];
+        return self.initCode.length < 20 ? Calldata.emptyBytes() : self.initCode[20:];
     }
     }
 
 
     /// @dev Returns `verificationGasLimit` from the {PackedUserOperation}.
     /// @dev Returns `verificationGasLimit` from the {PackedUserOperation}.
@@ -157,14 +154,6 @@ library ERC4337Utils {
 
 
     /// @dev Returns the fourth section of `paymasterAndData` from the {PackedUserOperation}.
     /// @dev Returns the fourth section of `paymasterAndData` from the {PackedUserOperation}.
     function paymasterData(PackedUserOperation calldata self) internal pure returns (bytes calldata) {
     function paymasterData(PackedUserOperation calldata self) internal pure returns (bytes calldata) {
-        return self.paymasterAndData.length < 52 ? _emptyCalldataBytes() : self.paymasterAndData[52:];
-    }
-
-    // slither-disable-next-line write-after-write
-    function _emptyCalldataBytes() private pure returns (bytes calldata result) {
-        assembly ("memory-safe") {
-            result.offset := 0
-            result.length := 0
-        }
+        return self.paymasterAndData.length < 52 ? Calldata.emptyBytes() : self.paymasterAndData[52:];
     }
     }
 }
 }

+ 5 - 3
contracts/account/utils/draft-ERC7579Utils.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.2.0) (account/utils/draft-ERC7579Utils.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (account/utils/draft-ERC7579Utils.sol)
 
 
 pragma solidity ^0.8.20;
 pragma solidity ^0.8.20;
 
 
@@ -218,7 +218,9 @@ library ERC7579Utils {
         uint256 value,
         uint256 value,
         bytes calldata data
         bytes calldata data
     ) private returns (bytes memory) {
     ) private returns (bytes memory) {
-        (bool success, bytes memory returndata) = target.call{value: value}(data);
+        (bool success, bytes memory returndata) = (target == address(0) ? address(this) : target).call{value: value}(
+            data
+        );
         return _validateExecutionMode(index, execType, success, returndata);
         return _validateExecutionMode(index, execType, success, returndata);
     }
     }
 
 
@@ -229,7 +231,7 @@ library ERC7579Utils {
         address target,
         address target,
         bytes calldata data
         bytes calldata data
     ) private returns (bytes memory) {
     ) private returns (bytes memory) {
-        (bool success, bytes memory returndata) = target.delegatecall(data);
+        (bool success, bytes memory returndata) = (target == address(0) ? address(this) : target).delegatecall(data);
         return _validateExecutionMode(index, execType, success, returndata);
         return _validateExecutionMode(index, execType, success, returndata);
     }
     }
 
 

+ 2 - 2
contracts/finance/VestingWallet.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.2.0) (finance/VestingWallet.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (finance/VestingWallet.sol)
 pragma solidity ^0.8.20;
 pragma solidity ^0.8.20;
 
 
 import {IERC20} from "../token/ERC20/IERC20.sol";
 import {IERC20} from "../token/ERC20/IERC20.sol";
@@ -16,7 +16,7 @@ import {Ownable} from "../access/Ownable.sol";
  * Consequently, if the vesting has already started, any amount of tokens sent to this contract will (at least partly)
  * Consequently, if the vesting has already started, any amount of tokens sent to this contract will (at least partly)
  * be immediately releasable.
  * be immediately releasable.
  *
  *
- * By setting the duration to 0, one can configure this contract to behave like an asset timelock that hold tokens for
+ * By setting the duration to 0, one can configure this contract to behave like an asset timelock that holds tokens for
  * a beneficiary until a specified time.
  * a beneficiary until a specified time.
  *
  *
  * NOTE: Since the wallet is {Ownable}, and ownership can be transferred, it is possible to sell unvested tokens.
  * NOTE: Since the wallet is {Ownable}, and ownership can be transferred, it is possible to sell unvested tokens.

+ 34 - 15
contracts/governance/Governor.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.2.0) (governance/Governor.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (governance/Governor.sol)
 
 
 pragma solidity ^0.8.20;
 pragma solidity ^0.8.20;
 
 
@@ -21,9 +21,9 @@ import {IGovernor, IERC6372} from "./IGovernor.sol";
  *
  *
  * This contract is abstract and requires several functions to be implemented in various modules:
  * This contract is abstract and requires several functions to be implemented in various modules:
  *
  *
- * - A counting module must implement {quorum}, {_quorumReached}, {_voteSucceeded} and {_countVote}
+ * - A counting module must implement {_quorumReached}, {_voteSucceeded} and {_countVote}
  * - A voting module must implement {_getVotes}
  * - A voting module must implement {_getVotes}
- * - Additionally, {votingPeriod} must also be implemented
+ * - Additionally, {votingPeriod}, {votingDelay}, and {quorum} must also be implemented
  */
  */
 abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC721Receiver, IERC1155Receiver {
 abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC721Receiver, IERC1155Receiver {
     using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;
     using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;
@@ -92,6 +92,7 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72
     function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {
     function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {
         return
         return
             interfaceId == type(IGovernor).interfaceId ||
             interfaceId == type(IGovernor).interfaceId ||
+            interfaceId == type(IGovernor).interfaceId ^ IGovernor.getProposalId.selector ||
             interfaceId == type(IERC1155Receiver).interfaceId ||
             interfaceId == type(IERC1155Receiver).interfaceId ||
             super.supportsInterface(interfaceId);
             super.supportsInterface(interfaceId);
     }
     }
@@ -132,6 +133,18 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72
         return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));
         return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));
     }
     }
 
 
+    /**
+     * @dev See {IGovernor-getProposalId}.
+     */
+    function getProposalId(
+        address[] memory targets,
+        uint256[] memory values,
+        bytes[] memory calldatas,
+        bytes32 descriptionHash
+    ) public view virtual returns (uint256) {
+        return hashProposal(targets, values, calldatas, descriptionHash);
+    }
+
     /**
     /**
      * @dev See {IGovernor-state}.
      * @dev See {IGovernor-state}.
      */
      */
@@ -317,7 +330,7 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72
         string memory description,
         string memory description,
         address proposer
         address proposer
     ) internal virtual returns (uint256 proposalId) {
     ) internal virtual returns (uint256 proposalId) {
-        proposalId = hashProposal(targets, values, calldatas, keccak256(bytes(description)));
+        proposalId = getProposalId(targets, values, calldatas, keccak256(bytes(description)));
 
 
         if (targets.length != values.length || targets.length != calldatas.length || targets.length == 0) {
         if (targets.length != values.length || targets.length != calldatas.length || targets.length == 0) {
             revert GovernorInvalidProposalLength(targets.length, calldatas.length, values.length);
             revert GovernorInvalidProposalLength(targets.length, calldatas.length, values.length);
@@ -358,7 +371,7 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72
         bytes[] memory calldatas,
         bytes[] memory calldatas,
         bytes32 descriptionHash
         bytes32 descriptionHash
     ) public virtual returns (uint256) {
     ) public virtual returns (uint256) {
-        uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);
+        uint256 proposalId = getProposalId(targets, values, calldatas, descriptionHash);
 
 
         _validateStateBitmap(proposalId, _encodeStateBitmap(ProposalState.Succeeded));
         _validateStateBitmap(proposalId, _encodeStateBitmap(ProposalState.Succeeded));
 
 
@@ -406,7 +419,7 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72
         bytes[] memory calldatas,
         bytes[] memory calldatas,
         bytes32 descriptionHash
         bytes32 descriptionHash
     ) public payable virtual returns (uint256) {
     ) public payable virtual returns (uint256) {
-        uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);
+        uint256 proposalId = getProposalId(targets, values, calldatas, descriptionHash);
 
 
         _validateStateBitmap(
         _validateStateBitmap(
             proposalId,
             proposalId,
@@ -442,7 +455,7 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72
      * performed (for example adding a vault/timelock).
      * performed (for example adding a vault/timelock).
      *
      *
      * NOTE: Calling this function directly will NOT check the current state of the proposal, set the executed flag to
      * NOTE: Calling this function directly will NOT check the current state of the proposal, set the executed flag to
-     * true or emit the `ProposalExecuted` event. Executing a proposal should be done using {execute} or {_execute}.
+     * true or emit the `ProposalExecuted` event. Executing a proposal should be done using {execute}.
      */
      */
     function _executeOperations(
     function _executeOperations(
         uint256 /* proposalId */,
         uint256 /* proposalId */,
@@ -468,14 +481,11 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72
     ) public virtual returns (uint256) {
     ) public virtual returns (uint256) {
         // The proposalId will be recomputed in the `_cancel` call further down. However we need the value before we
         // The proposalId will be recomputed in the `_cancel` call further down. However we need the value before we
         // do the internal call, because we need to check the proposal state BEFORE the internal `_cancel` call
         // do the internal call, because we need to check the proposal state BEFORE the internal `_cancel` call
-        // changes it. The `hashProposal` duplication has a cost that is limited, and that we accept.
-        uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);
+        // changes it. The `getProposalId` duplication has a cost that is limited, and that we accept.
+        uint256 proposalId = getProposalId(targets, values, calldatas, descriptionHash);
 
 
-        // public cancel restrictions (on top of existing _cancel restrictions).
-        _validateStateBitmap(proposalId, _encodeStateBitmap(ProposalState.Pending));
-        if (_msgSender() != proposalProposer(proposalId)) {
-            revert GovernorOnlyProposer(_msgSender());
-        }
+        address caller = _msgSender();
+        if (!_validateCancel(proposalId, caller)) revert GovernorUnableToCancel(proposalId, caller);
 
 
         return _cancel(targets, values, calldatas, descriptionHash);
         return _cancel(targets, values, calldatas, descriptionHash);
     }
     }
@@ -492,7 +502,7 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72
         bytes[] memory calldatas,
         bytes[] memory calldatas,
         bytes32 descriptionHash
         bytes32 descriptionHash
     ) internal virtual returns (uint256) {
     ) internal virtual returns (uint256) {
-        uint256 proposalId = hashProposal(targets, values, calldatas, descriptionHash);
+        uint256 proposalId = getProposalId(targets, values, calldatas, descriptionHash);
 
 
         _validateStateBitmap(
         _validateStateBitmap(
             proposalId,
             proposalId,
@@ -792,6 +802,15 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72
         }
         }
     }
     }
 
 
+    /**
+     * @dev Check if the `caller` can cancel the proposal with the given `proposalId`.
+     *
+     * The default implementation allows the proposal proposer to cancel the proposal during the pending state.
+     */
+    function _validateCancel(uint256 proposalId, address caller) internal view virtual returns (bool) {
+        return (state(proposalId) == ProposalState.Pending) && caller == proposalProposer(proposalId);
+    }
+
     /**
     /**
      * @inheritdoc IERC6372
      * @inheritdoc IERC6372
      */
      */

+ 20 - 7
contracts/governance/IGovernor.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (governance/IGovernor.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (governance/IGovernor.sol)
 
 
 pragma solidity ^0.8.20;
 pragma solidity ^0.8.20;
 
 
@@ -39,11 +39,6 @@ interface IGovernor is IERC165, IERC6372 {
      */
      */
     error GovernorDisabledDeposit();
     error GovernorDisabledDeposit();
 
 
-    /**
-     * @dev The `account` is not a proposer.
-     */
-    error GovernorOnlyProposer(address account);
-
     /**
     /**
      * @dev The `account` is not the governance executor.
      * @dev The `account` is not the governance executor.
      */
      */
@@ -112,6 +107,11 @@ interface IGovernor is IERC165, IERC6372 {
      */
      */
     error GovernorInvalidSignature(address voter);
     error GovernorInvalidSignature(address voter);
 
 
+    /**
+     * @dev The given `account` is unable to cancel the proposal with given `proposalId`.
+     */
+    error GovernorUnableToCancel(uint256 proposalId, address account);
+
     /**
     /**
      * @dev Emitted when a proposal is created.
      * @dev Emitted when a proposal is created.
      */
      */
@@ -203,7 +203,9 @@ interface IGovernor is IERC165, IERC6372 {
 
 
     /**
     /**
      * @notice module:core
      * @notice module:core
-     * @dev Hashing function used to (re)build the proposal id from the proposal details..
+     * @dev Hashing function used to (re)build the proposal id from the proposal details.
+     *
+     * NOTE: For all off-chain and external calls, use {getProposalId}.
      */
      */
     function hashProposal(
     function hashProposal(
         address[] memory targets,
         address[] memory targets,
@@ -212,6 +214,17 @@ interface IGovernor is IERC165, IERC6372 {
         bytes32 descriptionHash
         bytes32 descriptionHash
     ) external pure returns (uint256);
     ) external pure returns (uint256);
 
 
+    /**
+     * @notice module:core
+     * @dev Function used to get the proposal id from the proposal details.
+     */
+    function getProposalId(
+        address[] memory targets,
+        uint256[] memory values,
+        bytes[] memory calldatas,
+        bytes32 descriptionHash
+    ) external view returns (uint256);
+
     /**
     /**
      * @notice module:core
      * @notice module:core
      * @dev Current state of a proposal, following Compound's convention
      * @dev Current state of a proposal, following Compound's convention

+ 16 - 4
contracts/governance/README.adoc

@@ -20,17 +20,19 @@ For a written walkthrough, check out our guide on xref:ROOT:governance.adoc[How
 
 
 Votes modules determine the source of voting power, and sometimes quorum number.
 Votes modules determine the source of voting power, and sometimes quorum number.
 
 
-* {GovernorVotes}: Extracts voting weight from an {ERC20Votes}, or since v4.5 an {ERC721Votes} token.
+* {GovernorVotes}: Extracts voting weight from an {IVotes} contract.
 
 
 * {GovernorVotesQuorumFraction}: Combines with `GovernorVotes` to set the quorum as a fraction of the total token supply.
 * {GovernorVotesQuorumFraction}: Combines with `GovernorVotes` to set the quorum as a fraction of the total token supply.
 
 
+* {GovernorVotesSuperQuorumFraction}: Combines `GovernorSuperQuorum` with `GovernorVotesQuorumFraction` to set the super quorum as a fraction of the total token supply.
+
 Counting modules determine valid voting options.
 Counting modules determine valid voting options.
 
 
 * {GovernorCountingSimple}: Simple voting mechanism with 3 voting options: Against, For and Abstain.
 * {GovernorCountingSimple}: Simple voting mechanism with 3 voting options: Against, For and Abstain.
 
 
 * {GovernorCountingFractional}: A more modular voting system that allows a user to vote with only part of its voting power, and to split that weight arbitrarily between the 3 different options (Against, For and Abstain).
 * {GovernorCountingFractional}: A more modular voting system that allows a user to vote with only part of its voting power, and to split that weight arbitrarily between the 3 different options (Against, For and Abstain).
 
 
-* {GovernorCountingOverridable}: An extended version of `GovernorCountingSimple` which allows delegatees to override their delegates while the vote is live.
+* {GovernorCountingOverridable}: An extended version of `GovernorCountingSimple` which allows delegatees to override their delegates while the vote is live. Must be used in conjunction with {VotesExtended}.
 
 
 Timelock extensions add a delay for governance decisions to be executed. The workflow is extended to require a `queue` step before execution. With these modules, proposals are executed by the external timelock contract, thus it is the timelock that has to hold the assets that are being governed.
 Timelock extensions add a delay for governance decisions to be executed. The workflow is extended to require a `queue` step before execution. With these modules, proposals are executed by the external timelock contract, thus it is the timelock that has to hold the assets that are being governed.
 
 
@@ -48,6 +50,10 @@ Other extensions can customize the behavior or interface in multiple ways.
 
 
 * {GovernorPreventLateQuorum}: Ensures there is a minimum voting period after quorum is reached as a security protection against large voters.
 * {GovernorPreventLateQuorum}: Ensures there is a minimum voting period after quorum is reached as a security protection against large voters.
 
 
+* {GovernorProposalGuardian}: Adds a proposal guardian that can cancel proposals at any stage in their lifecycle--this permission is passed on to the proposers if the guardian is not set.
+
+* {GovernorSuperQuorum}: Extension of {Governor} with a super quorum. Proposals that meet the super quorum (and have a majority of for votes) advance to the `Succeeded` state before the proposal deadline.
+
 In addition to modules and extensions, the core contract requires a few virtual functions to be implemented to your particular specifications:
 In addition to modules and extensions, the core contract requires a few virtual functions to be implemented to your particular specifications:
 
 
 * <<Governor-votingDelay-,`votingDelay()`>>: Delay (in ERC-6372 clock) since the proposal is submitted until voting power is fixed and voting starts. This can be used to enforce a delay after a proposal is published for users to buy tokens, or delegate their votes.
 * <<Governor-votingDelay-,`votingDelay()`>>: Delay (in ERC-6372 clock) since the proposal is submitted until voting power is fixed and voting starts. This can be used to enforce a delay after a proposal is published for users to buy tokens, or delegate their votes.
@@ -68,12 +74,14 @@ NOTE: Functions of the `Governor` contract do not include access control. If you
 
 
 {{GovernorCountingFractional}}
 {{GovernorCountingFractional}}
 
 
-{{GovernorCountingOverride}}
+{{GovernorCountingOverridable}}
 
 
 {{GovernorVotes}}
 {{GovernorVotes}}
 
 
 {{GovernorVotesQuorumFraction}}
 {{GovernorVotesQuorumFraction}}
 
 
+{{GovernorVotesSuperQuorumFraction}}
+
 === Extensions
 === Extensions
 
 
 {{GovernorTimelockAccess}}
 {{GovernorTimelockAccess}}
@@ -88,6 +96,10 @@ NOTE: Functions of the `Governor` contract do not include access control. If you
 
 
 {{GovernorStorage}}
 {{GovernorStorage}}
 
 
+{{GovernorProposalGuardian}}
+
+{{GovernorSuperQuorum}}
+
 == Utils
 == Utils
 
 
 {{Votes}}
 {{Votes}}
@@ -103,7 +115,7 @@ In a governance system, the {TimelockController} contract is in charge of introd
 [[timelock-terminology]]
 [[timelock-terminology]]
 ==== Terminology
 ==== Terminology
 
 
-* *Operation:* A transaction (or a set of transactions) that is the subject of the timelock. It has to be scheduled by a proposer and executed by an executor. The timelock enforces a minimum delay between the proposition and the execution (see xref:access-control.adoc#operation_lifecycle[operation lifecycle]). If the operation contains multiple transactions (batch mode), they are executed atomically. Operations are identified by the hash of their content.
+* *Operation:* A transaction (or a set of transactions) that is the subject of the timelock. It has to be scheduled by a proposer and executed by an executor. The timelock enforces a minimum delay between the proposition and the execution. If the operation contains multiple transactions (batch mode), they are executed atomically. Operations are identified by the hash of their content.
 * *Operation status:*
 * *Operation status:*
 ** *Unset:* An operation that is not part of the timelock mechanism.
 ** *Unset:* An operation that is not part of the timelock mechanism.
 ** *Waiting:* An operation that has been scheduled, before the timer expires.
 ** *Waiting:* An operation that has been scheduled, before the timer expires.

+ 2 - 2
contracts/governance/TimelockController.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.0.0) (governance/TimelockController.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (governance/TimelockController.sol)
 
 
 pragma solidity ^0.8.20;
 pragma solidity ^0.8.20;
 
 
@@ -152,7 +152,7 @@ contract TimelockController is AccessControl, ERC721Holder, ERC1155Holder {
     /**
     /**
      * @dev Contract might receive/hold ETH as part of the maintenance process.
      * @dev Contract might receive/hold ETH as part of the maintenance process.
      */
      */
-    receive() external payable {}
+    receive() external payable virtual {}
 
 
     /**
     /**
      * @dev See {IERC165-supportsInterface}.
      * @dev See {IERC165-supportsInterface}.

+ 4 - 4
contracts/governance/extensions/GovernorCountingFractional.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (governance/extensions/GovernorCountingFractional.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (governance/extensions/GovernorCountingFractional.sol)
 
 
 pragma solidity ^0.8.20;
 pragma solidity ^0.8.20;
 
 
@@ -27,7 +27,7 @@ import {Math} from "../../utils/math/Math.sol";
  * * Voting from an L2 with tokens held by a bridge
  * * Voting from an L2 with tokens held by a bridge
  * * Voting privately from a shielded pool using zero knowledge proofs.
  * * Voting privately from a shielded pool using zero knowledge proofs.
  *
  *
- * Based on ScopeLift's GovernorCountingFractional[https://github.com/ScopeLift/flexible-voting/blob/e5de2efd1368387b840931f19f3c184c85842761/src/GovernorCountingFractional.sol]
+ * Based on ScopeLift's https://github.com/ScopeLift/flexible-voting/blob/e5de2efd1368387b840931f19f3c184c85842761/src/GovernorCountingFractional.sol[`GovernorCountingFractional`]
  *
  *
  * _Available since v5.1._
  * _Available since v5.1._
  */
  */
@@ -125,9 +125,9 @@ abstract contract GovernorCountingFractional is Governor {
      *
      *
      * `abi.encodePacked(uint128(againstVotes), uint128(forVotes), uint128(abstainVotes))`
      * `abi.encodePacked(uint128(againstVotes), uint128(forVotes), uint128(abstainVotes))`
      *
      *
-     * NOTE: Consider that fractional voting restricts the number of casted vote (in each category) to 128 bits.
+     * NOTE: Consider that fractional voting restricts the number of casted votes (in each category) to 128 bits.
      * Depending on how many decimals the underlying token has, a single voter may require to split their vote into
      * Depending on how many decimals the underlying token has, a single voter may require to split their vote into
-     * multiple vote operations. For precision higher than ~30 decimals, large token holders may require an
+     * multiple vote operations. For precision higher than ~30 decimals, large token holders may require a
      * potentially large number of calls to cast all their votes. The voter has the possibility to cast all the
      * potentially large number of calls to cast all their votes. The voter has the possibility to cast all the
      * remaining votes in a single operation using the traditional "bravo" vote.
      * remaining votes in a single operation using the traditional "bravo" vote.
      */
      */

+ 18 - 18
contracts/governance/extensions/GovernorCountingOverridable.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.2.0) (governance/extensions/GovernorCountingOverridable.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (governance/extensions/GovernorCountingOverridable.sol)
 
 
 pragma solidity ^0.8.20;
 pragma solidity ^0.8.20;
 
 
@@ -27,8 +27,8 @@ abstract contract GovernorCountingOverridable is GovernorVotes {
 
 
     struct VoteReceipt {
     struct VoteReceipt {
         uint8 casted; // 0 if vote was not casted. Otherwise: support + 1
         uint8 casted; // 0 if vote was not casted. Otherwise: support + 1
-        bool hasOverriden;
-        uint208 overridenWeight;
+        bool hasOverridden;
+        uint208 overriddenWeight;
     }
     }
 
 
     struct ProposalVote {
     struct ProposalVote {
@@ -42,7 +42,7 @@ abstract contract GovernorCountingOverridable is GovernorVotes {
     /// @dev A delegated vote on `proposalId` was overridden by `weight`
     /// @dev A delegated vote on `proposalId` was overridden by `weight`
     event OverrideVoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);
     event OverrideVoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);
 
 
-    error GovernorAlreadyOverridenVote(address account);
+    error GovernorAlreadyOverriddenVote(address account);
 
 
     mapping(uint256 proposalId => ProposalVote) private _proposalVotes;
     mapping(uint256 proposalId => ProposalVote) private _proposalVotes;
 
 
@@ -70,7 +70,7 @@ abstract contract GovernorCountingOverridable is GovernorVotes {
      * @dev Check if an `account` has overridden their delegate for a proposal.
      * @dev Check if an `account` has overridden their delegate for a proposal.
      */
      */
     function hasVotedOverride(uint256 proposalId, address account) public view virtual returns (bool) {
     function hasVotedOverride(uint256 proposalId, address account) public view virtual returns (bool) {
-        return _proposalVotes[proposalId].voteReceipt[account].hasOverriden;
+        return _proposalVotes[proposalId].voteReceipt[account].hasOverridden;
     }
     }
 
 
     /**
     /**
@@ -122,7 +122,7 @@ abstract contract GovernorCountingOverridable is GovernorVotes {
             revert GovernorAlreadyCastVote(account);
             revert GovernorAlreadyCastVote(account);
         }
         }
 
 
-        totalWeight -= proposalVote.voteReceipt[account].overridenWeight;
+        totalWeight -= proposalVote.voteReceipt[account].overriddenWeight;
         proposalVote.votes[support] += totalWeight;
         proposalVote.votes[support] += totalWeight;
         proposalVote.voteReceipt[account].casted = support + 1;
         proposalVote.voteReceipt[account].casted = support + 1;
 
 
@@ -141,26 +141,26 @@ abstract contract GovernorCountingOverridable is GovernorVotes {
             revert GovernorInvalidVoteType();
             revert GovernorInvalidVoteType();
         }
         }
 
 
-        if (proposalVote.voteReceipt[account].hasOverriden) {
-            revert GovernorAlreadyOverridenVote(account);
+        if (proposalVote.voteReceipt[account].hasOverridden) {
+            revert GovernorAlreadyOverriddenVote(account);
         }
         }
 
 
         uint256 snapshot = proposalSnapshot(proposalId);
         uint256 snapshot = proposalSnapshot(proposalId);
-        uint256 overridenWeight = VotesExtended(address(token())).getPastBalanceOf(account, snapshot);
+        uint256 overriddenWeight = VotesExtended(address(token())).getPastBalanceOf(account, snapshot);
         address delegate = VotesExtended(address(token())).getPastDelegate(account, snapshot);
         address delegate = VotesExtended(address(token())).getPastDelegate(account, snapshot);
         uint8 delegateCasted = proposalVote.voteReceipt[delegate].casted;
         uint8 delegateCasted = proposalVote.voteReceipt[delegate].casted;
 
 
-        proposalVote.voteReceipt[account].hasOverriden = true;
-        proposalVote.votes[support] += overridenWeight;
+        proposalVote.voteReceipt[account].hasOverridden = true;
+        proposalVote.votes[support] += overriddenWeight;
         if (delegateCasted == 0) {
         if (delegateCasted == 0) {
-            proposalVote.voteReceipt[delegate].overridenWeight += SafeCast.toUint208(overridenWeight);
+            proposalVote.voteReceipt[delegate].overriddenWeight += SafeCast.toUint208(overriddenWeight);
         } else {
         } else {
             uint8 delegateSupport = delegateCasted - 1;
             uint8 delegateSupport = delegateCasted - 1;
-            proposalVote.votes[delegateSupport] -= overridenWeight;
-            emit VoteReduced(delegate, proposalId, delegateSupport, overridenWeight);
+            proposalVote.votes[delegateSupport] -= overriddenWeight;
+            emit VoteReduced(delegate, proposalId, delegateSupport, overriddenWeight);
         }
         }
 
 
-        return overridenWeight;
+        return overriddenWeight;
     }
     }
 
 
     /// @dev Variant of {Governor-_castVote} that deals with vote overrides. Returns the overridden weight.
     /// @dev Variant of {Governor-_castVote} that deals with vote overrides. Returns the overridden weight.
@@ -172,13 +172,13 @@ abstract contract GovernorCountingOverridable is GovernorVotes {
     ) internal virtual returns (uint256) {
     ) internal virtual returns (uint256) {
         _validateStateBitmap(proposalId, _encodeStateBitmap(ProposalState.Active));
         _validateStateBitmap(proposalId, _encodeStateBitmap(ProposalState.Active));
 
 
-        uint256 overridenWeight = _countOverride(proposalId, account, support);
+        uint256 overriddenWeight = _countOverride(proposalId, account, support);
 
 
-        emit OverrideVoteCast(account, proposalId, support, overridenWeight, reason);
+        emit OverrideVoteCast(account, proposalId, support, overriddenWeight, reason);
 
 
         _tallyUpdated(proposalId);
         _tallyUpdated(proposalId);
 
 
-        return overridenWeight;
+        return overriddenWeight;
     }
     }
 
 
     /// @dev Public function for casting an override vote. Returns the overridden weight.
     /// @dev Public function for casting an override vote. Returns the overridden weight.

+ 58 - 0
contracts/governance/extensions/GovernorProposalGuardian.sol

@@ -0,0 +1,58 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v5.3.0) (governance/extensions/GovernorProposalGuardian.sol)
+pragma solidity ^0.8.20;
+
+import {Governor} from "../Governor.sol";
+
+/**
+ * @dev Extension of {Governor} which adds a proposal guardian that can cancel proposals at any stage in the proposal's lifecycle.
+ *
+ * NOTE: if the proposal guardian is not configured, then proposers take this role for their proposals.
+ */
+abstract contract GovernorProposalGuardian is Governor {
+    address private _proposalGuardian;
+
+    event ProposalGuardianSet(address oldProposalGuardian, address newProposalGuardian);
+
+    /**
+     * @dev Getter that returns the address of the proposal guardian.
+     */
+    function proposalGuardian() public view virtual returns (address) {
+        return _proposalGuardian;
+    }
+
+    /**
+     * @dev Update the proposal guardian's address. This operation can only be performed through a governance proposal.
+     *
+     * Emits a {ProposalGuardianSet} event.
+     */
+    function setProposalGuardian(address newProposalGuardian) public virtual onlyGovernance {
+        _setProposalGuardian(newProposalGuardian);
+    }
+
+    /**
+     * @dev Internal setter for the proposal guardian.
+     *
+     * Emits a {ProposalGuardianSet} event.
+     */
+    function _setProposalGuardian(address newProposalGuardian) internal virtual {
+        emit ProposalGuardianSet(_proposalGuardian, newProposalGuardian);
+        _proposalGuardian = newProposalGuardian;
+    }
+
+    /**
+     * @dev Override {Governor-_validateCancel} to implement the extended cancellation logic.
+     *
+     * * The {proposalGuardian} can cancel any proposal at any point.
+     * * If no proposal guardian is set, the {IGovernor-proposalProposer} can cancel their proposals at any point.
+     * * In any case, permissions defined in {Governor-_validateCancel} (or another override) remains valid.
+     */
+    function _validateCancel(uint256 proposalId, address caller) internal view virtual override returns (bool) {
+        address guardian = proposalGuardian();
+
+        return
+            guardian == caller ||
+            (guardian == address(0) && caller == proposalProposer(proposalId)) ||
+            super._validateCancel(proposalId, caller);
+    }
+}

+ 77 - 0
contracts/governance/extensions/GovernorSequentialProposalId.sol

@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v5.3.0) (governance/extensions/GovernorSequentialProposalId.sol)
+
+pragma solidity ^0.8.20;
+
+import {Governor} from "../Governor.sol";
+
+/**
+ * @dev Extension of {Governor} that changes the numbering of proposal ids from the default hash-based approach to
+ * sequential ids.
+ */
+abstract contract GovernorSequentialProposalId is Governor {
+    uint256 private _latestProposalId;
+    mapping(uint256 proposalHash => uint256 proposalId) private _proposalIds;
+
+    /**
+     * @dev The {latestProposalId} may only be initialized if it hasn't been set yet
+     * (through initialization or the creation of a proposal).
+     */
+    error GovernorAlreadyInitializedLatestProposalId();
+
+    /**
+     * @dev See {IGovernor-getProposalId}.
+     */
+    function getProposalId(
+        address[] memory targets,
+        uint256[] memory values,
+        bytes[] memory calldatas,
+        bytes32 descriptionHash
+    ) public view virtual override returns (uint256) {
+        uint256 proposalHash = hashProposal(targets, values, calldatas, descriptionHash);
+        uint256 storedProposalId = _proposalIds[proposalHash];
+        if (storedProposalId == 0) {
+            revert GovernorNonexistentProposal(0);
+        }
+        return storedProposalId;
+    }
+
+    /**
+     * @dev Returns the latest proposal id. A return value of 0 means no proposals have been created yet.
+     */
+    function latestProposalId() public view virtual returns (uint256) {
+        return _latestProposalId;
+    }
+
+    /**
+     * @dev See {IGovernor-_propose}.
+     * Hook into the proposing mechanism to increment proposal count.
+     */
+    function _propose(
+        address[] memory targets,
+        uint256[] memory values,
+        bytes[] memory calldatas,
+        string memory description,
+        address proposer
+    ) internal virtual override returns (uint256) {
+        uint256 proposalHash = hashProposal(targets, values, calldatas, keccak256(bytes(description)));
+        uint256 storedProposalId = _proposalIds[proposalHash];
+        if (storedProposalId == 0) {
+            _proposalIds[proposalHash] = ++_latestProposalId;
+        }
+        return super._propose(targets, values, calldatas, description, proposer);
+    }
+
+    /**
+     * @dev Internal function to set the {latestProposalId}. This function is helpful when transitioning
+     * from another governance system. The next proposal id will be `newLatestProposalId` + 1.
+     *
+     * May only call this function if the current value of {latestProposalId} is 0.
+     */
+    function _initializeLatestProposalId(uint256 newLatestProposalId) internal virtual {
+        if (_latestProposalId != 0) {
+            revert GovernorAlreadyInitializedLatestProposalId();
+        }
+        _latestProposalId = newLatestProposalId;
+    }
+}

+ 2 - 2
contracts/governance/extensions/GovernorStorage.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (governance/extensions/GovernorStorage.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (governance/extensions/GovernorStorage.sol)
 
 
 pragma solidity ^0.8.20;
 pragma solidity ^0.8.20;
 
 
@@ -50,7 +50,7 @@ abstract contract GovernorStorage is Governor {
     }
     }
 
 
     /**
     /**
-     * @dev Version of {IGovernorTimelock-queue} with only `proposalId` as an argument.
+     * @dev Version of {IGovernor-queue} with only `proposalId` as an argument.
      */
      */
     function queue(uint256 proposalId) public virtual {
     function queue(uint256 proposalId) public virtual {
         // here, using storage is more efficient than memory
         // here, using storage is more efficient than memory

+ 60 - 0
contracts/governance/extensions/GovernorSuperQuorum.sol

@@ -0,0 +1,60 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v5.3.0) (governance/extensions/GovernorSuperQuorum.sol)
+pragma solidity ^0.8.20;
+
+import {Governor} from "../Governor.sol";
+import {SafeCast} from "../../utils/math/SafeCast.sol";
+import {Checkpoints} from "../../utils/structs/Checkpoints.sol";
+
+/**
+ * @dev Extension of {Governor} with a super quorum. Proposals that meet the super quorum (and have a majority of for
+ * votes) advance to the `Succeeded` state before the proposal deadline. Counting modules that want to use this
+ * extension must implement {proposalVotes}.
+ */
+abstract contract GovernorSuperQuorum is Governor {
+    /**
+     * @dev Minimum number of cast votes required for a proposal to reach super quorum. Only FOR votes are counted
+     * towards the super quorum. Once the super quorum is reached, an active proposal can proceed to the next state
+     * without waiting for the proposal deadline.
+     *
+     * NOTE: The `timepoint` parameter corresponds to the snapshot used for counting the vote. This enables scaling of the
+     * quorum depending on values such as the `totalSupply` of a token at this timepoint (see {ERC20Votes}).
+     *
+     * NOTE: Make sure the value specified for the super quorum is greater than {quorum}, otherwise, it may be
+     * possible to pass a proposal with less votes than the default quorum.
+     */
+    function superQuorum(uint256 timepoint) public view virtual returns (uint256);
+
+    /**
+     * @dev Accessor to the internal vote counts. This must be implemented by the counting module. Counting modules
+     * that don't implement this function are incompatible with this module
+     */
+    function proposalVotes(
+        uint256 proposalId
+    ) public view virtual returns (uint256 againstVotes, uint256 forVotes, uint256 abstainVotes);
+
+    /**
+     * @dev Overridden version of the {Governor-state} function that checks if the proposal has reached the super
+     * quorum.
+     *
+     * NOTE: If the proposal reaches super quorum but {_voteSucceeded} returns false, eg, assuming the super quorum
+     * has been set low enough that both FOR and AGAINST votes have exceeded it and AGAINST votes exceed FOR votes,
+     * the proposal continues to be active until {_voteSucceeded} returns true or the proposal deadline is reached.
+     * This means that with a low super quorum it is also possible that a vote can succeed prematurely before enough
+     * AGAINST voters have a chance to vote. Hence, it is recommended to set a high enough super quorum to avoid these
+     * types of scenarios.
+     */
+    function state(uint256 proposalId) public view virtual override returns (ProposalState) {
+        ProposalState currentState = super.state(proposalId);
+        if (currentState != ProposalState.Active) return currentState;
+
+        (, uint256 forVotes, ) = proposalVotes(proposalId);
+        if (forVotes < superQuorum(proposalSnapshot(proposalId)) || !_voteSucceeded(proposalId)) {
+            return ProposalState.Active;
+        } else if (proposalEta(proposalId) == 0) {
+            return ProposalState.Succeeded;
+        } else {
+            return ProposalState.Queued;
+        }
+    }
+}

+ 2 - 2
contracts/governance/extensions/GovernorTimelockAccess.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (governance/extensions/GovernorTimelockAccess.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (governance/extensions/GovernorTimelockAccess.sol)
 
 
 pragma solidity ^0.8.20;
 pragma solidity ^0.8.20;
 
 
@@ -277,7 +277,7 @@ abstract contract GovernorTimelockAccess is Governor {
     }
     }
 
 
     /**
     /**
-     * @dev See {IGovernor-_cancel}
+     * @dev See {Governor-_cancel}
      */
      */
     function _cancel(
     function _cancel(
         address[] memory targets,
         address[] memory targets,

+ 2 - 2
contracts/governance/extensions/GovernorTimelockCompound.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (governance/extensions/GovernorTimelockCompound.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (governance/extensions/GovernorTimelockCompound.sol)
 
 
 pragma solidity ^0.8.20;
 pragma solidity ^0.8.20;
 
 
@@ -10,7 +10,7 @@ import {SafeCast} from "../../utils/math/SafeCast.sol";
 
 
 /**
 /**
  * @dev Extension of {Governor} that binds the execution process to a Compound Timelock. This adds a delay, enforced by
  * @dev Extension of {Governor} that binds the execution process to a Compound Timelock. This adds a delay, enforced by
- * the external timelock to all successful proposal (in addition to the voting duration). The {Governor} needs to be
+ * the external timelock to all successful proposals (in addition to the voting duration). The {Governor} needs to be
  * the admin of the timelock for any operation to be performed. A public, unrestricted,
  * the admin of the timelock for any operation to be performed. A public, unrestricted,
  * {GovernorTimelockCompound-__acceptAdmin} is available to accept ownership of the timelock.
  * {GovernorTimelockCompound-__acceptAdmin} is available to accept ownership of the timelock.
  *
  *

+ 2 - 2
contracts/governance/extensions/GovernorTimelockControl.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (governance/extensions/GovernorTimelockControl.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (governance/extensions/GovernorTimelockControl.sol)
 
 
 pragma solidity ^0.8.20;
 pragma solidity ^0.8.20;
 
 
@@ -17,7 +17,7 @@ import {SafeCast} from "../../utils/math/SafeCast.sol";
  * the assets and permissions must be attached to the {TimelockController}. Any asset sent to the {Governor} will be
  * the assets and permissions must be attached to the {TimelockController}. Any asset sent to the {Governor} will be
  * inaccessible from a proposal, unless executed via {Governor-relay}.
  * inaccessible from a proposal, unless executed via {Governor-relay}.
  *
  *
- * WARNING: Setting up the TimelockController to have additional proposers or cancellers besides the governor is very
+ * WARNING: Setting up the TimelockController to have additional proposers or cancelers besides the governor is very
  * risky, as it grants them the ability to: 1) execute operations as the timelock, and thus possibly performing
  * risky, as it grants them the ability to: 1) execute operations as the timelock, and thus possibly performing
  * operations or accessing funds that are expected to only be accessible through a vote, and 2) block governance
  * operations or accessing funds that are expected to only be accessible through a vote, and 2) block governance
  * proposals that have been approved by the voters, effectively executing a Denial of Service attack.
  * proposals that have been approved by the voters, effectively executing a Denial of Service attack.

+ 17 - 14
contracts/governance/extensions/GovernorVotesQuorumFraction.sol

@@ -1,9 +1,10 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.0.0) (governance/extensions/GovernorVotesQuorumFraction.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (governance/extensions/GovernorVotesQuorumFraction.sol)
 
 
 pragma solidity ^0.8.20;
 pragma solidity ^0.8.20;
 
 
 import {GovernorVotes} from "./GovernorVotes.sol";
 import {GovernorVotes} from "./GovernorVotes.sol";
+import {Math} from "../../utils/math/Math.sol";
 import {SafeCast} from "../../utils/math/SafeCast.sol";
 import {SafeCast} from "../../utils/math/SafeCast.sol";
 import {Checkpoints} from "../../utils/structs/Checkpoints.sol";
 import {Checkpoints} from "../../utils/structs/Checkpoints.sol";
 
 
@@ -45,18 +46,7 @@ abstract contract GovernorVotesQuorumFraction is GovernorVotes {
      * @dev Returns the quorum numerator at a specific timepoint. See {quorumDenominator}.
      * @dev Returns the quorum numerator at a specific timepoint. See {quorumDenominator}.
      */
      */
     function quorumNumerator(uint256 timepoint) public view virtual returns (uint256) {
     function quorumNumerator(uint256 timepoint) public view virtual returns (uint256) {
-        uint256 length = _quorumNumeratorHistory._checkpoints.length;
-
-        // Optimistic search, check the latest checkpoint
-        Checkpoints.Checkpoint208 storage latest = _quorumNumeratorHistory._checkpoints[length - 1];
-        uint48 latestKey = latest._key;
-        uint208 latestValue = latest._value;
-        if (latestKey <= timepoint) {
-            return latestValue;
-        }
-
-        // Otherwise, do the binary search
-        return _quorumNumeratorHistory.upperLookupRecent(SafeCast.toUint48(timepoint));
+        return _optimisticUpperLookupRecent(_quorumNumeratorHistory, timepoint);
     }
     }
 
 
     /**
     /**
@@ -70,7 +60,7 @@ abstract contract GovernorVotesQuorumFraction is GovernorVotes {
      * @dev Returns the quorum for a timepoint, in terms of number of votes: `supply * numerator / denominator`.
      * @dev Returns the quorum for a timepoint, in terms of number of votes: `supply * numerator / denominator`.
      */
      */
     function quorum(uint256 timepoint) public view virtual override returns (uint256) {
     function quorum(uint256 timepoint) public view virtual override returns (uint256) {
-        return (token().getPastTotalSupply(timepoint) * quorumNumerator(timepoint)) / quorumDenominator();
+        return Math.mulDiv(token().getPastTotalSupply(timepoint), quorumNumerator(timepoint), quorumDenominator());
     }
     }
 
 
     /**
     /**
@@ -107,4 +97,17 @@ abstract contract GovernorVotesQuorumFraction is GovernorVotes {
 
 
         emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);
         emit QuorumNumeratorUpdated(oldQuorumNumerator, newQuorumNumerator);
     }
     }
+
+    /**
+     * @dev Returns the numerator at a specific timepoint.
+     */
+    function _optimisticUpperLookupRecent(
+        Checkpoints.Trace208 storage ckpts,
+        uint256 timepoint
+    ) internal view returns (uint256) {
+        // If trace is empty, key and value are both equal to 0.
+        // In that case `key <= timepoint` is true, and it is ok to return 0.
+        (, uint48 key, uint208 value) = ckpts.latestCheckpoint();
+        return key <= timepoint ? value : ckpts.upperLookupRecent(SafeCast.toUint48(timepoint));
+    }
 }
 }

+ 134 - 0
contracts/governance/extensions/GovernorVotesSuperQuorumFraction.sol

@@ -0,0 +1,134 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v5.3.0) (governance/extensions/GovernorVotesSuperQuorumFraction.sol)
+pragma solidity ^0.8.20;
+
+import {Governor} from "../Governor.sol";
+import {GovernorSuperQuorum} from "./GovernorSuperQuorum.sol";
+import {GovernorVotesQuorumFraction} from "./GovernorVotesQuorumFraction.sol";
+import {Math} from "../../utils/math/Math.sol";
+import {SafeCast} from "../../utils/math/SafeCast.sol";
+import {Checkpoints} from "../../utils/structs/Checkpoints.sol";
+
+/**
+ * @dev Extension of {GovernorVotesQuorumFraction} with a super quorum expressed as a
+ * fraction of the total supply. Proposals that meet the super quorum (and have a majority of for votes) advance to
+ * the `Succeeded` state before the proposal deadline.
+ */
+abstract contract GovernorVotesSuperQuorumFraction is GovernorVotesQuorumFraction, GovernorSuperQuorum {
+    using Checkpoints for Checkpoints.Trace208;
+
+    Checkpoints.Trace208 private _superQuorumNumeratorHistory;
+
+    event SuperQuorumNumeratorUpdated(uint256 oldSuperQuorumNumerator, uint256 newSuperQuorumNumerator);
+
+    /**
+     * @dev The super quorum set is not valid as it exceeds the quorum denominator.
+     */
+    error GovernorInvalidSuperQuorumFraction(uint256 superQuorumNumerator, uint256 denominator);
+
+    /**
+     * @dev The super quorum set is not valid as it is smaller or equal to the quorum.
+     */
+    error GovernorInvalidSuperQuorumTooSmall(uint256 superQuorumNumerator, uint256 quorumNumerator);
+
+    /**
+     * @dev The quorum set is not valid as it exceeds the super quorum.
+     */
+    error GovernorInvalidQuorumTooLarge(uint256 quorumNumerator, uint256 superQuorumNumerator);
+
+    /**
+     * @dev Initialize super quorum as a fraction of the token's total supply.
+     *
+     * The super quorum is specified as a fraction of the token's total supply and has to
+     * be greater than the quorum.
+     */
+    constructor(uint256 superQuorumNumeratorValue) {
+        _updateSuperQuorumNumerator(superQuorumNumeratorValue);
+    }
+
+    /**
+     * @dev Returns the current super quorum numerator.
+     */
+    function superQuorumNumerator() public view virtual returns (uint256) {
+        return _superQuorumNumeratorHistory.latest();
+    }
+
+    /**
+     * @dev Returns the super quorum numerator at a specific `timepoint`.
+     */
+    function superQuorumNumerator(uint256 timepoint) public view virtual returns (uint256) {
+        return _optimisticUpperLookupRecent(_superQuorumNumeratorHistory, timepoint);
+    }
+
+    /**
+     * @dev Returns the super quorum for a `timepoint`, in terms of number of votes: `supply * numerator / denominator`.
+     * See {GovernorSuperQuorum-superQuorum} for more details.
+     */
+    function superQuorum(uint256 timepoint) public view virtual override returns (uint256) {
+        return Math.mulDiv(token().getPastTotalSupply(timepoint), superQuorumNumerator(timepoint), quorumDenominator());
+    }
+
+    /**
+     * @dev Changes the super quorum numerator.
+     *
+     * Emits a {SuperQuorumNumeratorUpdated} event.
+     *
+     * Requirements:
+     *
+     * - Must be called through a governance proposal.
+     * - New super quorum numerator must be smaller or equal to the denominator.
+     * - New super quorum numerator must be greater than or equal to the quorum numerator.
+     */
+    function updateSuperQuorumNumerator(uint256 newSuperQuorumNumerator) public virtual onlyGovernance {
+        _updateSuperQuorumNumerator(newSuperQuorumNumerator);
+    }
+
+    /**
+     * @dev Changes the super quorum numerator.
+     *
+     * Emits a {SuperQuorumNumeratorUpdated} event.
+     *
+     * Requirements:
+     *
+     * - New super quorum numerator must be smaller or equal to the denominator.
+     * - New super quorum numerator must be greater than or equal to the quorum numerator.
+     */
+    function _updateSuperQuorumNumerator(uint256 newSuperQuorumNumerator) internal virtual {
+        uint256 denominator = quorumDenominator();
+        if (newSuperQuorumNumerator > denominator) {
+            revert GovernorInvalidSuperQuorumFraction(newSuperQuorumNumerator, denominator);
+        }
+
+        uint256 quorumNumerator = quorumNumerator();
+        if (newSuperQuorumNumerator < quorumNumerator) {
+            revert GovernorInvalidSuperQuorumTooSmall(newSuperQuorumNumerator, quorumNumerator);
+        }
+
+        uint256 oldSuperQuorumNumerator = _superQuorumNumeratorHistory.latest();
+        _superQuorumNumeratorHistory.push(clock(), SafeCast.toUint208(newSuperQuorumNumerator));
+
+        emit SuperQuorumNumeratorUpdated(oldSuperQuorumNumerator, newSuperQuorumNumerator);
+    }
+
+    /**
+     * @dev Overrides {GovernorVotesQuorumFraction-_updateQuorumNumerator} to ensure the super
+     * quorum numerator is greater than or equal to the quorum numerator.
+     */
+    function _updateQuorumNumerator(uint256 newQuorumNumerator) internal virtual override {
+        // Ignoring check when the superQuorum was never set (construction sets quorum before superQuorum)
+        if (_superQuorumNumeratorHistory.length() > 0) {
+            uint256 superQuorumNumerator_ = superQuorumNumerator();
+            if (newQuorumNumerator > superQuorumNumerator_) {
+                revert GovernorInvalidQuorumTooLarge(newQuorumNumerator, superQuorumNumerator_);
+            }
+        }
+        super._updateQuorumNumerator(newQuorumNumerator);
+    }
+
+    /// @inheritdoc GovernorSuperQuorum
+    function state(
+        uint256 proposalId
+    ) public view virtual override(Governor, GovernorSuperQuorum) returns (ProposalState) {
+        return super.state(proposalId);
+    }
+}

+ 2 - 2
contracts/interfaces/IERC1271.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1271.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (interfaces/IERC1271.sol)
 
 
 pragma solidity ^0.8.20;
 pragma solidity ^0.8.20;
 
 
@@ -11,7 +11,7 @@ interface IERC1271 {
     /**
     /**
      * @dev Should return whether the signature provided is valid for the provided data
      * @dev Should return whether the signature provided is valid for the provided data
      * @param hash      Hash of the data to be signed
      * @param hash      Hash of the data to be signed
-     * @param signature Signature byte array associated with _data
+     * @param signature Signature byte array associated with `hash`
      */
      */
     function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue);
     function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue);
 }
 }

+ 2 - 2
contracts/interfaces/IERC4626.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC4626.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (interfaces/IERC4626.sol)
 
 
 pragma solidity ^0.8.20;
 pragma solidity ^0.8.20;
 
 
@@ -198,7 +198,7 @@ interface IERC4626 is IERC20, IERC20Metadata {
     function maxRedeem(address owner) external view returns (uint256 maxShares);
     function maxRedeem(address owner) external view returns (uint256 maxShares);
 
 
     /**
     /**
-     * @dev Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block,
+     * @dev Allows an on-chain or off-chain user to simulate the effects of their redemption at the current block,
      * given current on-chain conditions.
      * given current on-chain conditions.
      *
      *
      * - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call
      * - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call

+ 15 - 1
contracts/interfaces/README.adoc

@@ -40,6 +40,10 @@ are useful to interact with third party contracts that implement them.
 - {IERC5313}
 - {IERC5313}
 - {IERC5805}
 - {IERC5805}
 - {IERC6372}
 - {IERC6372}
+- {IERC6909}
+- {IERC6909ContentURI}
+- {IERC6909Metadata}
+- {IERC6909TokenSupply}
 - {IERC7674}
 - {IERC7674}
 
 
 == Detailed ABI
 == Detailed ABI
@@ -74,12 +78,22 @@ are useful to interact with third party contracts that implement them.
 
 
 {{IERC4626}}
 {{IERC4626}}
 
 
-{{IERC5313}}
+{{IERC4906}}
 
 
 {{IERC5267}}
 {{IERC5267}}
 
 
+{{IERC5313}}
+
 {{IERC5805}}
 {{IERC5805}}
 
 
 {{IERC6372}}
 {{IERC6372}}
 
 
+{{IERC6909}}
+
+{{IERC6909ContentURI}}
+
+{{IERC6909Metadata}}
+
+{{IERC6909TokenSupply}}
+
 {{IERC7674}}
 {{IERC7674}}

+ 4 - 4
contracts/interfaces/draft-IERC4337.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.2.0) (interfaces/draft-IERC4337.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (interfaces/draft-IERC4337.sol)
 
 
 pragma solidity ^0.8.20;
 pragma solidity ^0.8.20;
 
 
@@ -21,7 +21,7 @@ pragma solidity ^0.8.20;
  * - `paymasterData` (`bytes`): Data for paymaster (only if paymaster exists)
  * - `paymasterData` (`bytes`): Data for paymaster (only if paymaster exists)
  * - `signature` (`bytes`): Data passed into the account to verify authorization
  * - `signature` (`bytes`): Data passed into the account to verify authorization
  *
  *
- * When passed to on-chain contacts, the following packed version is used.
+ * When passed to on-chain contracts, the following packed version is used.
  * - `sender` (`address`)
  * - `sender` (`address`)
  * - `nonce` (`uint256`)
  * - `nonce` (`uint256`)
  * - `initCode` (`bytes`): concatenation of factory address and factoryData (or empty)
  * - `initCode` (`bytes`): concatenation of factory address and factoryData (or empty)
@@ -164,13 +164,13 @@ interface IEntryPoint is IEntryPointNonces, IEntryPointStake {
 
 
     /**
     /**
      * @dev Executes a batch of user operations.
      * @dev Executes a batch of user operations.
-     * @param beneficiary Address to which gas is refunded up completing the execution.
+     * @param beneficiary Address to which gas is refunded upon completing the execution.
      */
      */
     function handleOps(PackedUserOperation[] calldata ops, address payable beneficiary) external;
     function handleOps(PackedUserOperation[] calldata ops, address payable beneficiary) external;
 
 
     /**
     /**
      * @dev Executes a batch of aggregated user operations per aggregator.
      * @dev Executes a batch of aggregated user operations per aggregator.
-     * @param beneficiary Address to which gas is refunded up completing the execution.
+     * @param beneficiary Address to which gas is refunded upon completing the execution.
      */
      */
     function handleAggregatedOps(
     function handleAggregatedOps(
         UserOpsPerAggregator[] calldata opsPerAggregator,
         UserOpsPerAggregator[] calldata opsPerAggregator,

+ 125 - 0
contracts/interfaces/draft-IERC6909.sol

@@ -0,0 +1,125 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v5.3.0) (interfaces/draft-IERC6909.sol)
+
+pragma solidity ^0.8.20;
+
+import {IERC165} from "../utils/introspection/IERC165.sol";
+
+/**
+ * @dev Required interface of an ERC-6909 compliant contract, as defined in the
+ * https://eips.ethereum.org/EIPS/eip-6909[ERC].
+ */
+interface IERC6909 is IERC165 {
+    /**
+     * @dev Emitted when the allowance of a `spender` for an `owner` is set for a token of type `id`.
+     * The new allowance is `amount`.
+     */
+    event Approval(address indexed owner, address indexed spender, uint256 indexed id, uint256 amount);
+
+    /**
+     * @dev Emitted when `owner` grants or revokes operator status for a `spender`.
+     */
+    event OperatorSet(address indexed owner, address indexed spender, bool approved);
+
+    /**
+     * @dev Emitted when `amount` tokens of type `id` are moved from `sender` to `receiver` initiated by `caller`.
+     */
+    event Transfer(
+        address caller,
+        address indexed sender,
+        address indexed receiver,
+        uint256 indexed id,
+        uint256 amount
+    );
+
+    /**
+     * @dev Returns the amount of tokens of type `id` owned by `owner`.
+     */
+    function balanceOf(address owner, uint256 id) external view returns (uint256);
+
+    /**
+     * @dev Returns the amount of tokens of type `id` that `spender` is allowed to spend on behalf of `owner`.
+     *
+     * NOTE: Does not include operator allowances.
+     */
+    function allowance(address owner, address spender, uint256 id) external view returns (uint256);
+
+    /**
+     * @dev Returns true if `spender` is set as an operator for `owner`.
+     */
+    function isOperator(address owner, address spender) external view returns (bool);
+
+    /**
+     * @dev Sets an approval to `spender` for `amount` of tokens of type `id` from the caller's tokens. An `amount` of
+     * `type(uint256).max` signifies an unlimited approval.
+     *
+     * Must return true.
+     */
+    function approve(address spender, uint256 id, uint256 amount) external returns (bool);
+
+    /**
+     * @dev Grants or revokes unlimited transfer permission of any token id to `spender` for the caller's tokens.
+     *
+     * Must return true.
+     */
+    function setOperator(address spender, bool approved) external returns (bool);
+
+    /**
+     * @dev Transfers `amount` of token type `id` from the caller's account to `receiver`.
+     *
+     * Must return true.
+     */
+    function transfer(address receiver, uint256 id, uint256 amount) external returns (bool);
+
+    /**
+     * @dev Transfers `amount` of token type `id` from `sender` to `receiver`.
+     *
+     * Must return true.
+     */
+    function transferFrom(address sender, address receiver, uint256 id, uint256 amount) external returns (bool);
+}
+
+/**
+ * @dev Optional extension of {IERC6909} that adds metadata functions.
+ */
+interface IERC6909Metadata is IERC6909 {
+    /**
+     * @dev Returns the name of the token of type `id`.
+     */
+    function name(uint256 id) external view returns (string memory);
+
+    /**
+     * @dev Returns the ticker symbol of the token of type `id`.
+     */
+    function symbol(uint256 id) external view returns (string memory);
+
+    /**
+     * @dev Returns the number of decimals for the token of type `id`.
+     */
+    function decimals(uint256 id) external view returns (uint8);
+}
+
+/**
+ * @dev Optional extension of {IERC6909} that adds content URI functions.
+ */
+interface IERC6909ContentURI is IERC6909 {
+    /**
+     * @dev Returns URI for the contract.
+     */
+    function contractURI() external view returns (string memory);
+
+    /**
+     * @dev Returns the URI for the token of type `id`.
+     */
+    function tokenURI(uint256 id) external view returns (string memory);
+}
+
+/**
+ * @dev Optional extension of {IERC6909} that adds a token supply function.
+ */
+interface IERC6909TokenSupply is IERC6909 {
+    /**
+     * @dev Returns the total supply of the token of type `id`.
+     */
+    function totalSupply(uint256 id) external view returns (uint256);
+}

+ 7 - 7
contracts/interfaces/draft-IERC7579.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.2.0) (interfaces/draft-IERC7579.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (interfaces/draft-IERC7579.sol)
 pragma solidity ^0.8.20;
 pragma solidity ^0.8.20;
 
 
 import {PackedUserOperation} from "./draft-IERC4337.sol";
 import {PackedUserOperation} from "./draft-IERC4337.sol";
@@ -15,7 +15,7 @@ uint256 constant MODULE_TYPE_HOOK = 4;
 interface IERC7579Module {
 interface IERC7579Module {
     /**
     /**
      * @dev This function is called by the smart account during installation of the module
      * @dev This function is called by the smart account during installation of the module
-     * @param data arbitrary data that may be required on the module during `onInstall` initialization
+     * @param data arbitrary data that may be passed to the module during `onInstall` initialization
      *
      *
      * MUST revert on error (e.g. if module is already enabled)
      * MUST revert on error (e.g. if module is already enabled)
      */
      */
@@ -23,7 +23,7 @@ interface IERC7579Module {
 
 
     /**
     /**
      * @dev This function is called by the smart account during uninstallation of the module
      * @dev This function is called by the smart account during uninstallation of the module
-     * @param data arbitrary data that may be required on the module during `onUninstall` de-initialization
+     * @param data arbitrary data that may be passed to the module during `onUninstall` de-initialization
      *
      *
      * MUST revert on error
      * MUST revert on error
      */
      */
@@ -186,7 +186,7 @@ interface IERC7579ModuleConfig {
      * @dev Installs a Module of a certain type on the smart account
      * @dev Installs a Module of a certain type on the smart account
      * @param moduleTypeId the module type ID according to the ERC-7579 spec
      * @param moduleTypeId the module type ID according to the ERC-7579 spec
      * @param module the module address
      * @param module the module address
-     * @param initData arbitrary data that may be required on the module during `onInstall`
+     * @param initData arbitrary data that may be passed to the module during `onInstall`
      * initialization.
      * initialization.
      *
      *
      * MUST implement authorization control
      * MUST implement authorization control
@@ -200,8 +200,8 @@ interface IERC7579ModuleConfig {
      * @dev Uninstalls a Module of a certain type on the smart account
      * @dev Uninstalls a Module of a certain type on the smart account
      * @param moduleTypeId the module type ID according the ERC-7579 spec
      * @param moduleTypeId the module type ID according the ERC-7579 spec
      * @param module the module address
      * @param module the module address
-     * @param deInitData arbitrary data that may be required on the module during `onInstall`
-     * initialization.
+     * @param deInitData arbitrary data that may be passed to the module during `onUninstall`
+     * deinitialization.
      *
      *
      * MUST implement authorization control
      * MUST implement authorization control
      * MUST call `onUninstall` on the module with the `deInitData` parameter if provided
      * MUST call `onUninstall` on the module with the `deInitData` parameter if provided
@@ -214,7 +214,7 @@ interface IERC7579ModuleConfig {
      * @dev Returns whether a module is installed on the smart account
      * @dev Returns whether a module is installed on the smart account
      * @param moduleTypeId the module type ID according the ERC-7579 spec
      * @param moduleTypeId the module type ID according the ERC-7579 spec
      * @param module the module address
      * @param module the module address
-     * @param additionalContext arbitrary data that may be required to determine if the module is installed
+     * @param additionalContext arbitrary data that may be passed to determine if the module is installed
      *
      *
      * MUST return true if the module is installed and false otherwise
      * MUST return true if the module is installed and false otherwise
      */
      */

+ 5 - 2
contracts/metatx/ERC2771Forwarder.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (metatx/ERC2771Forwarder.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (metatx/ERC2771Forwarder.sol)
 
 
 pragma solidity ^0.8.20;
 pragma solidity ^0.8.20;
 
 
@@ -302,8 +302,11 @@ contract ERC2771Forwarder is EIP712, Nonces {
      *
      *
      * This function performs a static call to the target contract calling the
      * This function performs a static call to the target contract calling the
      * {ERC2771Context-isTrustedForwarder} function.
      * {ERC2771Context-isTrustedForwarder} function.
+     *
+     * NOTE: Consider the execution of this forwarder is permissionless. Without this check, anyone may transfer assets
+     * that are owned by, or are approved to this forwarder.
      */
      */
-    function _isTrustedByTarget(address target) private view returns (bool) {
+    function _isTrustedByTarget(address target) internal view virtual returns (bool) {
         bytes memory encodedParams = abi.encodeCall(ERC2771Context.isTrustedForwarder, (address(this)));
         bytes memory encodedParams = abi.encodeCall(ERC2771Context.isTrustedForwarder, (address(this)));
 
 
         bool success;
         bool success;

+ 5 - 5
contracts/mocks/AuthorityMock.sol

@@ -12,7 +12,7 @@ contract NotAuthorityMock is IAuthority {
 }
 }
 
 
 contract AuthorityNoDelayMock is IAuthority {
 contract AuthorityNoDelayMock is IAuthority {
-    bool _immediate;
+    bool private _immediate;
 
 
     function canCall(
     function canCall(
         address /* caller */,
         address /* caller */,
@@ -28,14 +28,14 @@ contract AuthorityNoDelayMock is IAuthority {
 }
 }
 
 
 contract AuthorityDelayMock {
 contract AuthorityDelayMock {
-    bool _immediate;
-    uint32 _delay;
+    bool private _immediate;
+    uint256 private _delay;
 
 
     function canCall(
     function canCall(
         address /* caller */,
         address /* caller */,
         address /* target */,
         address /* target */,
         bytes4 /* selector */
         bytes4 /* selector */
-    ) external view returns (bool immediate, uint32 delay) {
+    ) external view returns (bool immediate, uint256 delay) {
         return (_immediate, _delay);
         return (_immediate, _delay);
     }
     }
 
 
@@ -43,7 +43,7 @@ contract AuthorityDelayMock {
         _immediate = immediate;
         _immediate = immediate;
     }
     }
 
 
-    function _setDelay(uint32 delay) external {
+    function _setDelay(uint256 delay) external {
         _delay = delay;
         _delay = delay;
     }
     }
 }
 }

+ 8 - 0
contracts/mocks/MerkleTreeMock.sol

@@ -14,6 +14,7 @@ contract MerkleTreeMock {
     bytes32 public root;
     bytes32 public root;
 
 
     event LeafInserted(bytes32 leaf, uint256 index, bytes32 root);
     event LeafInserted(bytes32 leaf, uint256 index, bytes32 root);
+    event LeafUpdated(bytes32 oldLeaf, bytes32 newLeaf, uint256 index, bytes32 root);
 
 
     function setup(uint8 _depth, bytes32 _zero) public {
     function setup(uint8 _depth, bytes32 _zero) public {
         root = _tree.setup(_depth, _zero);
         root = _tree.setup(_depth, _zero);
@@ -25,6 +26,13 @@ contract MerkleTreeMock {
         root = currentRoot;
         root = currentRoot;
     }
     }
 
 
+    function update(uint256 index, bytes32 oldValue, bytes32 newValue, bytes32[] memory proof) public {
+        (bytes32 oldRoot, bytes32 newRoot) = _tree.update(index, oldValue, newValue, proof);
+        if (oldRoot != root) revert MerkleTree.MerkleTreeUpdateInvalidProof();
+        emit LeafUpdated(oldValue, newValue, index, newRoot);
+        root = newRoot;
+    }
+
     function depth() public view returns (uint256) {
     function depth() public view returns (uint256) {
         return _tree.depth();
         return _tree.depth();
     }
     }

+ 2 - 2
contracts/mocks/docs/access-control/AccessControlModified.sol

@@ -5,10 +5,10 @@ pragma solidity ^0.8.20;
 import {AccessControl} from "../../../access/AccessControl.sol";
 import {AccessControl} from "../../../access/AccessControl.sol";
 
 
 contract AccessControlModified is AccessControl {
 contract AccessControlModified is AccessControl {
-    error AccessControlNonRevokable();
+    error AccessControlNonRevocable();
 
 
     // Override the revokeRole function
     // Override the revokeRole function
     function revokeRole(bytes32, address) public pure override {
     function revokeRole(bytes32, address) public pure override {
-        revert AccessControlNonRevokable();
+        revert AccessControlNonRevocable();
     }
     }
 }
 }

+ 26 - 0
contracts/mocks/docs/token/ERC6909/ERC6909GameItems.sol

@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.20;
+
+import {ERC6909Metadata} from "../../../../token/ERC6909/extensions/draft-ERC6909Metadata.sol";
+
+contract ERC6909GameItems is ERC6909Metadata {
+    uint256 public constant GOLD = 0;
+    uint256 public constant SILVER = 1;
+    uint256 public constant THORS_HAMMER = 2;
+    uint256 public constant SWORD = 3;
+    uint256 public constant SHIELD = 4;
+
+    constructor() {
+        _setDecimals(GOLD, 18);
+        _setDecimals(SILVER, 18);
+        // Default decimals is 0
+        _setDecimals(SWORD, 9);
+        _setDecimals(SHIELD, 9);
+
+        _mint(msg.sender, GOLD, 10 ** 18);
+        _mint(msg.sender, SILVER, 10_000 ** 18);
+        _mint(msg.sender, THORS_HAMMER, 1);
+        _mint(msg.sender, SWORD, 10 ** 9);
+        _mint(msg.sender, SHIELD, 10 ** 9);
+    }
+}

+ 27 - 0
contracts/mocks/governance/GovernorProposalGuardianMock.sol

@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: MIT
+
+pragma solidity ^0.8.20;
+
+import {Governor} from "../../governance/Governor.sol";
+import {GovernorSettings} from "../../governance/extensions/GovernorSettings.sol";
+import {GovernorCountingSimple} from "../../governance/extensions/GovernorCountingSimple.sol";
+import {GovernorVotesQuorumFraction} from "../../governance/extensions/GovernorVotesQuorumFraction.sol";
+import {GovernorProposalGuardian} from "../../governance/extensions/GovernorProposalGuardian.sol";
+
+abstract contract GovernorProposalGuardianMock is
+    GovernorSettings,
+    GovernorVotesQuorumFraction,
+    GovernorCountingSimple,
+    GovernorProposalGuardian
+{
+    function proposalThreshold() public view override(Governor, GovernorSettings) returns (uint256) {
+        return super.proposalThreshold();
+    }
+
+    function _validateCancel(
+        uint256 proposalId,
+        address caller
+    ) internal view override(Governor, GovernorProposalGuardian) returns (bool) {
+        return super._validateCancel(proposalId, caller);
+    }
+}

+ 39 - 0
contracts/mocks/governance/GovernorSequentialProposalIdMock.sol

@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: MIT
+
+pragma solidity ^0.8.20;
+
+import {Governor} from "../../governance/Governor.sol";
+import {GovernorSettings} from "../../governance/extensions/GovernorSettings.sol";
+import {GovernorCountingSimple} from "../../governance/extensions/GovernorCountingSimple.sol";
+import {GovernorVotesQuorumFraction} from "../../governance/extensions/GovernorVotesQuorumFraction.sol";
+import {GovernorSequentialProposalId} from "../../governance/extensions/GovernorSequentialProposalId.sol";
+
+abstract contract GovernorSequentialProposalIdMock is
+    GovernorSettings,
+    GovernorVotesQuorumFraction,
+    GovernorCountingSimple,
+    GovernorSequentialProposalId
+{
+    function proposalThreshold() public view override(Governor, GovernorSettings) returns (uint256) {
+        return super.proposalThreshold();
+    }
+
+    function getProposalId(
+        address[] memory targets,
+        uint256[] memory values,
+        bytes[] memory calldatas,
+        bytes32 descriptionHash
+    ) public view virtual override(Governor, GovernorSequentialProposalId) returns (uint256) {
+        return super.getProposalId(targets, values, calldatas, descriptionHash);
+    }
+
+    function _propose(
+        address[] memory targets,
+        uint256[] memory values,
+        bytes[] memory calldatas,
+        string memory description,
+        address proposer
+    ) internal virtual override(Governor, GovernorSequentialProposalId) returns (uint256 proposalId) {
+        return super._propose(targets, values, calldatas, description, proposer);
+    }
+}

+ 95 - 0
contracts/mocks/governance/GovernorSuperQuorumMock.sol

@@ -0,0 +1,95 @@
+// SPDX-License-Identifier: MIT
+
+pragma solidity ^0.8.20;
+
+import {Governor} from "../../governance/Governor.sol";
+import {GovernorSettings} from "../../governance/extensions/GovernorSettings.sol";
+import {GovernorVotes} from "../../governance/extensions/GovernorVotes.sol";
+import {GovernorSuperQuorum} from "../../governance/extensions/GovernorSuperQuorum.sol";
+import {GovernorCountingSimple} from "../../governance/extensions/GovernorCountingSimple.sol";
+import {GovernorTimelockControl} from "../../governance/extensions/GovernorTimelockControl.sol";
+
+abstract contract GovernorSuperQuorumMock is
+    GovernorSettings,
+    GovernorVotes,
+    GovernorTimelockControl,
+    GovernorSuperQuorum,
+    GovernorCountingSimple
+{
+    uint256 private _quorum;
+    uint256 private _superQuorum;
+
+    constructor(uint256 quorum_, uint256 superQuorum_) {
+        _quorum = quorum_;
+        _superQuorum = superQuorum_;
+    }
+
+    function quorum(uint256) public view override returns (uint256) {
+        return _quorum;
+    }
+
+    function superQuorum(uint256) public view override returns (uint256) {
+        return _superQuorum;
+    }
+
+    function state(
+        uint256 proposalId
+    ) public view override(Governor, GovernorSuperQuorum, GovernorTimelockControl) returns (ProposalState) {
+        return super.state(proposalId);
+    }
+
+    function proposalThreshold() public view override(Governor, GovernorSettings) returns (uint256) {
+        return super.proposalThreshold();
+    }
+
+    function proposalVotes(
+        uint256 proposalId
+    )
+        public
+        view
+        virtual
+        override(GovernorCountingSimple, GovernorSuperQuorum)
+        returns (uint256 againstVotes, uint256 forVotes, uint256 abstainVotes)
+    {
+        return super.proposalVotes(proposalId);
+    }
+
+    function _cancel(
+        address[] memory targets,
+        uint256[] memory values,
+        bytes[] memory calldatas,
+        bytes32 descriptionHash
+    ) internal override(Governor, GovernorTimelockControl) returns (uint256) {
+        return super._cancel(targets, values, calldatas, descriptionHash);
+    }
+
+    function _executeOperations(
+        uint256 proposalId,
+        address[] memory targets,
+        uint256[] memory values,
+        bytes[] memory calldatas,
+        bytes32 descriptionHash
+    ) internal override(Governor, GovernorTimelockControl) {
+        super._executeOperations(proposalId, targets, values, calldatas, descriptionHash);
+    }
+
+    function _executor() internal view override(Governor, GovernorTimelockControl) returns (address) {
+        return super._executor();
+    }
+
+    function _queueOperations(
+        uint256 proposalId,
+        address[] memory targets,
+        uint256[] memory values,
+        bytes[] memory calldatas,
+        bytes32 descriptionHash
+    ) internal override(Governor, GovernorTimelockControl) returns (uint48) {
+        return super._queueOperations(proposalId, targets, values, calldatas, descriptionHash);
+    }
+
+    function proposalNeedsQueuing(
+        uint256 proposalId
+    ) public view override(Governor, GovernorTimelockControl) returns (bool) {
+        return super.proposalNeedsQueuing(proposalId);
+    }
+}

+ 37 - 0
contracts/mocks/governance/GovernorVotesSuperQuorumFractionMock.sol

@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: MIT
+
+pragma solidity ^0.8.20;
+
+import {Governor} from "../../governance/Governor.sol";
+import {GovernorSettings} from "../../governance/extensions/GovernorSettings.sol";
+import {GovernorSuperQuorum} from "../../governance/extensions/GovernorSuperQuorum.sol";
+import {GovernorCountingSimple} from "../../governance/extensions/GovernorCountingSimple.sol";
+import {GovernorVotesSuperQuorumFraction} from "../../governance/extensions/GovernorVotesSuperQuorumFraction.sol";
+
+abstract contract GovernorVotesSuperQuorumFractionMock is
+    GovernorSettings,
+    GovernorVotesSuperQuorumFraction,
+    GovernorCountingSimple
+{
+    function proposalThreshold() public view override(Governor, GovernorSettings) returns (uint256) {
+        return super.proposalThreshold();
+    }
+
+    function proposalVotes(
+        uint256 proposalId
+    )
+        public
+        view
+        virtual
+        override(GovernorCountingSimple, GovernorSuperQuorum)
+        returns (uint256 againstVotes, uint256 forVotes, uint256 abstainVotes)
+    {
+        return super.proposalVotes(proposalId);
+    }
+
+    function state(
+        uint256 proposalId
+    ) public view override(Governor, GovernorVotesSuperQuorumFraction) returns (ProposalState) {
+        return super.state(proposalId);
+    }
+}

+ 1 - 1
contracts/mocks/token/ERC20ForceApproveMock.sol

@@ -4,7 +4,7 @@ pragma solidity ^0.8.20;
 
 
 import {ERC20} from "../../token/ERC20/ERC20.sol";
 import {ERC20} from "../../token/ERC20/ERC20.sol";
 
 
-// contract that replicate USDT (0xdac17f958d2ee523a2206206994597c13d831ec7) approval behavior
+// contract that replicates USDT (0xdac17f958d2ee523a2206206994597c13d831ec7) approval behavior
 abstract contract ERC20ForceApproveMock is ERC20 {
 abstract contract ERC20ForceApproveMock is ERC20 {
     function approve(address spender, uint256 amount) public virtual override returns (bool) {
     function approve(address spender, uint256 amount) public virtual override returns (bool) {
         require(amount == 0 || allowance(msg.sender, spender) == 0, "USDT approval failure");
         require(amount == 0 || allowance(msg.sender, spender) == 0, "USDT approval failure");

+ 1 - 1
contracts/package.json

@@ -1,7 +1,7 @@
 {
 {
   "name": "@openzeppelin/contracts",
   "name": "@openzeppelin/contracts",
   "description": "Secure Smart Contract library for Solidity",
   "description": "Secure Smart Contract library for Solidity",
-  "version": "5.2.0",
+  "version": "5.3.0",
   "files": [
   "files": [
     "**/*.sol",
     "**/*.sol",
     "/build/contracts/*.json",
     "/build/contracts/*.json",

+ 4 - 4
contracts/proxy/Clones.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.2.0) (proxy/Clones.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (proxy/Clones.sol)
 
 
 pragma solidity ^0.8.20;
 pragma solidity ^0.8.20;
 
 
@@ -21,7 +21,7 @@ library Clones {
     error CloneArgumentsTooLong();
     error CloneArgumentsTooLong();
 
 
     /**
     /**
-     * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.
+     * @dev Deploys and returns the address of a clone that mimics the behavior of `implementation`.
      *
      *
      * This function uses the create opcode, which should never revert.
      * This function uses the create opcode, which should never revert.
      */
      */
@@ -54,7 +54,7 @@ library Clones {
     }
     }
 
 
     /**
     /**
-     * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.
+     * @dev Deploys and returns the address of a clone that mimics the behavior of `implementation`.
      *
      *
      * This function uses the create2 opcode and a `salt` to deterministically deploy
      * This function uses the create2 opcode and a `salt` to deterministically deploy
      * the clone. Using the same `implementation` and `salt` multiple times will revert, since
      * the clone. Using the same `implementation` and `salt` multiple times will revert, since
@@ -158,7 +158,7 @@ library Clones {
     }
     }
 
 
     /**
     /**
-     * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation` with custom
+     * @dev Deploys and returns the address of a clone that mimics the behavior of `implementation` with custom
      * immutable arguments. These are provided through `args` and cannot be changed after deployment. To
      * immutable arguments. These are provided through `args` and cannot be changed after deployment. To
      * access the arguments within the implementation, use {fetchCloneArgs}.
      * access the arguments within the implementation, use {fetchCloneArgs}.
      *
      *

+ 13 - 3
contracts/proxy/utils/Initializable.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (proxy/utils/Initializable.sol)
 
 
 pragma solidity ^0.8.20;
 pragma solidity ^0.8.20;
 
 
@@ -112,7 +112,7 @@ abstract contract Initializable {
         // Allowed calls:
         // Allowed calls:
         // - initialSetup: the contract is not in the initializing state and no previous version was
         // - initialSetup: the contract is not in the initializing state and no previous version was
         //                 initialized
         //                 initialized
-        // - construction: the contract is initialized at version 1 (no reininitialization) and the
+        // - construction: the contract is initialized at version 1 (no reinitialization) and the
         //                 current contract is just being deployed
         //                 current contract is just being deployed
         bool initialSetup = initialized == 0 && isTopLevelCall;
         bool initialSetup = initialized == 0 && isTopLevelCall;
         bool construction = initialized == 1 && address(this).code.length == 0;
         bool construction = initialized == 1 && address(this).code.length == 0;
@@ -216,13 +216,23 @@ abstract contract Initializable {
         return _getInitializableStorage()._initializing;
         return _getInitializableStorage()._initializing;
     }
     }
 
 
+    /**
+     * @dev Pointer to storage slot. Allows integrators to override it with a custom storage location.
+     *
+     * NOTE: Consider following the ERC-7201 formula to derive storage locations.
+     */
+    function _initializableStorageSlot() internal pure virtual returns (bytes32) {
+        return INITIALIZABLE_STORAGE;
+    }
+
     /**
     /**
      * @dev Returns a pointer to the storage namespace.
      * @dev Returns a pointer to the storage namespace.
      */
      */
     // solhint-disable-next-line var-name-mixedcase
     // solhint-disable-next-line var-name-mixedcase
     function _getInitializableStorage() private pure returns (InitializableStorage storage $) {
     function _getInitializableStorage() private pure returns (InitializableStorage storage $) {
+        bytes32 slot = _initializableStorageSlot();
         assembly {
         assembly {
-            $.slot := INITIALIZABLE_STORAGE
+            $.slot := slot
         }
         }
     }
     }
 }
 }

+ 1 - 2
contracts/proxy/utils/UUPSUpgradeable.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.2.0) (proxy/utils/UUPSUpgradeable.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (proxy/utils/UUPSUpgradeable.sol)
 
 
 pragma solidity ^0.8.22;
 pragma solidity ^0.8.22;
 
 
@@ -91,7 +91,6 @@ abstract contract UUPSUpgradeable is IERC1822Proxiable {
     /**
     /**
      * @dev Reverts if the execution is not performed via delegatecall or the execution
      * @dev Reverts if the execution is not performed via delegatecall or the execution
      * context is not of a proxy with an ERC-1967 compliant implementation pointing to self.
      * context is not of a proxy with an ERC-1967 compliant implementation pointing to self.
-     * See {_onlyProxy}.
      */
      */
     function _checkProxy() internal view virtual {
     function _checkProxy() internal view virtual {
         if (
         if (

+ 3 - 3
contracts/token/ERC1155/IERC1155.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/IERC1155.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC1155/IERC1155.sol)
 
 
 pragma solidity ^0.8.20;
 pragma solidity ^0.8.20;
 
 
@@ -81,7 +81,7 @@ interface IERC1155 is IERC165 {
      * @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`.
      * @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`.
      *
      *
      * WARNING: This function can potentially allow a reentrancy attack when transferring tokens
      * WARNING: This function can potentially allow a reentrancy attack when transferring tokens
-     * to an untrusted contract, when invoking {onERC1155Received} on the receiver.
+     * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155Received} on the receiver.
      * Ensure to follow the checks-effects-interactions pattern and consider employing
      * Ensure to follow the checks-effects-interactions pattern and consider employing
      * reentrancy guards when interacting with untrusted contracts.
      * reentrancy guards when interacting with untrusted contracts.
      *
      *
@@ -101,7 +101,7 @@ interface IERC1155 is IERC165 {
      * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.
      * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.
      *
      *
      * WARNING: This function can potentially allow a reentrancy attack when transferring tokens
      * WARNING: This function can potentially allow a reentrancy attack when transferring tokens
-     * to an untrusted contract, when invoking {onERC1155BatchReceived} on the receiver.
+     * to an untrusted contract, when invoking {IERC1155Receiver-onERC1155BatchReceived} on the receiver.
      * Ensure to follow the checks-effects-interactions pattern and consider employing
      * Ensure to follow the checks-effects-interactions pattern and consider employing
      * reentrancy guards when interacting with untrusted contracts.
      * reentrancy guards when interacting with untrusted contracts.
      *
      *

+ 3 - 3
contracts/token/ERC1155/utils/ERC1155Utils.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/utils/ERC1155Utils.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC1155/utils/ERC1155Utils.sol)
 
 
 pragma solidity ^0.8.20;
 pragma solidity ^0.8.20;
 
 
@@ -15,7 +15,7 @@ import {IERC1155Errors} from "../../../interfaces/draft-IERC6093.sol";
  */
  */
 library ERC1155Utils {
 library ERC1155Utils {
     /**
     /**
-     * @dev Performs an acceptance check for the provided `operator` by calling {IERC1155-onERC1155Received}
+     * @dev Performs an acceptance check for the provided `operator` by calling {IERC1155Receiver-onERC1155Received}
      * on the `to` address. The `operator` is generally the address that initiated the token transfer (i.e. `msg.sender`).
      * on the `to` address. The `operator` is generally the address that initiated the token transfer (i.e. `msg.sender`).
      *
      *
      * The acceptance call is not executed and treated as a no-op if the target address doesn't contain code (i.e. an EOA).
      * The acceptance call is not executed and treated as a no-op if the target address doesn't contain code (i.e. an EOA).
@@ -50,7 +50,7 @@ library ERC1155Utils {
     }
     }
 
 
     /**
     /**
-     * @dev Performs a batch acceptance check for the provided `operator` by calling {IERC1155-onERC1155BatchReceived}
+     * @dev Performs a batch acceptance check for the provided `operator` by calling {IERC1155Receiver-onERC1155BatchReceived}
      * on the `to` address. The `operator` is generally the address that initiated the token transfer (i.e. `msg.sender`).
      * on the `to` address. The `operator` is generally the address that initiated the token transfer (i.e. `msg.sender`).
      *
      *
      * The acceptance call is not executed and treated as a no-op if the target address doesn't contain code (i.e. an EOA).
      * The acceptance call is not executed and treated as a no-op if the target address doesn't contain code (i.e. an EOA).

+ 4 - 5
contracts/token/ERC20/ERC20.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.2.0) (token/ERC20/ERC20.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/ERC20.sol)
 
 
 pragma solidity ^0.8.20;
 pragma solidity ^0.8.20;
 
 
@@ -39,8 +39,7 @@ abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {
     /**
     /**
      * @dev Sets the values for {name} and {symbol}.
      * @dev Sets the values for {name} and {symbol}.
      *
      *
-     * All two of these values are immutable: they can only be set once during
-     * construction.
+     * Both values are immutable: they can only be set once during construction.
      */
      */
     constructor(string memory name_, string memory symbol_) {
     constructor(string memory name_, string memory symbol_) {
         _name = name_;
         _name = name_;
@@ -241,7 +240,7 @@ abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {
     }
     }
 
 
     /**
     /**
-     * @dev Sets `value` as the allowance of `spender` over the `owner` s tokens.
+     * @dev Sets `value` as the allowance of `spender` over the `owner`'s tokens.
      *
      *
      * This internal function is equivalent to `approve`, and can be used to
      * This internal function is equivalent to `approve`, and can be used to
      * e.g. set automatic allowances for certain subsystems, etc.
      * e.g. set automatic allowances for certain subsystems, etc.
@@ -291,7 +290,7 @@ abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {
     }
     }
 
 
     /**
     /**
-     * @dev Updates `owner` s allowance for `spender` based on spent `value`.
+     * @dev Updates `owner`'s allowance for `spender` based on spent `value`.
      *
      *
      * Does not update the allowance value in case of infinite allowance.
      * Does not update the allowance value in case of infinite allowance.
      * Revert if not enough allowance is available.
      * Revert if not enough allowance is available.

+ 5 - 5
contracts/token/ERC20/README.adoc

@@ -7,11 +7,11 @@ This set of interfaces, contracts, and utilities are all related to the https://
 
 
 TIP: For an overview of ERC-20 tokens and a walk through on how to create a token contract read our xref:ROOT:erc20.adoc[ERC-20 guide].
 TIP: For an overview of ERC-20 tokens and a walk through on how to create a token contract read our xref:ROOT:erc20.adoc[ERC-20 guide].
 
 
-There are a few core contracts that implement the behavior specified in the ERC:
+There are a few core contracts that implement the behavior specified in the ERC-20 standard:
 
 
 * {IERC20}: the interface all ERC-20 implementations should conform to.
 * {IERC20}: the interface all ERC-20 implementations should conform to.
-* {IERC20Metadata}: the extended ERC-20 interface including the <<ERC20-name,`name`>>, <<ERC20-symbol,`symbol`>> and <<ERC20-decimals,`decimals`>> functions.
-* {ERC20}: the implementation of the ERC-20 interface, including the <<ERC20-name,`name`>>, <<ERC20-symbol,`symbol`>> and <<ERC20-decimals,`decimals`>> optional standard extension to the base interface.
+* {IERC20Metadata}: the extended ERC-20 interface including the <<ERC20-name--,`name`>>, <<ERC20-symbol--,`symbol`>> and <<ERC20-decimals--,`decimals`>> functions.
+* {ERC20}: the implementation of the ERC-20 interface, including the <<ERC20-name--,`name`>>, <<ERC20-symbol--,`symbol`>> and <<ERC20-decimals--,`decimals`>> optional extensions to the standard interface.
 
 
 Additionally there are multiple custom extensions, including:
 Additionally there are multiple custom extensions, including:
 
 
@@ -30,9 +30,9 @@ Finally, there are some utilities to interact with ERC-20 contracts in various w
 
 
 * {SafeERC20}: a wrapper around the interface that eliminates the need to handle boolean return values.
 * {SafeERC20}: a wrapper around the interface that eliminates the need to handle boolean return values.
 
 
-Other utilities that support ERC-20 assets can be found in codebase:
+Other utilities that support ERC-20 assets can be found in the codebase:
 
 
-* ERC-20 tokens can be timelocked (held tokens for a beneficiary until a specified time) or vested (released following a given schedule) using a {VestingWallet}.
+* ERC-20 tokens can be timelocked (held for a beneficiary until a specified time) or vested (released following a given schedule) using a {VestingWallet}.
 
 
 NOTE: This core set of contracts is designed to be unopinionated, allowing developers to access the internal functions in ERC-20 (such as <<ERC20-_mint-address-uint256-,`_mint`>>) and expose them as external functions in the way they prefer.
 NOTE: This core set of contracts is designed to be unopinionated, allowing developers to access the internal functions in ERC-20 (such as <<ERC20-_mint-address-uint256-,`_mint`>>) and expose them as external functions in the way they prefer.
 
 

+ 7 - 7
contracts/token/ERC20/extensions/ERC4626.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/ERC4626.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/extensions/ERC4626.sol)
 
 
 pragma solidity ^0.8.20;
 pragma solidity ^0.8.20;
 
 
@@ -34,7 +34,7 @@ import {Math} from "../../../utils/math/Math.sol";
  * offset (0) makes it non-profitable even if an attacker is able to capture value from multiple user deposits, as a result
  * offset (0) makes it non-profitable even if an attacker is able to capture value from multiple user deposits, as a result
  * of the value being captured by the virtual shares (out of the attacker's donation) matching the attacker's expected gains.
  * of the value being captured by the virtual shares (out of the attacker's donation) matching the attacker's expected gains.
  * With a larger offset, the attack becomes orders of magnitude more expensive than it is profitable. More details about the
  * With a larger offset, the attack becomes orders of magnitude more expensive than it is profitable. More details about the
- * underlying math can be found xref:erc4626.adoc#inflation-attack[here].
+ * underlying math can be found xref:ROOT:erc4626.adoc#inflation-attack[here].
  *
  *
  * The drawback of this approach is that the virtual shares do capture (a very small) part of the value being accrued
  * The drawback of this approach is that the virtual shares do capture (a very small) part of the value being accrued
  * to the vault. Also, if the vault experiences losses, the users try to exit the vault, the virtual shares and assets
  * to the vault. Also, if the vault experiences losses, the users try to exit the vault, the virtual shares and assets
@@ -114,7 +114,7 @@ abstract contract ERC4626 is ERC20, IERC4626 {
 
 
     /** @dev See {IERC4626-totalAssets}. */
     /** @dev See {IERC4626-totalAssets}. */
     function totalAssets() public view virtual returns (uint256) {
     function totalAssets() public view virtual returns (uint256) {
-        return _asset.balanceOf(address(this));
+        return IERC20(asset()).balanceOf(address(this));
     }
     }
 
 
     /** @dev See {IERC4626-convertToShares}. */
     /** @dev See {IERC4626-convertToShares}. */
@@ -237,14 +237,14 @@ abstract contract ERC4626 is ERC20, IERC4626 {
      * @dev Deposit/mint common workflow.
      * @dev Deposit/mint common workflow.
      */
      */
     function _deposit(address caller, address receiver, uint256 assets, uint256 shares) internal virtual {
     function _deposit(address caller, address receiver, uint256 assets, uint256 shares) internal virtual {
-        // If _asset is ERC-777, `transferFrom` can trigger a reentrancy BEFORE the transfer happens through the
+        // If asset() is ERC-777, `transferFrom` can trigger a reentrancy BEFORE the transfer happens through the
         // `tokensToSend` hook. On the other hand, the `tokenReceived` hook, that is triggered after the transfer,
         // `tokensToSend` hook. On the other hand, the `tokenReceived` hook, that is triggered after the transfer,
         // calls the vault, which is assumed not malicious.
         // calls the vault, which is assumed not malicious.
         //
         //
         // Conclusion: we need to do the transfer before we mint so that any reentrancy would happen before the
         // Conclusion: we need to do the transfer before we mint so that any reentrancy would happen before the
         // assets are transferred and before the shares are minted, which is a valid state.
         // assets are transferred and before the shares are minted, which is a valid state.
         // slither-disable-next-line reentrancy-no-eth
         // slither-disable-next-line reentrancy-no-eth
-        SafeERC20.safeTransferFrom(_asset, caller, address(this), assets);
+        SafeERC20.safeTransferFrom(IERC20(asset()), caller, address(this), assets);
         _mint(receiver, shares);
         _mint(receiver, shares);
 
 
         emit Deposit(caller, receiver, assets, shares);
         emit Deposit(caller, receiver, assets, shares);
@@ -264,14 +264,14 @@ abstract contract ERC4626 is ERC20, IERC4626 {
             _spendAllowance(owner, caller, shares);
             _spendAllowance(owner, caller, shares);
         }
         }
 
 
-        // If _asset is ERC-777, `transfer` can trigger a reentrancy AFTER the transfer happens through the
+        // If asset() is ERC-777, `transfer` can trigger a reentrancy AFTER the transfer happens through the
         // `tokensReceived` hook. On the other hand, the `tokensToSend` hook, that is triggered before the transfer,
         // `tokensReceived` hook. On the other hand, the `tokensToSend` hook, that is triggered before the transfer,
         // calls the vault, which is assumed not malicious.
         // calls the vault, which is assumed not malicious.
         //
         //
         // Conclusion: we need to do the transfer after the burn so that any reentrancy would happen after the
         // Conclusion: we need to do the transfer after the burn so that any reentrancy would happen after the
         // shares are burned and after the assets are transferred, which is a valid state.
         // shares are burned and after the assets are transferred, which is a valid state.
         _burn(owner, shares);
         _burn(owner, shares);
-        SafeERC20.safeTransfer(_asset, receiver, assets);
+        SafeERC20.safeTransfer(IERC20(asset()), receiver, assets);
 
 
         emit Withdraw(caller, receiver, owner, assets, shares);
         emit Withdraw(caller, receiver, owner, assets, shares);
     }
     }

+ 2 - 2
contracts/token/ERC20/extensions/draft-ERC20TemporaryApproval.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/draft-ERC20TemporaryApproval.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/extensions/draft-ERC20TemporaryApproval.sol)
 
 
 pragma solidity ^0.8.24;
 pragma solidity ^0.8.24;
 
 
@@ -61,7 +61,7 @@ abstract contract ERC20TemporaryApproval is ERC20, IERC7674 {
     }
     }
 
 
     /**
     /**
-     * @dev Sets `value` as the temporary allowance of `spender` over the `owner` s tokens.
+     * @dev Sets `value` as the temporary allowance of `spender` over the `owner`'s tokens.
      *
      *
      * This internal function is equivalent to `temporaryApprove`, and can be used to e.g. set automatic allowances
      * This internal function is equivalent to `temporaryApprove`, and can be used to e.g. set automatic allowances
      * for certain subsystems, etc.
      * for certain subsystems, etc.

+ 15 - 1
contracts/token/ERC20/utils/SafeERC20.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.2.0) (token/ERC20/utils/SafeERC20.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/utils/SafeERC20.sol)
 
 
 pragma solidity ^0.8.20;
 pragma solidity ^0.8.20;
 
 
@@ -42,6 +42,20 @@ library SafeERC20 {
         _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
         _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
     }
     }
 
 
+    /**
+     * @dev Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful.
+     */
+    function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) {
+        return _callOptionalReturnBool(token, abi.encodeCall(token.transfer, (to, value)));
+    }
+
+    /**
+     * @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful.
+     */
+    function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) {
+        return _callOptionalReturnBool(token, abi.encodeCall(token.transferFrom, (from, to, value)));
+    }
+
     /**
     /**
      * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
      * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
      * non-reverting calls are assumed to be successful.
      * non-reverting calls are assumed to be successful.

+ 27 - 0
contracts/token/ERC6909/README.adoc

@@ -0,0 +1,27 @@
+= ERC-6909
+
+[.readme-notice]
+NOTE: This document is better viewed at https://docs.openzeppelin.com/contracts/api/token/erc6909
+
+This set of interfaces and contracts are all related to the https://eips.ethereum.org/EIPS/eip-6909[ERC-6909 Minimal Multi-Token Interface].
+
+The ERC consists of four interfaces which fulfill different roles--the interfaces are as follows:
+
+. {IERC6909}: Base interface for a vanilla ERC6909 token.
+. {IERC6909ContentURI}: Extends the base interface and adds content URI (contract and token level) functionality.
+. {IERC6909Metadata}: Extends the base interface and adds metadata functionality, which exposes a name, symbol, and decimals for each token id.
+. {IERC6909TokenSupply}: Extends the base interface and adds total supply functionality for each token id.
+
+Implementations are provided for each of the 4 interfaces defined in the ERC.
+
+== Core
+
+{{ERC6909}}
+
+== Extensions
+
+{{ERC6909ContentURI}}
+
+{{ERC6909Metadata}}
+
+{{ERC6909TokenSupply}}

+ 224 - 0
contracts/token/ERC6909/draft-ERC6909.sol

@@ -0,0 +1,224 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC6909/draft-ERC6909.sol)
+
+pragma solidity ^0.8.20;
+
+import {IERC6909} from "../../interfaces/draft-IERC6909.sol";
+import {Context} from "../../utils/Context.sol";
+import {IERC165, ERC165} from "../../utils/introspection/ERC165.sol";
+
+/**
+ * @dev Implementation of ERC-6909.
+ * See https://eips.ethereum.org/EIPS/eip-6909
+ */
+contract ERC6909 is Context, ERC165, IERC6909 {
+    mapping(address owner => mapping(uint256 id => uint256)) private _balances;
+
+    mapping(address owner => mapping(address operator => bool)) private _operatorApprovals;
+
+    mapping(address owner => mapping(address spender => mapping(uint256 id => uint256))) private _allowances;
+
+    error ERC6909InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 id);
+    error ERC6909InsufficientAllowance(address spender, uint256 allowance, uint256 needed, uint256 id);
+    error ERC6909InvalidApprover(address approver);
+    error ERC6909InvalidReceiver(address receiver);
+    error ERC6909InvalidSender(address sender);
+    error ERC6909InvalidSpender(address spender);
+
+    /// @inheritdoc IERC165
+    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
+        return interfaceId == type(IERC6909).interfaceId || super.supportsInterface(interfaceId);
+    }
+
+    /// @inheritdoc IERC6909
+    function balanceOf(address owner, uint256 id) public view virtual override returns (uint256) {
+        return _balances[owner][id];
+    }
+
+    /// @inheritdoc IERC6909
+    function allowance(address owner, address spender, uint256 id) public view virtual override returns (uint256) {
+        return _allowances[owner][spender][id];
+    }
+
+    /// @inheritdoc IERC6909
+    function isOperator(address owner, address spender) public view virtual override returns (bool) {
+        return _operatorApprovals[owner][spender];
+    }
+
+    /// @inheritdoc IERC6909
+    function approve(address spender, uint256 id, uint256 amount) public virtual override returns (bool) {
+        _approve(_msgSender(), spender, id, amount);
+        return true;
+    }
+
+    /// @inheritdoc IERC6909
+    function setOperator(address spender, bool approved) public virtual override returns (bool) {
+        _setOperator(_msgSender(), spender, approved);
+        return true;
+    }
+
+    /// @inheritdoc IERC6909
+    function transfer(address receiver, uint256 id, uint256 amount) public virtual override returns (bool) {
+        _transfer(_msgSender(), receiver, id, amount);
+        return true;
+    }
+
+    /// @inheritdoc IERC6909
+    function transferFrom(
+        address sender,
+        address receiver,
+        uint256 id,
+        uint256 amount
+    ) public virtual override returns (bool) {
+        address caller = _msgSender();
+        if (sender != caller && !isOperator(sender, caller)) {
+            _spendAllowance(sender, caller, id, amount);
+        }
+        _transfer(sender, receiver, id, amount);
+        return true;
+    }
+
+    /**
+     * @dev Creates `amount` of token `id` and assigns them to `account`, by transferring it from address(0).
+     * Relies on the `_update` mechanism.
+     *
+     * Emits a {Transfer} event with `from` set to the zero address.
+     *
+     * NOTE: This function is not virtual, {_update} should be overridden instead.
+     */
+    function _mint(address to, uint256 id, uint256 amount) internal {
+        if (to == address(0)) {
+            revert ERC6909InvalidReceiver(address(0));
+        }
+        _update(address(0), to, id, amount);
+    }
+
+    /**
+     * @dev Moves `amount` of token `id` from `from` to `to` without checking for approvals. This function verifies
+     * that neither the sender nor the receiver are address(0), which means it cannot mint or burn tokens.
+     * Relies on the `_update` mechanism.
+     *
+     * Emits a {Transfer} event.
+     *
+     * NOTE: This function is not virtual, {_update} should be overridden instead.
+     */
+    function _transfer(address from, address to, uint256 id, uint256 amount) internal {
+        if (from == address(0)) {
+            revert ERC6909InvalidSender(address(0));
+        }
+        if (to == address(0)) {
+            revert ERC6909InvalidReceiver(address(0));
+        }
+        _update(from, to, id, amount);
+    }
+
+    /**
+     * @dev Destroys a `amount` of token `id` from `account`.
+     * Relies on the `_update` mechanism.
+     *
+     * Emits a {Transfer} event with `to` set to the zero address.
+     *
+     * NOTE: This function is not virtual, {_update} should be overridden instead
+     */
+    function _burn(address from, uint256 id, uint256 amount) internal {
+        if (from == address(0)) {
+            revert ERC6909InvalidSender(address(0));
+        }
+        _update(from, address(0), id, amount);
+    }
+
+    /**
+     * @dev Transfers `amount` of token `id` from `from` to `to`, or alternatively mints (or burns) if `from`
+     * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding
+     * this function.
+     *
+     * Emits a {Transfer} event.
+     */
+    function _update(address from, address to, uint256 id, uint256 amount) internal virtual {
+        address caller = _msgSender();
+
+        if (from != address(0)) {
+            uint256 fromBalance = _balances[from][id];
+            if (fromBalance < amount) {
+                revert ERC6909InsufficientBalance(from, fromBalance, amount, id);
+            }
+            unchecked {
+                // Overflow not possible: amount <= fromBalance.
+                _balances[from][id] = fromBalance - amount;
+            }
+        }
+        if (to != address(0)) {
+            _balances[to][id] += amount;
+        }
+
+        emit Transfer(caller, from, to, id, amount);
+    }
+
+    /**
+     * @dev Sets `amount` as the allowance of `spender` over the `owner`'s `id` tokens.
+     *
+     * This internal function is equivalent to `approve`, and can be used to e.g. set automatic allowances for certain
+     * subsystems, etc.
+     *
+     * Emits an {Approval} event.
+     *
+     * Requirements:
+     *
+     * - `owner` cannot be the zero address.
+     * - `spender` cannot be the zero address.
+     */
+    function _approve(address owner, address spender, uint256 id, uint256 amount) internal virtual {
+        if (owner == address(0)) {
+            revert ERC6909InvalidApprover(address(0));
+        }
+        if (spender == address(0)) {
+            revert ERC6909InvalidSpender(address(0));
+        }
+        _allowances[owner][spender][id] = amount;
+        emit Approval(owner, spender, id, amount);
+    }
+
+    /**
+     * @dev Approve `spender` to operate on all of `owner`'s tokens
+     *
+     * This internal function is equivalent to `setOperator`, and can be used to e.g. set automatic allowances for
+     * certain subsystems, etc.
+     *
+     * Emits an {OperatorSet} event.
+     *
+     * Requirements:
+     *
+     * - `owner` cannot be the zero address.
+     * - `spender` cannot be the zero address.
+     */
+    function _setOperator(address owner, address spender, bool approved) internal virtual {
+        if (owner == address(0)) {
+            revert ERC6909InvalidApprover(address(0));
+        }
+        if (spender == address(0)) {
+            revert ERC6909InvalidSpender(address(0));
+        }
+        _operatorApprovals[owner][spender] = approved;
+        emit OperatorSet(owner, spender, approved);
+    }
+
+    /**
+     * @dev Updates `owner`'s allowance for `spender` based on spent `amount`.
+     *
+     * Does not update the allowance value in case of infinite allowance.
+     * Revert if not enough allowance is available.
+     *
+     * Does not emit an {Approval} event.
+     */
+    function _spendAllowance(address owner, address spender, uint256 id, uint256 amount) internal virtual {
+        uint256 currentAllowance = allowance(owner, spender, id);
+        if (currentAllowance < type(uint256).max) {
+            if (currentAllowance < amount) {
+                revert ERC6909InsufficientAllowance(spender, currentAllowance, amount, id);
+            }
+            unchecked {
+                _allowances[owner][spender][id] = currentAllowance - amount;
+            }
+        }
+    }
+}

+ 53 - 0
contracts/token/ERC6909/extensions/draft-ERC6909ContentURI.sol

@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC6909/extensions/draft-ERC6909ContentURI.sol)
+
+pragma solidity ^0.8.20;
+
+import {ERC6909} from "../draft-ERC6909.sol";
+import {IERC6909ContentURI} from "../../../interfaces/draft-IERC6909.sol";
+
+/**
+ * @dev Implementation of the Content URI extension defined in ERC6909.
+ */
+contract ERC6909ContentURI is ERC6909, IERC6909ContentURI {
+    string private _contractURI;
+    mapping(uint256 id => string) private _tokenURIs;
+
+    /// @dev Event emitted when the contract URI is changed. See https://eips.ethereum.org/EIPS/eip-7572[ERC-7572] for details.
+    event ContractURIUpdated();
+
+    /// @dev See {IERC1155-URI}
+    event URI(string value, uint256 indexed id);
+
+    /// @inheritdoc IERC6909ContentURI
+    function contractURI() public view virtual override returns (string memory) {
+        return _contractURI;
+    }
+
+    /// @inheritdoc IERC6909ContentURI
+    function tokenURI(uint256 id) public view virtual override returns (string memory) {
+        return _tokenURIs[id];
+    }
+
+    /**
+     * @dev Sets the {contractURI} for the contract.
+     *
+     * Emits a {ContractURIUpdated} event.
+     */
+    function _setContractURI(string memory newContractURI) internal virtual {
+        _contractURI = newContractURI;
+
+        emit ContractURIUpdated();
+    }
+
+    /**
+     * @dev Sets the {tokenURI} for a given token of type `id`.
+     *
+     * Emits a {URI} event.
+     */
+    function _setTokenURI(uint256 id, string memory newTokenURI) internal virtual {
+        _tokenURIs[id] = newTokenURI;
+
+        emit URI(newTokenURI, id);
+    }
+}

+ 77 - 0
contracts/token/ERC6909/extensions/draft-ERC6909Metadata.sol

@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC6909/extensions/draft-ERC6909Metadata.sol)
+
+pragma solidity ^0.8.20;
+
+import {ERC6909} from "../draft-ERC6909.sol";
+import {IERC6909Metadata} from "../../../interfaces/draft-IERC6909.sol";
+
+/**
+ * @dev Implementation of the Metadata extension defined in ERC6909. Exposes the name, symbol, and decimals of each token id.
+ */
+contract ERC6909Metadata is ERC6909, IERC6909Metadata {
+    struct TokenMetadata {
+        string name;
+        string symbol;
+        uint8 decimals;
+    }
+
+    mapping(uint256 id => TokenMetadata) private _tokenMetadata;
+
+    /// @dev The name of the token of type `id` was updated to `newName`.
+    event ERC6909NameUpdated(uint256 indexed id, string newName);
+
+    /// @dev The symbol for the token of type `id` was updated to `newSymbol`.
+    event ERC6909SymbolUpdated(uint256 indexed id, string newSymbol);
+
+    /// @dev The decimals value for token of type `id` was updated to `newDecimals`.
+    event ERC6909DecimalsUpdated(uint256 indexed id, uint8 newDecimals);
+
+    /// @inheritdoc IERC6909Metadata
+    function name(uint256 id) public view virtual override returns (string memory) {
+        return _tokenMetadata[id].name;
+    }
+
+    /// @inheritdoc IERC6909Metadata
+    function symbol(uint256 id) public view virtual override returns (string memory) {
+        return _tokenMetadata[id].symbol;
+    }
+
+    /// @inheritdoc IERC6909Metadata
+    function decimals(uint256 id) public view virtual override returns (uint8) {
+        return _tokenMetadata[id].decimals;
+    }
+
+    /**
+     * @dev Sets the `name` for a given token of type `id`.
+     *
+     * Emits an {ERC6909NameUpdated} event.
+     */
+    function _setName(uint256 id, string memory newName) internal virtual {
+        _tokenMetadata[id].name = newName;
+
+        emit ERC6909NameUpdated(id, newName);
+    }
+
+    /**
+     * @dev Sets the `symbol` for a given token of type `id`.
+     *
+     * Emits an {ERC6909SymbolUpdated} event.
+     */
+    function _setSymbol(uint256 id, string memory newSymbol) internal virtual {
+        _tokenMetadata[id].symbol = newSymbol;
+
+        emit ERC6909SymbolUpdated(id, newSymbol);
+    }
+
+    /**
+     * @dev Sets the `decimals` for a given token of type `id`.
+     *
+     * Emits an {ERC6909DecimalsUpdated} event.
+     */
+    function _setDecimals(uint256 id, uint8 newDecimals) internal virtual {
+        _tokenMetadata[id].decimals = newDecimals;
+
+        emit ERC6909DecimalsUpdated(id, newDecimals);
+    }
+}

+ 35 - 0
contracts/token/ERC6909/extensions/draft-ERC6909TokenSupply.sol

@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC6909/extensions/draft-ERC6909TokenSupply.sol)
+
+pragma solidity ^0.8.20;
+
+import {ERC6909} from "../draft-ERC6909.sol";
+import {IERC6909TokenSupply} from "../../../interfaces/draft-IERC6909.sol";
+
+/**
+ * @dev Implementation of the Token Supply extension defined in ERC6909.
+ * Tracks the total supply of each token id individually.
+ */
+contract ERC6909TokenSupply is ERC6909, IERC6909TokenSupply {
+    mapping(uint256 id => uint256) private _totalSupplies;
+
+    /// @inheritdoc IERC6909TokenSupply
+    function totalSupply(uint256 id) public view virtual override returns (uint256) {
+        return _totalSupplies[id];
+    }
+
+    /// @dev Override the `_update` function to update the total supply of each token id as necessary.
+    function _update(address from, address to, uint256 id, uint256 amount) internal virtual override {
+        super._update(from, to, id, amount);
+
+        if (from == address(0)) {
+            _totalSupplies[id] += amount;
+        }
+        if (to == address(0)) {
+            unchecked {
+                // amount <= _balances[from][id] <= _totalSupplies[id]
+                _totalSupplies[id] -= amount;
+            }
+        }
+    }
+}

+ 2 - 2
contracts/token/ERC721/README.adoc

@@ -3,7 +3,7 @@
 [.readme-notice]
 [.readme-notice]
 NOTE: This document is better viewed at https://docs.openzeppelin.com/contracts/api/token/erc721
 NOTE: This document is better viewed at https://docs.openzeppelin.com/contracts/api/token/erc721
 
 
-This set of interfaces, contracts, and utilities are all related to the https://eips.ethereum.org/EIPS/eip-721[ERC-721 Non-Fungible Token Standard].
+This set of interfaces, contracts, and utilities is all related to the https://eips.ethereum.org/EIPS/eip-721[ERC-721 Non-Fungible Token Standard].
 
 
 TIP: For a walk through on how to create an ERC-721 token read our xref:ROOT:erc721.adoc[ERC-721 guide].
 TIP: For a walk through on how to create an ERC-721 token read our xref:ROOT:erc721.adoc[ERC-721 guide].
 
 
@@ -22,7 +22,7 @@ OpenZeppelin Contracts provides implementations of all four interfaces:
 
 
 Additionally there are a few of other extensions:
 Additionally there are a few of other extensions:
 
 
-* {ERC721Consecutive}: An implementation of https://eips.ethereum.org/EIPS/eip-2309[ERC-2309] for minting batchs of tokens during construction, in accordance with ERC-721.
+* {ERC721Consecutive}: An implementation of https://eips.ethereum.org/EIPS/eip-2309[ERC-2309] for minting batches of tokens during construction, in accordance with ERC-721.
 * {ERC721URIStorage}: A more flexible but more expensive way of storing metadata.
 * {ERC721URIStorage}: A more flexible but more expensive way of storing metadata.
 * {ERC721Votes}: Support for voting and vote delegation.
 * {ERC721Votes}: Support for voting and vote delegation.
 * {ERC721Royalty}: A way to signal royalty information following ERC-2981.
 * {ERC721Royalty}: A way to signal royalty information following ERC-2981.

+ 2 - 2
contracts/token/ERC721/extensions/ERC721Consecutive.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/extensions/ERC721Consecutive.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC721/extensions/ERC721Consecutive.sol)
 
 
 pragma solidity ^0.8.20;
 pragma solidity ^0.8.20;
 
 
@@ -159,7 +159,7 @@ abstract contract ERC721Consecutive is IERC2309, ERC721 {
     }
     }
 
 
     /**
     /**
-     * @dev Used to offset the first token id in {_nextConsecutiveId}
+     * @dev Used to offset the first token id in `_nextConsecutiveId`
      */
      */
     function _firstConsecutiveId() internal view virtual returns (uint96) {
     function _firstConsecutiveId() internal view virtual returns (uint96) {
         return 0;
         return 0;

+ 2 - 2
contracts/token/ERC721/extensions/ERC721URIStorage.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/extensions/ERC721URIStorage.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC721/extensions/ERC721URIStorage.sol)
 
 
 pragma solidity ^0.8.20;
 pragma solidity ^0.8.20;
 
 
@@ -52,7 +52,7 @@ abstract contract ERC721URIStorage is IERC4906, ERC721 {
     /**
     /**
      * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.
      * @dev Sets `_tokenURI` as the tokenURI of `tokenId`.
      *
      *
-     * Emits {MetadataUpdate}.
+     * Emits {IERC4906-MetadataUpdate}.
      */
      */
     function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {
     function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal virtual {
         _tokenURIs[tokenId] = _tokenURI;
         _tokenURIs[tokenId] = _tokenURI;

+ 2 - 2
contracts/token/ERC721/utils/ERC721Utils.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/utils/ERC721Utils.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC721/utils/ERC721Utils.sol)
 
 
 pragma solidity ^0.8.20;
 pragma solidity ^0.8.20;
 
 
@@ -15,7 +15,7 @@ import {IERC721Errors} from "../../../interfaces/draft-IERC6093.sol";
  */
  */
 library ERC721Utils {
 library ERC721Utils {
     /**
     /**
-     * @dev Performs an acceptance check for the provided `operator` by calling {IERC721-onERC721Received}
+     * @dev Performs an acceptance check for the provided `operator` by calling {IERC721Receiver-onERC721Received}
      * on the `to` address. The `operator` is generally the address that initiated the token transfer (i.e. `msg.sender`).
      * on the `to` address. The `operator` is generally the address that initiated the token transfer (i.e. `msg.sender`).
      *
      *
      * The acceptance call is not executed and treated as a no-op if the target address doesn't contain code (i.e. an EOA).
      * The acceptance call is not executed and treated as a no-op if the target address doesn't contain code (i.e. an EOA).

+ 2 - 2
contracts/token/common/ERC2981.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (token/common/ERC2981.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (token/common/ERC2981.sol)
 
 
 pragma solidity ^0.8.20;
 pragma solidity ^0.8.20;
 
 
@@ -39,7 +39,7 @@ abstract contract ERC2981 is IERC2981, ERC165 {
     error ERC2981InvalidDefaultRoyaltyReceiver(address receiver);
     error ERC2981InvalidDefaultRoyaltyReceiver(address receiver);
 
 
     /**
     /**
-     * @dev The royalty set for an specific `tokenId` is invalid (eg. (numerator / denominator) >= 1).
+     * @dev The royalty set for a specific `tokenId` is invalid (eg. (numerator / denominator) >= 1).
      */
      */
     error ERC2981InvalidTokenRoyalty(uint256 tokenId, uint256 numerator, uint256 denominator);
     error ERC2981InvalidTokenRoyalty(uint256 tokenId, uint256 numerator, uint256 denominator);
 
 

+ 4 - 4
contracts/utils/Arrays.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (utils/Arrays.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (utils/Arrays.sol)
 // This file was procedurally generated from scripts/generate/templates/Arrays.js.
 // This file was procedurally generated from scripts/generate/templates/Arrays.js.
 
 
 pragma solidity ^0.8.20;
 pragma solidity ^0.8.20;
@@ -448,7 +448,7 @@ library Arrays {
     }
     }
 
 
     /**
     /**
-     * @dev Helper to set the length of an dynamic array. Directly writing to `.length` is forbidden.
+     * @dev Helper to set the length of a 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.
      * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.
      */
      */
@@ -459,7 +459,7 @@ library Arrays {
     }
     }
 
 
     /**
     /**
-     * @dev Helper to set the length of an dynamic array. Directly writing to `.length` is forbidden.
+     * @dev Helper to set the length of a 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.
      * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.
      */
      */
@@ -470,7 +470,7 @@ library Arrays {
     }
     }
 
 
     /**
     /**
-     * @dev Helper to set the length of an dynamic array. Directly writing to `.length` is forbidden.
+     * @dev Helper to set the length of a 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.
      * WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.
      */
      */

+ 25 - 0
contracts/utils/Calldata.sol

@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v5.3.0) (utils/Calldata.sol)
+
+pragma solidity ^0.8.20;
+
+/**
+ * @dev Helper library for manipulating objects in calldata.
+ */
+library Calldata {
+    // slither-disable-next-line write-after-write
+    function emptyBytes() internal pure returns (bytes calldata result) {
+        assembly ("memory-safe") {
+            result.offset := 0
+            result.length := 0
+        }
+    }
+
+    // slither-disable-next-line write-after-write
+    function emptyString() internal pure returns (string calldata result) {
+        assembly ("memory-safe") {
+            result.offset := 0
+            result.length := 0
+        }
+    }
+}

+ 3 - 3
contracts/utils/Multicall.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.0.1) (utils/Multicall.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (utils/Multicall.sol)
 
 
 pragma solidity ^0.8.20;
 pragma solidity ^0.8.20;
 
 
@@ -13,10 +13,10 @@ import {Context} from "./Context.sol";
  * careful about sending transactions invoking {multicall}. For example, a relay address that filters function
  * careful about sending transactions invoking {multicall}. For example, a relay address that filters function
  * selectors won't filter calls nested within a {multicall} operation.
  * selectors won't filter calls nested within a {multicall} operation.
  *
  *
- * NOTE: Since 5.0.1 and 4.9.4, this contract identifies non-canonical contexts (i.e. `msg.sender` is not {_msgSender}).
+ * NOTE: Since 5.0.1 and 4.9.4, this contract identifies non-canonical contexts (i.e. `msg.sender` is not {Context-_msgSender}).
  * If a non-canonical context is identified, the following self `delegatecall` appends the last bytes of `msg.data`
  * If a non-canonical context is identified, the following self `delegatecall` appends the last bytes of `msg.data`
  * to the subcall. This makes it safe to use with {ERC2771Context}. Contexts that don't affect the resolution of
  * to the subcall. This makes it safe to use with {ERC2771Context}. Contexts that don't affect the resolution of
- * {_msgSender} are not propagated to subcalls.
+ * {Context-_msgSender} are not propagated to subcalls.
  */
  */
 abstract contract Multicall is Context {
 abstract contract Multicall is Context {
     /**
     /**

+ 1 - 8
contracts/utils/Pausable.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.0.0) (utils/Pausable.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (utils/Pausable.sol)
 
 
 pragma solidity ^0.8.20;
 pragma solidity ^0.8.20;
 
 
@@ -37,13 +37,6 @@ abstract contract Pausable is Context {
      */
      */
     error ExpectedPause();
     error ExpectedPause();
 
 
-    /**
-     * @dev Initializes the contract in unpaused state.
-     */
-    constructor() {
-        _paused = false;
-    }
-
     /**
     /**
      * @dev Modifier to make a function callable only when the contract is not paused.
      * @dev Modifier to make a function callable only when the contract is not paused.
      *
      *

+ 13 - 4
contracts/utils/README.adoc

@@ -18,12 +18,12 @@ Miscellaneous contracts and libraries containing utility functions you can use t
  * {ReentrancyGuardTransient}: Variant of {ReentrancyGuard} that uses transient storage (https://eips.ethereum.org/EIPS/eip-1153[EIP-1153]).
  * {ReentrancyGuardTransient}: Variant of {ReentrancyGuard} that uses transient storage (https://eips.ethereum.org/EIPS/eip-1153[EIP-1153]).
  * {Pausable}: A common emergency response mechanism that can pause functionality while a remediation is pending.
  * {Pausable}: A common emergency response mechanism that can pause functionality while a remediation is pending.
  * {Nonces}: Utility for tracking and verifying address nonces that only increment.
  * {Nonces}: Utility for tracking and verifying address nonces that only increment.
- * {NoncesKeyed}: Alternative to {Nonces}, that support key-ed nonces following https://eips.ethereum.org/EIPS/eip-4337#semi-abstracted-nonce-support[ERC-4337 speciciations].
+ * {NoncesKeyed}: Alternative to {Nonces}, that support keyed nonces following https://eips.ethereum.org/EIPS/eip-4337#semi-abstracted-nonce-support[ERC-4337 specifications].
  * {ERC165}, {ERC165Checker}: Utilities for inspecting interfaces supported by contracts.
  * {ERC165}, {ERC165Checker}: Utilities for inspecting interfaces supported by contracts.
  * {BitMaps}: A simple library to manage boolean value mapped to a numerical index in an efficient way.
  * {BitMaps}: A simple library to manage boolean value mapped to a numerical index in an efficient way.
  * {EnumerableMap}: A type like Solidity's https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`], but with key-value _enumeration_: this will let you know how many entries a mapping has, and iterate over them (which is not possible with `mapping`).
  * {EnumerableMap}: A type like Solidity's https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`], but with key-value _enumeration_: this will let you know how many entries a mapping has, and iterate over them (which is not possible with `mapping`).
  * {EnumerableSet}: Like {EnumerableMap}, but for https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets]. Can be used to store privileged accounts, issued IDs, etc.
  * {EnumerableSet}: Like {EnumerableMap}, but for https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets]. Can be used to store privileged accounts, issued IDs, etc.
- * {DoubleEndedQueue}: An implementation of a https://en.wikipedia.org/wiki/Double-ended_queue[double ended queue] whose values can be removed added or remove from both sides. Useful for FIFO and LIFO structures.
+ * {DoubleEndedQueue}: An implementation of a https://en.wikipedia.org/wiki/Double-ended_queue[double ended queue] whose values can be added or removed from both sides. Useful for FIFO and LIFO structures.
  * {CircularBuffer}: A data structure to store the last N values pushed to it.
  * {CircularBuffer}: A data structure to store the last N values pushed to it.
  * {Checkpoints}: A data structure to store values mapped to a strictly increasing key. Can be used for storing and accessing values over time.
  * {Checkpoints}: A data structure to store values mapped to a strictly increasing key. Can be used for storing and accessing values over time.
  * {Heap}: A library that implements a https://en.wikipedia.org/wiki/Binary_heap[binary heap] in storage.
  * {Heap}: A library that implements a https://en.wikipedia.org/wiki/Binary_heap[binary heap] in storage.
@@ -33,8 +33,9 @@ Miscellaneous contracts and libraries containing utility functions you can use t
  * {Arrays}: Collection of functions that operate on https://docs.soliditylang.org/en/latest/types.html#arrays[`arrays`].
  * {Arrays}: Collection of functions that operate on https://docs.soliditylang.org/en/latest/types.html#arrays[`arrays`].
  * {Base64}: On-chain base64 and base64URL encoding according to https://datatracker.ietf.org/doc/html/rfc4648[RFC-4648].
  * {Base64}: On-chain base64 and base64URL encoding according to https://datatracker.ietf.org/doc/html/rfc4648[RFC-4648].
  * {Bytes}: Common operations on bytes objects.
  * {Bytes}: Common operations on bytes objects.
+ * {Calldata}: Helpers for manipulating calldata.
  * {Strings}: Common operations for strings formatting.
  * {Strings}: Common operations for strings formatting.
- * {ShortString}: Library to encode (and decode) short strings into (or from) a single bytes32 slot for optimizing costs. Short strings are limited to 31 characters.
+ * {ShortStrings}: Library to encode (and decode) short strings into (or from) a single bytes32 slot for optimizing costs. Short strings are limited to 31 characters.
  * {SlotDerivation}: Methods for deriving storage slot from ERC-7201 namespaces as well as from constructions such as mapping and arrays.
  * {SlotDerivation}: Methods for deriving storage slot from ERC-7201 namespaces as well as from constructions such as mapping and arrays.
  * {StorageSlot}: Methods for accessing specific storage slots formatted as common primitive types.
  * {StorageSlot}: Methods for accessing specific storage slots formatted as common primitive types.
  * {TransientSlot}: Primitives for reading from and writing to transient storage (only value types are currently supported).
  * {TransientSlot}: Primitives for reading from and writing to transient storage (only value types are currently supported).
@@ -42,7 +43,7 @@ Miscellaneous contracts and libraries containing utility functions you can use t
  * {Context}: A utility for abstracting the sender and calldata in the current execution context.
  * {Context}: A utility for abstracting the sender and calldata in the current execution context.
  * {Packing}: A library for packing and unpacking multiple values into bytes32
  * {Packing}: A library for packing and unpacking multiple values into bytes32
  * {Panic}: A library to revert with https://docs.soliditylang.org/en/v0.8.20/control-structures.html#panic-via-assert-and-error-via-require[Solidity panic codes].
  * {Panic}: A library to revert with https://docs.soliditylang.org/en/v0.8.20/control-structures.html#panic-via-assert-and-error-via-require[Solidity panic codes].
- * {Comparators}: A library that contains comparator functions to use with with the {Heap} library.
+ * {Comparators}: A library that contains comparator functions to use with the {Heap} library.
  * {CAIP2}, {CAIP10}: Libraries for formatting and parsing CAIP-2 and CAIP-10 identifiers.
  * {CAIP2}, {CAIP10}: Libraries for formatting and parsing CAIP-2 and CAIP-10 identifiers.
 
 
 [NOTE]
 [NOTE]
@@ -128,6 +129,10 @@ Ethereum contracts have no native concept of an interface, so applications must
 
 
 {{Base64}}
 {{Base64}}
 
 
+{{Bytes}}
+
+{{Calldata}}
+
 {{Strings}}
 {{Strings}}
 
 
 {{ShortStrings}}
 {{ShortStrings}}
@@ -147,3 +152,7 @@ Ethereum contracts have no native concept of an interface, so applications must
 {{Panic}}
 {{Panic}}
 
 
 {{Comparators}}
 {{Comparators}}
+
+{{CAIP2}}
+
+{{CAIP10}}

+ 2 - 2
contracts/utils/ReentrancyGuardTransient.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuardTransient.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (utils/ReentrancyGuardTransient.sol)
 
 
 pragma solidity ^0.8.24;
 pragma solidity ^0.8.24;
 
 
@@ -38,7 +38,7 @@ abstract contract ReentrancyGuardTransient {
     }
     }
 
 
     function _nonReentrantBefore() private {
     function _nonReentrantBefore() private {
-        // On the first call to nonReentrant, _status will be NOT_ENTERED
+        // On the first call to nonReentrant, REENTRANCY_GUARD_STORAGE.asBoolean().tload() will be false
         if (_reentrancyGuardEntered()) {
         if (_reentrancyGuardEntered()) {
             revert ReentrancyGuardReentrantCall();
             revert ReentrancyGuardReentrantCall();
         }
         }

+ 3 - 3
contracts/utils/ShortStrings.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (utils/ShortStrings.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (utils/ShortStrings.sol)
 
 
 pragma solidity ^0.8.20;
 pragma solidity ^0.8.20;
 
 
@@ -95,7 +95,7 @@ library ShortStrings {
     }
     }
 
 
     /**
     /**
-     * @dev Decode a string that was encoded to `ShortString` or written to storage using {setWithFallback}.
+     * @dev Decode a string that was encoded to `ShortString` or written to storage using {toShortStringWithFallback}.
      */
      */
     function toStringWithFallback(ShortString value, string storage store) internal pure returns (string memory) {
     function toStringWithFallback(ShortString value, string storage store) internal pure returns (string memory) {
         if (ShortString.unwrap(value) != FALLBACK_SENTINEL) {
         if (ShortString.unwrap(value) != FALLBACK_SENTINEL) {
@@ -107,7 +107,7 @@ library ShortStrings {
 
 
     /**
     /**
      * @dev Return the length of a string that was encoded to `ShortString` or written to storage using
      * @dev Return the length of a string that was encoded to `ShortString` or written to storage using
-     * {setWithFallback}.
+     * {toShortStringWithFallback}.
      *
      *
      * WARNING: This will return the "byte length" of the string. This may not reflect the actual length in terms of
      * WARNING: This will return the "byte length" of the string. This may not reflect the actual length in terms of
      * actual characters as the UTF-8 encoding of a single character can span over multiple bytes.
      * actual characters as the UTF-8 encoding of a single character can span over multiple bytes.

+ 2 - 2
contracts/utils/SlotDerivation.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (utils/SlotDerivation.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (utils/SlotDerivation.sol)
 // This file was procedurally generated from scripts/generate/templates/SlotDerivation.js.
 // This file was procedurally generated from scripts/generate/templates/SlotDerivation.js.
 
 
 pragma solidity ^0.8.20;
 pragma solidity ^0.8.20;
@@ -19,7 +19,7 @@ pragma solidity ^0.8.20;
  *     using SlotDerivation for bytes32;
  *     using SlotDerivation for bytes32;
  *
  *
  *     // Declare a namespace
  *     // Declare a namespace
- *     string private constant _NAMESPACE = "<namespace>" // eg. OpenZeppelin.Slot
+ *     string private constant _NAMESPACE = "<namespace>"; // eg. OpenZeppelin.Slot
  *
  *
  *     function setValueInNamespace(uint256 key, address newValue) internal {
  *     function setValueInNamespace(uint256 key, address newValue) internal {
  *         _NAMESPACE.erc7201Slot().deriveMapping(key).getAddressSlot().value = newValue;
  *         _NAMESPACE.erc7201Slot().deriveMapping(key).getAddressSlot().value = newValue;

+ 59 - 10
contracts/utils/Strings.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.2.0) (utils/Strings.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (utils/Strings.sol)
 
 
 pragma solidity ^0.8.20;
 pragma solidity ^0.8.20;
 
 
@@ -15,6 +15,14 @@ library Strings {
 
 
     bytes16 private constant HEX_DIGITS = "0123456789abcdef";
     bytes16 private constant HEX_DIGITS = "0123456789abcdef";
     uint8 private constant ADDRESS_LENGTH = 20;
     uint8 private constant ADDRESS_LENGTH = 20;
+    uint256 private constant SPECIAL_CHARS_LOOKUP =
+        (1 << 0x08) | // backspace
+            (1 << 0x09) | // tab
+            (1 << 0x0a) | // newline
+            (1 << 0x0c) | // form feed
+            (1 << 0x0d) | // carriage return
+            (1 << 0x22) | // double quote
+            (1 << 0x5c); // backslash
 
 
     /**
     /**
      * @dev The `value` string doesn't fit in the specified `length`.
      * @dev The `value` string doesn't fit in the specified `length`.
@@ -139,7 +147,7 @@ library Strings {
     }
     }
 
 
     /**
     /**
-     * @dev Variant of {parseUint} that parses a substring of `input` located between position `begin` (included) and
+     * @dev Variant of {parseUint-string} that parses a substring of `input` located between position `begin` (included) and
      * `end` (excluded).
      * `end` (excluded).
      *
      *
      * Requirements:
      * Requirements:
@@ -177,7 +185,7 @@ library Strings {
     }
     }
 
 
     /**
     /**
-     * @dev Implementation of {tryParseUint} that does not check bounds. Caller should make sure that
+     * @dev Implementation of {tryParseUint-string-uint256-uint256} that does not check bounds. Caller should make sure that
      * `begin <= end <= input.length`. Other inputs would result in undefined behavior.
      * `begin <= end <= input.length`. Other inputs would result in undefined behavior.
      */
      */
     function _tryParseUintUncheckedBounds(
     function _tryParseUintUncheckedBounds(
@@ -250,7 +258,7 @@ library Strings {
     }
     }
 
 
     /**
     /**
-     * @dev Implementation of {tryParseInt} that does not check bounds. Caller should make sure that
+     * @dev Implementation of {tryParseInt-string-uint256-uint256} that does not check bounds. Caller should make sure that
      * `begin <= end <= input.length`. Other inputs would result in undefined behavior.
      * `begin <= end <= input.length`. Other inputs would result in undefined behavior.
      */
      */
     function _tryParseIntUncheckedBounds(
     function _tryParseIntUncheckedBounds(
@@ -287,7 +295,7 @@ library Strings {
     }
     }
 
 
     /**
     /**
-     * @dev Variant of {parseHexUint} that parses a substring of `input` located between position `begin` (included) and
+     * @dev Variant of {parseHexUint-string} that parses a substring of `input` located between position `begin` (included) and
      * `end` (excluded).
      * `end` (excluded).
      *
      *
      * Requirements:
      * Requirements:
@@ -325,7 +333,7 @@ library Strings {
     }
     }
 
 
     /**
     /**
-     * @dev Implementation of {tryParseHexUint} that does not check bounds. Caller should make sure that
+     * @dev Implementation of {tryParseHexUint-string-uint256-uint256} that does not check bounds. Caller should make sure that
      * `begin <= end <= input.length`. Other inputs would result in undefined behavior.
      * `begin <= end <= input.length`. Other inputs would result in undefined behavior.
      */
      */
     function _tryParseHexUintUncheckedBounds(
     function _tryParseHexUintUncheckedBounds(
@@ -346,7 +354,7 @@ library Strings {
             result *= 16;
             result *= 16;
             unchecked {
             unchecked {
                 // Multiplying by 16 is equivalent to a shift of 4 bits (with additional overflow check).
                 // Multiplying by 16 is equivalent to a shift of 4 bits (with additional overflow check).
-                // This guaratees that adding a value < 16 will not cause an overflow, hence the unchecked.
+                // This guarantees that adding a value < 16 will not cause an overflow, hence the unchecked.
                 result += chr;
                 result += chr;
             }
             }
         }
         }
@@ -364,7 +372,7 @@ library Strings {
     }
     }
 
 
     /**
     /**
-     * @dev Variant of {parseAddress} that parses a substring of `input` located between position `begin` (included) and
+     * @dev Variant of {parseAddress-string} that parses a substring of `input` located between position `begin` (included) and
      * `end` (excluded).
      * `end` (excluded).
      *
      *
      * Requirements:
      * Requirements:
@@ -378,7 +386,7 @@ library Strings {
 
 
     /**
     /**
      * @dev Variant of {parseAddress-string} that returns false if the parsing fails because the input is not a properly
      * @dev Variant of {parseAddress-string} that returns false if the parsing fails because the input is not a properly
-     * formatted address. See {parseAddress} requirements.
+     * formatted address. See {parseAddress-string} requirements.
      */
      */
     function tryParseAddress(string memory input) internal pure returns (bool success, address value) {
     function tryParseAddress(string memory input) internal pure returns (bool success, address value) {
         return tryParseAddress(input, 0, bytes(input).length);
         return tryParseAddress(input, 0, bytes(input).length);
@@ -386,7 +394,7 @@ library Strings {
 
 
     /**
     /**
      * @dev Variant of {parseAddress-string-uint256-uint256} that returns false if the parsing fails because input is not a properly
      * @dev Variant of {parseAddress-string-uint256-uint256} that returns false if the parsing fails because input is not a properly
-     * formatted address. See {parseAddress} requirements.
+     * formatted address. See {parseAddress-string-uint256-uint256} requirements.
      */
      */
     function tryParseAddress(
     function tryParseAddress(
         string memory input,
         string memory input,
@@ -426,6 +434,47 @@ library Strings {
         return value;
         return value;
     }
     }
 
 
+    /**
+     * @dev Escape special characters in JSON strings. This can be useful to prevent JSON injection in NFT metadata.
+     *
+     * WARNING: This function should only be used in double quoted JSON strings. Single quotes are not escaped.
+     *
+     * NOTE: This function escapes all unicode characters, and not just the ones in ranges defined in section 2.5 of
+     * RFC-4627 (U+0000 to U+001F, U+0022 and U+005C). ECMAScript's `JSON.parse` does recover escaped unicode
+     * characters that are not in this range, but other tooling may provide different results.
+     */
+    function escapeJSON(string memory input) internal pure returns (string memory) {
+        bytes memory buffer = bytes(input);
+        bytes memory output = new bytes(2 * buffer.length); // worst case scenario
+        uint256 outputLength = 0;
+
+        for (uint256 i; i < buffer.length; ++i) {
+            bytes1 char = bytes1(_unsafeReadBytesOffset(buffer, i));
+            if (((SPECIAL_CHARS_LOOKUP & (1 << uint8(char))) != 0)) {
+                output[outputLength++] = "\\";
+                if (char == 0x08) output[outputLength++] = "b";
+                else if (char == 0x09) output[outputLength++] = "t";
+                else if (char == 0x0a) output[outputLength++] = "n";
+                else if (char == 0x0c) output[outputLength++] = "f";
+                else if (char == 0x0d) output[outputLength++] = "r";
+                else if (char == 0x5c) output[outputLength++] = "\\";
+                else if (char == 0x22) {
+                    // solhint-disable-next-line quotes
+                    output[outputLength++] = '"';
+                }
+            } else {
+                output[outputLength++] = char;
+            }
+        }
+        // write the actual length and deallocate unused memory
+        assembly ("memory-safe") {
+            mstore(output, outputLength)
+            mstore(0x40, add(output, shl(5, shr(5, add(outputLength, 63)))))
+        }
+
+        return string(output);
+    }
+
     /**
     /**
      * @dev Reads a bytes32 from a bytes array without bounds checking.
      * @dev Reads a bytes32 from a bytes array without bounds checking.
      *
      *

+ 6 - 6
contracts/utils/TransientSlot.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (utils/TransientSlot.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (utils/TransientSlot.sol)
 // This file was procedurally generated from scripts/generate/templates/TransientSlot.js.
 // This file was procedurally generated from scripts/generate/templates/TransientSlot.js.
 
 
 pragma solidity ^0.8.24;
 pragma solidity ^0.8.24;
@@ -32,7 +32,7 @@ pragma solidity ^0.8.24;
  */
  */
 library TransientSlot {
 library TransientSlot {
     /**
     /**
-     * @dev UDVT that represent a slot holding a address.
+     * @dev UDVT that represents a slot holding an address.
      */
      */
     type AddressSlot is bytes32;
     type AddressSlot is bytes32;
 
 
@@ -44,7 +44,7 @@ library TransientSlot {
     }
     }
 
 
     /**
     /**
-     * @dev UDVT that represent a slot holding a bool.
+     * @dev UDVT that represents a slot holding a bool.
      */
      */
     type BooleanSlot is bytes32;
     type BooleanSlot is bytes32;
 
 
@@ -56,7 +56,7 @@ library TransientSlot {
     }
     }
 
 
     /**
     /**
-     * @dev UDVT that represent a slot holding a bytes32.
+     * @dev UDVT that represents a slot holding a bytes32.
      */
      */
     type Bytes32Slot is bytes32;
     type Bytes32Slot is bytes32;
 
 
@@ -68,7 +68,7 @@ library TransientSlot {
     }
     }
 
 
     /**
     /**
-     * @dev UDVT that represent a slot holding a uint256.
+     * @dev UDVT that represents a slot holding a uint256.
      */
      */
     type Uint256Slot is bytes32;
     type Uint256Slot is bytes32;
 
 
@@ -80,7 +80,7 @@ library TransientSlot {
     }
     }
 
 
     /**
     /**
-     * @dev UDVT that represent a slot holding a int256.
+     * @dev UDVT that represents a slot holding a int256.
      */
      */
     type Int256Slot is bytes32;
     type Int256Slot is bytes32;
 
 

+ 4 - 2
contracts/utils/cryptography/EIP712.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/EIP712.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (utils/cryptography/EIP712.sol)
 
 
 pragma solidity ^0.8.20;
 pragma solidity ^0.8.20;
 
 
@@ -48,7 +48,9 @@ abstract contract EIP712 is IERC5267 {
 
 
     ShortString private immutable _name;
     ShortString private immutable _name;
     ShortString private immutable _version;
     ShortString private immutable _version;
+    // slither-disable-next-line constable-states
     string private _nameFallback;
     string private _nameFallback;
+    // slither-disable-next-line constable-states
     string private _versionFallback;
     string private _versionFallback;
 
 
     /**
     /**
@@ -109,7 +111,7 @@ abstract contract EIP712 is IERC5267 {
     }
     }
 
 
     /**
     /**
-     * @dev See {IERC-5267}.
+     * @inheritdoc IERC5267
      */
      */
     function eip712Domain()
     function eip712Domain()
         public
         public

+ 3 - 3
contracts/utils/cryptography/Hashes.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/Hashes.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (utils/cryptography/Hashes.sol)
 
 
 pragma solidity ^0.8.20;
 pragma solidity ^0.8.20;
 
 
@@ -15,13 +15,13 @@ library Hashes {
      * NOTE: Equivalent to the `standardNodeHash` in our https://github.com/OpenZeppelin/merkle-tree[JavaScript library].
      * 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) {
     function commutativeKeccak256(bytes32 a, bytes32 b) internal pure returns (bytes32) {
-        return a < b ? _efficientKeccak256(a, b) : _efficientKeccak256(b, a);
+        return a < b ? efficientKeccak256(a, b) : efficientKeccak256(b, a);
     }
     }
 
 
     /**
     /**
      * @dev Implementation of keccak256(abi.encode(a, b)) that doesn't allocate or expand memory.
      * @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) {
+    function efficientKeccak256(bytes32 a, bytes32 b) internal pure returns (bytes32 value) {
         assembly ("memory-safe") {
         assembly ("memory-safe") {
             mstore(0x00, a)
             mstore(0x00, a)
             mstore(0x20, b)
             mstore(0x20, b)

+ 18 - 3
contracts/utils/cryptography/MessageHashUtils.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/MessageHashUtils.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (utils/cryptography/MessageHashUtils.sol)
 
 
 pragma solidity ^0.8.20;
 pragma solidity ^0.8.20;
 
 
@@ -19,7 +19,7 @@ library MessageHashUtils {
      *
      *
      * The digest is calculated by prefixing a bytes32 `messageHash` with
      * The digest is calculated by prefixing a bytes32 `messageHash` with
      * `"\x19Ethereum Signed Message:\n32"` and hashing the result. It corresponds with the
      * `"\x19Ethereum Signed Message:\n32"` and hashing the result. It corresponds with the
-     * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method.
+     * hash signed when using the https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sign[`eth_sign`] JSON-RPC method.
      *
      *
      * NOTE: The `messageHash` parameter is intended to be the result of hashing a raw message with
      * NOTE: The `messageHash` parameter is intended to be the result of hashing a raw message with
      * keccak256, although any bytes32 value can be safely used because the final digest will
      * keccak256, although any bytes32 value can be safely used because the final digest will
@@ -41,7 +41,7 @@ library MessageHashUtils {
      *
      *
      * The digest is calculated by prefixing an arbitrary `message` with
      * The digest is calculated by prefixing an arbitrary `message` with
      * `"\x19Ethereum Signed Message:\n" + len(message)` and hashing the result. It corresponds with the
      * `"\x19Ethereum Signed Message:\n" + len(message)` and hashing the result. It corresponds with the
-     * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method.
+     * hash signed when using the https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sign[`eth_sign`] JSON-RPC method.
      *
      *
      * See {ECDSA-recover}.
      * See {ECDSA-recover}.
      */
      */
@@ -63,6 +63,21 @@ library MessageHashUtils {
         return keccak256(abi.encodePacked(hex"19_00", validator, data));
         return keccak256(abi.encodePacked(hex"19_00", validator, data));
     }
     }
 
 
+    /**
+     * @dev Variant of {toDataWithIntendedValidatorHash-address-bytes} optimized for cases where `data` is a bytes32.
+     */
+    function toDataWithIntendedValidatorHash(
+        address validator,
+        bytes32 messageHash
+    ) internal pure returns (bytes32 digest) {
+        assembly ("memory-safe") {
+            mstore(0x00, hex"19_00")
+            mstore(0x02, shl(96, validator))
+            mstore(0x16, messageHash)
+            digest := keccak256(0x00, 0x36)
+        }
+    }
+
     /**
     /**
      * @dev Returns the keccak256 digest of an EIP-712 typed data (ERC-191 version `0x01`).
      * @dev Returns the keccak256 digest of an EIP-712 typed data (ERC-191 version `0x01`).
      *
      *

+ 41 - 3
contracts/utils/cryptography/P256.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (utils/cryptography/P256.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (utils/cryptography/P256.sol)
 pragma solidity ^0.8.20;
 pragma solidity ^0.8.20;
 
 
 import {Math} from "../math/Math.sol";
 import {Math} from "../math/Math.sol";
@@ -90,10 +90,48 @@ library P256 {
     ) private view returns (bool valid, bool supported) {
     ) private view returns (bool valid, bool supported) {
         if (!_isProperSignature(r, s) || !isValidPublicKey(qx, qy)) {
         if (!_isProperSignature(r, s) || !isValidPublicKey(qx, qy)) {
             return (false, true); // signature is invalid, and its not because the precompile is missing
             return (false, true); // signature is invalid, and its not because the precompile is missing
+        } else if (_rip7212(h, r, s, qx, qy)) {
+            return (true, true); // precompile is present, signature is valid
+        } else if (
+            // Given precompiles have no bytecode (i.e. `address(0x100).code.length == 0`), we use
+            // a valid signature with small `r` and `s` values to check if the precompile is present. Taken from
+            // https://github.com/C2SP/wycheproof/blob/4672ff74d68766e7785c2cac4c597effccef2c5c/testvectors/ecdsa_secp256r1_sha256_p1363_test.json#L1173-L1204
+            _rip7212(
+                0xbb5a52f42f9c9261ed4361f59422a1e30036e7c32b270c8807a419feca605023, // sha256("123400")
+                0x0000000000000000000000000000000000000000000000000000000000000005,
+                0x0000000000000000000000000000000000000000000000000000000000000001,
+                0xa71af64de5126a4a4e02b7922d66ce9415ce88a4c9d25514d91082c8725ac957,
+                0x5d47723c8fbe580bb369fec9c2665d8e30a435b9932645482e7c9f11e872296b
+            )
+        ) {
+            return (false, true); // precompile is present, signature is invalid
+        } else {
+            return (false, false); // precompile is absent
         }
         }
+    }
 
 
-        (bool success, bytes memory returndata) = address(0x100).staticcall(abi.encode(h, r, s, qx, qy));
-        return (success && returndata.length == 0x20) ? (abi.decode(returndata, (bool)), true) : (false, false);
+    /**
+     * @dev Low level helper for {_tryVerifyNative}. Calls the precompile and checks if there is a return value.
+     */
+    function _rip7212(bytes32 h, bytes32 r, bytes32 s, bytes32 qx, bytes32 qy) private view returns (bool isValid) {
+        assembly ("memory-safe") {
+            // Use the free memory pointer without updating it at the end of the function
+            let ptr := mload(0x40)
+            mstore(ptr, h)
+            mstore(add(ptr, 0x20), r)
+            mstore(add(ptr, 0x40), s)
+            mstore(add(ptr, 0x60), qx)
+            mstore(add(ptr, 0x80), qy)
+            // RIP-7212 precompiles return empty bytes when an invalid signature is passed, making it impossible
+            // to distinguish the presence of the precompile. Custom precompile implementations may decide to
+            // return `bytes32(0)` (i.e. false) without developers noticing, so we decide to evaluate the return value
+            // without expanding memory using scratch space.
+            mstore(0x00, 0) // zero out scratch space in case the precompile doesn't return anything
+            if iszero(staticcall(gas(), 0x100, ptr, 0xa0, 0x00, 0x20)) {
+                invalid()
+            }
+            isValid := mload(0x00)
+        }
     }
     }
 
 
     /**
     /**

+ 162 - 98
contracts/utils/math/Math.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/Math.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (utils/math/Math.sol)
 
 
 pragma solidity ^0.8.20;
 pragma solidity ^0.8.20;
 
 
@@ -18,38 +18,68 @@ library Math {
     }
     }
 
 
     /**
     /**
-     * @dev Returns the addition of two unsigned integers, with an success flag (no overflow).
+     * @dev Return the 512-bit addition of two uint256.
+     *
+     * The result is stored in two 256 variables such that sum = high * 2²⁵⁶ + low.
+     */
+    function add512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {
+        assembly ("memory-safe") {
+            low := add(a, b)
+            high := lt(low, a)
+        }
+    }
+
+    /**
+     * @dev Return the 512-bit multiplication of two uint256.
+     *
+     * The result is stored in two 256 variables such that product = high * 2²⁵⁶ + low.
+     */
+    function mul512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {
+        // 512-bit multiply [high low] = x * y. Compute the product mod 2²⁵⁶ and mod 2²⁵⁶ - 1, then use
+        // the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
+        // variables such that product = high * 2²⁵⁶ + low.
+        assembly ("memory-safe") {
+            let mm := mulmod(a, b, not(0))
+            low := mul(a, b)
+            high := sub(sub(mm, low), lt(mm, low))
+        }
+    }
+
+    /**
+     * @dev Returns the addition of two unsigned integers, with a success flag (no overflow).
      */
      */
     function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
     function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
         unchecked {
         unchecked {
             uint256 c = a + b;
             uint256 c = a + b;
-            if (c < a) return (false, 0);
-            return (true, c);
+            success = c >= a;
+            result = c * SafeCast.toUint(success);
         }
         }
     }
     }
 
 
     /**
     /**
-     * @dev Returns the subtraction of two unsigned integers, with an success flag (no overflow).
+     * @dev Returns the subtraction of two unsigned integers, with a success flag (no overflow).
      */
      */
     function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
     function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
         unchecked {
         unchecked {
-            if (b > a) return (false, 0);
-            return (true, a - b);
+            uint256 c = a - b;
+            success = c <= a;
+            result = c * SafeCast.toUint(success);
         }
         }
     }
     }
 
 
     /**
     /**
-     * @dev Returns the multiplication of two unsigned integers, with an success flag (no overflow).
+     * @dev Returns the multiplication of two unsigned integers, with a success flag (no overflow).
      */
      */
     function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
     function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
         unchecked {
         unchecked {
-            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
-            // benefit is lost if 'b' is also tested.
-            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
-            if (a == 0) return (true, 0);
             uint256 c = a * b;
             uint256 c = a * b;
-            if (c / a != b) return (false, 0);
-            return (true, c);
+            assembly ("memory-safe") {
+                // Only true when the multiplication doesn't overflow
+                // (c / a == b) || (a == 0)
+                success := or(eq(div(c, a), b), iszero(a))
+            }
+            // equivalent to: success ? c : 0
+            result = c * SafeCast.toUint(success);
         }
         }
     }
     }
 
 
@@ -58,8 +88,11 @@ library Math {
      */
      */
     function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
     function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
         unchecked {
         unchecked {
-            if (b == 0) return (false, 0);
-            return (true, a / b);
+            success = b > 0;
+            assembly ("memory-safe") {
+                // The `DIV` opcode returns zero when the denominator is 0.
+                result := div(a, b)
+            }
         }
         }
     }
     }
 
 
@@ -68,11 +101,38 @@ library Math {
      */
      */
     function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
     function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
         unchecked {
         unchecked {
-            if (b == 0) return (false, 0);
-            return (true, a % b);
+            success = b > 0;
+            assembly ("memory-safe") {
+                // The `MOD` opcode returns zero when the denominator is 0.
+                result := mod(a, b)
+            }
         }
         }
     }
     }
 
 
+    /**
+     * @dev Unsigned saturating addition, bounds to `2²⁵⁶ - 1` instead of overflowing.
+     */
+    function saturatingAdd(uint256 a, uint256 b) internal pure returns (uint256) {
+        (bool success, uint256 result) = tryAdd(a, b);
+        return ternary(success, result, type(uint256).max);
+    }
+
+    /**
+     * @dev Unsigned saturating subtraction, bounds to zero instead of overflowing.
+     */
+    function saturatingSub(uint256 a, uint256 b) internal pure returns (uint256) {
+        (, uint256 result) = trySub(a, b);
+        return result;
+    }
+
+    /**
+     * @dev Unsigned saturating multiplication, bounds to `2²⁵⁶ - 1` instead of overflowing.
+     */
+    function saturatingMul(uint256 a, uint256 b) internal pure returns (uint256) {
+        (bool success, uint256 result) = tryMul(a, b);
+        return ternary(success, result, type(uint256).max);
+    }
+
     /**
     /**
      * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.
      * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.
      *
      *
@@ -143,26 +203,18 @@ library Math {
      */
      */
     function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
     function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
         unchecked {
         unchecked {
-            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2²⁵⁶ and mod 2²⁵⁶ - 1, then use
-            // the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
-            // variables such that product = prod1 * 2²⁵⁶ + prod0.
-            uint256 prod0 = x * y; // Least significant 256 bits of the product
-            uint256 prod1; // Most significant 256 bits of the product
-            assembly {
-                let mm := mulmod(x, y, not(0))
-                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
-            }
+            (uint256 high, uint256 low) = mul512(x, y);
 
 
             // Handle non-overflow cases, 256 by 256 division.
             // Handle non-overflow cases, 256 by 256 division.
-            if (prod1 == 0) {
+            if (high == 0) {
                 // Solidity will revert if denominator == 0, unlike the div opcode on its own.
                 // Solidity will revert if denominator == 0, unlike the div opcode on its own.
                 // The surrounding unchecked block does not change this fact.
                 // The surrounding unchecked block does not change this fact.
                 // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
                 // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
-                return prod0 / denominator;
+                return low / denominator;
             }
             }
 
 
             // Make sure the result is less than 2²⁵⁶. Also prevents denominator == 0.
             // Make sure the result is less than 2²⁵⁶. Also prevents denominator == 0.
-            if (denominator <= prod1) {
+            if (denominator <= high) {
                 Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW));
                 Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW));
             }
             }
 
 
@@ -170,34 +222,34 @@ library Math {
             // 512 by 256 division.
             // 512 by 256 division.
             ///////////////////////////////////////////////
             ///////////////////////////////////////////////
 
 
-            // Make division exact by subtracting the remainder from [prod1 prod0].
+            // Make division exact by subtracting the remainder from [high low].
             uint256 remainder;
             uint256 remainder;
-            assembly {
+            assembly ("memory-safe") {
                 // Compute remainder using mulmod.
                 // Compute remainder using mulmod.
                 remainder := mulmod(x, y, denominator)
                 remainder := mulmod(x, y, denominator)
 
 
                 // Subtract 256 bit number from 512 bit number.
                 // Subtract 256 bit number from 512 bit number.
-                prod1 := sub(prod1, gt(remainder, prod0))
-                prod0 := sub(prod0, remainder)
+                high := sub(high, gt(remainder, low))
+                low := sub(low, remainder)
             }
             }
 
 
             // Factor powers of two out of denominator and compute largest power of two divisor of denominator.
             // Factor powers of two out of denominator and compute largest power of two divisor of denominator.
             // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.
             // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.
 
 
             uint256 twos = denominator & (0 - denominator);
             uint256 twos = denominator & (0 - denominator);
-            assembly {
+            assembly ("memory-safe") {
                 // Divide denominator by twos.
                 // Divide denominator by twos.
                 denominator := div(denominator, twos)
                 denominator := div(denominator, twos)
 
 
-                // Divide [prod1 prod0] by twos.
-                prod0 := div(prod0, twos)
+                // Divide [high low] by twos.
+                low := div(low, twos)
 
 
                 // Flip twos such that it is 2²⁵⁶ / twos. If twos is zero, then it becomes one.
                 // Flip twos such that it is 2²⁵⁶ / twos. If twos is zero, then it becomes one.
                 twos := add(div(sub(0, twos), twos), 1)
                 twos := add(div(sub(0, twos), twos), 1)
             }
             }
 
 
-            // Shift in bits from prod1 into prod0.
-            prod0 |= prod1 * twos;
+            // Shift in bits from high into low.
+            low |= high * twos;
 
 
             // Invert denominator mod 2²⁵⁶. Now that denominator is an odd number, it has an inverse modulo 2²⁵⁶ such
             // Invert denominator mod 2²⁵⁶. Now that denominator is an odd number, it has an inverse modulo 2²⁵⁶ such
             // that denominator * inv ≡ 1 mod 2²⁵⁶. Compute the inverse by starting with a seed that is correct for
             // that denominator * inv ≡ 1 mod 2²⁵⁶. Compute the inverse by starting with a seed that is correct for
@@ -215,9 +267,9 @@ library Math {
 
 
             // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
             // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
             // This will give us the correct result modulo 2²⁵⁶. Since the preconditions guarantee that the outcome is
             // This will give us the correct result modulo 2²⁵⁶. Since the preconditions guarantee that the outcome is
-            // less than 2²⁵⁶, this is the final result. We don't need to compute the high bits of the result and prod1
+            // less than 2²⁵⁶, this is the final result. We don't need to compute the high bits of the result and high
             // is no longer required.
             // is no longer required.
-            result = prod0 * inverse;
+            result = low * inverse;
             return result;
             return result;
         }
         }
     }
     }
@@ -229,6 +281,26 @@ library Math {
         return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);
         return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);
     }
     }
 
 
+    /**
+     * @dev Calculates floor(x * y >> n) with full precision. Throws if result overflows a uint256.
+     */
+    function mulShr(uint256 x, uint256 y, uint8 n) internal pure returns (uint256 result) {
+        unchecked {
+            (uint256 high, uint256 low) = mul512(x, y);
+            if (high >= 1 << n) {
+                Panic.panic(Panic.UNDER_OVERFLOW);
+            }
+            return (high << (256 - n)) | (low >> n);
+        }
+    }
+
+    /**
+     * @dev Calculates x * y >> n with full precision, following the selected rounding direction.
+     */
+    function mulShr(uint256 x, uint256 y, uint8 n, Rounding rounding) internal pure returns (uint256) {
+        return mulShr(x, y, n) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, 1 << n) > 0);
+    }
+
     /**
     /**
      * @dev Calculate the modular multiplicative inverse of a number in Z/nZ.
      * @dev Calculate the modular multiplicative inverse of a number in Z/nZ.
      *
      *
@@ -537,41 +609,45 @@ library Math {
      * @dev Return the log in base 2 of a positive value rounded towards zero.
      * @dev Return the log in base 2 of a positive value rounded towards zero.
      * Returns 0 if given 0.
      * Returns 0 if given 0.
      */
      */
-    function log2(uint256 value) internal pure returns (uint256) {
-        uint256 result = 0;
-        uint256 exp;
-        unchecked {
-            exp = 128 * SafeCast.toUint(value > (1 << 128) - 1);
-            value >>= exp;
-            result += exp;
-
-            exp = 64 * SafeCast.toUint(value > (1 << 64) - 1);
-            value >>= exp;
-            result += exp;
-
-            exp = 32 * SafeCast.toUint(value > (1 << 32) - 1);
-            value >>= exp;
-            result += exp;
-
-            exp = 16 * SafeCast.toUint(value > (1 << 16) - 1);
-            value >>= exp;
-            result += exp;
-
-            exp = 8 * SafeCast.toUint(value > (1 << 8) - 1);
-            value >>= exp;
-            result += exp;
-
-            exp = 4 * SafeCast.toUint(value > (1 << 4) - 1);
-            value >>= exp;
-            result += exp;
-
-            exp = 2 * SafeCast.toUint(value > (1 << 2) - 1);
-            value >>= exp;
-            result += exp;
-
-            result += SafeCast.toUint(value > 1);
+    function log2(uint256 x) internal pure returns (uint256 r) {
+        // If value has upper 128 bits set, log2 result is at least 128
+        r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;
+        // If upper 64 bits of 128-bit half set, add 64 to result
+        r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;
+        // If upper 32 bits of 64-bit half set, add 32 to result
+        r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;
+        // If upper 16 bits of 32-bit half set, add 16 to result
+        r |= SafeCast.toUint((x >> r) > 0xffff) << 4;
+        // If upper 8 bits of 16-bit half set, add 8 to result
+        r |= SafeCast.toUint((x >> r) > 0xff) << 3;
+        // If upper 4 bits of 8-bit half set, add 4 to result
+        r |= SafeCast.toUint((x >> r) > 0xf) << 2;
+
+        // Shifts value right by the current result and use it as an index into this lookup table:
+        //
+        // | x (4 bits) |  index  | table[index] = MSB position |
+        // |------------|---------|-----------------------------|
+        // |    0000    |    0    |        table[0] = 0         |
+        // |    0001    |    1    |        table[1] = 0         |
+        // |    0010    |    2    |        table[2] = 1         |
+        // |    0011    |    3    |        table[3] = 1         |
+        // |    0100    |    4    |        table[4] = 2         |
+        // |    0101    |    5    |        table[5] = 2         |
+        // |    0110    |    6    |        table[6] = 2         |
+        // |    0111    |    7    |        table[7] = 2         |
+        // |    1000    |    8    |        table[8] = 3         |
+        // |    1001    |    9    |        table[9] = 3         |
+        // |    1010    |   10    |        table[10] = 3        |
+        // |    1011    |   11    |        table[11] = 3        |
+        // |    1100    |   12    |        table[12] = 3        |
+        // |    1101    |   13    |        table[13] = 3        |
+        // |    1110    |   14    |        table[14] = 3        |
+        // |    1111    |   15    |        table[15] = 3        |
+        //
+        // The lookup table is represented as a 32-byte value with the MSB positions for 0-15 in the last 16 bytes.
+        assembly ("memory-safe") {
+            r := or(r, byte(shr(r, x), 0x0000010102020202030303030303030300000000000000000000000000000000))
         }
         }
-        return result;
     }
     }
 
 
     /**
     /**
@@ -640,29 +716,17 @@ library Math {
      *
      *
      * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
      * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
      */
      */
-    function log256(uint256 value) internal pure returns (uint256) {
-        uint256 result = 0;
-        uint256 isGt;
-        unchecked {
-            isGt = SafeCast.toUint(value > (1 << 128) - 1);
-            value >>= isGt * 128;
-            result += isGt * 16;
-
-            isGt = SafeCast.toUint(value > (1 << 64) - 1);
-            value >>= isGt * 64;
-            result += isGt * 8;
-
-            isGt = SafeCast.toUint(value > (1 << 32) - 1);
-            value >>= isGt * 32;
-            result += isGt * 4;
-
-            isGt = SafeCast.toUint(value > (1 << 16) - 1);
-            value >>= isGt * 16;
-            result += isGt * 2;
-
-            result += SafeCast.toUint(value > (1 << 8) - 1);
-        }
-        return result;
+    function log256(uint256 x) internal pure returns (uint256 r) {
+        // If value has upper 128 bits set, log2 result is at least 128
+        r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;
+        // If upper 64 bits of 128-bit half set, add 64 to result
+        r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;
+        // If upper 32 bits of 64-bit half set, add 32 to result
+        r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;
+        // If upper 16 bits of 32-bit half set, add 16 to result
+        r |= SafeCast.toUint((x >> r) > 0xffff) << 4;
+        // Add 1 if upper 8 bits of 16-bit half set, and divide accumulated result by 8
+        return (r >> 3) | SafeCast.toUint((x >> r) > 0xff);
     }
     }
 
 
     /**
     /**

+ 4 - 4
contracts/utils/structs/Checkpoints.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (utils/structs/Checkpoints.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (utils/structs/Checkpoints.sol)
 // This file was procedurally generated from scripts/generate/templates/Checkpoints.js.
 // This file was procedurally generated from scripts/generate/templates/Checkpoints.js.
 
 
 pragma solidity ^0.8.20;
 pragma solidity ^0.8.20;
@@ -114,7 +114,7 @@ library Checkpoints {
     }
     }
 
 
     /**
     /**
-     * @dev Returns the number of checkpoint.
+     * @dev Returns the number of checkpoints.
      */
      */
     function length(Trace224 storage self) internal view returns (uint256) {
     function length(Trace224 storage self) internal view returns (uint256) {
         return self._checkpoints.length;
         return self._checkpoints.length;
@@ -317,7 +317,7 @@ library Checkpoints {
     }
     }
 
 
     /**
     /**
-     * @dev Returns the number of checkpoint.
+     * @dev Returns the number of checkpoints.
      */
      */
     function length(Trace208 storage self) internal view returns (uint256) {
     function length(Trace208 storage self) internal view returns (uint256) {
         return self._checkpoints.length;
         return self._checkpoints.length;
@@ -520,7 +520,7 @@ library Checkpoints {
     }
     }
 
 
     /**
     /**
-     * @dev Returns the number of checkpoint.
+     * @dev Returns the number of checkpoints.
      */
      */
     function length(Trace160 storage self) internal view returns (uint256) {
     function length(Trace160 storage self) internal view returns (uint256) {
         return self._checkpoints.length;
         return self._checkpoints.length;

+ 2 - 2
contracts/utils/structs/CircularBuffer.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (utils/structs/CircularBuffer.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (utils/structs/CircularBuffer.sol)
 pragma solidity ^0.8.20;
 pragma solidity ^0.8.20;
 
 
 import {Math} from "../math/Math.sol";
 import {Math} from "../math/Math.sol";
@@ -62,7 +62,7 @@ library CircularBuffer {
     }
     }
 
 
     /**
     /**
-     * @dev Initialize a new CircularBuffer of given size.
+     * @dev Initialize a new CircularBuffer of a given size.
      *
      *
      * If the CircularBuffer was already setup and used, calling that function again will reset it to a blank state.
      * If the CircularBuffer was already setup and used, calling that function again will reset it to a blank state.
      *
      *

+ 96 - 1
contracts/utils/structs/EnumerableMap.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (utils/structs/EnumerableMap.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (utils/structs/EnumerableMap.sol)
 // This file was procedurally generated from scripts/generate/templates/EnumerableMap.js.
 // This file was procedurally generated from scripts/generate/templates/EnumerableMap.js.
 
 
 pragma solidity ^0.8.20;
 pragma solidity ^0.8.20;
@@ -16,6 +16,7 @@ import {EnumerableSet} from "./EnumerableSet.sol";
  * - Entries are added, removed, and checked for existence in constant time
  * - Entries are added, removed, and checked for existence in constant time
  * (O(1)).
  * (O(1)).
  * - Entries are enumerated in O(n). No guarantees are made on the ordering.
  * - Entries are enumerated in O(n). No guarantees are made on the ordering.
+ * - Map can be cleared (all entries removed) in O(n).
  *
  *
  * ```solidity
  * ```solidity
  * contract Example {
  * contract Example {
@@ -90,6 +91,20 @@ library EnumerableMap {
         return map._keys.remove(key);
         return map._keys.remove(key);
     }
     }
 
 
+    /**
+     * @dev Removes all the entries from a map. O(n).
+     *
+     * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
+     * function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block.
+     */
+    function clear(Bytes32ToBytes32Map storage map) internal {
+        uint256 len = length(map);
+        for (uint256 i = 0; i < len; ++i) {
+            delete map._values[map._keys.at(i)];
+        }
+        map._keys.clear();
+    }
+
     /**
     /**
      * @dev Returns true if the key is in the map. O(1).
      * @dev Returns true if the key is in the map. O(1).
      */
      */
@@ -185,6 +200,16 @@ library EnumerableMap {
         return remove(map._inner, bytes32(key));
         return remove(map._inner, bytes32(key));
     }
     }
 
 
+    /**
+     * @dev Removes all the entries from a map. O(n).
+     *
+     * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
+     * function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block.
+     */
+    function clear(UintToUintMap storage map) internal {
+        clear(map._inner);
+    }
+
     /**
     /**
      * @dev Returns true if the key is in the map. O(1).
      * @dev Returns true if the key is in the map. O(1).
      */
      */
@@ -278,6 +303,16 @@ library EnumerableMap {
         return remove(map._inner, bytes32(key));
         return remove(map._inner, bytes32(key));
     }
     }
 
 
+    /**
+     * @dev Removes all the entries from a map. O(n).
+     *
+     * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
+     * function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block.
+     */
+    function clear(UintToAddressMap storage map) internal {
+        clear(map._inner);
+    }
+
     /**
     /**
      * @dev Returns true if the key is in the map. O(1).
      * @dev Returns true if the key is in the map. O(1).
      */
      */
@@ -371,6 +406,16 @@ library EnumerableMap {
         return remove(map._inner, bytes32(key));
         return remove(map._inner, bytes32(key));
     }
     }
 
 
+    /**
+     * @dev Removes all the entries from a map. O(n).
+     *
+     * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
+     * function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block.
+     */
+    function clear(UintToBytes32Map storage map) internal {
+        clear(map._inner);
+    }
+
     /**
     /**
      * @dev Returns true if the key is in the map. O(1).
      * @dev Returns true if the key is in the map. O(1).
      */
      */
@@ -464,6 +509,16 @@ library EnumerableMap {
         return remove(map._inner, bytes32(uint256(uint160(key))));
         return remove(map._inner, bytes32(uint256(uint160(key))));
     }
     }
 
 
+    /**
+     * @dev Removes all the entries from a map. O(n).
+     *
+     * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
+     * function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block.
+     */
+    function clear(AddressToUintMap storage map) internal {
+        clear(map._inner);
+    }
+
     /**
     /**
      * @dev Returns true if the key is in the map. O(1).
      * @dev Returns true if the key is in the map. O(1).
      */
      */
@@ -557,6 +612,16 @@ library EnumerableMap {
         return remove(map._inner, bytes32(uint256(uint160(key))));
         return remove(map._inner, bytes32(uint256(uint160(key))));
     }
     }
 
 
+    /**
+     * @dev Removes all the entries from a map. O(n).
+     *
+     * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
+     * function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block.
+     */
+    function clear(AddressToAddressMap storage map) internal {
+        clear(map._inner);
+    }
+
     /**
     /**
      * @dev Returns true if the key is in the map. O(1).
      * @dev Returns true if the key is in the map. O(1).
      */
      */
@@ -650,6 +715,16 @@ library EnumerableMap {
         return remove(map._inner, bytes32(uint256(uint160(key))));
         return remove(map._inner, bytes32(uint256(uint160(key))));
     }
     }
 
 
+    /**
+     * @dev Removes all the entries from a map. O(n).
+     *
+     * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
+     * function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block.
+     */
+    function clear(AddressToBytes32Map storage map) internal {
+        clear(map._inner);
+    }
+
     /**
     /**
      * @dev Returns true if the key is in the map. O(1).
      * @dev Returns true if the key is in the map. O(1).
      */
      */
@@ -743,6 +818,16 @@ library EnumerableMap {
         return remove(map._inner, key);
         return remove(map._inner, key);
     }
     }
 
 
+    /**
+     * @dev Removes all the entries from a map. O(n).
+     *
+     * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
+     * function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block.
+     */
+    function clear(Bytes32ToUintMap storage map) internal {
+        clear(map._inner);
+    }
+
     /**
     /**
      * @dev Returns true if the key is in the map. O(1).
      * @dev Returns true if the key is in the map. O(1).
      */
      */
@@ -836,6 +921,16 @@ library EnumerableMap {
         return remove(map._inner, key);
         return remove(map._inner, key);
     }
     }
 
 
+    /**
+     * @dev Removes all the entries from a map. O(n).
+     *
+     * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
+     * function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block.
+     */
+    function clear(Bytes32ToAddressMap storage map) internal {
+        clear(map._inner);
+    }
+
     /**
     /**
      * @dev Returns true if the key is in the map. O(1).
      * @dev Returns true if the key is in the map. O(1).
      */
      */

+ 48 - 1
contracts/utils/structs/EnumerableSet.sol

@@ -1,9 +1,11 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (utils/structs/EnumerableSet.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (utils/structs/EnumerableSet.sol)
 // This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.
 // This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.
 
 
 pragma solidity ^0.8.20;
 pragma solidity ^0.8.20;
 
 
+import {Arrays} from "../Arrays.sol";
+
 /**
 /**
  * @dev Library for managing
  * @dev Library for managing
  * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
  * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
@@ -14,6 +16,7 @@ pragma solidity ^0.8.20;
  * - Elements are added, removed, and checked for existence in constant time
  * - Elements are added, removed, and checked for existence in constant time
  * (O(1)).
  * (O(1)).
  * - Elements are enumerated in O(n). No guarantees are made on the ordering.
  * - Elements are enumerated in O(n). No guarantees are made on the ordering.
+ * - Set can be cleared (all elements removed) in O(n).
  *
  *
  * ```solidity
  * ```solidity
  * contract Example {
  * contract Example {
@@ -114,6 +117,20 @@ library EnumerableSet {
         }
         }
     }
     }
 
 
+    /**
+     * @dev Removes all the values from a set. O(n).
+     *
+     * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
+     * function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block.
+     */
+    function _clear(Set storage set) private {
+        uint256 len = _length(set);
+        for (uint256 i = 0; i < len; ++i) {
+            delete set._positions[set._values[i]];
+        }
+        Arrays.unsafeSetLength(set._values, 0);
+    }
+
     /**
     /**
      * @dev Returns true if the value is in the set. O(1).
      * @dev Returns true if the value is in the set. O(1).
      */
      */
@@ -180,6 +197,16 @@ library EnumerableSet {
         return _remove(set._inner, value);
         return _remove(set._inner, value);
     }
     }
 
 
+    /**
+     * @dev Removes all the values from a set. O(n).
+     *
+     * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
+     * function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block.
+     */
+    function clear(Bytes32Set storage set) internal {
+        _clear(set._inner);
+    }
+
     /**
     /**
      * @dev Returns true if the value is in the set. O(1).
      * @dev Returns true if the value is in the set. O(1).
      */
      */
@@ -253,6 +280,16 @@ library EnumerableSet {
         return _remove(set._inner, bytes32(uint256(uint160(value))));
         return _remove(set._inner, bytes32(uint256(uint160(value))));
     }
     }
 
 
+    /**
+     * @dev Removes all the values from a set. O(n).
+     *
+     * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
+     * function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block.
+     */
+    function clear(AddressSet storage set) internal {
+        _clear(set._inner);
+    }
+
     /**
     /**
      * @dev Returns true if the value is in the set. O(1).
      * @dev Returns true if the value is in the set. O(1).
      */
      */
@@ -326,6 +363,16 @@ library EnumerableSet {
         return _remove(set._inner, bytes32(value));
         return _remove(set._inner, bytes32(value));
     }
     }
 
 
+    /**
+     * @dev Removes all the values from a set. O(n).
+     *
+     * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
+     * function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block.
+     */
+    function clear(UintSet storage set) internal {
+        _clear(set._inner);
+    }
+
     /**
     /**
      * @dev Returns true if the value is in the set. O(1).
      * @dev Returns true if the value is in the set. O(1).
      */
      */

+ 95 - 3
contracts/utils/structs/MerkleTree.sol

@@ -1,11 +1,12 @@
 // SPDX-License-Identifier: MIT
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (utils/structs/MerkleTree.sol)
+// OpenZeppelin Contracts (last updated v5.3.0) (utils/structs/MerkleTree.sol)
 
 
 pragma solidity ^0.8.20;
 pragma solidity ^0.8.20;
 
 
 import {Hashes} from "../cryptography/Hashes.sol";
 import {Hashes} from "../cryptography/Hashes.sol";
 import {Arrays} from "../Arrays.sol";
 import {Arrays} from "../Arrays.sol";
 import {Panic} from "../Panic.sol";
 import {Panic} from "../Panic.sol";
+import {StorageSlot} from "../StorageSlot.sol";
 
 
 /**
 /**
  * @dev Library for managing https://wikipedia.org/wiki/Merkle_Tree[Merkle Tree] data structures.
  * @dev Library for managing https://wikipedia.org/wiki/Merkle_Tree[Merkle Tree] data structures.
@@ -27,6 +28,12 @@ import {Panic} from "../Panic.sol";
  * _Available since v5.1._
  * _Available since v5.1._
  */
  */
 library MerkleTree {
 library MerkleTree {
+    /// @dev Error emitted when trying to update a leaf that was not previously pushed.
+    error MerkleTreeUpdateInvalidIndex(uint256 index, uint256 length);
+
+    /// @dev Error emitted when the proof used during an update is invalid (could not reproduce the side).
+    error MerkleTreeUpdateInvalidProof();
+
     /**
     /**
      * @dev A complete `bytes32` Merkle tree.
      * @dev A complete `bytes32` Merkle tree.
      *
      *
@@ -88,7 +95,7 @@ library MerkleTree {
 
 
         // Build each root of zero-filled subtrees
         // Build each root of zero-filled subtrees
         bytes32 currentZero = zero;
         bytes32 currentZero = zero;
-        for (uint32 i = 0; i < treeDepth; ++i) {
+        for (uint256 i = 0; i < treeDepth; ++i) {
             Arrays.unsafeAccess(self._zeros, i).value = currentZero;
             Arrays.unsafeAccess(self._zeros, i).value = currentZero;
             currentZero = fnHash(currentZero, currentZero);
             currentZero = fnHash(currentZero, currentZero);
         }
         }
@@ -143,7 +150,7 @@ library MerkleTree {
         // Rebuild branch from leaf to root
         // Rebuild branch from leaf to root
         uint256 currentIndex = index;
         uint256 currentIndex = index;
         bytes32 currentLevelHash = leaf;
         bytes32 currentLevelHash = leaf;
-        for (uint32 i = 0; i < treeDepth; i++) {
+        for (uint256 i = 0; i < treeDepth; i++) {
             // Reaching the parent node, is currentLevelHash the left child?
             // Reaching the parent node, is currentLevelHash the left child?
             bool isLeft = currentIndex % 2 == 0;
             bool isLeft = currentIndex % 2 == 0;
 
 
@@ -166,6 +173,91 @@ library MerkleTree {
         return (index, currentLevelHash);
         return (index, currentLevelHash);
     }
     }
 
 
+    /**
+     * @dev Change the value of the leaf at position `index` from `oldValue` to `newValue`. Returns the recomputed "old"
+     * root (before the update) and "new" root (after the update). The caller must verify that the reconstructed old
+     * root is the last known one.
+     *
+     * The `proof` must be an up-to-date inclusion proof for the leaf being updated. This means that this function is
+     * vulnerable to front-running. Any {push} or {update} operation (that changes the root of the tree) would render
+     * all "in flight" updates invalid.
+     *
+     * This variant uses {Hashes-commutativeKeccak256} to hash internal nodes. It should only be used on merkle trees
+     * that were setup using the same (default) hashing function (i.e. by calling
+     * {xref-MerkleTree-setup-struct-MerkleTree-Bytes32PushTree-uint8-bytes32-}[the default setup] function).
+     */
+    function update(
+        Bytes32PushTree storage self,
+        uint256 index,
+        bytes32 oldValue,
+        bytes32 newValue,
+        bytes32[] memory proof
+    ) internal returns (bytes32 oldRoot, bytes32 newRoot) {
+        return update(self, index, oldValue, newValue, proof, Hashes.commutativeKeccak256);
+    }
+
+    /**
+     * @dev Change the value of the leaf at position `index` from `oldValue` to `newValue`. Returns the recomputed "old"
+     * root (before the update) and "new" root (after the update). The caller must verify that the reconstructed old
+     * root is the last known one.
+     *
+     * The `proof` must be an up-to-date inclusion proof for the leaf being update. This means that this function is
+     * vulnerable to front-running. Any {push} or {update} operation (that changes the root of the tree) would render
+     * all "in flight" updates invalid.
+     *
+     * This variant uses a custom hashing function to hash internal nodes. It should only be called with the same
+     * function as the one used during the initial setup of the merkle tree.
+     */
+    function update(
+        Bytes32PushTree storage self,
+        uint256 index,
+        bytes32 oldValue,
+        bytes32 newValue,
+        bytes32[] memory proof,
+        function(bytes32, bytes32) view returns (bytes32) fnHash
+    ) internal returns (bytes32 oldRoot, bytes32 newRoot) {
+        unchecked {
+            // Check index range
+            uint256 length = self._nextLeafIndex;
+            if (index >= length) revert MerkleTreeUpdateInvalidIndex(index, length);
+
+            // Cache read
+            uint256 treeDepth = depth(self);
+
+            // Workaround stack too deep
+            bytes32[] storage sides = self._sides;
+
+            // This cannot overflow because: 0 <= index < length
+            uint256 lastIndex = length - 1;
+            uint256 currentIndex = index;
+            bytes32 currentLevelHashOld = oldValue;
+            bytes32 currentLevelHashNew = newValue;
+            for (uint32 i = 0; i < treeDepth; i++) {
+                bool isLeft = currentIndex % 2 == 0;
+
+                lastIndex >>= 1;
+                currentIndex >>= 1;
+
+                if (isLeft && currentIndex == lastIndex) {
+                    StorageSlot.Bytes32Slot storage side = Arrays.unsafeAccess(sides, i);
+                    if (side.value != currentLevelHashOld) revert MerkleTreeUpdateInvalidProof();
+                    side.value = currentLevelHashNew;
+                }
+
+                bytes32 sibling = proof[i];
+                currentLevelHashOld = fnHash(
+                    isLeft ? currentLevelHashOld : sibling,
+                    isLeft ? sibling : currentLevelHashOld
+                );
+                currentLevelHashNew = fnHash(
+                    isLeft ? currentLevelHashNew : sibling,
+                    isLeft ? sibling : currentLevelHashNew
+                );
+            }
+            return (currentLevelHashOld, currentLevelHashNew);
+        }
+    }
+
     /**
     /**
      * @dev Tree's depth (set at initialization)
      * @dev Tree's depth (set at initialization)
      */
      */

Nem az összes módosított fájl került megjelenítésre, mert túl sok fájl változott