Browse Source

Update docs

github-actions 2 months ago
parent
commit
cf44560de9
100 changed files with 1692 additions and 390 deletions
  1. 2 2
      .github/workflows/checks.yml
  2. 2 0
      .github/workflows/release-cycle.yml
  3. 62 1
      CHANGELOG.md
  4. 1 0
      README.md
  5. 1 1
      SECURITY.md
  6. BIN
      audits/2025-04-v5.3.pdf
  7. 1 0
      audits/README.md
  8. 3 5
      contracts/access/AccessControl.sol
  9. 2 2
      contracts/access/IAccessControl.sol
  10. 16 40
      contracts/access/extensions/AccessControlDefaultAdminRules.sol
  11. 3 4
      contracts/access/extensions/AccessControlEnumerable.sol
  12. 2 2
      contracts/access/extensions/IAccessControlDefaultAdminRules.sol
  13. 2 2
      contracts/access/extensions/IAccessControlEnumerable.sol
  14. 1 2
      contracts/access/manager/AccessManaged.sol
  15. 2 2
      contracts/access/manager/IAccessManaged.sol
  16. 3 5
      contracts/access/manager/IAccessManager.sol
  17. 2 2
      contracts/access/manager/IAuthority.sol
  18. 145 0
      contracts/account/Account.sol
  19. 20 2
      contracts/account/README.adoc
  20. 405 0
      contracts/account/extensions/draft-AccountERC7579.sol
  21. 107 0
      contracts/account/extensions/draft-AccountERC7579Hooked.sol
  22. 70 0
      contracts/account/extensions/draft-ERC7821.sol
  23. 21 0
      contracts/account/utils/EIP7702Utils.sol
  24. 2 2
      contracts/account/utils/draft-ERC7579Utils.sol
  25. 75 109
      contracts/governance/Governor.sol
  26. 2 2
      contracts/governance/IGovernor.sol
  27. 4 0
      contracts/governance/README.adoc
  28. 3 4
      contracts/governance/TimelockController.sol
  29. 6 12
      contracts/governance/extensions/GovernorCountingFractional.sol
  30. 5 8
      contracts/governance/extensions/GovernorCountingOverridable.sol
  31. 6 12
      contracts/governance/extensions/GovernorCountingSimple.sol
  32. 91 0
      contracts/governance/extensions/GovernorNoncesKeyed.sol
  33. 2 2
      contracts/governance/extensions/GovernorPreventLateQuorum.sol
  34. 2 2
      contracts/governance/extensions/GovernorProposalGuardian.sol
  35. 4 6
      contracts/governance/extensions/GovernorSequentialProposalId.sol
  36. 6 12
      contracts/governance/extensions/GovernorSettings.sol
  37. 2 2
      contracts/governance/extensions/GovernorStorage.sol
  38. 2 4
      contracts/governance/extensions/GovernorSuperQuorum.sol
  39. 9 12
      contracts/governance/extensions/GovernorTimelockAccess.sol
  40. 3 5
      contracts/governance/extensions/GovernorTimelockCompound.sol
  41. 3 6
      contracts/governance/extensions/GovernorTimelockControl.sol
  42. 2 3
      contracts/governance/extensions/GovernorVotes.sol
  43. 2 2
      contracts/governance/extensions/GovernorVotesQuorumFraction.sol
  44. 2 2
      contracts/governance/extensions/GovernorVotesSuperQuorumFraction.sol
  45. 2 2
      contracts/governance/utils/IVotes.sol
  46. 2 2
      contracts/interfaces/IERC1155.sol
  47. 2 2
      contracts/interfaces/IERC1155MetadataURI.sol
  48. 2 2
      contracts/interfaces/IERC1155Receiver.sol
  49. 3 3
      contracts/interfaces/IERC1271.sol
  50. 2 2
      contracts/interfaces/IERC1363.sol
  51. 2 2
      contracts/interfaces/IERC1363Receiver.sol
  52. 2 2
      contracts/interfaces/IERC1363Spender.sol
  53. 2 2
      contracts/interfaces/IERC165.sol
  54. 2 2
      contracts/interfaces/IERC1820Implementer.sol
  55. 2 2
      contracts/interfaces/IERC1820Registry.sol
  56. 2 2
      contracts/interfaces/IERC1967.sol
  57. 2 2
      contracts/interfaces/IERC20.sol
  58. 2 2
      contracts/interfaces/IERC20Metadata.sol
  59. 2 2
      contracts/interfaces/IERC2309.sol
  60. 2 2
      contracts/interfaces/IERC2612.sol
  61. 2 2
      contracts/interfaces/IERC2981.sol
  62. 2 2
      contracts/interfaces/IERC3156.sol
  63. 2 2
      contracts/interfaces/IERC3156FlashBorrower.sol
  64. 2 2
      contracts/interfaces/IERC3156FlashLender.sol
  65. 2 2
      contracts/interfaces/IERC4626.sol
  66. 2 2
      contracts/interfaces/IERC4906.sol
  67. 2 2
      contracts/interfaces/IERC5267.sol
  68. 2 2
      contracts/interfaces/IERC5313.sol
  69. 2 2
      contracts/interfaces/IERC5805.sol
  70. 2 2
      contracts/interfaces/IERC6372.sol
  71. 2 2
      contracts/interfaces/IERC721.sol
  72. 2 2
      contracts/interfaces/IERC721Enumerable.sol
  73. 2 2
      contracts/interfaces/IERC721Metadata.sol
  74. 2 2
      contracts/interfaces/IERC721Receiver.sol
  75. 2 2
      contracts/interfaces/IERC777.sol
  76. 2 2
      contracts/interfaces/IERC777Recipient.sol
  77. 2 2
      contracts/interfaces/IERC777Sender.sol
  78. 18 0
      contracts/interfaces/IERC7913.sol
  79. 3 0
      contracts/interfaces/README.adoc
  80. 2 2
      contracts/interfaces/draft-IERC1822.sol
  81. 2 2
      contracts/interfaces/draft-IERC4337.sol
  82. 2 2
      contracts/interfaces/draft-IERC6093.sol
  83. 2 2
      contracts/interfaces/draft-IERC6909.sol
  84. 2 2
      contracts/interfaces/draft-IERC7579.sol
  85. 2 2
      contracts/interfaces/draft-IERC7674.sol
  86. 31 0
      contracts/interfaces/draft-IERC7802.sol
  87. 44 0
      contracts/interfaces/draft-IERC7821.sol
  88. 9 5
      contracts/metatx/ERC2771Context.sol
  89. 0 1
      contracts/mocks/AccessManagerMock.sol
  90. 44 0
      contracts/mocks/ArraysMock.sol
  91. 5 0
      contracts/mocks/CallReceiverMock.sol
  92. 7 3
      contracts/mocks/Stateless.sol
  93. 169 0
      contracts/mocks/account/AccountMock.sol
  94. 115 0
      contracts/mocks/account/modules/ERC7579Mock.sol
  95. 0 17
      contracts/mocks/docs/access-control/AccessControlNonRevokableAdmin.sol
  96. 20 0
      contracts/mocks/docs/account/MyAccountERC7702.sol
  97. 37 0
      contracts/mocks/docs/account/MyFactoryAccount.sol
  98. 2 3
      contracts/mocks/docs/governance/MyGovernor.sol
  99. 2 2
      contracts/mocks/governance/GovernorCountingOverridableMock.sol
  100. 1 1
      contracts/mocks/governance/GovernorFractionalMock.sol

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

@@ -87,7 +87,7 @@ jobs:
       - name: Set up environment
         uses: ./.github/actions/setup
       - name: Run tests
-        run: forge test -vv
+        run: forge test -vvv
 
   coverage:
     runs-on: ubuntu-latest
@@ -118,7 +118,7 @@ jobs:
       - uses: actions/checkout@v4
       - name: Set up environment
         uses: ./.github/actions/setup
-      - uses: crytic/slither-action@v0.4.0
+      - uses: crytic/slither-action@v0.4.1
 
   codespell:
     runs-on: ubuntu-latest

+ 2 - 0
.github/workflows/release-cycle.yml

@@ -131,6 +131,7 @@ jobs:
     environment: npm
     permissions:
       contents: write
+      id-token: write
     if: needs.state.outputs.publish == 'true'
     runs-on: ubuntu-latest
     steps:
@@ -153,6 +154,7 @@ jobs:
           NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
           TARBALL: ${{ steps.pack.outputs.tarball }}
           TAG: ${{ steps.pack.outputs.tag }}
+          NPM_CONFIG_PROVENANCE: true
       - name: Create Github Release
         uses: actions/github-script@v7
         env:

+ 62 - 1
CHANGELOG.md

@@ -1,5 +1,67 @@
 # Changelog
 
+
+## 5.4.0 (2025-07-17)
+
+### Breaking changes
+
+- Update minimum pragma to 0.8.24 in `SignatureChecker`, `Governor` and Governor's extensions. ([#5716](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5716)).
+
+### Pragma changes
+
+- Reduced pragma requirement of interface files
+
+### Changes by category
+
+#### Account
+
+- `Account`: Added a simple ERC-4337 account implementation with minimal logic to process user operations. ([#5657](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5657))
+- `AccountERC7579`: Extension of `Account` that implements support for ERC-7579 modules of type executor, validator, and fallback handler. ([#5657](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5657))
+- `AccountERC7579Hooked`: Extension of `AccountERC7579` that implements support for ERC-7579 hook modules. ([#5657](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5657))
+- `EIP7702Utils`: Add a library for checking if an address has an EIP-7702 delegation in place. ([#5587](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5587))
+- `IERC7821`, `ERC7821`: Interface and logic for minimal batch execution. No support for additional `opData` is included. ([#5657](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5657))
+
+#### Governance
+
+- `GovernorNoncesKeyed`: Extension of `Governor` that adds support for keyed nonces when voting by sig. ([#5574](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5574))
+
+#### Tokens
+
+- `ERC20Bridgeable`: Implementation of ERC-7802 that makes an ERC-20 compatible with crosschain bridges. ([#5739](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5739))
+
+#### Cryptography
+
+##### Signers
+
+- `AbstractSigner`, `SignerECDSA`, `SignerP256`, and `SignerRSA`: Add an abstract contract and various implementations for contracts that deal with signature verification. ([#5657](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5657))
+- `SignerERC7702`: Implementation of `AbstractSigner` for Externally Owned Accounts (EOAs). Useful with ERC-7702. ([#5657](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5657))
+- `SignerERC7913`: Abstract signer that verifies signatures using the ERC-7913 workflow. ([#5659](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5659))
+- `MultiSignerERC7913`: Implementation of `AbstractSigner` that supports multiple ERC-7913 signers with a threshold-based signature verification system. ([#5659](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5659))
+- `MultiSignerERC7913Weighted`: Extension of `MultiSignerERC7913` that supports assigning different weights to each signer, enabling more flexible governance schemes. ([#5741](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5741))
+
+##### Verifiers
+
+- `ERC7913P256Verifier` and `ERC7913RSAVerifier`: Ready to use ERC-7913 verifiers that implement key verification for P256 (secp256r1) and RSA keys. ([#5659](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5659))
+
+##### Other
+
+- `SignatureChecker`: Add support for ERC-7913 signatures alongside existing ECDSA and ERC-1271 signature verification. ([#5659](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5659))
+- `ERC7739`: An abstract contract to validate signatures following the rehashing scheme from `ERC7739Utils`. ([#5664](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5664))
+- `ERC7739Utils`: Add a library that implements a defensive rehashing mechanism to prevent replayability of smart contract signatures based on the ERC-7739. ([#5664](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5664))
+
+#### Structures
+
+- `EnumerableMap`: Add support for `BytesToBytesMap` type. ([#5658](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5658))
+- `EnumerableMap`: Add `keys(uint256,uint256)` that returns a subset (slice) of the keys in the map. ([#5713](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5713))
+- `EnumerableSet`: Add support for `StringSet` and `BytesSet` types. ([#5658](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5658))
+- `EnumerableSet`: Add `values(uint256,uint256)` that returns a subset (slice) of the values in the set. ([#5713](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5713))
+
+#### Utils
+
+- `Arrays`: Add `unsafeAccess`, `unsafeMemoryAccess` and `unsafeSetLength` for `bytes[]` and `string[]`. ([#5568](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5568))
+- `Blockhash`: Add a library that provides access to historical block hashes using EIP-2935's history storage, extending the standard 256-block limit to 8191 blocks. ([#5642](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5642))
+- `Bytes`: Fix `lastIndexOf(bytes,byte,uint256)` with empty buffers and finite position to correctly return `type(uint256).max` instead of accessing uninitialized memory sections. ([#5797](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/5797))
+
 ## 5.3.0 (2025-04-09)
 
 ### Breaking Changes
@@ -8,7 +70,6 @@
 
 #### Custom error changes
 
-- Replace `AccessControlNonRevokable` with `AccessControlNonRevocable`.
 - Replace `GovernorAlreadyOverridenVote` with `GovernorAlreadyOverriddenVote`.
 - Replace `GovernorOnlyProposer` with `GovernorUnableToCancel`.
 

+ 1 - 0
README.md

@@ -1,5 +1,6 @@
 # <img src="logo.svg" alt="OpenZeppelin" height="40px">
 
+[![Github Release](https://img.shields.io/github/v/tag/OpenZeppelin/openzeppelin-contracts.svg?filter=v*&sort=semver&label=github)](https://github.com/OpenZeppelin/openzeppelin-contracts/releases/latest)
 [![NPM Package](https://img.shields.io/npm/v/@openzeppelin/contracts.svg)](https://www.npmjs.org/package/@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)

+ 1 - 1
SECURITY.md

@@ -40,4 +40,4 @@ Note as well that the Solidity language itself only guarantees security updates
 
 ## 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 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.
+Blockchain is a nascent technology and carries a high level of risk and uncertainty. OpenZeppelin makes certain software available under open source licenses, which disclaim all warranties in relation to the project and which limits the liability of OpenZeppelin. Subject to any particular licensing terms, your use of the project is governed by the terms found at [www.openzeppelin.com/tos](https://www.openzeppelin.com/tos) (the "Terms"). As set out in the Terms, you are solely responsible for any use of the project 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 issues or vulnerabilities or alert you to all or any of the risks of utilizing the project.

BIN
audits/2025-04-v5.3.pdf


+ 1 - 0
audits/README.md

@@ -2,6 +2,7 @@
 
 | Date          | Version | Commit                                                                           | Auditor      | Scope                | Links                                                       |
 | ------------- | ------- | -------------------------------------------------------------------------------- | ------------ | -------------------- | ----------------------------------------------------------- |
+| April 2025    | v5.3.0  | [`d4b2e98`](https://github.com/openzeppelin/openzeppelin-contracts/tree/d4b2e98) | OpenZeppelin | v5.3 Changes         | [🔗](./2025-04-v5.3.pdf)                                    |
 | 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)                                    |

+ 3 - 5
contracts/access/AccessControl.sol

@@ -1,11 +1,11 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.3.0) (access/AccessControl.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (access/AccessControl.sol)
 
 pragma solidity ^0.8.20;
 
 import {IAccessControl} from "./IAccessControl.sol";
 import {Context} from "../utils/Context.sol";
-import {ERC165} from "../utils/introspection/ERC165.sol";
+import {IERC165, ERC165} from "../utils/introspection/ERC165.sol";
 
 /**
  * @dev Contract module that allows children to implement role-based access
@@ -65,9 +65,7 @@ abstract contract AccessControl is Context, IAccessControl, ERC165 {
         _;
     }
 
-    /**
-     * @dev See {IERC165-supportsInterface}.
-     */
+    /// @inheritdoc IERC165
     function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
         return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
     }

+ 2 - 2
contracts/access/IAccessControl.sol

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.3.0) (access/IAccessControl.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (access/IAccessControl.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity >=0.8.4;
 
 /**
  * @dev External interface of AccessControl declared to support ERC-165 detection.

+ 16 - 40
contracts/access/extensions/AccessControlDefaultAdminRules.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/AccessControlDefaultAdminRules.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (access/extensions/AccessControlDefaultAdminRules.sol)
 
 pragma solidity ^0.8.20;
 
@@ -8,6 +8,7 @@ import {AccessControl, IAccessControl} from "../AccessControl.sol";
 import {SafeCast} from "../../utils/math/SafeCast.sol";
 import {Math} from "../../utils/math/Math.sol";
 import {IERC5313} from "../../interfaces/IERC5313.sol";
+import {IERC165} from "../../utils/introspection/ERC165.sol";
 
 /**
  * @dev Extension of {AccessControl} that allows specifying special rules to manage
@@ -23,6 +24,7 @@ import {IERC5313} from "../../interfaces/IERC5313.sol";
  * * Enforces a 2-step process to transfer the `DEFAULT_ADMIN_ROLE` to another account.
  * * Enforces a configurable delay between the two steps, with the ability to cancel before the transfer is accepted.
  * * The delay can be changed by scheduling, see {changeDefaultAdminDelay}.
+ * * Role transfers must wait at least one block after scheduling before it can be accepted.
  * * It is not possible to use another role to manage the `DEFAULT_ADMIN_ROLE`.
  *
  * Example usage:
@@ -59,16 +61,12 @@ abstract contract AccessControlDefaultAdminRules is IAccessControlDefaultAdminRu
         _grantRole(DEFAULT_ADMIN_ROLE, initialDefaultAdmin);
     }
 
-    /**
-     * @dev See {IERC165-supportsInterface}.
-     */
+    /// @inheritdoc IERC165
     function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
         return interfaceId == type(IAccessControlDefaultAdminRules).interfaceId || super.supportsInterface(interfaceId);
     }
 
-    /**
-     * @dev See {IERC5313-owner}.
-     */
+    /// @inheritdoc IERC5313
     function owner() public view virtual returns (address) {
         return defaultAdmin();
     }
@@ -140,9 +138,7 @@ abstract contract AccessControlDefaultAdminRules is IAccessControlDefaultAdminRu
         return super._grantRole(role, account);
     }
 
-    /**
-     * @dev See {AccessControl-_revokeRole}.
-     */
+    /// @inheritdoc AccessControl
     function _revokeRole(bytes32 role, address account) internal virtual override returns (bool) {
         if (role == DEFAULT_ADMIN_ROLE && account == defaultAdmin()) {
             delete _currentDefaultAdmin;
@@ -164,39 +160,29 @@ abstract contract AccessControlDefaultAdminRules is IAccessControlDefaultAdminRu
     /// AccessControlDefaultAdminRules accessors
     ///
 
-    /**
-     * @inheritdoc IAccessControlDefaultAdminRules
-     */
+    /// @inheritdoc IAccessControlDefaultAdminRules
     function defaultAdmin() public view virtual returns (address) {
         return _currentDefaultAdmin;
     }
 
-    /**
-     * @inheritdoc IAccessControlDefaultAdminRules
-     */
+    /// @inheritdoc IAccessControlDefaultAdminRules
     function pendingDefaultAdmin() public view virtual returns (address newAdmin, uint48 schedule) {
         return (_pendingDefaultAdmin, _pendingDefaultAdminSchedule);
     }
 
-    /**
-     * @inheritdoc IAccessControlDefaultAdminRules
-     */
+    /// @inheritdoc IAccessControlDefaultAdminRules
     function defaultAdminDelay() public view virtual returns (uint48) {
         uint48 schedule = _pendingDelaySchedule;
         return (_isScheduleSet(schedule) && _hasSchedulePassed(schedule)) ? _pendingDelay : _currentDelay;
     }
 
-    /**
-     * @inheritdoc IAccessControlDefaultAdminRules
-     */
+    /// @inheritdoc IAccessControlDefaultAdminRules
     function pendingDefaultAdminDelay() public view virtual returns (uint48 newDelay, uint48 schedule) {
         schedule = _pendingDelaySchedule;
         return (_isScheduleSet(schedule) && !_hasSchedulePassed(schedule)) ? (_pendingDelay, schedule) : (0, 0);
     }
 
-    /**
-     * @inheritdoc IAccessControlDefaultAdminRules
-     */
+    /// @inheritdoc IAccessControlDefaultAdminRules
     function defaultAdminDelayIncreaseWait() public view virtual returns (uint48) {
         return 5 days;
     }
@@ -205,9 +191,7 @@ abstract contract AccessControlDefaultAdminRules is IAccessControlDefaultAdminRu
     /// AccessControlDefaultAdminRules public and internal setters for defaultAdmin/pendingDefaultAdmin
     ///
 
-    /**
-     * @inheritdoc IAccessControlDefaultAdminRules
-     */
+    /// @inheritdoc IAccessControlDefaultAdminRules
     function beginDefaultAdminTransfer(address newAdmin) public virtual onlyRole(DEFAULT_ADMIN_ROLE) {
         _beginDefaultAdminTransfer(newAdmin);
     }
@@ -223,9 +207,7 @@ abstract contract AccessControlDefaultAdminRules is IAccessControlDefaultAdminRu
         emit DefaultAdminTransferScheduled(newAdmin, newSchedule);
     }
 
-    /**
-     * @inheritdoc IAccessControlDefaultAdminRules
-     */
+    /// @inheritdoc IAccessControlDefaultAdminRules
     function cancelDefaultAdminTransfer() public virtual onlyRole(DEFAULT_ADMIN_ROLE) {
         _cancelDefaultAdminTransfer();
     }
@@ -239,9 +221,7 @@ abstract contract AccessControlDefaultAdminRules is IAccessControlDefaultAdminRu
         _setPendingDefaultAdmin(address(0), 0);
     }
 
-    /**
-     * @inheritdoc IAccessControlDefaultAdminRules
-     */
+    /// @inheritdoc IAccessControlDefaultAdminRules
     function acceptDefaultAdminTransfer() public virtual {
         (address newDefaultAdmin, ) = pendingDefaultAdmin();
         if (_msgSender() != newDefaultAdmin) {
@@ -271,9 +251,7 @@ abstract contract AccessControlDefaultAdminRules is IAccessControlDefaultAdminRu
     /// AccessControlDefaultAdminRules public and internal setters for defaultAdminDelay/pendingDefaultAdminDelay
     ///
 
-    /**
-     * @inheritdoc IAccessControlDefaultAdminRules
-     */
+    /// @inheritdoc IAccessControlDefaultAdminRules
     function changeDefaultAdminDelay(uint48 newDelay) public virtual onlyRole(DEFAULT_ADMIN_ROLE) {
         _changeDefaultAdminDelay(newDelay);
     }
@@ -289,9 +267,7 @@ abstract contract AccessControlDefaultAdminRules is IAccessControlDefaultAdminRu
         emit DefaultAdminDelayChangeScheduled(newDelay, newSchedule);
     }
 
-    /**
-     * @inheritdoc IAccessControlDefaultAdminRules
-     */
+    /// @inheritdoc IAccessControlDefaultAdminRules
     function rollbackDefaultAdminDelay() public virtual onlyRole(DEFAULT_ADMIN_ROLE) {
         _rollbackDefaultAdminDelay();
     }

+ 3 - 4
contracts/access/extensions/AccessControlEnumerable.sol

@@ -1,11 +1,12 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (access/extensions/AccessControlEnumerable.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (access/extensions/AccessControlEnumerable.sol)
 
 pragma solidity ^0.8.20;
 
 import {IAccessControlEnumerable} from "./IAccessControlEnumerable.sol";
 import {AccessControl} from "../AccessControl.sol";
 import {EnumerableSet} from "../../utils/structs/EnumerableSet.sol";
+import {IERC165} from "../../utils/introspection/ERC165.sol";
 
 /**
  * @dev Extension of {AccessControl} that allows enumerating the members of each role.
@@ -15,9 +16,7 @@ abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessCon
 
     mapping(bytes32 role => EnumerableSet.AddressSet) private _roleMembers;
 
-    /**
-     * @dev See {IERC165-supportsInterface}.
-     */
+    /// @inheritdoc IERC165
     function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
         return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);
     }

+ 2 - 2
contracts/access/extensions/IAccessControlDefaultAdminRules.sol

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (access/extensions/IAccessControlDefaultAdminRules.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (access/extensions/IAccessControlDefaultAdminRules.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity >=0.8.4;
 
 import {IAccessControl} from "../IAccessControl.sol";
 

+ 2 - 2
contracts/access/extensions/IAccessControlEnumerable.sol

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (access/extensions/IAccessControlEnumerable.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (access/extensions/IAccessControlEnumerable.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity >=0.8.4;
 
 import {IAccessControl} from "../IAccessControl.sol";
 

+ 1 - 2
contracts/access/manager/AccessManaged.sol

@@ -1,9 +1,8 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (access/manager/AccessManaged.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (access/manager/AccessManaged.sol)
 
 pragma solidity ^0.8.20;
 
-import {IAuthority} from "./IAuthority.sol";
 import {AuthorityUtils} from "./AuthorityUtils.sol";
 import {IAccessManager} from "./IAccessManager.sol";
 import {IAccessManaged} from "./IAccessManaged.sol";

+ 2 - 2
contracts/access/manager/IAccessManaged.sol

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.0.0) (access/manager/IAccessManaged.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (access/manager/IAccessManaged.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity >=0.8.4;
 
 interface IAccessManaged {
     /**

+ 3 - 5
contracts/access/manager/IAccessManager.sol

@@ -1,9 +1,7 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (access/manager/IAccessManager.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (access/manager/IAccessManager.sol)
 
-pragma solidity ^0.8.20;
-
-import {Time} from "../../utils/types/Time.sol";
+pragma solidity >=0.8.4;
 
 interface IAccessManager {
     /**
@@ -99,7 +97,7 @@ interface IAccessManager {
      * previously set delay (not zero), then the function should return false and the caller should schedule the operation
      * for future execution.
      *
-     * If `immediate` is true, the delay can be disregarded and the operation can be immediately executed, otherwise
+     * If `allowed` is true, the delay can be disregarded and the operation can be immediately executed, otherwise
      * the operation can be executed if and only if delay is greater than 0.
      *
      * NOTE: The IAuthority interface does not include the `uint32` delay. This is an extension of that interface that

+ 2 - 2
contracts/access/manager/IAuthority.sol

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.0.0) (access/manager/IAuthority.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (access/manager/IAuthority.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity >=0.4.16;
 
 /**
  * @dev Standard interface for permissioning originally defined in Dappsys.

+ 145 - 0
contracts/account/Account.sol

@@ -0,0 +1,145 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v5.4.0) (account/Account.sol)
+
+pragma solidity ^0.8.20;
+
+import {PackedUserOperation, IAccount, IEntryPoint} from "../interfaces/draft-IERC4337.sol";
+import {ERC4337Utils} from "./utils/draft-ERC4337Utils.sol";
+import {AbstractSigner} from "../utils/cryptography/signers/AbstractSigner.sol";
+
+/**
+ * @dev A simple ERC4337 account implementation. This base implementation only includes the minimal logic to process
+ * user operations.
+ *
+ * Developers must implement the {AbstractSigner-_rawSignatureValidation} function to define the account's validation logic.
+ *
+ * NOTE: This core account doesn't include any mechanism for performing arbitrary external calls. This is an essential
+ * feature that all Account should have. We leave it up to the developers to implement the mechanism of their choice.
+ * Common choices include ERC-6900, ERC-7579 and ERC-7821 (among others).
+ *
+ * IMPORTANT: Implementing a mechanism to validate signatures is a security-sensitive operation as it may allow an
+ * attacker to bypass the account's security measures. Check out {SignerECDSA}, {SignerP256}, or {SignerRSA} for
+ * digital signature validation implementations.
+ *
+ * @custom:stateless
+ */
+abstract contract Account is AbstractSigner, IAccount {
+    /**
+     * @dev Unauthorized call to the account.
+     */
+    error AccountUnauthorized(address sender);
+
+    /**
+     * @dev Revert if the caller is not the entry point or the account itself.
+     */
+    modifier onlyEntryPointOrSelf() {
+        _checkEntryPointOrSelf();
+        _;
+    }
+
+    /**
+     * @dev Revert if the caller is not the entry point.
+     */
+    modifier onlyEntryPoint() {
+        _checkEntryPoint();
+        _;
+    }
+
+    /**
+     * @dev Canonical entry point for the account that forwards and validates user operations.
+     */
+    function entryPoint() public view virtual returns (IEntryPoint) {
+        return ERC4337Utils.ENTRYPOINT_V08;
+    }
+
+    /**
+     * @dev Return the account nonce for the canonical sequence.
+     */
+    function getNonce() public view virtual returns (uint256) {
+        return getNonce(0);
+    }
+
+    /**
+     * @dev Return the account nonce for a given sequence (key).
+     */
+    function getNonce(uint192 key) public view virtual returns (uint256) {
+        return entryPoint().getNonce(address(this), key);
+    }
+
+    /**
+     * @inheritdoc IAccount
+     */
+    function validateUserOp(
+        PackedUserOperation calldata userOp,
+        bytes32 userOpHash,
+        uint256 missingAccountFunds
+    ) public virtual onlyEntryPoint returns (uint256) {
+        uint256 validationData = _validateUserOp(userOp, userOpHash);
+        _payPrefund(missingAccountFunds);
+        return validationData;
+    }
+
+    /**
+     * @dev Returns the validationData for a given user operation. By default, this checks the signature of the
+     * signable hash (produced by {_signableUserOpHash}) using the abstract signer ({AbstractSigner-_rawSignatureValidation}).
+     *
+     * NOTE: The userOpHash is assumed to be correct. Calling this function with a userOpHash that does not match the
+     * userOp will result in undefined behavior.
+     */
+    function _validateUserOp(
+        PackedUserOperation calldata userOp,
+        bytes32 userOpHash
+    ) internal virtual returns (uint256) {
+        return
+            _rawSignatureValidation(_signableUserOpHash(userOp, userOpHash), userOp.signature)
+                ? ERC4337Utils.SIG_VALIDATION_SUCCESS
+                : ERC4337Utils.SIG_VALIDATION_FAILED;
+    }
+
+    /**
+     * @dev Virtual function that returns the signable hash for a user operations. Since v0.8.0 of the entrypoint,
+     * `userOpHash` is an EIP-712 hash that can be signed directly.
+     */
+    function _signableUserOpHash(
+        PackedUserOperation calldata /*userOp*/,
+        bytes32 userOpHash
+    ) internal view virtual returns (bytes32) {
+        return userOpHash;
+    }
+
+    /**
+     * @dev Sends the missing funds for executing the user operation to the {entrypoint}.
+     * The `missingAccountFunds` must be defined by the entrypoint when calling {validateUserOp}.
+     */
+    function _payPrefund(uint256 missingAccountFunds) internal virtual {
+        if (missingAccountFunds > 0) {
+            (bool success, ) = payable(msg.sender).call{value: missingAccountFunds}("");
+            success; // Silence warning. The entrypoint should validate the result.
+        }
+    }
+
+    /**
+     * @dev Ensures the caller is the {entrypoint}.
+     */
+    function _checkEntryPoint() internal view virtual {
+        address sender = msg.sender;
+        if (sender != address(entryPoint())) {
+            revert AccountUnauthorized(sender);
+        }
+    }
+
+    /**
+     * @dev Ensures the caller is the {entrypoint} or the account itself.
+     */
+    function _checkEntryPointOrSelf() internal view virtual {
+        address sender = msg.sender;
+        if (sender != address(this) && sender != address(entryPoint())) {
+            revert AccountUnauthorized(sender);
+        }
+    }
+
+    /**
+     * @dev Receive Ether.
+     */
+    receive() external payable virtual {}
+}

+ 20 - 2
contracts/account/README.adoc

@@ -1,9 +1,27 @@
 = Account
-
 [.readme-notice]
 NOTE: This document is better viewed at https://docs.openzeppelin.com/contracts/api/account
 
-This directory includes contracts to build accounts for ERC-4337.
+This directory includes contracts to build accounts for ERC-4337. These include:
+
+ * {Account}: An ERC-4337 smart account implementation that includes the core logic to process user operations.
+ * {AccountERC7579}: An extension of `Account` that implements support for ERC-7579 modules.
+ * {AccountERC7579Hooked}: An extension of `AccountERC7579` with support for a single hook module (type 4).
+ * {ERC7821}: Minimal batch executor implementation contracts. Useful to enable easy batch execution for smart contracts.
+ * {ERC4337Utils}: Utility functions for working with ERC-4337 user operations.
+ * {ERC7579Utils}: Utility functions for working with ERC-7579 modules and account modularity.
+
+== Core
+
+{{Account}}
+
+== Extensions
+
+{{AccountERC7579}}
+
+{{AccountERC7579Hooked}}
+
+{{ERC7821}}
 
 == Utilities
 

+ 405 - 0
contracts/account/extensions/draft-AccountERC7579.sol

@@ -0,0 +1,405 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v5.4.0) (account/extensions/draft-AccountERC7579.sol)
+
+pragma solidity ^0.8.26;
+
+import {PackedUserOperation} from "../../interfaces/draft-IERC4337.sol";
+import {IERC1271} from "../../interfaces/IERC1271.sol";
+import {IERC7579Module, IERC7579Validator, IERC7579Execution, IERC7579AccountConfig, IERC7579ModuleConfig, MODULE_TYPE_VALIDATOR, MODULE_TYPE_EXECUTOR, MODULE_TYPE_FALLBACK} from "../../interfaces/draft-IERC7579.sol";
+import {ERC7579Utils, Mode, CallType, ExecType} from "../../account/utils/draft-ERC7579Utils.sol";
+import {EnumerableSet} from "../../utils/structs/EnumerableSet.sol";
+import {Bytes} from "../../utils/Bytes.sol";
+import {Packing} from "../../utils/Packing.sol";
+import {Address} from "../../utils/Address.sol";
+import {Calldata} from "../../utils/Calldata.sol";
+import {Account} from "../Account.sol";
+
+/**
+ * @dev Extension of {Account} that implements support for ERC-7579 modules.
+ *
+ * To comply with the ERC-1271 support requirement, this contract defers signature validation to
+ * installed validator modules by calling {IERC7579Validator-isValidSignatureWithSender}.
+ *
+ * This contract does not implement validation logic for user operations since this functionality
+ * is often delegated to self-contained validation modules. Developers must install a validator module
+ * upon initialization (or any other mechanism to enable execution from the account):
+ *
+ * ```solidity
+ * contract MyAccountERC7579 is AccountERC7579, Initializable {
+ *   function initializeAccount(address validator, bytes calldata validatorData) public initializer {
+ *     _installModule(MODULE_TYPE_VALIDATOR, validator, validatorData);
+ *   }
+ * }
+ * ```
+ *
+ * [NOTE]
+ * ====
+ * * Hook support is not included. See {AccountERC7579Hooked} for a version that hooks to execution.
+ * * Validator selection, when verifying either ERC-1271 signature or ERC-4337 UserOperation is implemented in
+ *   internal virtual functions {_extractUserOpValidator} and {_extractSignatureValidator}. Both are implemented
+ *   following common practices. However, this part is not standardized in ERC-7579 (or in any follow-up ERC). Some
+ *   accounts may want to override these internal functions.
+ * * When combined with {ERC7739}, resolution ordering of {isValidSignature} may have an impact ({ERC7739} does not
+ *   call super). Manual resolution might be necessary.
+ * * Static calls (using callType `0xfe`) are currently NOT supported.
+ * ====
+ *
+ * WARNING: Removing all validator modules will render the account inoperable, as no user operations can be validated thereafter.
+ */
+abstract contract AccountERC7579 is Account, IERC1271, IERC7579Execution, IERC7579AccountConfig, IERC7579ModuleConfig {
+    using Bytes for *;
+    using ERC7579Utils for *;
+    using EnumerableSet for *;
+    using Packing for bytes32;
+
+    EnumerableSet.AddressSet private _validators;
+    EnumerableSet.AddressSet private _executors;
+    mapping(bytes4 selector => address) private _fallbacks;
+
+    /// @dev The account's {fallback} was called with a selector that doesn't have an installed handler.
+    error ERC7579MissingFallbackHandler(bytes4 selector);
+
+    /// @dev Modifier that checks if the caller is an installed module of the given type.
+    modifier onlyModule(uint256 moduleTypeId, bytes calldata additionalContext) {
+        _checkModule(moduleTypeId, msg.sender, additionalContext);
+        _;
+    }
+
+    /// @dev See {_fallback}.
+    fallback(bytes calldata) external payable virtual returns (bytes memory) {
+        return _fallback();
+    }
+
+    /// @inheritdoc IERC7579AccountConfig
+    function accountId() public view virtual returns (string memory) {
+        // vendorname.accountname.semver
+        return "@openzeppelin/community-contracts.AccountERC7579.v0.0.0";
+    }
+
+    /**
+     * @inheritdoc IERC7579AccountConfig
+     *
+     * @dev Supported call types:
+     * * Single (`0x00`): A single transaction execution.
+     * * Batch (`0x01`): A batch of transactions execution.
+     * * Delegate (`0xff`): A delegate call execution.
+     *
+     * Supported exec types:
+     * * Default (`0x00`): Default execution type (revert on failure).
+     * * Try (`0x01`): Try execution type (emits ERC7579TryExecuteFail on failure).
+     */
+    function supportsExecutionMode(bytes32 encodedMode) public view virtual returns (bool) {
+        (CallType callType, ExecType execType, , ) = Mode.wrap(encodedMode).decodeMode();
+        return
+            (callType == ERC7579Utils.CALLTYPE_SINGLE ||
+                callType == ERC7579Utils.CALLTYPE_BATCH ||
+                callType == ERC7579Utils.CALLTYPE_DELEGATECALL) &&
+            (execType == ERC7579Utils.EXECTYPE_DEFAULT || execType == ERC7579Utils.EXECTYPE_TRY);
+    }
+
+    /**
+     * @inheritdoc IERC7579AccountConfig
+     *
+     * @dev Supported module types:
+     *
+     * * Validator: A module used during the validation phase to determine if a transaction is valid and
+     * should be executed on the account.
+     * * Executor: A module that can execute transactions on behalf of the smart account via a callback.
+     * * Fallback Handler: A module that can extend the fallback functionality of a smart account.
+     */
+    function supportsModule(uint256 moduleTypeId) public view virtual returns (bool) {
+        return
+            moduleTypeId == MODULE_TYPE_VALIDATOR ||
+            moduleTypeId == MODULE_TYPE_EXECUTOR ||
+            moduleTypeId == MODULE_TYPE_FALLBACK;
+    }
+
+    /// @inheritdoc IERC7579ModuleConfig
+    function installModule(
+        uint256 moduleTypeId,
+        address module,
+        bytes calldata initData
+    ) public virtual onlyEntryPointOrSelf {
+        _installModule(moduleTypeId, module, initData);
+    }
+
+    /// @inheritdoc IERC7579ModuleConfig
+    function uninstallModule(
+        uint256 moduleTypeId,
+        address module,
+        bytes calldata deInitData
+    ) public virtual onlyEntryPointOrSelf {
+        _uninstallModule(moduleTypeId, module, deInitData);
+    }
+
+    /// @inheritdoc IERC7579ModuleConfig
+    function isModuleInstalled(
+        uint256 moduleTypeId,
+        address module,
+        bytes calldata additionalContext
+    ) public view virtual returns (bool) {
+        if (moduleTypeId == MODULE_TYPE_VALIDATOR) return _validators.contains(module);
+        if (moduleTypeId == MODULE_TYPE_EXECUTOR) return _executors.contains(module);
+        if (moduleTypeId == MODULE_TYPE_FALLBACK) return _fallbacks[bytes4(additionalContext[0:4])] == module;
+        return false;
+    }
+
+    /// @inheritdoc IERC7579Execution
+    function execute(bytes32 mode, bytes calldata executionCalldata) public payable virtual onlyEntryPointOrSelf {
+        _execute(Mode.wrap(mode), executionCalldata);
+    }
+
+    /// @inheritdoc IERC7579Execution
+    function executeFromExecutor(
+        bytes32 mode,
+        bytes calldata executionCalldata
+    )
+        public
+        payable
+        virtual
+        onlyModule(MODULE_TYPE_EXECUTOR, Calldata.emptyBytes())
+        returns (bytes[] memory returnData)
+    {
+        return _execute(Mode.wrap(mode), executionCalldata);
+    }
+
+    /**
+     * @dev Implement ERC-1271 through IERC7579Validator modules. If module based validation fails, fallback to
+     * "native" validation by the abstract signer.
+     *
+     * NOTE: when combined with {ERC7739}, resolution ordering may have an impact ({ERC7739} does not call super).
+     * Manual resolution might be necessary.
+     */
+    function isValidSignature(bytes32 hash, bytes calldata signature) public view virtual returns (bytes4) {
+        // check signature length is enough for extraction
+        if (signature.length >= 20) {
+            (address module, bytes calldata innerSignature) = _extractSignatureValidator(signature);
+            // if module is not installed, skip
+            if (isModuleInstalled(MODULE_TYPE_VALIDATOR, module, Calldata.emptyBytes())) {
+                // try validation, skip any revert
+                try IERC7579Validator(module).isValidSignatureWithSender(msg.sender, hash, innerSignature) returns (
+                    bytes4 magic
+                ) {
+                    return magic;
+                } catch {}
+            }
+        }
+        return bytes4(0xffffffff);
+    }
+
+    /**
+     * @dev Validates a user operation with {_signableUserOpHash} and returns the validation data
+     * if the module specified by the first 20 bytes of the nonce key is installed. Falls back to
+     * {Account-_validateUserOp} otherwise.
+     *
+     * See {_extractUserOpValidator} for the module extraction logic.
+     */
+    function _validateUserOp(
+        PackedUserOperation calldata userOp,
+        bytes32 userOpHash
+    ) internal virtual override returns (uint256) {
+        address module = _extractUserOpValidator(userOp);
+        return
+            isModuleInstalled(MODULE_TYPE_VALIDATOR, module, Calldata.emptyBytes())
+                ? IERC7579Validator(module).validateUserOp(userOp, _signableUserOpHash(userOp, userOpHash))
+                : super._validateUserOp(userOp, userOpHash);
+    }
+
+    /**
+     * @dev ERC-7579 execution logic. See {supportsExecutionMode} for supported modes.
+     *
+     * Reverts if the call type is not supported.
+     */
+    function _execute(
+        Mode mode,
+        bytes calldata executionCalldata
+    ) internal virtual returns (bytes[] memory returnData) {
+        (CallType callType, ExecType execType, , ) = mode.decodeMode();
+        if (callType == ERC7579Utils.CALLTYPE_SINGLE) return executionCalldata.execSingle(execType);
+        if (callType == ERC7579Utils.CALLTYPE_BATCH) return executionCalldata.execBatch(execType);
+        if (callType == ERC7579Utils.CALLTYPE_DELEGATECALL) return executionCalldata.execDelegateCall(execType);
+        revert ERC7579Utils.ERC7579UnsupportedCallType(callType);
+    }
+
+    /**
+     * @dev Installs a module of the given type with the given initialization data.
+     *
+     * For the fallback module type, the `initData` is expected to be the (packed) concatenation of a 4-byte
+     * selector and the rest of the data to be sent to the handler when calling {IERC7579Module-onInstall}.
+     *
+     * Requirements:
+     *
+     * * Module type must be supported. See {supportsModule}. Reverts with {ERC7579Utils-ERC7579UnsupportedModuleType}.
+     * * Module must be of the given type. Reverts with {ERC7579Utils-ERC7579MismatchedModuleTypeId}.
+     * * Module must not be already installed. Reverts with {ERC7579Utils-ERC7579AlreadyInstalledModule}.
+     *
+     * Emits a {IERC7579ModuleConfig-ModuleInstalled} event.
+     */
+    function _installModule(uint256 moduleTypeId, address module, bytes memory initData) internal virtual {
+        require(supportsModule(moduleTypeId), ERC7579Utils.ERC7579UnsupportedModuleType(moduleTypeId));
+        require(
+            IERC7579Module(module).isModuleType(moduleTypeId),
+            ERC7579Utils.ERC7579MismatchedModuleTypeId(moduleTypeId, module)
+        );
+
+        if (moduleTypeId == MODULE_TYPE_VALIDATOR) {
+            require(_validators.add(module), ERC7579Utils.ERC7579AlreadyInstalledModule(moduleTypeId, module));
+        } else if (moduleTypeId == MODULE_TYPE_EXECUTOR) {
+            require(_executors.add(module), ERC7579Utils.ERC7579AlreadyInstalledModule(moduleTypeId, module));
+        } else if (moduleTypeId == MODULE_TYPE_FALLBACK) {
+            bytes4 selector;
+            (selector, initData) = _decodeFallbackData(initData);
+            require(
+                _fallbacks[selector] == address(0),
+                ERC7579Utils.ERC7579AlreadyInstalledModule(moduleTypeId, module)
+            );
+            _fallbacks[selector] = module;
+        }
+
+        IERC7579Module(module).onInstall(initData);
+        emit ModuleInstalled(moduleTypeId, module);
+    }
+
+    /**
+     * @dev Uninstalls a module of the given type with the given de-initialization data.
+     *
+     * For the fallback module type, the `deInitData` is expected to be the (packed) concatenation of a 4-byte
+     * selector and the rest of the data to be sent to the handler when calling {IERC7579Module-onUninstall}.
+     *
+     * Requirements:
+     *
+     * * Module must be already installed. Reverts with {ERC7579Utils-ERC7579UninstalledModule} otherwise.
+     */
+    function _uninstallModule(uint256 moduleTypeId, address module, bytes memory deInitData) internal virtual {
+        require(supportsModule(moduleTypeId), ERC7579Utils.ERC7579UnsupportedModuleType(moduleTypeId));
+
+        if (moduleTypeId == MODULE_TYPE_VALIDATOR) {
+            require(_validators.remove(module), ERC7579Utils.ERC7579UninstalledModule(moduleTypeId, module));
+        } else if (moduleTypeId == MODULE_TYPE_EXECUTOR) {
+            require(_executors.remove(module), ERC7579Utils.ERC7579UninstalledModule(moduleTypeId, module));
+        } else if (moduleTypeId == MODULE_TYPE_FALLBACK) {
+            bytes4 selector;
+            (selector, deInitData) = _decodeFallbackData(deInitData);
+            require(
+                _fallbackHandler(selector) == module && module != address(0),
+                ERC7579Utils.ERC7579UninstalledModule(moduleTypeId, module)
+            );
+            delete _fallbacks[selector];
+        }
+
+        IERC7579Module(module).onUninstall(deInitData);
+        emit ModuleUninstalled(moduleTypeId, module);
+    }
+
+    /**
+     * @dev Fallback function that delegates the call to the installed handler for the given selector.
+     *
+     * Reverts with {ERC7579MissingFallbackHandler} if the handler is not installed.
+     *
+     * Calls the handler with the original `msg.sender` appended at the end of the calldata following
+     * the ERC-2771 format.
+     */
+    function _fallback() internal virtual returns (bytes memory) {
+        address handler = _fallbackHandler(msg.sig);
+        require(handler != address(0), ERC7579MissingFallbackHandler(msg.sig));
+
+        // From https://eips.ethereum.org/EIPS/eip-7579#fallback[ERC-7579 specifications]:
+        // - MUST utilize ERC-2771 to add the original msg.sender to the calldata sent to the fallback handler
+        // - MUST use call to invoke the fallback handler
+        (bool success, bytes memory returndata) = handler.call{value: msg.value}(
+            abi.encodePacked(msg.data, msg.sender)
+        );
+
+        if (success) return returndata;
+
+        assembly ("memory-safe") {
+            revert(add(returndata, 0x20), mload(returndata))
+        }
+    }
+
+    /// @dev Returns the fallback handler for the given selector. Returns `address(0)` if not installed.
+    function _fallbackHandler(bytes4 selector) internal view virtual returns (address) {
+        return _fallbacks[selector];
+    }
+
+    /// @dev Checks if the module is installed. Reverts if the module is not installed.
+    function _checkModule(
+        uint256 moduleTypeId,
+        address module,
+        bytes calldata additionalContext
+    ) internal view virtual {
+        require(
+            isModuleInstalled(moduleTypeId, module, additionalContext),
+            ERC7579Utils.ERC7579UninstalledModule(moduleTypeId, module)
+        );
+    }
+
+    /**
+     * @dev Extracts the nonce validator from the user operation.
+     *
+     * To construct a nonce key, set nonce as follows:
+     *
+     * ```
+     * <module address (20 bytes)> | <key (4 bytes)> | <nonce (8 bytes)>
+     * ```
+     * NOTE: The default behavior of this function replicates the behavior of
+     * https://github.com/rhinestonewtf/safe7579/blob/bb29e8b1a66658790c4169e72608e27d220f79be/src/Safe7579.sol#L266[Safe adapter],
+     * https://github.com/etherspot/etherspot-prime-contracts/blob/cfcdb48c4172cea0d66038324c0bae3288aa8caa/src/modular-etherspot-wallet/wallet/ModularEtherspotWallet.sol#L227[Etherspot's Prime Account], and
+     * https://github.com/erc7579/erc7579-implementation/blob/16138d1afd4e9711f6c1425133538837bd7787b5/src/MSAAdvanced.sol#L247[ERC7579 reference implementation].
+     *
+     * This is not standardized in ERC-7579 (or in any follow-up ERC). Some accounts may want to override these internal functions.
+     *
+     * For example, https://github.com/bcnmy/nexus/blob/54f4e19baaff96081a8843672977caf712ef19f4/contracts/lib/NonceLib.sol#L17[Biconomy's Nexus]
+     * uses a similar yet incompatible approach (the validator address is also part of the nonce, but not at the same location)
+     */
+    function _extractUserOpValidator(PackedUserOperation calldata userOp) internal pure virtual returns (address) {
+        return address(bytes32(userOp.nonce).extract_32_20(0));
+    }
+
+    /**
+     * @dev Extracts the signature validator from the signature.
+     *
+     * To construct a signature, set the first 20 bytes as the module address and the remaining bytes as the
+     * signature data:
+     *
+     * ```
+     * <module address (20 bytes)> | <signature data>
+     * ```
+     *
+     * NOTE: The default behavior of this function replicates the behavior of
+     * https://github.com/rhinestonewtf/safe7579/blob/bb29e8b1a66658790c4169e72608e27d220f79be/src/Safe7579.sol#L350[Safe adapter],
+     * https://github.com/bcnmy/nexus/blob/54f4e19baaff96081a8843672977caf712ef19f4/contracts/Nexus.sol#L239[Biconomy's Nexus],
+     * https://github.com/etherspot/etherspot-prime-contracts/blob/cfcdb48c4172cea0d66038324c0bae3288aa8caa/src/modular-etherspot-wallet/wallet/ModularEtherspotWallet.sol#L252[Etherspot's Prime Account], and
+     * https://github.com/erc7579/erc7579-implementation/blob/16138d1afd4e9711f6c1425133538837bd7787b5/src/MSAAdvanced.sol#L296[ERC7579 reference implementation].
+     *
+     * This is not standardized in ERC-7579 (or in any follow-up ERC). Some accounts may want to override these internal functions.
+     */
+    function _extractSignatureValidator(
+        bytes calldata signature
+    ) internal pure virtual returns (address module, bytes calldata innerSignature) {
+        return (address(bytes20(signature[0:20])), signature[20:]);
+    }
+
+    /**
+     * @dev Extract the function selector from initData/deInitData for MODULE_TYPE_FALLBACK
+     *
+     * NOTE: If we had calldata here, we could use calldata slice which are cheaper to manipulate and don't require
+     * actual copy. However, this would require `_installModule` to get a calldata bytes object instead of a memory
+     * bytes object. This would prevent calling `_installModule` from a contract constructor and would force the use
+     * of external initializers. That may change in the future, as most accounts will probably be deployed as
+     * clones/proxy/ERC-7702 delegates and therefore rely on initializers anyway.
+     */
+    function _decodeFallbackData(
+        bytes memory data
+    ) internal pure virtual returns (bytes4 selector, bytes memory remaining) {
+        return (bytes4(data), data.slice(4));
+    }
+
+    /// @dev By default, only use the modules for validation of userOp and signature. Disable raw signatures.
+    function _rawSignatureValidation(
+        bytes32 /*hash*/,
+        bytes calldata /*signature*/
+    ) internal view virtual override returns (bool) {
+        return false;
+    }
+}

+ 107 - 0
contracts/account/extensions/draft-AccountERC7579Hooked.sol

@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v5.4.0) (account/extensions/draft-AccountERC7579Hooked.sol)
+
+pragma solidity ^0.8.26;
+
+import {IERC7579Hook, MODULE_TYPE_HOOK} from "../../interfaces/draft-IERC7579.sol";
+import {ERC7579Utils, Mode} from "../../account/utils/draft-ERC7579Utils.sol";
+import {AccountERC7579} from "./draft-AccountERC7579.sol";
+
+/**
+ * @dev Extension of {AccountERC7579} with support for a single hook module (type 4).
+ *
+ * If installed, this extension will call the hook module's {IERC7579Hook-preCheck} before executing any operation
+ * with {_execute} (including {execute} and {executeFromExecutor} by default) and {IERC7579Hook-postCheck} thereafter.
+ *
+ * NOTE: Hook modules break the check-effect-interaction pattern. In particular, the {IERC7579Hook-preCheck} hook can
+ * lead to potentially dangerous reentrancy. Using the `withHook()` modifier is safe if no effect is performed
+ * before the preHook or after the postHook. That is the case on all functions here, but it may not be the case if
+ * functions that have this modifier are overridden. Developers should be extremely careful when implementing hook
+ * modules or further overriding functions that involve hooks.
+ */
+abstract contract AccountERC7579Hooked is AccountERC7579 {
+    address private _hook;
+
+    /// @dev A hook module is already present. This contract only supports one hook module.
+    error ERC7579HookModuleAlreadyPresent(address hook);
+
+    /**
+     * @dev Calls {IERC7579Hook-preCheck} before executing the modified function and {IERC7579Hook-postCheck}
+     * thereafter.
+     */
+    modifier withHook() {
+        address hook_ = hook();
+        bytes memory hookData;
+
+        // slither-disable-next-line reentrancy-no-eth
+        if (hook_ != address(0)) hookData = IERC7579Hook(hook_).preCheck(msg.sender, msg.value, msg.data);
+        _;
+        if (hook_ != address(0)) IERC7579Hook(hook_).postCheck(hookData);
+    }
+
+    /// @inheritdoc AccountERC7579
+    function accountId() public view virtual override returns (string memory) {
+        // vendorname.accountname.semver
+        return "@openzeppelin/community-contracts.AccountERC7579Hooked.v0.0.0";
+    }
+
+    /// @dev Returns the hook module address if installed, or `address(0)` otherwise.
+    function hook() public view virtual returns (address) {
+        return _hook;
+    }
+
+    /// @dev Supports hook modules. See {AccountERC7579-supportsModule}
+    function supportsModule(uint256 moduleTypeId) public view virtual override returns (bool) {
+        return moduleTypeId == MODULE_TYPE_HOOK || super.supportsModule(moduleTypeId);
+    }
+
+    /// @inheritdoc AccountERC7579
+    function isModuleInstalled(
+        uint256 moduleTypeId,
+        address module,
+        bytes calldata data
+    ) public view virtual override returns (bool) {
+        return
+            (moduleTypeId == MODULE_TYPE_HOOK && module == hook()) ||
+            super.isModuleInstalled(moduleTypeId, module, data);
+    }
+
+    /// @dev Installs a module with support for hook modules. See {AccountERC7579-_installModule}
+    function _installModule(
+        uint256 moduleTypeId,
+        address module,
+        bytes memory initData
+    ) internal virtual override withHook {
+        if (moduleTypeId == MODULE_TYPE_HOOK) {
+            require(_hook == address(0), ERC7579HookModuleAlreadyPresent(_hook));
+            _hook = module;
+        }
+        super._installModule(moduleTypeId, module, initData);
+    }
+
+    /// @dev Uninstalls a module with support for hook modules. See {AccountERC7579-_uninstallModule}
+    function _uninstallModule(
+        uint256 moduleTypeId,
+        address module,
+        bytes memory deInitData
+    ) internal virtual override withHook {
+        if (moduleTypeId == MODULE_TYPE_HOOK) {
+            require(_hook == module, ERC7579Utils.ERC7579UninstalledModule(moduleTypeId, module));
+            _hook = address(0);
+        }
+        super._uninstallModule(moduleTypeId, module, deInitData);
+    }
+
+    /// @dev Hooked version of {AccountERC7579-_execute}.
+    function _execute(
+        Mode mode,
+        bytes calldata executionCalldata
+    ) internal virtual override withHook returns (bytes[] memory) {
+        return super._execute(mode, executionCalldata);
+    }
+
+    /// @dev Hooked version of {AccountERC7579-_fallback}.
+    function _fallback() internal virtual override withHook returns (bytes memory) {
+        return super._fallback();
+    }
+}

+ 70 - 0
contracts/account/extensions/draft-ERC7821.sol

@@ -0,0 +1,70 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v5.4.0) (account/extensions/draft-ERC7821.sol)
+
+pragma solidity ^0.8.20;
+
+import {ERC7579Utils, Mode, CallType, ExecType, ModeSelector} from "../utils/draft-ERC7579Utils.sol";
+import {IERC7821} from "../../interfaces/draft-IERC7821.sol";
+import {Account} from "../Account.sol";
+
+/**
+ * @dev Minimal batch executor following ERC-7821.
+ *
+ * Only supports supports single batch mode (`0x01000000000000000000`). Does not support optional "opData".
+ *
+ * @custom:stateless
+ */
+abstract contract ERC7821 is IERC7821 {
+    using ERC7579Utils for *;
+
+    error UnsupportedExecutionMode();
+
+    /**
+     * @dev Executes the calls in `executionData` with no optional `opData` support.
+     *
+     * NOTE: Access to this function is controlled by {_erc7821AuthorizedExecutor}. Changing access permissions, for
+     * example to approve calls by the ERC-4337 entrypoint, should be implemented by overriding it.
+     *
+     * Reverts and bubbles up error if any call fails.
+     */
+    function execute(bytes32 mode, bytes calldata executionData) public payable virtual {
+        if (!_erc7821AuthorizedExecutor(msg.sender, mode, executionData))
+            revert Account.AccountUnauthorized(msg.sender);
+        if (!supportsExecutionMode(mode)) revert UnsupportedExecutionMode();
+        executionData.execBatch(ERC7579Utils.EXECTYPE_DEFAULT);
+    }
+
+    /// @inheritdoc IERC7821
+    function supportsExecutionMode(bytes32 mode) public view virtual returns (bool result) {
+        (CallType callType, ExecType execType, ModeSelector modeSelector, ) = Mode.wrap(mode).decodeMode();
+        return
+            callType == ERC7579Utils.CALLTYPE_BATCH &&
+            execType == ERC7579Utils.EXECTYPE_DEFAULT &&
+            modeSelector == ModeSelector.wrap(0x00000000);
+    }
+
+    /**
+     * @dev Access control mechanism for the {execute} function.
+     * By default, only the contract itself is allowed to execute.
+     *
+     * Override this function to implement custom access control, for example to allow the
+     * ERC-4337 entrypoint to execute.
+     *
+     * ```solidity
+     * function _erc7821AuthorizedExecutor(
+     *   address caller,
+     *   bytes32 mode,
+     *   bytes calldata executionData
+     * ) internal view virtual override returns (bool) {
+     *   return caller == address(entryPoint()) || super._erc7821AuthorizedExecutor(caller, mode, executionData);
+     * }
+     * ```
+     */
+    function _erc7821AuthorizedExecutor(
+        address caller,
+        bytes32 /* mode */,
+        bytes calldata /* executionData */
+    ) internal view virtual returns (bool) {
+        return caller == address(this);
+    }
+}

+ 21 - 0
contracts/account/utils/EIP7702Utils.sol

@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v5.4.0) (account/utils/EIP7702Utils.sol)
+
+pragma solidity ^0.8.20;
+
+/**
+ * @dev Library with common EIP-7702 utility functions.
+ *
+ * See https://eips.ethereum.org/EIPS/eip-7702[ERC-7702].
+ */
+library EIP7702Utils {
+    bytes3 internal constant EIP7702_PREFIX = 0xef0100;
+
+    /**
+     * @dev Returns the address of the delegate if `account` as an EIP-7702 delegation setup, or address(0) otherwise.
+     */
+    function fetchDelegate(address account) internal view returns (address) {
+        bytes23 delegation = bytes23(account.code);
+        return bytes3(delegation) == EIP7702_PREFIX ? address(bytes20(delegation << 24)) : address(0);
+    }
+}

+ 2 - 2
contracts/account/utils/draft-ERC7579Utils.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.3.0) (account/utils/draft-ERC7579Utils.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (account/utils/draft-ERC7579Utils.sol)
 
 pragma solidity ^0.8.20;
 
@@ -204,7 +204,7 @@ library ERC7579Utils {
                 revert ERC7579DecodingError();
 
             assembly ("memory-safe") {
-                executionBatch.offset := add(add(executionCalldata.offset, arrayLengthOffset), 32)
+                executionBatch.offset := add(add(executionCalldata.offset, arrayLengthOffset), 0x20)
                 executionBatch.length := arrayLength
             }
         }

+ 75 - 109
contracts/governance/Governor.sol

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.3.0) (governance/Governor.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (governance/Governor.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity ^0.8.24;
 
 import {IERC721Receiver} from "../token/ERC721/IERC721Receiver.sol";
 import {IERC1155Receiver} from "../token/ERC1155/IERC1155Receiver.sol";
@@ -86,9 +86,7 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72
         }
     }
 
-    /**
-     * @dev See {IERC165-supportsInterface}.
-     */
+    /// @inheritdoc IERC165
     function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {
         return
             interfaceId == type(IGovernor).interfaceId ||
@@ -97,16 +95,12 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72
             super.supportsInterface(interfaceId);
     }
 
-    /**
-     * @dev See {IGovernor-name}.
-     */
+    /// @inheritdoc IGovernor
     function name() public view virtual returns (string memory) {
         return _name;
     }
 
-    /**
-     * @dev See {IGovernor-version}.
-     */
+    /// @inheritdoc IGovernor
     function version() public view virtual returns (string memory) {
         return "1";
     }
@@ -133,9 +127,7 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72
         return uint256(keccak256(abi.encode(targets, values, calldatas, descriptionHash)));
     }
 
-    /**
-     * @dev See {IGovernor-getProposalId}.
-     */
+    /// @inheritdoc IGovernor
     function getProposalId(
         address[] memory targets,
         uint256[] memory values,
@@ -145,9 +137,7 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72
         return hashProposal(targets, values, calldatas, descriptionHash);
     }
 
-    /**
-     * @dev See {IGovernor-state}.
-     */
+    /// @inheritdoc IGovernor
     function state(uint256 proposalId) public view virtual returns (ProposalState) {
         // We read the struct fields into the stack at once so Solidity emits a single SLOAD
         ProposalCore storage proposal = _proposals[proposalId];
@@ -187,44 +177,32 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72
         }
     }
 
-    /**
-     * @dev See {IGovernor-proposalThreshold}.
-     */
+    /// @inheritdoc IGovernor
     function proposalThreshold() public view virtual returns (uint256) {
         return 0;
     }
 
-    /**
-     * @dev See {IGovernor-proposalSnapshot}.
-     */
+    /// @inheritdoc IGovernor
     function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256) {
         return _proposals[proposalId].voteStart;
     }
 
-    /**
-     * @dev See {IGovernor-proposalDeadline}.
-     */
+    /// @inheritdoc IGovernor
     function proposalDeadline(uint256 proposalId) public view virtual returns (uint256) {
         return _proposals[proposalId].voteStart + _proposals[proposalId].voteDuration;
     }
 
-    /**
-     * @dev See {IGovernor-proposalProposer}.
-     */
+    /// @inheritdoc IGovernor
     function proposalProposer(uint256 proposalId) public view virtual returns (address) {
         return _proposals[proposalId].proposer;
     }
 
-    /**
-     * @dev See {IGovernor-proposalEta}.
-     */
+    /// @inheritdoc IGovernor
     function proposalEta(uint256 proposalId) public view virtual returns (uint256) {
         return _proposals[proposalId].etaSeconds;
     }
 
-    /**
-     * @dev See {IGovernor-proposalNeedsQueuing}.
-     */
+    /// @inheritdoc IGovernor
     function proposalNeedsQueuing(uint256) public view virtual returns (bool) {
         return false;
     }
@@ -362,9 +340,7 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72
         // Using a named return variable to avoid stack too deep errors
     }
 
-    /**
-     * @dev See {IGovernor-queue}.
-     */
+    /// @inheritdoc IGovernor
     function queue(
         address[] memory targets,
         uint256[] memory values,
@@ -410,9 +386,7 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72
         return 0;
     }
 
-    /**
-     * @dev See {IGovernor-execute}.
-     */
+    /// @inheritdoc IGovernor
     function execute(
         address[] memory targets,
         uint256[] memory values,
@@ -470,9 +444,7 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72
         }
     }
 
-    /**
-     * @dev See {IGovernor-cancel}.
-     */
+    /// @inheritdoc IGovernor
     function cancel(
         address[] memory targets,
         uint256[] memory values,
@@ -518,16 +490,12 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72
         return proposalId;
     }
 
-    /**
-     * @dev See {IGovernor-getVotes}.
-     */
+    /// @inheritdoc IGovernor
     function getVotes(address account, uint256 timepoint) public view virtual returns (uint256) {
         return _getVotes(account, timepoint, _defaultParams());
     }
 
-    /**
-     * @dev See {IGovernor-getVotesWithParams}.
-     */
+    /// @inheritdoc IGovernor
     function getVotesWithParams(
         address account,
         uint256 timepoint,
@@ -536,17 +504,13 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72
         return _getVotes(account, timepoint, params);
     }
 
-    /**
-     * @dev See {IGovernor-castVote}.
-     */
+    /// @inheritdoc IGovernor
     function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256) {
         address voter = _msgSender();
         return _castVote(proposalId, voter, support, "");
     }
 
-    /**
-     * @dev See {IGovernor-castVoteWithReason}.
-     */
+    /// @inheritdoc IGovernor
     function castVoteWithReason(
         uint256 proposalId,
         uint8 support,
@@ -556,9 +520,7 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72
         return _castVote(proposalId, voter, support, reason);
     }
 
-    /**
-     * @dev See {IGovernor-castVoteWithReasonAndParams}.
-     */
+    /// @inheritdoc IGovernor
     function castVoteWithReasonAndParams(
         uint256 proposalId,
         uint8 support,
@@ -569,31 +531,20 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72
         return _castVote(proposalId, voter, support, reason, params);
     }
 
-    /**
-     * @dev See {IGovernor-castVoteBySig}.
-     */
+    /// @inheritdoc IGovernor
     function castVoteBySig(
         uint256 proposalId,
         uint8 support,
         address voter,
         bytes memory signature
     ) public virtual returns (uint256) {
-        bool valid = SignatureChecker.isValidSignatureNow(
-            voter,
-            _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support, voter, _useNonce(voter)))),
-            signature
-        );
-
-        if (!valid) {
+        if (!_validateVoteSig(proposalId, support, voter, signature)) {
             revert GovernorInvalidSignature(voter);
         }
-
         return _castVote(proposalId, voter, support, "");
     }
 
-    /**
-     * @dev See {IGovernor-castVoteWithReasonAndParamsBySig}.
-     */
+    /// @inheritdoc IGovernor
     function castVoteWithReasonAndParamsBySig(
         uint256 proposalId,
         uint8 support,
@@ -602,31 +553,56 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72
         bytes memory params,
         bytes memory signature
     ) public virtual returns (uint256) {
-        bool valid = SignatureChecker.isValidSignatureNow(
-            voter,
-            _hashTypedDataV4(
-                keccak256(
-                    abi.encode(
-                        EXTENDED_BALLOT_TYPEHASH,
-                        proposalId,
-                        support,
-                        voter,
-                        _useNonce(voter),
-                        keccak256(bytes(reason)),
-                        keccak256(params)
-                    )
-                )
-            ),
-            signature
-        );
-
-        if (!valid) {
+        if (!_validateExtendedVoteSig(proposalId, support, voter, reason, params, signature)) {
             revert GovernorInvalidSignature(voter);
         }
-
         return _castVote(proposalId, voter, support, reason, params);
     }
 
+    /// @dev Validate the `signature` used in {castVoteBySig} function.
+    function _validateVoteSig(
+        uint256 proposalId,
+        uint8 support,
+        address voter,
+        bytes memory signature
+    ) internal virtual returns (bool) {
+        return
+            SignatureChecker.isValidSignatureNow(
+                voter,
+                _hashTypedDataV4(keccak256(abi.encode(BALLOT_TYPEHASH, proposalId, support, voter, _useNonce(voter)))),
+                signature
+            );
+    }
+
+    /// @dev Validate the `signature` used in {castVoteWithReasonAndParamsBySig} function.
+    function _validateExtendedVoteSig(
+        uint256 proposalId,
+        uint8 support,
+        address voter,
+        string memory reason,
+        bytes memory params,
+        bytes memory signature
+    ) internal virtual returns (bool) {
+        return
+            SignatureChecker.isValidSignatureNow(
+                voter,
+                _hashTypedDataV4(
+                    keccak256(
+                        abi.encode(
+                            EXTENDED_BALLOT_TYPEHASH,
+                            proposalId,
+                            support,
+                            voter,
+                            _useNonce(voter),
+                            keccak256(bytes(reason)),
+                            keccak256(params)
+                        )
+                    )
+                ),
+                signature
+            );
+    }
+
     /**
      * @dev Internal vote casting mechanism: Check that the vote is pending, that it has not been cast yet, retrieve
      * voting weight using {IGovernor-getVotes} and call the {_countVote} internal function. Uses the _defaultParams().
@@ -811,30 +787,20 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72
         return (state(proposalId) == ProposalState.Pending) && caller == proposalProposer(proposalId);
     }
 
-    /**
-     * @inheritdoc IERC6372
-     */
+    /// @inheritdoc IERC6372
     function clock() public view virtual returns (uint48);
 
-    /**
-     * @inheritdoc IERC6372
-     */
+    /// @inheritdoc IERC6372
     // solhint-disable-next-line func-name-mixedcase
     function CLOCK_MODE() public view virtual returns (string memory);
 
-    /**
-     * @inheritdoc IGovernor
-     */
+    /// @inheritdoc IGovernor
     function votingDelay() public view virtual returns (uint256);
 
-    /**
-     * @inheritdoc IGovernor
-     */
+    /// @inheritdoc IGovernor
     function votingPeriod() public view virtual returns (uint256);
 
-    /**
-     * @inheritdoc IGovernor
-     */
+    /// @inheritdoc IGovernor
     function quorum(uint256 timepoint) public view virtual returns (uint256);
 
     /**
@@ -846,7 +812,7 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72
     function _unsafeReadBytesOffset(bytes memory buffer, uint256 offset) private pure returns (bytes32 value) {
         // This is not memory safe in the general case, but all calls to this private function are within bounds.
         assembly ("memory-safe") {
-            value := mload(add(buffer, add(0x20, offset)))
+            value := mload(add(add(buffer, 0x20), offset))
         }
     }
 }

+ 2 - 2
contracts/governance/IGovernor.sol

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.3.0) (governance/IGovernor.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (governance/IGovernor.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity >=0.8.4;
 
 import {IERC165} from "../interfaces/IERC165.sol";
 import {IERC6372} from "../interfaces/IERC6372.sol";

+ 4 - 0
contracts/governance/README.adoc

@@ -54,6 +54,8 @@ Other extensions can customize the behavior or interface in multiple ways.
 
 * {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.
 
+* {GovernorNoncesKeyed}: An extension of {Governor} with support for keyed nonces in addition to traditional nonces when voting by signature.
+
 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.
@@ -100,6 +102,8 @@ NOTE: Functions of the `Governor` contract do not include access control. If you
 
 {{GovernorSuperQuorum}}
 
+{{GovernorNoncesKeyed}}
+
 == Utils
 
 {{Votes}}

+ 3 - 4
contracts/governance/TimelockController.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.3.0) (governance/TimelockController.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (governance/TimelockController.sol)
 
 pragma solidity ^0.8.20;
 
@@ -7,6 +7,7 @@ import {AccessControl} from "../access/AccessControl.sol";
 import {ERC721Holder} from "../token/ERC721/utils/ERC721Holder.sol";
 import {ERC1155Holder} from "../token/ERC1155/utils/ERC1155Holder.sol";
 import {Address} from "../utils/Address.sol";
+import {IERC165} from "../utils/introspection/ERC165.sol";
 
 /**
  * @dev Contract module which acts as a timelocked controller. When set as the
@@ -154,9 +155,7 @@ contract TimelockController is AccessControl, ERC721Holder, ERC1155Holder {
      */
     receive() external payable virtual {}
 
-    /**
-     * @dev See {IERC165-supportsInterface}.
-     */
+    /// @inheritdoc IERC165
     function supportsInterface(
         bytes4 interfaceId
     ) public view virtual override(AccessControl, ERC1155Holder) returns (bool) {

+ 6 - 12
contracts/governance/extensions/GovernorCountingFractional.sol

@@ -1,9 +1,9 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.3.0) (governance/extensions/GovernorCountingFractional.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (governance/extensions/GovernorCountingFractional.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity ^0.8.24;
 
-import {Governor} from "../Governor.sol";
+import {IGovernor, Governor} from "../Governor.sol";
 import {GovernorCountingSimple} from "./GovernorCountingSimple.sol";
 import {Math} from "../../utils/math/Math.sol";
 
@@ -53,17 +53,13 @@ abstract contract GovernorCountingFractional is Governor {
      */
     error GovernorExceedRemainingWeight(address voter, uint256 usedVotes, uint256 remainingWeight);
 
-    /**
-     * @dev See {IGovernor-COUNTING_MODE}.
-     */
+    /// @inheritdoc IGovernor
     // solhint-disable-next-line func-name-mixedcase
     function COUNTING_MODE() public pure virtual override returns (string memory) {
         return "support=bravo,fractional&quorum=for,abstain&params=fractional";
     }
 
-    /**
-     * @dev See {IGovernor-hasVoted}.
-     */
+    /// @inheritdoc IGovernor
     function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {
         return usedVotes(proposalId, account) > 0;
     }
@@ -86,9 +82,7 @@ abstract contract GovernorCountingFractional is Governor {
         return (proposalVote.againstVotes, proposalVote.forVotes, proposalVote.abstainVotes);
     }
 
-    /**
-     * @dev See {Governor-_quorumReached}.
-     */
+    /// @inheritdoc Governor
     function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {
         ProposalVote storage proposalVote = _proposalVotes[proposalId];
         return quorum(proposalSnapshot(proposalId)) <= proposalVote.forVotes + proposalVote.abstainVotes;

+ 5 - 8
contracts/governance/extensions/GovernorCountingOverridable.sol

@@ -1,12 +1,13 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.3.0) (governance/extensions/GovernorCountingOverridable.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (governance/extensions/GovernorCountingOverridable.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity ^0.8.24;
 
 import {SignatureChecker} from "../../utils/cryptography/SignatureChecker.sol";
 import {SafeCast} from "../../utils/math/SafeCast.sol";
 import {VotesExtended} from "../utils/VotesExtended.sol";
 import {GovernorVotes} from "./GovernorVotes.sol";
+import {IGovernor, Governor} from "../Governor.sol";
 
 /**
  * @dev Extension of {Governor} which enables delegators to override the vote of their delegates. This module requires a
@@ -46,9 +47,7 @@ abstract contract GovernorCountingOverridable is GovernorVotes {
 
     mapping(uint256 proposalId => ProposalVote) private _proposalVotes;
 
-    /**
-     * @dev See {IGovernor-COUNTING_MODE}.
-     */
+    /// @inheritdoc IGovernor
     // solhint-disable-next-line func-name-mixedcase
     function COUNTING_MODE() public pure virtual override returns (string memory) {
         return "support=bravo,override&quorum=for,abstain&overridable=true";
@@ -83,9 +82,7 @@ abstract contract GovernorCountingOverridable is GovernorVotes {
         return (votes[uint8(VoteType.Against)], votes[uint8(VoteType.For)], votes[uint8(VoteType.Abstain)]);
     }
 
-    /**
-     * @dev See {Governor-_quorumReached}.
-     */
+    /// @inheritdoc Governor
     function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {
         uint256[3] storage votes = _proposalVotes[proposalId].votes;
         return quorum(proposalSnapshot(proposalId)) <= votes[uint8(VoteType.For)] + votes[uint8(VoteType.Abstain)];

+ 6 - 12
contracts/governance/extensions/GovernorCountingSimple.sol

@@ -1,9 +1,9 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (governance/extensions/GovernorCountingSimple.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (governance/extensions/GovernorCountingSimple.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity ^0.8.24;
 
-import {Governor} from "../Governor.sol";
+import {IGovernor, Governor} from "../Governor.sol";
 
 /**
  * @dev Extension of {Governor} for simple, 3 options, vote counting.
@@ -27,17 +27,13 @@ abstract contract GovernorCountingSimple is Governor {
 
     mapping(uint256 proposalId => ProposalVote) private _proposalVotes;
 
-    /**
-     * @dev See {IGovernor-COUNTING_MODE}.
-     */
+    /// @inheritdoc IGovernor
     // solhint-disable-next-line func-name-mixedcase
     function COUNTING_MODE() public pure virtual override returns (string memory) {
         return "support=bravo&quorum=for,abstain";
     }
 
-    /**
-     * @dev See {IGovernor-hasVoted}.
-     */
+    /// @inheritdoc IGovernor
     function hasVoted(uint256 proposalId, address account) public view virtual override returns (bool) {
         return _proposalVotes[proposalId].hasVoted[account];
     }
@@ -52,9 +48,7 @@ abstract contract GovernorCountingSimple is Governor {
         return (proposalVote.againstVotes, proposalVote.forVotes, proposalVote.abstainVotes);
     }
 
-    /**
-     * @dev See {Governor-_quorumReached}.
-     */
+    /// @inheritdoc Governor
     function _quorumReached(uint256 proposalId) internal view virtual override returns (bool) {
         ProposalVote storage proposalVote = _proposalVotes[proposalId];
 

+ 91 - 0
contracts/governance/extensions/GovernorNoncesKeyed.sol

@@ -0,0 +1,91 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v5.4.0) (governance/extensions/GovernorNoncesKeyed.sol)
+
+pragma solidity ^0.8.24;
+
+import {Governor} from "../Governor.sol";
+import {Nonces} from "../../utils/Nonces.sol";
+import {NoncesKeyed} from "../../utils/NoncesKeyed.sol";
+import {SignatureChecker} from "../../utils/cryptography/SignatureChecker.sol";
+
+/**
+ * @dev An extension of {Governor} that extends existing nonce management to use {NoncesKeyed}, where the key is the low-order 192 bits of the `proposalId`.
+ * This is useful for voting by signature while maintaining separate sequences of nonces for each proposal.
+ *
+ * NOTE: Traditional (un-keyed) nonces are still supported and can continue to be used as if this extension was not present.
+ */
+abstract contract GovernorNoncesKeyed is Governor, NoncesKeyed {
+    function _useCheckedNonce(address owner, uint256 nonce) internal virtual override(Nonces, NoncesKeyed) {
+        super._useCheckedNonce(owner, nonce);
+    }
+
+    /**
+     * @dev Check the signature against keyed nonce and falls back to the traditional nonce.
+     *
+     * NOTE: This function won't call `super._validateVoteSig` if the keyed nonce is valid.
+     * Side effects may be skipped depending on the linearization of the function.
+     */
+    function _validateVoteSig(
+        uint256 proposalId,
+        uint8 support,
+        address voter,
+        bytes memory signature
+    ) internal virtual override returns (bool) {
+        if (
+            SignatureChecker.isValidSignatureNow(
+                voter,
+                _hashTypedDataV4(
+                    keccak256(
+                        abi.encode(BALLOT_TYPEHASH, proposalId, support, voter, nonces(voter, uint192(proposalId)))
+                    )
+                ),
+                signature
+            )
+        ) {
+            _useNonce(voter, uint192(proposalId));
+            return true;
+        } else {
+            return super._validateVoteSig(proposalId, support, voter, signature);
+        }
+    }
+
+    /**
+     * @dev Check the signature against keyed nonce and falls back to the traditional nonce.
+     *
+     * NOTE: This function won't call `super._validateExtendedVoteSig` if the keyed nonce is valid.
+     * Side effects may be skipped depending on the linearization of the function.
+     */
+    function _validateExtendedVoteSig(
+        uint256 proposalId,
+        uint8 support,
+        address voter,
+        string memory reason,
+        bytes memory params,
+        bytes memory signature
+    ) internal virtual override returns (bool) {
+        if (
+            SignatureChecker.isValidSignatureNow(
+                voter,
+                _hashTypedDataV4(
+                    keccak256(
+                        abi.encode(
+                            EXTENDED_BALLOT_TYPEHASH,
+                            proposalId,
+                            support,
+                            voter,
+                            nonces(voter, uint192(proposalId)),
+                            keccak256(bytes(reason)),
+                            keccak256(params)
+                        )
+                    )
+                ),
+                signature
+            )
+        ) {
+            _useNonce(voter, uint192(proposalId));
+            return true;
+        } else {
+            return super._validateExtendedVoteSig(proposalId, support, voter, reason, params, signature);
+        }
+    }
+}

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

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.2.0) (governance/extensions/GovernorPreventLateQuorum.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (governance/extensions/GovernorPreventLateQuorum.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity ^0.8.24;
 
 import {Governor} from "../Governor.sol";
 import {Math} from "../../utils/math/Math.sol";

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

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.3.0) (governance/extensions/GovernorProposalGuardian.sol)
-pragma solidity ^0.8.20;
+// OpenZeppelin Contracts (last updated v5.4.0) (governance/extensions/GovernorProposalGuardian.sol)
+pragma solidity ^0.8.24;
 
 import {Governor} from "../Governor.sol";
 

+ 4 - 6
contracts/governance/extensions/GovernorSequentialProposalId.sol

@@ -1,9 +1,9 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.3.0) (governance/extensions/GovernorSequentialProposalId.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (governance/extensions/GovernorSequentialProposalId.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity ^0.8.24;
 
-import {Governor} from "../Governor.sol";
+import {IGovernor, Governor} from "../Governor.sol";
 
 /**
  * @dev Extension of {Governor} that changes the numbering of proposal ids from the default hash-based approach to
@@ -19,9 +19,7 @@ abstract contract GovernorSequentialProposalId is Governor {
      */
     error GovernorAlreadyInitializedLatestProposalId();
 
-    /**
-     * @dev See {IGovernor-getProposalId}.
-     */
+    /// @inheritdoc IGovernor
     function getProposalId(
         address[] memory targets,
         uint256[] memory values,

+ 6 - 12
contracts/governance/extensions/GovernorSettings.sol

@@ -1,9 +1,9 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.0.0) (governance/extensions/GovernorSettings.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (governance/extensions/GovernorSettings.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity ^0.8.24;
 
-import {Governor} from "../Governor.sol";
+import {IGovernor, Governor} from "../Governor.sol";
 
 /**
  * @dev Extension of {Governor} for settings updatable through governance.
@@ -29,23 +29,17 @@ abstract contract GovernorSettings is Governor {
         _setProposalThreshold(initialProposalThreshold);
     }
 
-    /**
-     * @dev See {IGovernor-votingDelay}.
-     */
+    /// @inheritdoc IGovernor
     function votingDelay() public view virtual override returns (uint256) {
         return _votingDelay;
     }
 
-    /**
-     * @dev See {IGovernor-votingPeriod}.
-     */
+    /// @inheritdoc IGovernor
     function votingPeriod() public view virtual override returns (uint256) {
         return _votingPeriod;
     }
 
-    /**
-     * @dev See {Governor-proposalThreshold}.
-     */
+    /// @inheritdoc Governor
     function proposalThreshold() public view virtual override returns (uint256) {
         return _proposalThreshold;
     }

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

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.3.0) (governance/extensions/GovernorStorage.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (governance/extensions/GovernorStorage.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity ^0.8.24;
 
 import {Governor} from "../Governor.sol";
 

+ 2 - 4
contracts/governance/extensions/GovernorSuperQuorum.sol

@@ -1,10 +1,8 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.3.0) (governance/extensions/GovernorSuperQuorum.sol)
-pragma solidity ^0.8.20;
+// OpenZeppelin Contracts (last updated v5.4.0) (governance/extensions/GovernorSuperQuorum.sol)
+pragma solidity ^0.8.24;
 
 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

+ 9 - 12
contracts/governance/extensions/GovernorTimelockAccess.sol

@@ -1,9 +1,9 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.3.0) (governance/extensions/GovernorTimelockAccess.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (governance/extensions/GovernorTimelockAccess.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity ^0.8.24;
 
-import {Governor} from "../Governor.sol";
+import {IGovernor, Governor} from "../Governor.sol";
 import {AuthorityUtils} from "../../access/manager/AuthorityUtils.sol";
 import {IAccessManager} from "../../access/manager/IAccessManager.sol";
 import {Address} from "../../utils/Address.sol";
@@ -171,16 +171,12 @@ abstract contract GovernorTimelockAccess is Governor {
         return (delay, indirect, withDelay);
     }
 
-    /**
-     * @dev See {IGovernor-proposalNeedsQueuing}.
-     */
+    /// @inheritdoc IGovernor
     function proposalNeedsQueuing(uint256 proposalId) public view virtual override returns (bool) {
         return _executionPlan[proposalId].delay > 0;
     }
 
-    /**
-     * @dev See {IGovernor-propose}
-     */
+    /// @inheritdoc IGovernor
     function propose(
         address[] memory targets,
         uint256[] memory values,
@@ -237,6 +233,9 @@ abstract contract GovernorTimelockAccess is Governor {
         for (uint256 i = 0; i < targets.length; ++i) {
             (, bool withDelay, ) = _getManagerData(plan, i);
             if (withDelay) {
+                // This function can reenter when calling `_manager.schedule` before performing state updates in `_setManagerData`.
+                // However, the `manager` is a trusted contract in the current context's security model (e.g. an `AccessManager`).
+                // slither-disable-next-line reentrancy-no-eth
                 (, uint32 nonce) = _manager.schedule(targets[i], calldatas[i], etaSeconds);
                 _setManagerData(plan, i, true, nonce);
             }
@@ -276,9 +275,7 @@ abstract contract GovernorTimelockAccess is Governor {
         }
     }
 
-    /**
-     * @dev See {Governor-_cancel}
-     */
+    /// @inheritdoc Governor
     function _cancel(
         address[] memory targets,
         uint256[] memory values,

+ 3 - 5
contracts/governance/extensions/GovernorTimelockCompound.sol

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.3.0) (governance/extensions/GovernorTimelockCompound.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (governance/extensions/GovernorTimelockCompound.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity ^0.8.24;
 
 import {IGovernor, Governor} from "../Governor.sol";
 import {ICompoundTimelock} from "../../vendor/compound/ICompoundTimelock.sol";
@@ -53,9 +53,7 @@ abstract contract GovernorTimelockCompound is Governor {
         return address(_timelock);
     }
 
-    /**
-     * @dev See {IGovernor-proposalNeedsQueuing}.
-     */
+    /// @inheritdoc IGovernor
     function proposalNeedsQueuing(uint256) public view virtual override returns (bool) {
         return true;
     }

+ 3 - 6
contracts/governance/extensions/GovernorTimelockControl.sol

@@ -1,11 +1,10 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.3.0) (governance/extensions/GovernorTimelockControl.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (governance/extensions/GovernorTimelockControl.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity ^0.8.24;
 
 import {IGovernor, Governor} from "../Governor.sol";
 import {TimelockController} from "../TimelockController.sol";
-import {IERC165} from "../../interfaces/IERC165.sol";
 import {SafeCast} from "../../utils/math/SafeCast.sol";
 
 /**
@@ -67,9 +66,7 @@ abstract contract GovernorTimelockControl is Governor {
         return address(_timelock);
     }
 
-    /**
-     * @dev See {IGovernor-proposalNeedsQueuing}.
-     */
+    /// @inheritdoc IGovernor
     function proposalNeedsQueuing(uint256) public view virtual override returns (bool) {
         return true;
     }

+ 2 - 3
contracts/governance/extensions/GovernorVotes.sol

@@ -1,12 +1,11 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (governance/extensions/GovernorVotes.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (governance/extensions/GovernorVotes.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity ^0.8.24;
 
 import {Governor} from "../Governor.sol";
 import {IVotes} from "../utils/IVotes.sol";
 import {IERC5805} from "../../interfaces/IERC5805.sol";
-import {SafeCast} from "../../utils/math/SafeCast.sol";
 import {Time} from "../../utils/types/Time.sol";
 
 /**

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

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.3.0) (governance/extensions/GovernorVotesQuorumFraction.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (governance/extensions/GovernorVotesQuorumFraction.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity ^0.8.24;
 
 import {GovernorVotes} from "./GovernorVotes.sol";
 import {Math} from "../../utils/math/Math.sol";

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

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.3.0) (governance/extensions/GovernorVotesSuperQuorumFraction.sol)
-pragma solidity ^0.8.20;
+// OpenZeppelin Contracts (last updated v5.4.0) (governance/extensions/GovernorVotesSuperQuorumFraction.sol)
+pragma solidity ^0.8.24;
 
 import {Governor} from "../Governor.sol";
 import {GovernorSuperQuorum} from "./GovernorSuperQuorum.sol";

+ 2 - 2
contracts/governance/utils/IVotes.sol

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.0.0) (governance/utils/IVotes.sol)
-pragma solidity ^0.8.20;
+// OpenZeppelin Contracts (last updated v5.4.0) (governance/utils/IVotes.sol)
+pragma solidity >=0.8.4;
 
 /**
  * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.

+ 2 - 2
contracts/interfaces/IERC1155.sol

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC1155.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC1155.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity >=0.6.2;
 
 import {IERC1155} from "../token/ERC1155/IERC1155.sol";

+ 2 - 2
contracts/interfaces/IERC1155MetadataURI.sol

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC1155MetadataURI.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC1155MetadataURI.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity >=0.6.2;
 
 import {IERC1155MetadataURI} from "../token/ERC1155/extensions/IERC1155MetadataURI.sol";

+ 2 - 2
contracts/interfaces/IERC1155Receiver.sol

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC1155Receiver.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC1155Receiver.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity >=0.6.2;
 
 import {IERC1155Receiver} from "../token/ERC1155/IERC1155Receiver.sol";

+ 3 - 3
contracts/interfaces/IERC1271.sol

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.3.0) (interfaces/IERC1271.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC1271.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity >=0.5.0;
 
 /**
  * @dev Interface of the ERC-1271 standard signature validation method for
@@ -13,5 +13,5 @@ interface IERC1271 {
      * @param hash      Hash of the data to be signed
      * @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 calldata signature) external view returns (bytes4 magicValue);
 }

+ 2 - 2
contracts/interfaces/IERC1363.sol

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC1363.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity >=0.6.2;
 
 import {IERC20} from "./IERC20.sol";
 import {IERC165} from "./IERC165.sol";

+ 2 - 2
contracts/interfaces/IERC1363Receiver.sol

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363Receiver.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC1363Receiver.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity >=0.5.0;
 
 /**
  * @title IERC1363Receiver

+ 2 - 2
contracts/interfaces/IERC1363Spender.sol

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363Spender.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC1363Spender.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity >=0.5.0;
 
 /**
  * @title IERC1363Spender

+ 2 - 2
contracts/interfaces/IERC165.sol

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC165.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity >=0.4.16;
 
 import {IERC165} from "../utils/introspection/IERC165.sol";

+ 2 - 2
contracts/interfaces/IERC1820Implementer.sol

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1820Implementer.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC1820Implementer.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity >=0.4.16;
 
 /**
  * @dev Interface for an ERC-1820 implementer, as defined in the

+ 2 - 2
contracts/interfaces/IERC1820Registry.sol

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1820Registry.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC1820Registry.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity >=0.5.0;
 
 /**
  * @dev Interface of the global ERC-1820 Registry, as defined in the

+ 2 - 2
contracts/interfaces/IERC1967.sol

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC1967.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC1967.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity >=0.4.11;
 
 /**
  * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.

+ 2 - 2
contracts/interfaces/IERC20.sol

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC20.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity >=0.4.16;
 
 import {IERC20} from "../token/ERC20/IERC20.sol";

+ 2 - 2
contracts/interfaces/IERC20Metadata.sol

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20Metadata.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC20Metadata.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity >=0.6.2;
 
 import {IERC20Metadata} from "../token/ERC20/extensions/IERC20Metadata.sol";

+ 2 - 2
contracts/interfaces/IERC2309.sol

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC2309.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC2309.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity >=0.4.11;
 
 /**
  * @dev ERC-2309: ERC-721 Consecutive Transfer Extension.

+ 2 - 2
contracts/interfaces/IERC2612.sol

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC2612.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC2612.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity >=0.6.2;
 
 import {IERC20Permit} from "../token/ERC20/extensions/IERC20Permit.sol";
 

+ 2 - 2
contracts/interfaces/IERC2981.sol

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC2981.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC2981.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity >=0.6.2;
 
 import {IERC165} from "../utils/introspection/IERC165.sol";
 

+ 2 - 2
contracts/interfaces/IERC3156.sol

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC3156.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC3156.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity >=0.5.0;
 
 import {IERC3156FlashBorrower} from "./IERC3156FlashBorrower.sol";
 import {IERC3156FlashLender} from "./IERC3156FlashLender.sol";

+ 2 - 2
contracts/interfaces/IERC3156FlashBorrower.sol

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC3156FlashBorrower.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC3156FlashBorrower.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity >=0.5.0;
 
 /**
  * @dev Interface of the ERC-3156 FlashBorrower, as defined in

+ 2 - 2
contracts/interfaces/IERC3156FlashLender.sol

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC3156FlashLender.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC3156FlashLender.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity >=0.5.0;
 
 import {IERC3156FlashBorrower} from "./IERC3156FlashBorrower.sol";
 

+ 2 - 2
contracts/interfaces/IERC4626.sol

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.3.0) (interfaces/IERC4626.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC4626.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity >=0.6.2;
 
 import {IERC20} from "../token/ERC20/IERC20.sol";
 import {IERC20Metadata} from "../token/ERC20/extensions/IERC20Metadata.sol";

+ 2 - 2
contracts/interfaces/IERC4906.sol

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC4906.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC4906.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity >=0.6.2;
 
 import {IERC165} from "./IERC165.sol";
 import {IERC721} from "./IERC721.sol";

+ 2 - 2
contracts/interfaces/IERC5267.sol

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC5267.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC5267.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity >=0.4.16;
 
 interface IERC5267 {
     /**

+ 2 - 2
contracts/interfaces/IERC5313.sol

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC5313.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC5313.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity >=0.4.16;
 
 /**
  * @dev Interface for the Light Contract Ownership Standard.

+ 2 - 2
contracts/interfaces/IERC5805.sol

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC5805.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC5805.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity >=0.8.4;
 
 import {IVotes} from "../governance/utils/IVotes.sol";
 import {IERC6372} from "./IERC6372.sol";

+ 2 - 2
contracts/interfaces/IERC6372.sol

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC6372.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC6372.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity >=0.4.16;
 
 interface IERC6372 {
     /**

+ 2 - 2
contracts/interfaces/IERC721.sol

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC721.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC721.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity >=0.6.2;
 
 import {IERC721} from "../token/ERC721/IERC721.sol";

+ 2 - 2
contracts/interfaces/IERC721Enumerable.sol

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC721Enumerable.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC721Enumerable.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity >=0.6.2;
 
 import {IERC721Enumerable} from "../token/ERC721/extensions/IERC721Enumerable.sol";

+ 2 - 2
contracts/interfaces/IERC721Metadata.sol

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC721Metadata.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC721Metadata.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity >=0.6.2;
 
 import {IERC721Metadata} from "../token/ERC721/extensions/IERC721Metadata.sol";

+ 2 - 2
contracts/interfaces/IERC721Receiver.sol

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC721Receiver.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC721Receiver.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity >=0.5.0;
 
 import {IERC721Receiver} from "../token/ERC721/IERC721Receiver.sol";

+ 2 - 2
contracts/interfaces/IERC777.sol

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC777.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC777.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity >=0.5.0;
 
 /**
  * @dev Interface of the ERC-777 Token standard as defined in the ERC.

+ 2 - 2
contracts/interfaces/IERC777Recipient.sol

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC777Recipient.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC777Recipient.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity >=0.5.0;
 
 /**
  * @dev Interface of the ERC-777 Tokens Recipient standard as defined in the ERC.

+ 2 - 2
contracts/interfaces/IERC777Sender.sol

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC777Sender.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC777Sender.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity >=0.5.0;
 
 /**
  * @dev Interface of the ERC-777 Tokens Sender standard as defined in the ERC.

+ 18 - 0
contracts/interfaces/IERC7913.sol

@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC7913.sol)
+
+pragma solidity >=0.5.0;
+
+/**
+ * @dev Signature verifier interface.
+ */
+interface IERC7913SignatureVerifier {
+    /**
+     * @dev Verifies `signature` as a valid signature of `hash` by `key`.
+     *
+     * MUST return the bytes4 magic value IERC7913SignatureVerifier.verify.selector if the signature is valid.
+     * SHOULD return 0xffffffff or revert if the signature is not valid.
+     * SHOULD return 0xffffffff or revert if the key is empty
+     */
+    function verify(bytes calldata key, bytes32 hash, bytes calldata signature) external view returns (bytes4);
+}

+ 3 - 0
contracts/interfaces/README.adoc

@@ -45,6 +45,7 @@ are useful to interact with third party contracts that implement them.
 - {IERC6909Metadata}
 - {IERC6909TokenSupply}
 - {IERC7674}
+- {IERC7802}
 
 == Detailed ABI
 
@@ -97,3 +98,5 @@ are useful to interact with third party contracts that implement them.
 {{IERC6909TokenSupply}}
 
 {{IERC7674}}
+
+{{IERC7802}}

+ 2 - 2
contracts/interfaces/draft-IERC1822.sol

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC1822.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/draft-IERC1822.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity >=0.4.16;
 
 /**
  * @dev ERC-1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified

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

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.3.0) (interfaces/draft-IERC4337.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/draft-IERC4337.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity >=0.8.4;
 
 /**
  * @dev A https://github.com/ethereum/ercs/blob/master/ERCS/erc-4337.md#useroperation[user operation] is composed of the following elements:

+ 2 - 2
contracts/interfaces/draft-IERC6093.sol

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC6093.sol)
-pragma solidity ^0.8.20;
+// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/draft-IERC6093.sol)
+pragma solidity >=0.8.4;
 
 /**
  * @dev Standard ERC-20 Errors

+ 2 - 2
contracts/interfaces/draft-IERC6909.sol

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.3.0) (interfaces/draft-IERC6909.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/draft-IERC6909.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity >=0.6.2;
 
 import {IERC165} from "../utils/introspection/IERC165.sol";
 

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

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.3.0) (interfaces/draft-IERC7579.sol)
-pragma solidity ^0.8.20;
+// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/draft-IERC7579.sol)
+pragma solidity >=0.8.4;
 
 import {PackedUserOperation} from "./draft-IERC4337.sol";
 

+ 2 - 2
contracts/interfaces/draft-IERC7674.sol

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC7674.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/draft-IERC7674.sol)
 
-pragma solidity ^0.8.20;
+pragma solidity >=0.6.2;
 
 import {IERC20} from "./IERC20.sol";
 

+ 31 - 0
contracts/interfaces/draft-IERC7802.sol

@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/draft-IERC7802.sol)
+pragma solidity >=0.6.2;
+
+import {IERC165} from "./IERC165.sol";
+
+/// @title IERC7802
+/// @notice Defines the interface for crosschain ERC20 transfers.
+interface IERC7802 is IERC165 {
+    /// @notice Emitted when a crosschain transfer mints tokens.
+    /// @param to       Address of the account tokens are being minted for.
+    /// @param amount   Amount of tokens minted.
+    /// @param sender   Address of the caller (msg.sender) who invoked crosschainMint.
+    event CrosschainMint(address indexed to, uint256 amount, address indexed sender);
+
+    /// @notice Emitted when a crosschain transfer burns tokens.
+    /// @param from     Address of the account tokens are being burned from.
+    /// @param amount   Amount of tokens burned.
+    /// @param sender   Address of the caller (msg.sender) who invoked crosschainBurn.
+    event CrosschainBurn(address indexed from, uint256 amount, address indexed sender);
+
+    /// @notice Mint tokens through a crosschain transfer.
+    /// @param _to     Address to mint tokens to.
+    /// @param _amount Amount of tokens to mint.
+    function crosschainMint(address _to, uint256 _amount) external;
+
+    /// @notice Burn tokens through a crosschain transfer.
+    /// @param _from   Address to burn tokens from.
+    /// @param _amount Amount of tokens to burn.
+    function crosschainBurn(address _from, uint256 _amount) external;
+}

+ 44 - 0
contracts/interfaces/draft-IERC7821.sol

@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: MIT
+// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/draft-IERC7821.sol)
+
+pragma solidity >=0.5.0;
+
+/**
+ * @dev Interface for minimal batch executor.
+ */
+interface IERC7821 {
+    /**
+     * @dev Executes the calls in `executionData`.
+     * Reverts and bubbles up error if any call fails.
+     *
+     * `executionData` encoding:
+     * - If `opData` is empty, `executionData` is simply `abi.encode(calls)`.
+     * - Else, `executionData` is `abi.encode(calls, opData)`.
+     *   See: https://eips.ethereum.org/EIPS/eip-7579
+     *
+     * Supported modes:
+     * - `bytes32(0x01000000000000000000...)`: does not support optional `opData`.
+     * - `bytes32(0x01000000000078210001...)`: supports optional `opData`.
+     *
+     * Authorization checks:
+     * - If `opData` is empty, the implementation SHOULD require that
+     *   `msg.sender == address(this)`.
+     * - If `opData` is not empty, the implementation SHOULD use the signature
+     *   encoded in `opData` to determine if the caller can perform the execution.
+     *
+     * `opData` may be used to store additional data for authentication,
+     * paymaster data, gas limits, etc.
+     *
+     * For calldata compression efficiency, if a Call.to is `address(0)`,
+     * it will be replaced with `address(this)`.
+     */
+    function execute(bytes32 mode, bytes calldata executionData) external payable;
+
+    /**
+     * @dev This function is provided for frontends to detect support.
+     * Only returns true for:
+     * - `bytes32(0x01000000000000000000...)`: does not support optional `opData`.
+     * - `bytes32(0x01000000000078210001...)`: supports optional `opData`.
+     */
+    function supportsExecutionMode(bytes32 mode) external view returns (bool);
+}

+ 9 - 5
contracts/metatx/ERC2771Context.sol

@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: MIT
-// OpenZeppelin Contracts (last updated v5.1.0) (metatx/ERC2771Context.sol)
+// OpenZeppelin Contracts (last updated v5.4.0) (metatx/ERC2771Context.sol)
 
 pragma solidity ^0.8.20;
 
@@ -55,8 +55,10 @@ abstract contract ERC2771Context is Context {
     function _msgSender() internal view virtual override returns (address) {
         uint256 calldataLength = msg.data.length;
         uint256 contextSuffixLength = _contextSuffixLength();
-        if (isTrustedForwarder(msg.sender) && calldataLength >= contextSuffixLength) {
-            return address(bytes20(msg.data[calldataLength - contextSuffixLength:]));
+        if (calldataLength >= contextSuffixLength && isTrustedForwarder(msg.sender)) {
+            unchecked {
+                return address(bytes20(msg.data[calldataLength - contextSuffixLength:]));
+            }
         } else {
             return super._msgSender();
         }
@@ -70,8 +72,10 @@ abstract contract ERC2771Context is Context {
     function _msgData() internal view virtual override returns (bytes calldata) {
         uint256 calldataLength = msg.data.length;
         uint256 contextSuffixLength = _contextSuffixLength();
-        if (isTrustedForwarder(msg.sender) && calldataLength >= contextSuffixLength) {
-            return msg.data[:calldataLength - contextSuffixLength];
+        if (calldataLength >= contextSuffixLength && isTrustedForwarder(msg.sender)) {
+            unchecked {
+                return msg.data[:calldataLength - contextSuffixLength];
+            }
         } else {
             return super._msgData();
         }

+ 0 - 1
contracts/mocks/AccessManagerMock.sol

@@ -3,7 +3,6 @@
 pragma solidity ^0.8.20;
 
 import {AccessManager} from "../access/manager/AccessManager.sol";
-import {StorageSlot} from "../utils/StorageSlot.sol";
 
 contract AccessManagerMock is AccessManager {
     event CalledRestricted(address caller);

+ 44 - 0
contracts/mocks/ArraysMock.sol

@@ -125,3 +125,47 @@ contract Bytes32ArraysMock {
         return _array.length;
     }
 }
+
+contract BytesArraysMock {
+    using Arrays for bytes[];
+
+    bytes[] private _array;
+
+    constructor(bytes[] memory array) {
+        _array = array;
+    }
+
+    function unsafeAccess(uint256 pos) external view returns (bytes memory) {
+        return _array.unsafeAccess(pos).value;
+    }
+
+    function unsafeSetLength(uint256 newLength) external {
+        _array.unsafeSetLength(newLength);
+    }
+
+    function length() external view returns (uint256) {
+        return _array.length;
+    }
+}
+
+contract StringArraysMock {
+    using Arrays for string[];
+
+    string[] private _array;
+
+    constructor(string[] memory array) {
+        _array = array;
+    }
+
+    function unsafeAccess(uint256 pos) external view returns (string memory) {
+        return _array.unsafeAccess(pos).value;
+    }
+
+    function unsafeSetLength(uint256 newLength) external {
+        _array.unsafeSetLength(newLength);
+    }
+
+    function length() external view returns (uint256) {
+        return _array.length;
+    }
+}

+ 5 - 0
contracts/mocks/CallReceiverMock.sol

@@ -5,6 +5,7 @@ pragma solidity ^0.8.20;
 contract CallReceiverMock {
     event MockFunctionCalled();
     event MockFunctionCalledWithArgs(uint256 a, uint256 b);
+    event MockFunctionCalledExtra(address caller, uint256 value);
 
     uint256[] private _array;
 
@@ -58,6 +59,10 @@ contract CallReceiverMock {
         }
         return "0x1234";
     }
+
+    function mockFunctionExtra() public payable {
+        emit MockFunctionCalledExtra(msg.sender, msg.value);
+    }
 }
 
 contract CallReceiverMockTrustingForwarder is CallReceiverMock {

+ 7 - 3
contracts/mocks/Stateless.sol

@@ -9,6 +9,7 @@ import {Arrays} from "../utils/Arrays.sol";
 import {AuthorityUtils} from "../access/manager/AuthorityUtils.sol";
 import {Base64} from "../utils/Base64.sol";
 import {BitMaps} from "../utils/structs/BitMaps.sol";
+import {Blockhash} from "../utils/Blockhash.sol";
 import {Bytes} from "../utils/Bytes.sol";
 import {CAIP2} from "../utils/CAIP2.sol";
 import {CAIP10} from "../utils/CAIP10.sol";
@@ -18,15 +19,18 @@ import {Clones} from "../proxy/Clones.sol";
 import {Create2} from "../utils/Create2.sol";
 import {DoubleEndedQueue} from "../utils/structs/DoubleEndedQueue.sol";
 import {ECDSA} from "../utils/cryptography/ECDSA.sol";
+import {EIP7702Utils} from "../account/utils/EIP7702Utils.sol";
 import {EnumerableMap} from "../utils/structs/EnumerableMap.sol";
 import {EnumerableSet} from "../utils/structs/EnumerableSet.sol";
-import {ERC1155Holder} from "../token/ERC1155/utils/ERC1155Holder.sol";
 import {ERC165} from "../utils/introspection/ERC165.sol";
 import {ERC165Checker} from "../utils/introspection/ERC165Checker.sol";
-import {ERC1967Utils} from "../proxy/ERC1967/ERC1967Utils.sol";
 import {ERC721Holder} from "../token/ERC721/utils/ERC721Holder.sol";
+import {ERC1155Holder} from "../token/ERC1155/utils/ERC1155Holder.sol";
+import {ERC1967Utils} from "../proxy/ERC1967/ERC1967Utils.sol";
 import {ERC4337Utils} from "../account/utils/draft-ERC4337Utils.sol";
 import {ERC7579Utils} from "../account/utils/draft-ERC7579Utils.sol";
+import {ERC7913P256Verifier} from "../utils/cryptography/verifiers/ERC7913P256Verifier.sol";
+import {ERC7913RSAVerifier} from "../utils/cryptography/verifiers/ERC7913RSAVerifier.sol";
 import {Heap} from "../utils/structs/Heap.sol";
 import {Math} from "../utils/math/Math.sol";
 import {MerkleProof} from "../utils/cryptography/MerkleProof.sol";
@@ -34,8 +38,8 @@ import {MessageHashUtils} from "../utils/cryptography/MessageHashUtils.sol";
 import {Nonces} from "../utils/Nonces.sol";
 import {NoncesKeyed} from "../utils/NoncesKeyed.sol";
 import {P256} from "../utils/cryptography/P256.sol";
-import {Panic} from "../utils/Panic.sol";
 import {Packing} from "../utils/Packing.sol";
+import {Panic} from "../utils/Panic.sol";
 import {RSA} from "../utils/cryptography/RSA.sol";
 import {SafeCast} from "../utils/math/SafeCast.sol";
 import {SafeERC20} from "../token/ERC20/utils/SafeERC20.sol";

+ 169 - 0
contracts/mocks/account/AccountMock.sol

@@ -0,0 +1,169 @@
+// SPDX-License-Identifier: MIT
+
+pragma solidity ^0.8.27;
+
+import {Account} from "../../account/Account.sol";
+import {AccountERC7579} from "../../account/extensions/draft-AccountERC7579.sol";
+import {AccountERC7579Hooked} from "../../account/extensions/draft-AccountERC7579Hooked.sol";
+import {ERC721Holder} from "../../token/ERC721/utils/ERC721Holder.sol";
+import {ERC1155Holder} from "../../token/ERC1155/utils/ERC1155Holder.sol";
+import {ERC4337Utils} from "../../account/utils/draft-ERC4337Utils.sol";
+import {ERC7739} from "../../utils/cryptography/signers/draft-ERC7739.sol";
+import {ERC7821} from "../../account/extensions/draft-ERC7821.sol";
+import {MODULE_TYPE_VALIDATOR} from "../../interfaces/draft-IERC7579.sol";
+import {PackedUserOperation} from "../../interfaces/draft-IERC4337.sol";
+import {AbstractSigner} from "../../utils/cryptography/signers/AbstractSigner.sol";
+import {SignerECDSA} from "../../utils/cryptography/signers/SignerECDSA.sol";
+import {SignerP256} from "../../utils/cryptography/signers/SignerP256.sol";
+import {SignerRSA} from "../../utils/cryptography/signers/SignerRSA.sol";
+import {SignerERC7702} from "../../utils/cryptography/signers/SignerERC7702.sol";
+import {SignerERC7913} from "../../utils/cryptography/signers/SignerERC7913.sol";
+import {MultiSignerERC7913} from "../../utils/cryptography/signers/MultiSignerERC7913.sol";
+import {MultiSignerERC7913Weighted} from "../../utils/cryptography/signers/MultiSignerERC7913Weighted.sol";
+
+abstract contract AccountMock is Account, ERC7739, ERC7821, ERC721Holder, ERC1155Holder {
+    /// Validates a user operation with a boolean signature.
+    function _rawSignatureValidation(bytes32 hash, bytes calldata signature) internal pure override returns (bool) {
+        return signature.length >= 32 && bytes32(signature) == hash;
+    }
+
+    /// @inheritdoc ERC7821
+    function _erc7821AuthorizedExecutor(
+        address caller,
+        bytes32 mode,
+        bytes calldata executionData
+    ) internal view virtual override returns (bool) {
+        return caller == address(entryPoint()) || super._erc7821AuthorizedExecutor(caller, mode, executionData);
+    }
+}
+
+abstract contract AccountECDSAMock is Account, SignerECDSA, ERC7739, ERC7821, ERC721Holder, ERC1155Holder {
+    /// @inheritdoc ERC7821
+    function _erc7821AuthorizedExecutor(
+        address caller,
+        bytes32 mode,
+        bytes calldata executionData
+    ) internal view virtual override returns (bool) {
+        return caller == address(entryPoint()) || super._erc7821AuthorizedExecutor(caller, mode, executionData);
+    }
+}
+
+abstract contract AccountP256Mock is Account, SignerP256, ERC7739, ERC7821, ERC721Holder, ERC1155Holder {
+    /// @inheritdoc ERC7821
+    function _erc7821AuthorizedExecutor(
+        address caller,
+        bytes32 mode,
+        bytes calldata executionData
+    ) internal view virtual override returns (bool) {
+        return caller == address(entryPoint()) || super._erc7821AuthorizedExecutor(caller, mode, executionData);
+    }
+}
+
+abstract contract AccountRSAMock is Account, SignerRSA, ERC7739, ERC7821, ERC721Holder, ERC1155Holder {
+    /// @inheritdoc ERC7821
+    function _erc7821AuthorizedExecutor(
+        address caller,
+        bytes32 mode,
+        bytes calldata executionData
+    ) internal view virtual override returns (bool) {
+        return caller == address(entryPoint()) || super._erc7821AuthorizedExecutor(caller, mode, executionData);
+    }
+}
+
+abstract contract AccountERC7702Mock is Account, SignerERC7702, ERC7739, ERC7821, ERC721Holder, ERC1155Holder {
+    /// @inheritdoc ERC7821
+    function _erc7821AuthorizedExecutor(
+        address caller,
+        bytes32 mode,
+        bytes calldata executionData
+    ) internal view virtual override returns (bool) {
+        return caller == address(entryPoint()) || super._erc7821AuthorizedExecutor(caller, mode, executionData);
+    }
+}
+
+abstract contract AccountERC7702WithModulesMock is
+    Account,
+    AccountERC7579,
+    SignerERC7702,
+    ERC7739,
+    ERC721Holder,
+    ERC1155Holder
+{
+    function _validateUserOp(
+        PackedUserOperation calldata userOp,
+        bytes32 userOpHash
+    ) internal virtual override(Account, AccountERC7579) returns (uint256) {
+        return super._validateUserOp(userOp, userOpHash);
+    }
+
+    /// @dev Resolve implementation of ERC-1271 by both ERC7739 and AccountERC7579 to support both schemes.
+    function isValidSignature(
+        bytes32 hash,
+        bytes calldata signature
+    ) public view virtual override(ERC7739, AccountERC7579) returns (bytes4) {
+        // ERC-7739 can return the fn selector (success), 0xffffffff (invalid) or 0x77390001 (detection).
+        // If the return is 0xffffffff, we fallback to validation using ERC-7579 modules.
+        bytes4 erc7739magic = ERC7739.isValidSignature(hash, signature);
+        return erc7739magic == bytes4(0xffffffff) ? AccountERC7579.isValidSignature(hash, signature) : erc7739magic;
+    }
+
+    /// @dev Enable signature using the ERC-7702 signer.
+    function _rawSignatureValidation(
+        bytes32 hash,
+        bytes calldata signature
+    ) internal view virtual override(AbstractSigner, AccountERC7579, SignerERC7702) returns (bool) {
+        return SignerERC7702._rawSignatureValidation(hash, signature);
+    }
+}
+
+abstract contract AccountERC7579Mock is AccountERC7579 {
+    constructor(address validator, bytes memory initData) {
+        _installModule(MODULE_TYPE_VALIDATOR, validator, initData);
+    }
+}
+
+abstract contract AccountERC7579HookedMock is AccountERC7579Hooked {
+    constructor(address validator, bytes memory initData) {
+        _installModule(MODULE_TYPE_VALIDATOR, validator, initData);
+    }
+}
+
+abstract contract AccountERC7913Mock is Account, SignerERC7913, ERC7739, ERC7821, ERC721Holder, ERC1155Holder {
+    /// @inheritdoc ERC7821
+    function _erc7821AuthorizedExecutor(
+        address caller,
+        bytes32 mode,
+        bytes calldata executionData
+    ) internal view virtual override returns (bool) {
+        return caller == address(entryPoint()) || super._erc7821AuthorizedExecutor(caller, mode, executionData);
+    }
+}
+
+abstract contract AccountMultiSignerMock is Account, MultiSignerERC7913, ERC7739, ERC7821, ERC721Holder, ERC1155Holder {
+    /// @inheritdoc ERC7821
+    function _erc7821AuthorizedExecutor(
+        address caller,
+        bytes32 mode,
+        bytes calldata executionData
+    ) internal view virtual override returns (bool) {
+        return caller == address(entryPoint()) || super._erc7821AuthorizedExecutor(caller, mode, executionData);
+    }
+}
+
+abstract contract AccountMultiSignerWeightedMock is
+    Account,
+    MultiSignerERC7913Weighted,
+    ERC7739,
+    ERC7821,
+    ERC721Holder,
+    ERC1155Holder
+{
+    /// @inheritdoc ERC7821
+    function _erc7821AuthorizedExecutor(
+        address caller,
+        bytes32 mode,
+        bytes calldata executionData
+    ) internal view virtual override returns (bool) {
+        return caller == address(entryPoint()) || super._erc7821AuthorizedExecutor(caller, mode, executionData);
+    }
+}

+ 115 - 0
contracts/mocks/account/modules/ERC7579Mock.sol

@@ -0,0 +1,115 @@
+// SPDX-License-Identifier: MIT
+
+pragma solidity ^0.8.24;
+
+import {MODULE_TYPE_HOOK, MODULE_TYPE_FALLBACK, MODULE_TYPE_VALIDATOR, IERC7579Hook, IERC7579Module, IERC7579Validator} from "../../../interfaces/draft-IERC7579.sol";
+import {SignatureChecker} from "../../../utils/cryptography/SignatureChecker.sol";
+import {PackedUserOperation} from "../../../interfaces/draft-IERC4337.sol";
+import {IERC1271} from "../../../interfaces/IERC1271.sol";
+import {ERC4337Utils} from "../../../account/utils/draft-ERC4337Utils.sol";
+
+abstract contract ERC7579ModuleMock is IERC7579Module {
+    uint256 private _moduleTypeId;
+
+    event ModuleInstalledReceived(address account, bytes data);
+    event ModuleUninstalledReceived(address account, bytes data);
+
+    constructor(uint256 moduleTypeId) {
+        _moduleTypeId = moduleTypeId;
+    }
+
+    function onInstall(bytes calldata data) public virtual {
+        emit ModuleInstalledReceived(msg.sender, data);
+    }
+
+    function onUninstall(bytes calldata data) public virtual {
+        emit ModuleUninstalledReceived(msg.sender, data);
+    }
+
+    function isModuleType(uint256 moduleTypeId) external view returns (bool) {
+        return moduleTypeId == _moduleTypeId;
+    }
+}
+
+abstract contract ERC7579HookMock is ERC7579ModuleMock(MODULE_TYPE_HOOK), IERC7579Hook {
+    event PreCheck(address sender, uint256 value, bytes data);
+    event PostCheck(bytes hookData);
+
+    function preCheck(
+        address msgSender,
+        uint256 value,
+        bytes calldata msgData
+    ) external returns (bytes memory hookData) {
+        emit PreCheck(msgSender, value, msgData);
+        return msgData;
+    }
+
+    function postCheck(bytes calldata hookData) external {
+        emit PostCheck(hookData);
+    }
+}
+
+abstract contract ERC7579FallbackHandlerMock is ERC7579ModuleMock(MODULE_TYPE_FALLBACK) {
+    event ERC7579FallbackHandlerMockCalled(address account, address sender, uint256 value, bytes data);
+
+    error ERC7579FallbackHandlerMockRevert();
+
+    function _msgAccount() internal view returns (address) {
+        return msg.sender;
+    }
+
+    function _msgSender() internal pure returns (address) {
+        return address(bytes20(msg.data[msg.data.length - 20:]));
+    }
+
+    function _msgData() internal pure returns (bytes calldata) {
+        return msg.data[:msg.data.length - 20];
+    }
+
+    function callPayable() public payable {
+        emit ERC7579FallbackHandlerMockCalled(_msgAccount(), _msgSender(), msg.value, _msgData());
+    }
+
+    function callView() public view returns (address, address) {
+        return (_msgAccount(), _msgSender());
+    }
+
+    function callRevert() public pure {
+        revert ERC7579FallbackHandlerMockRevert();
+    }
+}
+
+abstract contract ERC7579ValidatorMock is ERC7579ModuleMock(MODULE_TYPE_VALIDATOR), IERC7579Validator {
+    mapping(address sender => address signer) private _associatedSigners;
+
+    function onInstall(bytes calldata data) public virtual override(IERC7579Module, ERC7579ModuleMock) {
+        _associatedSigners[msg.sender] = address(bytes20(data[0:20]));
+        super.onInstall(data);
+    }
+
+    function onUninstall(bytes calldata data) public virtual override(IERC7579Module, ERC7579ModuleMock) {
+        delete _associatedSigners[msg.sender];
+        super.onUninstall(data);
+    }
+
+    function validateUserOp(
+        PackedUserOperation calldata userOp,
+        bytes32 userOpHash
+    ) public view virtual returns (uint256) {
+        return
+            SignatureChecker.isValidSignatureNow(_associatedSigners[msg.sender], userOpHash, userOp.signature)
+                ? ERC4337Utils.SIG_VALIDATION_SUCCESS
+                : ERC4337Utils.SIG_VALIDATION_FAILED;
+    }
+
+    function isValidSignatureWithSender(
+        address /*sender*/,
+        bytes32 hash,
+        bytes calldata signature
+    ) public view virtual returns (bytes4) {
+        return
+            SignatureChecker.isValidSignatureNow(_associatedSigners[msg.sender], hash, signature)
+                ? IERC1271.isValidSignature.selector
+                : bytes4(0xffffffff);
+    }
+}

+ 0 - 17
contracts/mocks/docs/access-control/AccessControlNonRevokableAdmin.sol

@@ -1,17 +0,0 @@
-// contracts/AccessControlNonRevokableAdmin.sol
-// SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
-
-import {AccessControl} from "../../../access/AccessControl.sol";
-
-contract AccessControlNonRevokableAdmin is AccessControl {
-    error AccessControlNonRevokable();
-
-    function revokeRole(bytes32 role, address account) public override {
-        if (role == DEFAULT_ADMIN_ROLE) {
-            revert AccessControlNonRevokable();
-        }
-
-        super.revokeRole(role, account);
-    }
-}

+ 20 - 0
contracts/mocks/docs/account/MyAccountERC7702.sol

@@ -0,0 +1,20 @@
+// contracts/MyAccountERC7702.sol
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.20;
+
+import {Account} from "../../../account/Account.sol";
+import {ERC721Holder} from "../../../token/ERC721/utils/ERC721Holder.sol";
+import {ERC1155Holder} from "../../../token/ERC1155/utils/ERC1155Holder.sol";
+import {ERC7821} from "../../../account/extensions/draft-ERC7821.sol";
+import {SignerERC7702} from "../../../utils/cryptography/signers/SignerERC7702.sol";
+
+contract MyAccountERC7702 is Account, SignerERC7702, ERC7821, ERC721Holder, ERC1155Holder {
+    /// @dev Allows the entry point as an authorized executor.
+    function _erc7821AuthorizedExecutor(
+        address caller,
+        bytes32 mode,
+        bytes calldata executionData
+    ) internal view virtual override returns (bool) {
+        return caller == address(entryPoint()) || super._erc7821AuthorizedExecutor(caller, mode, executionData);
+    }
+}

+ 37 - 0
contracts/mocks/docs/account/MyFactoryAccount.sol

@@ -0,0 +1,37 @@
+// contracts/MyFactoryAccount.sol
+// SPDX-License-Identifier: MIT
+
+pragma solidity ^0.8.20;
+
+import {Clones} from "../../../proxy/Clones.sol";
+import {Address} from "../../../utils/Address.sol";
+
+/**
+ * @dev A factory contract to create accounts on demand.
+ */
+contract MyFactoryAccount {
+    using Clones for address;
+    using Address for address;
+
+    address private immutable _impl;
+
+    constructor(address impl_) {
+        require(impl_.code.length > 0);
+        _impl = impl_;
+    }
+
+    /// @dev Predict the address of the account
+    function predictAddress(bytes calldata callData) public view returns (address) {
+        return _impl.predictDeterministicAddress(keccak256(callData), address(this));
+    }
+
+    /// @dev Create clone accounts on demand
+    function cloneAndInitialize(bytes calldata callData) public returns (address) {
+        address predicted = predictAddress(callData);
+        if (predicted.code.length == 0) {
+            _impl.cloneDeterministic(keccak256(callData));
+            predicted.functionCall(callData);
+        }
+        return predicted;
+    }
+}

+ 2 - 3
contracts/mocks/docs/governance/MyGovernor.sol

@@ -1,14 +1,13 @@
 // SPDX-License-Identifier: MIT
-pragma solidity ^0.8.20;
+pragma solidity ^0.8.24;
 
-import {IGovernor, Governor} from "../../../governance/Governor.sol";
+import {Governor} from "../../../governance/Governor.sol";
 import {GovernorCountingSimple} from "../../../governance/extensions/GovernorCountingSimple.sol";
 import {GovernorVotes} from "../../../governance/extensions/GovernorVotes.sol";
 import {GovernorVotesQuorumFraction} from "../../../governance/extensions/GovernorVotesQuorumFraction.sol";
 import {GovernorTimelockControl} from "../../../governance/extensions/GovernorTimelockControl.sol";
 import {TimelockController} from "../../../governance/TimelockController.sol";
 import {IVotes} from "../../../governance/utils/IVotes.sol";
-import {IERC165} from "../../../interfaces/IERC165.sol";
 
 contract MyGovernor is
     Governor,

+ 2 - 2
contracts/mocks/governance/GovernorCountingOverridableMock.sol

@@ -1,11 +1,11 @@
 // SPDX-License-Identifier: MIT
 
-pragma solidity ^0.8.20;
+pragma solidity ^0.8.24;
 
 import {Governor} from "../../governance/Governor.sol";
 import {GovernorSettings} from "../../governance/extensions/GovernorSettings.sol";
 import {GovernorVotesQuorumFraction} from "../../governance/extensions/GovernorVotesQuorumFraction.sol";
-import {GovernorCountingOverridable, VotesExtended} from "../../governance/extensions/GovernorCountingOverridable.sol";
+import {GovernorCountingOverridable} from "../../governance/extensions/GovernorCountingOverridable.sol";
 
 abstract contract GovernorCountingOverridableMock is
     GovernorSettings,

+ 1 - 1
contracts/mocks/governance/GovernorFractionalMock.sol

@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: MIT
 
-pragma solidity ^0.8.20;
+pragma solidity ^0.8.24;
 
 import {Governor} from "../../governance/Governor.sol";
 import {GovernorSettings} from "../../governance/extensions/GovernorSettings.sol";

Some files were not shown because too many files changed in this diff