diff --git a/CHANGELOG.md b/CHANGELOG.md index f8b4a792..ff7de06d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ## 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 diff --git a/contracts/account/Account.sol b/contracts/account/Account.sol index c7645e62..a474fe5b 100644 --- a/contracts/account/Account.sol +++ b/contracts/account/Account.sol @@ -5,17 +5,26 @@ pragma solidity ^0.8.20; import {ERC721Holder} from "@openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol"; import {ERC1155Holder} from "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.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"; /** * @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. * * {ERC7739} for ERC-1271 signature support with ERC-7739 replay protection + * * {ERC7821} for performing external calls in batches. * * 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, ERC721Holder, ERC1155Holder, ERC7739 {} +abstract contract Account is AccountCore, ERC721Holder, ERC1155Holder, ERC7739, ERC7821 { + /// @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()); + } +} diff --git a/contracts/account/README.adoc b/contracts/account/README.adoc index f2a6d075..dae9f859 100644 --- a/contracts/account/README.adoc +++ b/contracts/account/README.adoc @@ -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 @@ -14,4 +19,4 @@ This directory includes contracts to build accounts for ERC-4337. {{AccountSignerERC7702}} -{{AccountERC7821}} +{{ERC7821}} diff --git a/contracts/account/extensions/AccountERC7821.sol b/contracts/account/extensions/ERC7821.sol similarity index 50% rename from contracts/account/extensions/AccountERC7821.sol rename to contracts/account/extensions/ERC7821.sol index 5f558de9..74fff639 100644 --- a/contracts/account/extensions/AccountERC7821.sol +++ b/contracts/account/extensions/ERC7821.sol @@ -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); } @@ -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); + } } diff --git a/foundry.toml b/foundry.toml index cf3fd677..9de79314 100644 --- a/foundry.toml +++ b/foundry.toml @@ -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']