Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: merge account interfaces #148

Merged
merged 1 commit into from
Aug 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions src/account/AccountLoupe.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,12 @@
pragma solidity ^0.8.25;

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

import {EnumerableMap} from "@openzeppelin/contracts/utils/structs/EnumerableMap.sol";
import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";

import {HookConfigLib} from "../helpers/HookConfigLib.sol";
import {ExecutionDataView, IAccountLoupe, ValidationDataView} from "../interfaces/IAccountLoupe.sol";
import {HookConfig, IModuleManager, ModuleEntity} from "../interfaces/IModuleManager.sol";
import {IStandardExecutor} from "../interfaces/IStandardExecutor.sol";
import {HookConfig, IModularAccount, ModuleEntity} from "../interfaces/IModularAccount.sol";
import {ExecutionData, ValidationData, getAccountStorage} from "./AccountStorage.sol";

abstract contract AccountLoupe is IAccountLoupe {
Expand All @@ -20,10 +18,10 @@ abstract contract AccountLoupe is IAccountLoupe {
/// @inheritdoc IAccountLoupe
function getExecutionData(bytes4 selector) external view override returns (ExecutionDataView memory data) {
if (
selector == IStandardExecutor.execute.selector || selector == IStandardExecutor.executeBatch.selector
selector == IModularAccount.execute.selector || selector == IModularAccount.executeBatch.selector
|| selector == UUPSUpgradeable.upgradeToAndCall.selector
|| selector == IModuleManager.installExecution.selector
|| selector == IModuleManager.uninstallExecution.selector
|| selector == IModularAccount.installExecution.selector
|| selector == IModularAccount.uninstallExecution.selector
) {
data.module = address(this);
data.allowGlobalValidation = true;
Expand Down
2 changes: 1 addition & 1 deletion src/account/AccountStorage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ pragma solidity ^0.8.25;

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

import {HookConfig, ModuleEntity} from "../interfaces/IModuleManager.sol";
import {HookConfig, ModuleEntity} from "../interfaces/IModularAccount.sol";

// bytes = keccak256("ERC6900.UpgradeableModularAccount.Storage")
bytes32 constant _ACCOUNT_STORAGE_SLOT = 0x9f09680beaa4e5c9f38841db2460c401499164f368baef687948c315d9073e40;
Expand Down
5 changes: 2 additions & 3 deletions src/account/ModuleManagerInternals.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
pragma solidity ^0.8.25;

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

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

import {MAX_PRE_VALIDATION_HOOKS} from "../helpers/Constants.sol";
Expand All @@ -11,8 +10,8 @@ import {KnownSelectors} from "../helpers/KnownSelectors.sol";
import {ModuleEntityLib} from "../helpers/ModuleEntityLib.sol";
import {ValidationConfigLib} from "../helpers/ValidationConfigLib.sol";
import {ExecutionManifest, ManifestExecutionHook} from "../interfaces/IExecutionModule.sol";
import {HookConfig, IModularAccount, ModuleEntity, ValidationConfig} from "../interfaces/IModularAccount.sol";
import {IModule} from "../interfaces/IModule.sol";
import {HookConfig, IModuleManager, ModuleEntity, ValidationConfig} from "../interfaces/IModuleManager.sol";
import {
AccountStorage,
ExecutionData,
Expand All @@ -22,7 +21,7 @@ import {
toSetValue
} from "./AccountStorage.sol";

abstract contract ModuleManagerInternals is IModuleManager {
abstract contract ModuleManagerInternals is IModularAccount {
using EnumerableSet for EnumerableSet.Bytes32Set;
using ModuleEntityLib for ModuleEntity;
using ValidationConfigLib for ValidationConfig;
Expand Down
2 changes: 1 addition & 1 deletion src/account/SemiModularAccount.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interface

import {ModuleEntityLib} from "../helpers/ModuleEntityLib.sol";

import {ModuleEntity, ValidationConfig} from "../interfaces/IModuleManager.sol";
import {ModuleEntity, ValidationConfig} from "../interfaces/IModularAccount.sol";

import {MessageHashUtils} from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol";
import {SignatureChecker} from "@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol";
Expand Down
34 changes: 14 additions & 20 deletions src/account/UpgradeableModularAccount.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
pragma solidity ^0.8.25;

import {BaseAccount} from "@eth-infinitism/account-abstraction/core/BaseAccount.sol";

import {IAccountExecute} from "@eth-infinitism/account-abstraction/interfaces/IAccountExecute.sol";
import {IEntryPoint} from "@eth-infinitism/account-abstraction/interfaces/IEntryPoint.sol";
import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interfaces/PackedUserOperation.sol";
Expand All @@ -12,20 +11,15 @@ import {UUPSUpgradeable} from "@openzeppelin/contracts/proxy/utils/UUPSUpgradeab
import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";

import {DIRECT_CALL_VALIDATION_ENTITYID} from "../helpers/Constants.sol";
import {HookConfig, HookConfigLib} from "../helpers/HookConfigLib.sol";
import {ModuleEntityLib} from "../helpers/ModuleEntityLib.sol";

import {SparseCalldataSegmentLib} from "../helpers/SparseCalldataSegmentLib.sol";
import {ValidationConfigLib} from "../helpers/ValidationConfigLib.sol";
import {_coalescePreValidation, _coalesceValidation} from "../helpers/ValidationResHelpers.sol";

import {DIRECT_CALL_VALIDATION_ENTITYID} from "../helpers/Constants.sol";

import {IExecutionHookModule} from "../interfaces/IExecutionHookModule.sol";
import {ExecutionManifest} from "../interfaces/IExecutionModule.sol";
import {IModuleManager, ModuleEntity, ValidationConfig} from "../interfaces/IModuleManager.sol";
import {Call, IStandardExecutor} from "../interfaces/IStandardExecutor.sol";

import {Call, IModularAccount, ModuleEntity, ValidationConfig} from "../interfaces/IModularAccount.sol";
import {IValidationHookModule} from "../interfaces/IValidationHookModule.sol";
import {IValidationModule} from "../interfaces/IValidationModule.sol";
import {AccountExecutor} from "./AccountExecutor.sol";
Expand All @@ -35,13 +29,13 @@ import {AccountStorageInitializable} from "./AccountStorageInitializable.sol";
import {ModuleManagerInternals} from "./ModuleManagerInternals.sol";

contract UpgradeableModularAccount is
IModularAccount,
AccountExecutor,
AccountLoupe,
AccountStorageInitializable,
BaseAccount,
IERC165,
IERC1271,
IStandardExecutor,
IAccountExecute,
ModuleManagerInternals,
UUPSUpgradeable
Expand Down Expand Up @@ -152,7 +146,7 @@ contract UpgradeableModularAccount is
_doCachedPostExecHooks(postPermissionHooks);
}

/// @inheritdoc IStandardExecutor
/// @inheritdoc IModularAccount
/// @notice May be validated by a global validation.
function execute(address target, uint256 value, bytes calldata data)
external
Expand All @@ -164,7 +158,7 @@ contract UpgradeableModularAccount is
result = _exec(target, value, data);
}

/// @inheritdoc IStandardExecutor
/// @inheritdoc IModularAccount
/// @notice May be validated by a global validation function.
function executeBatch(Call[] calldata calls)
external
Expand All @@ -181,7 +175,7 @@ contract UpgradeableModularAccount is
}
}

/// @inheritdoc IStandardExecutor
/// @inheritdoc IModularAccount
function executeWithAuthorization(bytes calldata data, bytes calldata authorization)
external
payable
Expand Down Expand Up @@ -214,7 +208,7 @@ contract UpgradeableModularAccount is
return returnData;
}

/// @inheritdoc IModuleManager
/// @inheritdoc IModularAccount
/// @notice May be validated by a global validation.
function installExecution(
address module,
Expand All @@ -224,7 +218,7 @@ contract UpgradeableModularAccount is
_installExecution(module, manifest, moduleInstallData);
}

/// @inheritdoc IModuleManager
/// @inheritdoc IModularAccount
/// @notice May be validated by a global validation.
function uninstallExecution(
address module,
Expand All @@ -245,7 +239,7 @@ contract UpgradeableModularAccount is
_installValidation(validationConfig, selectors, installData, hooks);
}

/// @inheritdoc IModuleManager
/// @inheritdoc IModularAccount
/// @notice May be validated by a global validation.
function installValidation(
ValidationConfig validationConfig,
Expand All @@ -256,7 +250,7 @@ contract UpgradeableModularAccount is
_installValidation(validationConfig, selectors, installData, hooks);
}

/// @inheritdoc IModuleManager
/// @inheritdoc IModularAccount
/// @notice May be validated by a global validation.
function uninstallValidation(
ModuleEntity validationFunction,
Expand Down Expand Up @@ -651,15 +645,15 @@ contract UpgradeableModularAccount is

_checkIfValidationAppliesSelector(outerSelector, validationFunction, isGlobal);

if (outerSelector == IStandardExecutor.execute.selector) {
if (outerSelector == IModularAccount.execute.selector) {
(address target,,) = abi.decode(callData[4:], (address, uint256, bytes));

if (target == address(this)) {
// There is no point to call `execute` to recurse exactly once - this is equivalent to just having
// the calldata as a top-level call.
revert SelfCallRecursionDepthExceeded();
}
} else if (outerSelector == IStandardExecutor.executeBatch.selector) {
} else if (outerSelector == IModularAccount.executeBatch.selector) {
// executeBatch may be used to batch account actions together, by targetting the account itself.
// If this is done, we must ensure all of the inner calls are allowed by the provided validation
// function.
Expand All @@ -671,8 +665,8 @@ contract UpgradeableModularAccount is
bytes4 nestedSelector = bytes4(calls[i].data);

if (
nestedSelector == IStandardExecutor.execute.selector
|| nestedSelector == IStandardExecutor.executeBatch.selector
nestedSelector == IModularAccount.execute.selector
|| nestedSelector == IModularAccount.executeBatch.selector
) {
// To prevent arbitrarily-deep recursive checking, we limit the depth of self-calls to one
// for the purposes of batching.
Expand Down
2 changes: 1 addition & 1 deletion src/helpers/HookConfigLib.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.25;

import {HookConfig, ModuleEntity} from "../interfaces/IModuleManager.sol";
import {HookConfig, ModuleEntity} from "../interfaces/IModularAccount.sol";

// Hook types:
// Exec hook: bools for hasPre, hasPost
Expand Down
19 changes: 8 additions & 11 deletions src/helpers/KnownSelectors.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,10 @@ import {UUPSUpgradeable} from "@openzeppelin/contracts/proxy/utils/UUPSUpgradeab
import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";

import {IAccountLoupe} from "../interfaces/IAccountLoupe.sol";

import {IExecutionHookModule} from "../interfaces/IExecutionHookModule.sol";
import {IExecutionModule} from "../interfaces/IExecutionModule.sol";
import {IModularAccount} from "../interfaces/IModularAccount.sol";
import {IModule} from "../interfaces/IModule.sol";
import {IModuleManager} from "../interfaces/IModuleManager.sol";
import {IStandardExecutor} from "../interfaces/IStandardExecutor.sol";

import {IValidationHookModule} from "../interfaces/IValidationHookModule.sol";
import {IValidationModule} from "../interfaces/IValidationModule.sol";

Expand All @@ -25,18 +22,18 @@ library KnownSelectors {
return
// check against IAccount methods
selector == IAccount.validateUserOp.selector
// check against IModuleManager methods
|| selector == IModuleManager.installExecution.selector
|| selector == IModuleManager.uninstallExecution.selector
// check against module manager methods
|| selector == IModularAccount.installExecution.selector
|| selector == IModularAccount.uninstallExecution.selector
// check against IERC165 methods
|| selector == IERC165.supportsInterface.selector
// check against UUPSUpgradeable methods
|| selector == UUPSUpgradeable.proxiableUUID.selector
|| selector == UUPSUpgradeable.upgradeToAndCall.selector
// check against IStandardExecutor methods
|| selector == IStandardExecutor.execute.selector || selector == IStandardExecutor.executeBatch.selector
|| selector == IStandardExecutor.executeWithAuthorization.selector
// check against IAccountLoupe methods
// check against IModularAccount methods
|| selector == IModularAccount.execute.selector || selector == IModularAccount.executeBatch.selector
|| selector == IModularAccount.executeWithAuthorization.selector
// check against account loupe methods
|| selector == IAccountLoupe.getExecutionData.selector
|| selector == IAccountLoupe.getValidationData.selector;
}
Expand Down
2 changes: 1 addition & 1 deletion src/helpers/ModuleEntityLib.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.25;

import {ModuleEntity} from "../interfaces/IModuleManager.sol";
import {ModuleEntity} from "../interfaces/IModularAccount.sol";

library ModuleEntityLib {
// Magic value for hooks that should always revert.
Expand Down
2 changes: 1 addition & 1 deletion src/helpers/ValidationConfigLib.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.25;

import {ModuleEntity, ValidationConfig} from "../interfaces/IModuleManager.sol";
import {ModuleEntity, ValidationConfig} from "../interfaces/IModularAccount.sol";

// Validation config is a packed representation of a validation function and flags for its configuration.
// Layout:
Expand Down
2 changes: 1 addition & 1 deletion src/interfaces/IAccountLoupe.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.25;

import {HookConfig, ModuleEntity} from "../interfaces/IModuleManager.sol";
import {HookConfig, ModuleEntity} from "../interfaces/IModularAccount.sol";

// Represents data associated with a specifc function selector.
struct ExecutionDataView {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,44 @@ type ValidationConfig is bytes26;

type HookConfig is bytes26;

interface IModuleManager {
struct Call {
// The target address for the account to call.
address target;
// The value to send with the call.
uint256 value;
// The calldata for the call.
bytes data;
}

interface IModularAccount {
event ExecutionInstalled(address indexed module, ExecutionManifest manifest);
event ExecutionUninstalled(address indexed module, bool onUninstallSucceeded, ExecutionManifest manifest);
event ValidationInstalled(address indexed module, uint32 indexed entityId);
event ValidationUninstalled(address indexed module, uint32 indexed entityId, bool onUninstallSucceeded);

/// @notice Standard execute method.
/// @param target The target address for the account to call.
/// @param value The value to send with the call.
/// @param data The calldata for the call.
/// @return The return data from the call.
function execute(address target, uint256 value, bytes calldata data) external payable returns (bytes memory);

/// @notice Standard executeBatch method.
/// @dev If the target is a module, the call SHOULD revert. If any of the calls revert, the entire batch MUST
/// revert.
/// @param calls The array of calls.
/// @return An array containing the return data from the calls.
function executeBatch(Call[] calldata calls) external payable returns (bytes[] memory);

/// @notice Execute a call using a specified runtime validation.
/// @param data The calldata to send to the account.
/// @param authorization The authorization data to use for the call. The first 24 bytes specifies which runtime
/// validation to use, and the rest is sent as a parameter to runtime validation.
function executeWithAuthorization(bytes calldata data, bytes calldata authorization)
external
payable
returns (bytes memory);

/// @notice Install a module to the modular account.
/// @param module The module to install.
/// @param manifest the manifest describing functions to install
Expand Down
36 changes: 0 additions & 36 deletions src/interfaces/IStandardExecutor.sol

This file was deleted.

6 changes: 3 additions & 3 deletions src/modules/ERC20TokenLimitModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";

import {IExecutionHookModule} from "../interfaces/IExecutionHookModule.sol";
import {Call, IModularAccount} from "../interfaces/IModularAccount.sol";
import {IModule, ModuleMetadata} from "../interfaces/IModule.sol";
import {Call, IStandardExecutor} from "../interfaces/IStandardExecutor.sol";

import {BaseModule, IERC165} from "./BaseModule.sol";

Expand Down Expand Up @@ -59,12 +59,12 @@ contract ERC20TokenLimitModule is BaseModule, IExecutionHookModule {
{
(bytes4 selector, bytes memory callData) = _getSelectorAndCalldata(data);

if (selector == IStandardExecutor.execute.selector) {
if (selector == IModularAccount.execute.selector) {
(address token,, bytes memory innerCalldata) = abi.decode(callData, (address, uint256, bytes));
if (_tokenList.contains(msg.sender, SetValue.wrap(bytes30(bytes20(token))))) {
_decrementLimit(entityId, token, innerCalldata);
}
} else if (selector == IStandardExecutor.executeBatch.selector) {
} else if (selector == IModularAccount.executeBatch.selector) {
Call[] memory calls = abi.decode(callData, (Call[]));
for (uint256 i = 0; i < calls.length; i++) {
if (_tokenList.contains(msg.sender, SetValue.wrap(bytes30(bytes20(calls[i].target))))) {
Expand Down
Loading
Loading