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 d0ce310
Show file tree
Hide file tree
Showing 31 changed files with 172 additions and 178 deletions.
11 changes: 6 additions & 5 deletions src/account/AccountLoupe.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ import {EnumerableMap} from "@openzeppelin/contracts/utils/structs/EnumerableMap
import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";

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

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

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

abstract contract AccountLoupe is IAccountLoupe {
Expand All @@ -20,10 +21,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: 3 additions & 2 deletions src/account/ModuleManagerInternals.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ 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 +27,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
28 changes: 14 additions & 14 deletions src/account/UpgradeableModularAccount.sol
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ import {DIRECT_CALL_VALIDATION_ENTITYID, RESERVED_VALIDATION_DATA_INDEX} from ".

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";
Expand All @@ -35,13 +35,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 +155,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 +167,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 +184,7 @@ contract UpgradeableModularAccount is
}
}

/// @inheritdoc IStandardExecutor
/// @inheritdoc IModularAccount
function executeWithAuthorization(bytes calldata data, bytes calldata authorization)
external
payable
Expand Down Expand Up @@ -217,7 +217,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 +227,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 +250,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 +261,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 +642,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 +662,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
21 changes: 10 additions & 11 deletions src/helpers/KnownSelectors.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,12 @@ import {IPaymaster} from "@eth-infinitism/account-abstraction/interfaces/IPaymas
import {UUPSUpgradeable} from "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol";
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 {IAccountLoupe} from "../interfaces/IAccountLoupe.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 +24,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.

7 changes: 4 additions & 3 deletions src/modules/ERC20TokenLimitModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ 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 +60,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
7 changes: 4 additions & 3 deletions src/modules/NativeTokenLimitModule.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interface
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 {IValidationHookModule} from "../interfaces/IValidationHookModule.sol";
import {BaseModule, IERC165} from "./BaseModule.sol";
Expand Down Expand Up @@ -143,9 +144,9 @@ contract NativeTokenLimitModule is BaseModule, IExecutionHookModule, IValidation

uint256 value;
// Get value being sent
if (selector == IStandardExecutor.execute.selector) {
if (selector == IModularAccount.execute.selector) {
(, value) = abi.decode(callData, (address, uint256));
} 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++) {
value += calls[i].value;
Expand Down
Loading

0 comments on commit d0ce310

Please sign in to comment.