Skip to content

Commit

Permalink
feat: merge istandardexecutor and imodulemanager
Browse files Browse the repository at this point in the history
  • Loading branch information
adamegyed committed Aug 20, 2024
1 parent 41d9893 commit 95e4f2f
Show file tree
Hide file tree
Showing 31 changed files with 166 additions and 186 deletions.
11 changes: 5 additions & 6 deletions src/account/AccountLoupe.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@
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 +19,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
4 changes: 2 additions & 2 deletions src/account/ModuleManagerInternals.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import {ModuleEntityLib} from "../helpers/ModuleEntityLib.sol";
import {ValidationConfigLib} from "../helpers/ValidationConfigLib.sol";
import {IExecutionHookModule} from "../interfaces/IExecutionHookModule.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 {IValidationHookModule} from "../interfaces/IValidationHookModule.sol";
import {IValidationModule} from "../interfaces/IValidationModule.sol";

Expand All @@ -26,7 +26,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
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, RESERVED_VALIDATION_DATA_INDEX} 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, RESERVED_VALIDATION_DATA_INDEX} 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 @@ -155,7 +149,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 @@ -167,7 +161,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 @@ -184,7 +178,7 @@ contract UpgradeableModularAccount is
}
}

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

/// @inheritdoc IModuleManager
/// @inheritdoc IModularAccount
/// @notice May be validated by a global validation.
function installExecution(
address module,
Expand All @@ -227,7 +221,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 @@ -250,7 +244,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 @@ -261,7 +255,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 @@ -642,15 +636,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 @@ -662,8 +656,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

0 comments on commit 95e4f2f

Please sign in to comment.