Skip to content

Commit

Permalink
Merge branch 'master' into aa/move-eip712-to-account
Browse files Browse the repository at this point in the history
  • Loading branch information
Amxx authored Jan 13, 2025
2 parents 35e2d01 + 120127b commit 47dd724
Show file tree
Hide file tree
Showing 27 changed files with 191 additions and 139 deletions.
3 changes: 3 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,6 @@

## Owners of the OpenZeppelin Community Contracts CODEOWNERS file
/.github/CODEOWNERS @OpenZeppelin/contracts

## Axelar
/contracts/crosschain/axelar/ @cjcobb23
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 13-01-2025

- Rename `ERC7739Signer` into `ERC7739` to avoid confusion with the `AbstractSigner` family of contracts.
- Remove `AccountERC7821` in favor of `ERC7821`, an ERC-7821 implementation that doesn't rely on (but is compatible with) `AccountCore`.

## 23-12-2024

- `AccountERC7821`: Account implementation that implements ERC-7821 for minimal batch execution interface. No support for additional `opData` is included.
Expand Down
22 changes: 15 additions & 7 deletions contracts/account/Account.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,24 @@
pragma solidity ^0.8.20;

import {PackedUserOperation} from "@openzeppelin/contracts/interfaces/draft-IERC4337.sol";
import {EIP712} from "@openzeppelin/contracts/utils/cryptography/EIP712.sol";
import {ERC721Holder} from "@openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol";
import {ERC1155Holder} from "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol";
import {ERC7739Signer} from "../utils/cryptography/ERC7739Signer.sol";
import {ERC7739} from "../utils/cryptography/ERC7739.sol";
import {ERC7821} from "./extensions/ERC7821.sol";
import {AccountCore} from "./AccountCore.sol";
import {AccountERC7821} from "./extensions/AccountERC7821.sol";
import {EIP712} from "@openzeppelin/contracts/utils/cryptography/EIP712.sol";

/**
* @dev Extension of {AccountCore} with recommended feature that most account abstraction implementation will want:
*
* * {AccountERC7821} for performing external calls in batches.
* * {ERC721Holder} and {ERC1155Holder} to accept ERC-712 and ERC-1155 token transfers transfers.
* * {ERC7739Signer} for ERC-1271 signature support with ERC-7739 replay protection
* * {ERC7739} for ERC-1271 signature support with ERC-7739 replay protection
* * {ERC7821} for performing external calls in batches.
*
* NOTE: To use this contract, the {ERC7739Signer-_rawSignatureValidation} function must be
* NOTE: To use this contract, the {ERC7739-_rawSignatureValidation} function must be
* implemented using a specific signature verification algorithm. See {SignerECDSA}, {SignerP256} or {SignerRSA}.
*/
abstract contract Account is AccountCore, AccountERC7821, EIP712, ERC721Holder, ERC1155Holder, ERC7739Signer {
abstract contract Account is AccountCore, EIP712, ERC721Holder, ERC1155Holder, ERC7739, ERC7821 {
bytes32 internal constant _PACKED_USER_OPERATION =
keccak256(
"PackedUserOperation(address sender,uint256 nonce,bytes initCode,bytes callData,bytes32 accountGasLimits,uint256 preVerificationGas,bytes32 gasFees,bytes paymasterAndData)"
Expand Down Expand Up @@ -51,5 +51,13 @@ abstract contract Account is AccountCore, AccountERC7821, EIP712, ERC721Holder,
)
)
);

/// @inheritdoc ERC7821
function _erc7821AuthorizedExecutor(
address caller,
bytes32 mode,
bytes calldata executionData
) internal view virtual override returns (bool) {
return super._erc7821AuthorizedExecutor(caller, mode, executionData) || caller == address(entryPoint());
}
}
9 changes: 7 additions & 2 deletions contracts/account/README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@
[.readme-notice]
NOTE: This document is better viewed at https://docs.openzeppelin.com/community-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:

* {AccountCore}: An ERC-4337 smart account implementation that includes the core logic to process user operations.
* {Account}: An extension of `AccountCore` that implements the recommended features for ERC-4337 smart accounts.
* {AccountSignerERC7702}: An account implementation with low-level signature validation performed by an EOA.
* {ERC7821}: Minimal batch executor implementation contracts. Useful to enable easy batch execution for smart contracts.

== Core

Expand All @@ -14,4 +19,4 @@ This directory includes contracts to build accounts for ERC-4337.

{{SignerERC7702}}

{{AccountERC7821}}
{{ERC7821}}
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,24 @@ import {IERC7821} from "../../interfaces/IERC7821.sol";
import {AccountCore} from "../AccountCore.sol";

/**
* @dev Minimal batch executor following ERC7821. Only supports basic mode (no optional "opData").
* @dev Minimal batch executor following ERC-7821. Only supports basic mode (no optional "opData").
*/
abstract contract AccountERC7821 is AccountCore, IERC7821 {
abstract contract ERC7821 is IERC7821 {
using ERC7579Utils for *;

error UnsupportedExecutionMode();

/// @inheritdoc IERC7821
function execute(bytes32 mode, bytes calldata executionData) public payable virtual onlyEntryPointOrSelf {
/**
* @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 implement 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 AccountCore.AccountUnauthorized(msg.sender);
if (!supportsExecutionMode(mode)) revert UnsupportedExecutionMode();
executionData.execBatch(ERC7579Utils.EXECTYPE_DEFAULT);
}
Expand All @@ -28,4 +37,15 @@ abstract contract AccountERC7821 is AccountCore, IERC7821 {
execType == ERC7579Utils.EXECTYPE_DEFAULT &&
modeSelector == ModeSelector.wrap(0x00000000);
}

/**
* @dev Access control mechanism for the {execute} function.
*/
function _erc7821AuthorizedExecutor(
address caller,
bytes32 /* mode */,
bytes calldata /* executionData */
) internal view virtual returns (bool) {
return caller == address(this);
}
}
24 changes: 24 additions & 0 deletions contracts/mocks/docs/utils/cryptography/ERC7739SignerECDSA.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// contracts/ERC7739ECDSA.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import {EIP712} from "@openzeppelin/contracts/utils/cryptography/EIP712.sol";

import {ERC7739} from "../../../../utils/cryptography/ERC7739.sol";

contract ERC7739ECDSA is ERC7739 {
address private immutable _signer;

constructor(address signerAddr) EIP712("ERC7739ECDSA", "1") {
_signer = signerAddr;
}

function _rawSignatureValidation(
bytes32 hash,
bytes calldata signature
) internal view virtual override returns (bool) {
(address recovered, ECDSA.RecoverError err, ) = ECDSA.tryRecover(hash, signature);
return _signer == recovered && err == ECDSA.RecoverError.NoError;
}
}
6 changes: 3 additions & 3 deletions contracts/mocks/utils/cryptography/ERC7739SignerECDSAMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ pragma solidity ^0.8.20;

import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import {EIP712} from "@openzeppelin/contracts/utils/cryptography/EIP712.sol";
import {ERC7739Signer} from "../../../utils/cryptography/ERC7739Signer.sol";
import {ERC7739} from "../../../utils/cryptography/ERC7739.sol";
import {SignerECDSA} from "../../../utils/cryptography/SignerECDSA.sol";

contract ERC7739SignerECDSAMock is ERC7739Signer, SignerECDSA {
constructor(address signerAddr) EIP712("ERC7739SignerECDSA", "1") {
contract ERC7739ECDSAMock is ERC7739, SignerECDSA {
constructor(address signerAddr) EIP712("ERC7739ECDSA", "1") {
_initializeSigner(signerAddr);
}
}
6 changes: 3 additions & 3 deletions contracts/mocks/utils/cryptography/ERC7739SignerP256Mock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
pragma solidity ^0.8.20;

import {EIP712} from "@openzeppelin/contracts/utils/cryptography/EIP712.sol";
import {ERC7739Signer} from "../../../utils/cryptography/ERC7739Signer.sol";
import {ERC7739} from "../../../utils/cryptography/ERC7739.sol";
import {SignerP256} from "../../../utils/cryptography/SignerP256.sol";

contract ERC7739SignerP256Mock is ERC7739Signer, SignerP256 {
constructor(bytes32 qx, bytes32 qy) EIP712("ERC7739SignerP256", "1") {
contract ERC7739P256Mock is ERC7739, SignerP256 {
constructor(bytes32 qx, bytes32 qy) EIP712("ERC7739P256", "1") {
_initializeSigner(qx, qy);
}
}
6 changes: 3 additions & 3 deletions contracts/mocks/utils/cryptography/ERC7739SignerRSAMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
pragma solidity ^0.8.20;

import {EIP712} from "@openzeppelin/contracts/utils/cryptography/EIP712.sol";
import {ERC7739Signer} from "../../../utils/cryptography/ERC7739Signer.sol";
import {ERC7739} from "../../../utils/cryptography/ERC7739.sol";
import {SignerRSA} from "../../../utils/cryptography/SignerRSA.sol";

contract ERC7739SignerRSAMock is ERC7739Signer, SignerRSA {
constructor(bytes memory e, bytes memory n) EIP712("ERC7739SignerRSA", "1") {
contract ERC7739RSAMock is ERC7739, SignerRSA {
constructor(bytes memory e, bytes memory n) EIP712("ERC7739RSA", "1") {
_initializeSigner(e, n);
}
}
4 changes: 2 additions & 2 deletions contracts/utils/README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ NOTE: This document is better viewed at https://docs.openzeppelin.com/community-
Miscellaneous contracts and libraries containing utility functions you can use to improve security, work with new data types, or safely use low-level primitives.

* {AbstractSigner}: Abstract contract for internal signature validation in smart contracts.
* {ERC7739Signer}: An abstract contract to validate signatures following the rehashing scheme from `ERC7739Utils`.
* {ERC7739}: An abstract contract to validate signatures following the rehashing scheme from `ERC7739Utils`.
* {ERC7739Utils}: Utilities library that implements a defensive rehashing mechanism to prevent replayability of smart contract signatures based on ERC-7739.
* {SignerECDSA}, {SignerP256}, {SignerRSA}: Implementations of an {AbstractSigner} with specific signature validation algorithms.
* {Masks}: Library to handle `bytes32` masks.
Expand All @@ -15,7 +15,7 @@ Miscellaneous contracts and libraries containing utility functions you can use t

{{AbstractSigner}}

{{ERC7739Signer}}
{{ERC7739}}

{{ERC7739Utils}}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import {ERC7739Utils} from "./ERC7739Utils.sol";
* may limit the ability of the signer to be used within the ERC-4337 validation phase (due to
* https://eips.ethereum.org/EIPS/eip-7562#storage-rules[ERC-7562 storage access rules]).
*/
abstract contract ERC7739Signer is AbstractSigner, EIP712, IERC1271 {
abstract contract ERC7739 is AbstractSigner, EIP712, IERC1271 {
using ERC7739Utils for *;
using MessageHashUtils for bytes32;

Expand Down
24 changes: 5 additions & 19 deletions contracts/utils/cryptography/ERC7739Utils.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

pragma solidity ^0.8.20;

import {Calldata} from "@openzeppelin/contracts/utils/Calldata.sol";

/**
* @dev Utilities to process https://ercs.ethereum.org/ERCS/erc-7739[ERC-7739] typed data signatures
* that are specific to an EIP-712 domain.
Expand Down Expand Up @@ -71,13 +73,13 @@ library ERC7739Utils {
unchecked {
uint256 sigLength = encodedSignature.length;

if (sigLength < 4) return (_emptyCalldataBytes(), 0, 0, _emptyCalldataString());
if (sigLength < 4) return (Calldata.emptyBytes(), 0, 0, Calldata.emptyString());

uint256 contentsDescrEnd = sigLength - 2; // Last 2 bytes
uint256 contentsDescrLength = uint16(bytes2(encodedSignature[contentsDescrEnd:]));

if (contentsDescrLength + 64 > contentsDescrEnd)
return (_emptyCalldataBytes(), 0, 0, _emptyCalldataString());
return (Calldata.emptyBytes(), 0, 0, Calldata.emptyString());

uint256 contentsHashEnd = contentsDescrEnd - contentsDescrLength;
uint256 separatorEnd = contentsHashEnd - 32;
Expand Down Expand Up @@ -195,23 +197,7 @@ library ERC7739Utils {
}
}
}
return (_emptyCalldataString(), _emptyCalldataString());
}

// slither-disable-next-line write-after-write
function _emptyCalldataBytes() private pure returns (bytes calldata result) {
assembly ("memory-safe") {
result.offset := 0
result.length := 0
}
}

// slither-disable-next-line write-after-write
function _emptyCalldataString() private pure returns (string calldata result) {
assembly ("memory-safe") {
result.offset := 0
result.length := 0
}
return (Calldata.emptyString(), Calldata.emptyString());
}

function _isForbiddenChar(bytes1 char) private pure returns (bool) {
Expand Down
2 changes: 2 additions & 0 deletions foundry.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
[profile.default]
solc_version = '0.8.27'
evm_version = 'cancun'
optimizer = true
optimizer-runs = 200
src = 'contracts'
out = 'out'
libs = ['node_modules', 'lib']
Expand Down
2 changes: 1 addition & 1 deletion lib/@openzeppelin-contracts
Submodule @openzeppelin-contracts updated 58 files
+0 −5 .changeset/eighty-hounds-promise.md
+0 −5 .changeset/four-chairs-help.md
+5 −0 .changeset/good-cameras-serve.md
+0 −5 .changeset/great-lions-hear.md
+0 −5 .changeset/healthy-books-shout.md
+0 −5 .changeset/hot-shrimps-wait.md
+5 −0 .changeset/long-walls-draw.md
+0 −5 .changeset/lovely-dodos-lay.md
+0 −5 .changeset/pink-wasps-hammer.md
+0 −5 .changeset/proud-planes-arrive.md
+0 −5 .changeset/seven-donkeys-tap.md
+0 −5 .changeset/small-seahorses-bathe.md
+0 −5 .changeset/tricky-bats-pretend.md
+0 −5 .changeset/weak-roses-bathe.md
+42 −0 CHANGELOG.md
+1 −1 contracts/access/AccessControl.sol
+5 −11 contracts/account/utils/draft-ERC4337Utils.sol
+1 −0 contracts/account/utils/draft-ERC7579Utils.sol
+1 −1 contracts/finance/VestingWallet.sol
+1 −1 contracts/governance/Governor.sol
+1 −0 contracts/governance/extensions/GovernorCountingOverridable.sol
+1 −1 contracts/governance/extensions/GovernorPreventLateQuorum.sol
+1 −1 contracts/governance/utils/Votes.sol
+1 −0 contracts/governance/utils/VotesExtended.sol
+1 −0 contracts/interfaces/draft-IERC4337.sol
+123 −0 contracts/interfaces/draft-IERC6909.sol
+3 −2 contracts/interfaces/draft-IERC7579.sol
+1 −1 contracts/package.json
+1 −1 contracts/proxy/Clones.sol
+1 −1 contracts/proxy/ERC1967/ERC1967Proxy.sol
+1 −1 contracts/proxy/ERC1967/ERC1967Utils.sol
+1 −1 contracts/proxy/beacon/BeaconProxy.sol
+1 −1 contracts/proxy/transparent/ProxyAdmin.sol
+1 −1 contracts/proxy/transparent/TransparentUpgradeableProxy.sol
+1 −1 contracts/proxy/utils/UUPSUpgradeable.sol
+1 −1 contracts/token/ERC20/ERC20.sol
+1 −1 contracts/token/ERC20/extensions/ERC1363.sol
+1 −1 contracts/token/ERC20/utils/SafeERC20.sol
+1 −1 contracts/utils/Address.sol
+1 −0 contracts/utils/Bytes.sol
+1 −0 contracts/utils/CAIP10.sol
+1 −0 contracts/utils/CAIP2.sol
+24 −0 contracts/utils/Calldata.sol
+1 −0 contracts/utils/NoncesKeyed.sol
+1 −1 contracts/utils/Packing.sol
+1 −1 contracts/utils/ReentrancyGuardTransient.sol
+1 −1 contracts/utils/Strings.sol
+2 −2 contracts/utils/cryptography/MessageHashUtils.sol
+2 −2 contracts/utils/structs/MerkleTree.sol
+1 −1 docs/modules/ROOT/pages/access-control.adoc
+1 −1 docs/modules/ROOT/pages/index.adoc
+1 −1 package.json
+1 −1 scripts/prepare-docs.sh
+43 −43 test/account/utils/draft-ERC4337Utils.test.js
+31 −28 test/account/utils/draft-ERC7579Utils.test.js
+12 −12 test/governance/extensions/GovernorSequentialProposalId.test.js
+22 −0 test/utils/Calldata.test.js
+25 −25 test/utils/Nonces.behavior.js
2 changes: 1 addition & 1 deletion lib/@openzeppelin-contracts-upgradeable
Submodule @openzeppelin-contracts-upgradeable updated 90 files
+5 −0 .changeset/brave-islands-sparkle.md
+5 −0 .changeset/cyan-taxis-travel.md
+0 −5 .changeset/eighty-hounds-promise.md
+0 −5 .changeset/four-chairs-help.md
+5 −0 .changeset/good-cameras-serve.md
+0 −5 .changeset/great-lions-hear.md
+0 −5 .changeset/healthy-books-shout.md
+0 −5 .changeset/hot-shrimps-wait.md
+5 −0 .changeset/long-walls-draw.md
+0 −5 .changeset/lovely-dodos-lay.md
+0 −5 .changeset/pink-wasps-hammer.md
+0 −5 .changeset/proud-planes-arrive.md
+0 −5 .changeset/seven-donkeys-tap.md
+5 −0 .changeset/seven-insects-taste.md
+0 −5 .changeset/small-seahorses-bathe.md
+5 −0 .changeset/ten-fishes-fold.md
+5 −0 .changeset/thin-eels-cross.md
+0 −5 .changeset/tricky-bats-pretend.md
+0 −5 .changeset/weak-roses-bathe.md
+0 −8 .githooks/pre-push
+1 −5 .github/workflows/checks.yml
+1 −1 .github/workflows/formal-verification.yml
+2 −0 .husky/pre-commit
+42 −0 CHANGELOG.md
+ audits/2024-12-v5.2.pdf
+9 −8 audits/README.md
+1 −1 contracts/access/AccessControlUpgradeable.sol
+1 −1 contracts/finance/VestingWalletUpgradeable.sol
+20 −7 contracts/governance/GovernorUpgradeable.sol
+5 −4 contracts/governance/extensions/GovernorCountingOverridableUpgradeable.sol
+1 −1 contracts/governance/extensions/GovernorPreventLateQuorumUpgradeable.sol
+98 −0 contracts/governance/extensions/GovernorSequentialProposalIdUpgradeable.sol
+1 −1 contracts/governance/extensions/GovernorTimelockCompoundUpgradeable.sol
+1 −0 contracts/governance/utils/VotesExtendedUpgradeable.sol
+1 −1 contracts/governance/utils/VotesUpgradeable.sol
+7 −0 contracts/mocks/WithInit.sol
+45 −0 contracts/mocks/governance/GovernorSequentialProposalIdMockUpgradeable.sol
+2 −2 contracts/package.json
+1 −1 contracts/proxy/utils/UUPSUpgradeable.sol
+1 −1 contracts/token/ERC20/ERC20Upgradeable.sol
+6 −3 contracts/token/ERC20/extensions/ERC1363Upgradeable.sol
+5 −8 contracts/token/ERC20/extensions/ERC4626Upgradeable.sol
+1 −1 contracts/token/ERC721/README.adoc
+1 −0 contracts/utils/NoncesKeyedUpgradeable.sol
+1 −1 contracts/utils/README.adoc
+1 −1 contracts/utils/ReentrancyGuardTransientUpgradeable.sol
+1 −1 docs/modules/ROOT/pages/access-control.adoc
+1 −1 docs/modules/ROOT/pages/erc1155.adoc
+1 −1 docs/modules/ROOT/pages/index.adoc
+1 −0 foundry.toml
+1 −1 fv-requirements.txt
+31 −0 hardhat/common-contracts.js
+1 −1 lib/openzeppelin-contracts
+828 −123 package-lock.json
+19 −7 package.json
+2 −0 scripts/checks/coverage.sh
+1 −1 scripts/checks/inheritance-ordering.js
+1 −1 scripts/checks/pragma-consistency.js
+1 −1 scripts/prepare-docs.sh
+0 −5 scripts/prepare.sh
+10 −0 scripts/set-max-old-space-size.sh
+4 −1 scripts/solhint-custom/package.json
+1 −2 slither.config.json
+1 −1 solhint.config.js
+1 −1 test/TESTING.md
+78 −37 test/account/utils/draft-ERC4337Utils.test.js
+421 −0 test/account/utils/draft-ERC7579Utils.t.sol
+45 −42 test/account/utils/draft-ERC7579Utils.test.js
+1 −0 test/bin/EntryPoint070.abi
+ test/bin/EntryPoint070.bytecode
+1 −0 test/bin/SenderCreator070.abi
+ test/bin/SenderCreator070.bytecode
+1 −1 test/governance/Governor.test.js
+1 −1 test/governance/extensions/GovernorCountingFractional.test.js
+3 −1 test/governance/extensions/GovernorCountingOverridable.test.js
+1 −1 test/governance/extensions/GovernorERC721.test.js
+1 −1 test/governance/extensions/GovernorPreventLateQuorum.test.js
+202 −0 test/governance/extensions/GovernorSequentialProposalId.test.js
+1 −1 test/governance/extensions/GovernorStorage.test.js
+1 −1 test/governance/extensions/GovernorTimelockAccess.test.js
+1 −1 test/governance/extensions/GovernorTimelockCompound.test.js
+1 −1 test/governance/extensions/GovernorTimelockControl.test.js
+1 −1 test/governance/extensions/GovernorVotesQuorumFraction.test.js
+1 −1 test/governance/extensions/GovernorWithParams.test.js
+14 −12 test/helpers/governance.js
+7 −2 test/helpers/iterate.js
+1 −1 test/metatx/ERC2771Context.test.js
+22 −0 test/utils/Calldata.test.js
+25 −25 test/utils/Nonces.behavior.js
+45 −33 test/utils/introspection/SupportsInterface.behavior.js
2 changes: 1 addition & 1 deletion lib/forge-std
Loading

0 comments on commit 47dd724

Please sign in to comment.