Browse Source

Merge branch 'master' of github.com:OpenZeppelin/openzeppelin-contracts into typo-fixes

Gonzalo Othacehe 3 months ago
parent
commit
d43e45b352
100 changed files with 1152 additions and 103 deletions
  1. 5 0
      .changeset/all-geese-stand.md
  2. 5 0
      .changeset/clean-ways-push.md
  3. 5 0
      .changeset/eight-radios-check.md
  4. 5 0
      .changeset/fine-frogs-bake.md
  5. 5 0
      .changeset/full-ways-help.md
  6. 5 0
      .changeset/funny-years-yawn.md
  7. 5 0
      .changeset/hot-grapes-lie.md
  8. 5 0
      .changeset/lazy-poets-cheer.md
  9. 5 0
      .changeset/long-hornets-mate.md
  10. 5 0
      .changeset/nice-rings-wish.md
  11. 5 0
      .changeset/pink-dolls-shop.md
  12. 5 0
      .changeset/popular-geese-tan.md
  13. 5 0
      .changeset/public-crabs-heal.md
  14. 5 0
      .changeset/quiet-kiwis-feel.md
  15. 5 0
      .changeset/rich-cows-repair.md
  16. 5 0
      .changeset/ripe-bears-hide.md
  17. 5 0
      .changeset/rotten-apes-lie.md
  18. 5 0
      .changeset/social-walls-obey.md
  19. 5 0
      .changeset/sour-pens-shake.md
  20. 5 0
      .changeset/strong-points-change.md
  21. 5 0
      .changeset/tame-bears-mix.md
  22. 10 0
      .github/CODEOWNERS
  23. 2 3
      .github/actions/setup/action.yml
  24. 4 6
      .github/workflows/checks.yml
  25. 4 0
      CHANGELOG.md
  26. 1 1
      SECURITY.md
  27. 1 1
      contracts/access/IAccessControl.sol
  28. 1 0
      contracts/access/extensions/AccessControlDefaultAdminRules.sol
  29. 1 1
      contracts/access/extensions/IAccessControlDefaultAdminRules.sol
  30. 1 1
      contracts/access/extensions/IAccessControlEnumerable.sol
  31. 1 1
      contracts/access/manager/IAccessManaged.sol
  32. 1 1
      contracts/access/manager/IAccessManager.sol
  33. 1 1
      contracts/access/manager/IAuthority.sol
  34. 144 0
      contracts/account/Account.sol
  35. 20 2
      contracts/account/README.adoc
  36. 413 0
      contracts/account/extensions/draft-AccountERC7579.sol
  37. 106 0
      contracts/account/extensions/draft-AccountERC7579Hooked.sol
  38. 69 0
      contracts/account/extensions/draft-ERC7821.sol
  39. 20 0
      contracts/account/utils/EIP7702Utils.sol
  40. 47 29
      contracts/governance/Governor.sol
  41. 1 1
      contracts/governance/IGovernor.sol
  42. 4 0
      contracts/governance/README.adoc
  43. 1 1
      contracts/governance/extensions/GovernorCountingFractional.sol
  44. 1 1
      contracts/governance/extensions/GovernorCountingOverridable.sol
  45. 1 1
      contracts/governance/extensions/GovernorCountingSimple.sol
  46. 90 0
      contracts/governance/extensions/GovernorNoncesKeyed.sol
  47. 1 1
      contracts/governance/extensions/GovernorPreventLateQuorum.sol
  48. 1 1
      contracts/governance/extensions/GovernorProposalGuardian.sol
  49. 1 1
      contracts/governance/extensions/GovernorSequentialProposalId.sol
  50. 1 1
      contracts/governance/extensions/GovernorSettings.sol
  51. 1 1
      contracts/governance/extensions/GovernorStorage.sol
  52. 1 1
      contracts/governance/extensions/GovernorSuperQuorum.sol
  53. 1 1
      contracts/governance/extensions/GovernorTimelockAccess.sol
  54. 1 1
      contracts/governance/extensions/GovernorTimelockCompound.sol
  55. 1 1
      contracts/governance/extensions/GovernorTimelockControl.sol
  56. 1 1
      contracts/governance/extensions/GovernorVotes.sol
  57. 1 1
      contracts/governance/extensions/GovernorVotesQuorumFraction.sol
  58. 1 1
      contracts/governance/extensions/GovernorVotesSuperQuorumFraction.sol
  59. 1 1
      contracts/governance/utils/IVotes.sol
  60. 1 1
      contracts/interfaces/IERC1155.sol
  61. 1 1
      contracts/interfaces/IERC1155MetadataURI.sol
  62. 1 1
      contracts/interfaces/IERC1155Receiver.sol
  63. 2 2
      contracts/interfaces/IERC1271.sol
  64. 1 1
      contracts/interfaces/IERC1363.sol
  65. 1 1
      contracts/interfaces/IERC1363Receiver.sol
  66. 1 1
      contracts/interfaces/IERC1363Spender.sol
  67. 1 1
      contracts/interfaces/IERC165.sol
  68. 1 1
      contracts/interfaces/IERC1820Implementer.sol
  69. 1 1
      contracts/interfaces/IERC1820Registry.sol
  70. 1 1
      contracts/interfaces/IERC1967.sol
  71. 1 1
      contracts/interfaces/IERC20.sol
  72. 1 1
      contracts/interfaces/IERC20Metadata.sol
  73. 1 1
      contracts/interfaces/IERC2309.sol
  74. 1 1
      contracts/interfaces/IERC2612.sol
  75. 1 1
      contracts/interfaces/IERC2981.sol
  76. 1 1
      contracts/interfaces/IERC3156.sol
  77. 1 1
      contracts/interfaces/IERC3156FlashBorrower.sol
  78. 1 1
      contracts/interfaces/IERC3156FlashLender.sol
  79. 1 1
      contracts/interfaces/IERC4626.sol
  80. 1 1
      contracts/interfaces/IERC4906.sol
  81. 1 1
      contracts/interfaces/IERC5267.sol
  82. 1 1
      contracts/interfaces/IERC5313.sol
  83. 1 1
      contracts/interfaces/IERC5805.sol
  84. 1 1
      contracts/interfaces/IERC6372.sol
  85. 1 1
      contracts/interfaces/IERC721.sol
  86. 1 1
      contracts/interfaces/IERC721Enumerable.sol
  87. 1 1
      contracts/interfaces/IERC721Metadata.sol
  88. 1 1
      contracts/interfaces/IERC721Receiver.sol
  89. 1 1
      contracts/interfaces/IERC777.sol
  90. 1 1
      contracts/interfaces/IERC777Recipient.sol
  91. 1 1
      contracts/interfaces/IERC777Sender.sol
  92. 17 0
      contracts/interfaces/IERC7913.sol
  93. 3 0
      contracts/interfaces/README.adoc
  94. 1 1
      contracts/interfaces/draft-IERC1822.sol
  95. 1 1
      contracts/interfaces/draft-IERC4337.sol
  96. 1 1
      contracts/interfaces/draft-IERC6093.sol
  97. 1 1
      contracts/interfaces/draft-IERC6909.sol
  98. 1 1
      contracts/interfaces/draft-IERC7579.sol
  99. 1 1
      contracts/interfaces/draft-IERC7674.sol
  100. 30 0
      contracts/interfaces/draft-IERC7802.sol

+ 5 - 0
.changeset/all-geese-stand.md

@@ -0,0 +1,5 @@
+---
+'openzeppelin-solidity': patch
+---
+
+Add constructors to the different signers.

+ 5 - 0
.changeset/clean-ways-push.md

@@ -0,0 +1,5 @@
+---
+'openzeppelin-solidity': minor
+---
+
+`AccountERC7579`: Extension of `Account` that implements support for ERC-7579 modules of type executor, validator, and fallback handler.

+ 5 - 0
.changeset/eight-radios-check.md

@@ -0,0 +1,5 @@
+---
+'openzeppelin-solidity': minor
+---
+
+`Checkpoints`: Add a new checkpoint variant `Checkpoint256` using `uint256` type for the value and key.

+ 5 - 0
.changeset/fine-frogs-bake.md

@@ -0,0 +1,5 @@
+---
+'openzeppelin-solidity': minor
+---
+
+`EnumerableMap`: Add `keys(uint256,uint256)` that returns a subset (slice) of the keys in the map.

+ 5 - 0
.changeset/full-ways-help.md

@@ -0,0 +1,5 @@
+---
+'openzeppelin-solidity': minor
+---
+
+`EIP7702Utils`: Add a library for checking if an address has an EIP-7702 delegation in place.

+ 5 - 0
.changeset/funny-years-yawn.md

@@ -0,0 +1,5 @@
+---
+'openzeppelin-solidity': minor
+---
+
+`Account`: Added a simple ERC-4337 account implementation with minimal logic to process user operations.

+ 5 - 0
.changeset/hot-grapes-lie.md

@@ -0,0 +1,5 @@
+---
+'openzeppelin-solidity': minor
+---
+
+`EnumerableSet`: Add `values(uint256,uint256)` that returns a subset (slice) of the values in the set.

+ 5 - 0
.changeset/lazy-poets-cheer.md

@@ -0,0 +1,5 @@
+---
+'openzeppelin-solidity': minor
+---
+
+`SignerERC7702`: Implementation of `AbstractSigner` for Externally Owned Accounts (EOAs). Useful with ERC-7702.

+ 5 - 0
.changeset/long-hornets-mate.md

@@ -0,0 +1,5 @@
+---
+'openzeppelin-solidity': minor
+---
+
+`EnumerableMap`: Add support for `BytesToBytesMap` type.

+ 5 - 0
.changeset/nice-rings-wish.md

@@ -0,0 +1,5 @@
+---
+'openzeppelin-solidity': minor
+---
+
+`ERC7913P256Verifier` and `ERC7913RSAVerifier`: Ready to use ERC-7913 verifiers that implement key verification for P256 (secp256r1) and RSA keys.

+ 5 - 0
.changeset/pink-dolls-shop.md

@@ -0,0 +1,5 @@
+---
+'openzeppelin-solidity': minor
+---
+
+`EnumerableSet`: Add support for `StringSet` and `BytesSet` types.

+ 5 - 0
.changeset/popular-geese-tan.md

@@ -0,0 +1,5 @@
+---
+'openzeppelin-solidity': minor
+---
+
+`GovernorNoncesKeyed`: Extension of `Governor` that adds support for keyed nonces when voting by sig.

+ 5 - 0
.changeset/public-crabs-heal.md

@@ -0,0 +1,5 @@
+---
+'openzeppelin-solidity': minor
+---
+
+`MultiSignerERC7913Weighted`: Extension of `MultiSignerERC7913` that supports assigning different weights to each signer, enabling more flexible governance schemes.

+ 5 - 0
.changeset/quiet-kiwis-feel.md

@@ -0,0 +1,5 @@
+---
+'openzeppelin-solidity': minor
+---
+
+`SignerERC7913`: Abstract signer that verifies signatures using the ERC-7913 workflow.

+ 5 - 0
.changeset/rich-cows-repair.md

@@ -0,0 +1,5 @@
+---
+'openzeppelin-solidity': minor
+---
+
+`InteroperableAddress`: Add a library for formatting and parsing ERC-7930 interoperable addresses.

+ 5 - 0
.changeset/ripe-bears-hide.md

@@ -0,0 +1,5 @@
+---
+'openzeppelin-solidity': minor
+---
+
+`ERC20Bridgeable`: Implementation of ERC-7802 that makes an ERC-20 compatible with crosschain bridges.

+ 5 - 0
.changeset/rotten-apes-lie.md

@@ -0,0 +1,5 @@
+---
+'openzeppelin-solidity': minor
+---
+
+`IERC7821`, `ERC7821`: Interface and logic for minimal batch execution. No support for additional `opData` is included.

+ 5 - 0
.changeset/social-walls-obey.md

@@ -0,0 +1,5 @@
+---
+'openzeppelin-solidity': minor
+---
+
+`MultiSignerERC7913`: Implementation of `AbstractSigner` that supports multiple ERC-7913 signers with a threshold-based signature verification system.

+ 5 - 0
.changeset/sour-pens-shake.md

@@ -0,0 +1,5 @@
+---
+'openzeppelin-solidity': minor
+---
+
+`SignatureChecker`: Add support for ERC-7913 signatures alongside existing ECDSA and ERC-1271 signature verification.

+ 5 - 0
.changeset/strong-points-change.md

@@ -0,0 +1,5 @@
+---
+'openzeppelin-solidity': minor
+---
+
+`AccountERC7579Hooked`: Extension of `AccountERC7579` that implements support for ERC-7579 hook modules.

+ 5 - 0
.changeset/tame-bears-mix.md

@@ -0,0 +1,5 @@
+---
+'openzeppelin-solidity': minor
+---
+
+`AbstractSigner`, `SignerECDSA`, `SignerP256`, and `SignerRSA`: Add an abstract contract and various implementations for contracts that deal with signature verification.

+ 10 - 0
.github/CODEOWNERS

@@ -0,0 +1,10 @@
+# List of approvers/reviewers for OpenZeppelin Contracts
+#
+# Get in touch with us via the OpenZeppelin Forum
+#  https://forum.openzeppelin.com/
+# 
+# Learn about CODEOWNERS file format: 
+#  https://help.github.com/en/articles/about-code-owners
+
+# These owners will be the default owners for everything in the repo.
+* @OpenZeppelin/contracts

+ 2 - 3
.github/actions/setup/action.yml

@@ -6,15 +6,14 @@ runs:
   steps:
     - uses: actions/setup-node@v4
       with:
-        node-version: 20.x
+        node-version: 22.x
     - uses: actions/cache@v4
       id: cache
       with:
         path: '**/node_modules'
         key: npm-v3-${{ hashFiles('**/package-lock.json') }}
     - name: Install dependencies
-      ## TODO: Remove when EIP-7702 authorizations are enabled in latest non-beta ethers version
-      run: npm ci --legacy-peer-deps
+      run: npm ci
       shell: bash
       if: steps.cache.outputs.cache-hit != 'true'
     - name: Install Foundry

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

@@ -41,8 +41,8 @@ jobs:
         run: npm run test
       - name: Check linearisation of the inheritance graph
         run: npm run test:inheritance
-      - name: Check pragma consistency between files
-        run: npm run test:pragma
+      - name: Check pragma validity
+        run: npm run test:pragma -- --concurrency 1
       - name: Check procedurally generated contracts are up-to-date
         run: npm run test:generation
       - name: Compare gas costs
@@ -70,8 +70,8 @@ jobs:
         run: npm run test
       - name: Check linearisation of the inheritance graph
         run: npm run test:inheritance
-      - name: Check pragma consistency between files
-        run: npm run test:pragma
+      - name: Check pragma validity
+        run: npm run test:pragma -- --concurrency 1
       - name: Check storage layout
         uses: ./.github/actions/storage-layout
         continue-on-error: ${{ contains(github.event.pull_request.labels.*.name, 'breaking change') }}
@@ -118,8 +118,6 @@ jobs:
       - uses: actions/checkout@v4
       - name: Set up environment
         uses: ./.github/actions/setup
-      ## TODO: Remove when EIP-7702 authorizations are enabled in latest non-beta ethers version
-      - run: rm package-lock.json package.json # Dependencies already installed
       - uses: crytic/slither-action@v0.4.1
 
   codespell:

+ 4 - 0
CHANGELOG.md

@@ -1,5 +1,9 @@
 # Changelog
 
+### 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)).
+
 ## 5.3.0 (2025-04-09)
 
 ### Breaking Changes

+ 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.

+ 1 - 1
contracts/access/IAccessControl.sol

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
 // OpenZeppelin Contracts (last updated v5.3.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.

+ 1 - 0
contracts/access/extensions/AccessControlDefaultAdminRules.sol

@@ -24,6 +24,7 @@ import {IERC165} from "../../utils/introspection/ERC165.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:

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

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

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

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

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

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

+ 1 - 1
contracts/access/manager/IAccessManager.sol

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

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

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

+ 144 - 0
contracts/account/Account.sol

@@ -0,0 +1,144 @@
+// SPDX-License-Identifier: MIT
+
+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
 

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

@@ -0,0 +1,413 @@
+// SPDX-License-Identifier: MIT
+
+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 {ERC7579UnsupportedModuleType}.
+     * * Module must be of the given type. Reverts with {ERC7579MismatchedModuleTypeId}.
+     * * Module must not be already installed. Reverts with {ERC7579AlreadyInstalledModule}.
+     *
+     * Emits a {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 {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;
+    }
+}

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

@@ -0,0 +1,106 @@
+// SPDX-License-Identifier: MIT
+
+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();
+    }
+}

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

@@ -0,0 +1,69 @@
+// SPDX-License-Identifier: MIT
+
+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);
+    }
+}

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

@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: MIT
+
+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);
+    }
+}

+ 47 - 29
contracts/governance/Governor.sol

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
 // OpenZeppelin Contracts (last updated v5.3.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";
@@ -538,16 +538,9 @@ abstract contract Governor is Context, ERC165, EIP712, Nonces, IGovernor, IERC72
         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, "");
     }
 
@@ -560,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().

+ 1 - 1
contracts/governance/IGovernor.sol

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
 // OpenZeppelin Contracts (last updated v5.3.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}}

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

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

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

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
 // OpenZeppelin Contracts (last updated v5.3.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";

+ 1 - 1
contracts/governance/extensions/GovernorCountingSimple.sol

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

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

@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: MIT
+
+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 first 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);
+        }
+    }
+}

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

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
 // OpenZeppelin Contracts (last updated v5.2.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";

+ 1 - 1
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;
+pragma solidity ^0.8.24;
 
 import {Governor} from "../Governor.sol";
 

+ 1 - 1
contracts/governance/extensions/GovernorSequentialProposalId.sol

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

+ 1 - 1
contracts/governance/extensions/GovernorSettings.sol

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

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

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

+ 1 - 1
contracts/governance/extensions/GovernorSuperQuorum.sol

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

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

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

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

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
 // OpenZeppelin Contracts (last updated v5.3.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";

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

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
 // OpenZeppelin Contracts (last updated v5.3.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";

+ 1 - 1
contracts/governance/extensions/GovernorVotes.sol

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
 // OpenZeppelin Contracts (last updated v5.1.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";

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

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
 // OpenZeppelin Contracts (last updated v5.3.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";

+ 1 - 1
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;
+pragma solidity ^0.8.24;
 
 import {Governor} from "../Governor.sol";
 import {GovernorSuperQuorum} from "./GovernorSuperQuorum.sol";

+ 1 - 1
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;
+pragma solidity >=0.8.4;
 
 /**
  * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.

+ 1 - 1
contracts/interfaces/IERC1155.sol

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

+ 1 - 1
contracts/interfaces/IERC1155MetadataURI.sol

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

+ 1 - 1
contracts/interfaces/IERC1155Receiver.sol

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

+ 2 - 2
contracts/interfaces/IERC1271.sol

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
 // OpenZeppelin Contracts (last updated v5.3.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);
 }

+ 1 - 1
contracts/interfaces/IERC1363.sol

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

+ 1 - 1
contracts/interfaces/IERC1363Receiver.sol

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

+ 1 - 1
contracts/interfaces/IERC1363Spender.sol

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

+ 1 - 1
contracts/interfaces/IERC165.sol

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

+ 1 - 1
contracts/interfaces/IERC1820Implementer.sol

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
 // OpenZeppelin Contracts (last updated v5.1.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

+ 1 - 1
contracts/interfaces/IERC1820Registry.sol

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
 // OpenZeppelin Contracts (last updated v5.1.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

+ 1 - 1
contracts/interfaces/IERC1967.sol

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
 // OpenZeppelin Contracts (last updated v5.0.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.

+ 1 - 1
contracts/interfaces/IERC20.sol

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

+ 1 - 1
contracts/interfaces/IERC20Metadata.sol

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

+ 1 - 1
contracts/interfaces/IERC2309.sol

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

+ 1 - 1
contracts/interfaces/IERC2612.sol

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

+ 1 - 1
contracts/interfaces/IERC2981.sol

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

+ 1 - 1
contracts/interfaces/IERC3156.sol

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

+ 1 - 1
contracts/interfaces/IERC3156FlashBorrower.sol

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

+ 1 - 1
contracts/interfaces/IERC3156FlashLender.sol

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

+ 1 - 1
contracts/interfaces/IERC4626.sol

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
 // OpenZeppelin Contracts (last updated v5.3.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";

+ 1 - 1
contracts/interfaces/IERC4906.sol

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

+ 1 - 1
contracts/interfaces/IERC5267.sol

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

+ 1 - 1
contracts/interfaces/IERC5313.sol

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

+ 1 - 1
contracts/interfaces/IERC5805.sol

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
 // OpenZeppelin Contracts (last updated v5.0.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";

+ 1 - 1
contracts/interfaces/IERC6372.sol

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

+ 1 - 1
contracts/interfaces/IERC721.sol

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

+ 1 - 1
contracts/interfaces/IERC721Enumerable.sol

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

+ 1 - 1
contracts/interfaces/IERC721Metadata.sol

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

+ 1 - 1
contracts/interfaces/IERC721Receiver.sol

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

+ 1 - 1
contracts/interfaces/IERC777.sol

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
 // OpenZeppelin Contracts (last updated v5.1.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.

+ 1 - 1
contracts/interfaces/IERC777Recipient.sol

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
 // OpenZeppelin Contracts (last updated v5.1.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.

+ 1 - 1
contracts/interfaces/IERC777Sender.sol

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
 // OpenZeppelin Contracts (last updated v5.1.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.

+ 17 - 0
contracts/interfaces/IERC7913.sol

@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: MIT
+
+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}}

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

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
 // OpenZeppelin Contracts (last updated v5.1.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

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

@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: MIT
 // OpenZeppelin Contracts (last updated v5.3.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:

+ 1 - 1
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;
+pragma solidity >=0.8.4;
 
 /**
  * @dev Standard ERC-20 Errors

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

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

+ 1 - 1
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;
+pragma solidity >=0.8.4;
 
 import {PackedUserOperation} from "./draft-IERC4337.sol";
 

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

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

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

@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: MIT
+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;
+}

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