Skip to content

Commit

Permalink
feat: [v0.8-develop, experimental] split up interfaces by type [1/N] (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
adamegyed authored May 31, 2024
1 parent 59e8564 commit ed804c3
Show file tree
Hide file tree
Showing 18 changed files with 184 additions and 260 deletions.
15 changes: 9 additions & 6 deletions src/account/UpgradeableModularAccount.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet
import {FunctionReferenceLib} from "../helpers/FunctionReferenceLib.sol";
import {_coalescePreValidation, _coalesceValidation} from "../helpers/ValidationDataHelpers.sol";
import {IPlugin, PluginManifest} from "../interfaces/IPlugin.sol";
import {IValidation} from "../interfaces/IValidation.sol";
import {IValidationHook} from "../interfaces/IValidationHook.sol";
import {IExecutionHook} from "../interfaces/IExecutionHook.sol";
import {IPluginExecutor} from "../interfaces/IPluginExecutor.sol";
import {FunctionReference, IPluginManager} from "../interfaces/IPluginManager.sol";
import {IStandardExecutor, Call} from "../interfaces/IStandardExecutor.sol";
Expand Down Expand Up @@ -364,7 +367,7 @@ contract UpgradeableModularAccount is
FunctionReference preUserOpValidationHook = toFunctionReference(key);

(address plugin, uint8 functionId) = preUserOpValidationHook.unpack();
currentValidationData = IPlugin(plugin).preUserOpValidationHook(functionId, userOp, userOpHash);
currentValidationData = IValidationHook(plugin).preUserOpValidationHook(functionId, userOp, userOpHash);

if (uint160(currentValidationData) > 1) {
// If the aggregator is not 0 or 1, it is an unexpected value
Expand All @@ -376,7 +379,7 @@ contract UpgradeableModularAccount is
// Run the user op validationFunction
{
(address plugin, uint8 functionId) = userOpValidationFunction.unpack();
currentValidationData = IPlugin(plugin).userOpValidationFunction(functionId, userOp, userOpHash);
currentValidationData = IValidation(plugin).validateUserOp(functionId, userOp, userOpHash);

if (preUserOpValidationHooksLength != 0) {
// If we have other validation data we need to coalesce with
Expand Down Expand Up @@ -408,7 +411,7 @@ contract UpgradeableModularAccount is

(address plugin, uint8 functionId) = preRuntimeValidationHook.unpack();
// solhint-disable-next-line no-empty-blocks
try IPlugin(plugin).preRuntimeValidationHook(functionId, msg.sender, msg.value, msg.data) {}
try IValidationHook(plugin).preRuntimeValidationHook(functionId, msg.sender, msg.value, msg.data) {}
catch (bytes memory revertReason) {
revert PreRuntimeValidationHookFailed(plugin, functionId, revertReason);
}
Expand All @@ -419,7 +422,7 @@ contract UpgradeableModularAccount is
if (!runtimeValidationFunction.isEmptyOrMagicValue()) {
(address plugin, uint8 functionId) = runtimeValidationFunction.unpack();
// solhint-disable-next-line no-empty-blocks
try IPlugin(plugin).runtimeValidationFunction(functionId, msg.sender, msg.value, msg.data) {}
try IValidation(plugin).validateRuntime(functionId, msg.sender, msg.value, msg.data) {}
catch (bytes memory revertReason) {
revert RuntimeValidationFunctionReverted(plugin, functionId, revertReason);
}
Expand Down Expand Up @@ -475,7 +478,7 @@ contract UpgradeableModularAccount is
returns (bytes memory preExecHookReturnData)
{
(address plugin, uint8 functionId) = preExecHook.unpack();
try IPlugin(plugin).preExecutionHook(functionId, msg.sender, msg.value, data) returns (
try IExecutionHook(plugin).preExecutionHook(functionId, msg.sender, msg.value, data) returns (
bytes memory returnData
) {
preExecHookReturnData = returnData;
Expand All @@ -500,7 +503,7 @@ contract UpgradeableModularAccount is

(address plugin, uint8 functionId) = postHookToRun.postExecHook.unpack();
// solhint-disable-next-line no-empty-blocks
try IPlugin(plugin).postExecutionHook(functionId, postHookToRun.preExecHookReturnData) {}
try IExecutionHook(plugin).postExecutionHook(functionId, postHookToRun.preExecHookReturnData) {}
catch (bytes memory revertReason) {
revert PostExecHookReverted(plugin, functionId, revertReason);
}
Expand Down
25 changes: 25 additions & 0 deletions src/interfaces/IExecutionHook.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.25;

import {IPlugin} from "./IPlugin.sol";

interface IExecutionHook is IPlugin {
/// @notice Run the pre execution hook specified by the `functionId`.
/// @dev To indicate the entire call should revert, the function MUST revert.
/// @param functionId An identifier that routes the call to different internal implementations, should there be
/// more than one.
/// @param sender The caller address.
/// @param value The call value.
/// @param data The calldata sent.
/// @return Context to pass to a post execution hook, if present. An empty bytes array MAY be returned.
function preExecutionHook(uint8 functionId, address sender, uint256 value, bytes calldata data)
external
returns (bytes memory);

/// @notice Run the post execution hook specified by the `functionId`.
/// @dev To indicate the entire call should revert, the function MUST revert.
/// @param functionId An identifier that routes the call to different internal implementations, should there be
/// more than one.
/// @param preExecHookData The context returned by its associated pre execution hook.
function postExecutionHook(uint8 functionId, bytes calldata preExecHookData) external;
}
64 changes: 2 additions & 62 deletions src/interfaces/IPlugin.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 {PackedUserOperation} from "@eth-infinitism/account-abstraction/interfaces/PackedUserOperation.sol";
import {IERC165} from "@openzeppelin/contracts/interfaces/IERC165.sol";

// Forge formatter will displace the first comment for the enum field out of the enum itself,
// so annotating here to prevent that.
Expand Down Expand Up @@ -96,7 +96,7 @@ struct PluginManifest {
ManifestExecutionHook[] executionHooks;
}

interface IPlugin {
interface IPlugin is IERC165 {
/// @notice Initialize plugin data for the modular account.
/// @dev Called by the modular account during `installPlugin`.
/// @param data Optional bytes array to be decoded and used by the plugin to setup initial plugin data for the
Expand All @@ -109,66 +109,6 @@ interface IPlugin {
/// account.
function onUninstall(bytes calldata data) external;

/// @notice Run the pre user operation validation hook specified by the `functionId`.
/// @dev Pre user operation validation hooks MUST NOT return an authorizer value other than 0 or 1.
/// @param functionId An identifier that routes the call to different internal implementations, should there be
/// more than one.
/// @param userOp The user operation.
/// @param userOpHash The user operation hash.
/// @return Packed validation data for validAfter (6 bytes), validUntil (6 bytes), and authorizer (20 bytes).
function preUserOpValidationHook(uint8 functionId, PackedUserOperation calldata userOp, bytes32 userOpHash)
external
returns (uint256);

/// @notice Run the user operation validationFunction specified by the `functionId`.
/// @param functionId An identifier that routes the call to different internal implementations, should there be
/// more than one.
/// @param userOp The user operation.
/// @param userOpHash The user operation hash.
/// @return Packed validation data for validAfter (6 bytes), validUntil (6 bytes), and authorizer (20 bytes).
function userOpValidationFunction(uint8 functionId, PackedUserOperation calldata userOp, bytes32 userOpHash)
external
returns (uint256);

/// @notice Run the pre runtime validation hook specified by the `functionId`.
/// @dev To indicate the entire call should revert, the function MUST revert.
/// @param functionId An identifier that routes the call to different internal implementations, should there be
/// more than one.
/// @param sender The caller address.
/// @param value The call value.
/// @param data The calldata sent.
function preRuntimeValidationHook(uint8 functionId, address sender, uint256 value, bytes calldata data)
external;

/// @notice Run the runtime validationFunction specified by the `functionId`.
/// @dev To indicate the entire call should revert, the function MUST revert.
/// @param functionId An identifier that routes the call to different internal implementations, should there be
/// more than one.
/// @param sender The caller address.
/// @param value The call value.
/// @param data The calldata sent.
function runtimeValidationFunction(uint8 functionId, address sender, uint256 value, bytes calldata data)
external;

/// @notice Run the pre execution hook specified by the `functionId`.
/// @dev To indicate the entire call should revert, the function MUST revert.
/// @param functionId An identifier that routes the call to different internal implementations, should there be
/// more than one.
/// @param sender The caller address.
/// @param value The call value.
/// @param data The calldata sent.
/// @return Context to pass to a post execution hook, if present. An empty bytes array MAY be returned.
function preExecutionHook(uint8 functionId, address sender, uint256 value, bytes calldata data)
external
returns (bytes memory);

/// @notice Run the post execution hook specified by the `functionId`.
/// @dev To indicate the entire call should revert, the function MUST revert.
/// @param functionId An identifier that routes the call to different internal implementations, should there be
/// more than one.
/// @param preExecHookData The context returned by its associated pre execution hook.
function postExecutionHook(uint8 functionId, bytes calldata preExecHookData) external;

/// @notice Describe the contents and intended configuration of the plugin.
/// @dev This manifest MUST stay constant over time.
/// @return A manifest describing the contents and intended configuration of the plugin.
Expand Down
27 changes: 27 additions & 0 deletions src/interfaces/IValidation.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.25;

import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interfaces/PackedUserOperation.sol";

import {IPlugin} from "./IPlugin.sol";

interface IValidation is IPlugin {
/// @notice Run the user operation validationFunction specified by the `functionId`.
/// @param functionId An identifier that routes the call to different internal implementations, should there be
/// more than one.
/// @param userOp The user operation.
/// @param userOpHash The user operation hash.
/// @return Packed validation data for validAfter (6 bytes), validUntil (6 bytes), and authorizer (20 bytes).
function validateUserOp(uint8 functionId, PackedUserOperation calldata userOp, bytes32 userOpHash)
external
returns (uint256);

/// @notice Run the runtime validationFunction specified by the `functionId`.
/// @dev To indicate the entire call should revert, the function MUST revert.
/// @param functionId An identifier that routes the call to different internal implementations, should there be
/// more than one.
/// @param sender The caller address.
/// @param value The call value.
/// @param data The calldata sent.
function validateRuntime(uint8 functionId, address sender, uint256 value, bytes calldata data) external;
}
29 changes: 29 additions & 0 deletions src/interfaces/IValidationHook.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.25;

import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interfaces/PackedUserOperation.sol";

import {IPlugin} from "./IPlugin.sol";

interface IValidationHook is IPlugin {
/// @notice Run the pre user operation validation hook specified by the `functionId`.
/// @dev Pre user operation validation hooks MUST NOT return an authorizer value other than 0 or 1.
/// @param functionId An identifier that routes the call to different internal implementations, should there be
/// more than one.
/// @param userOp The user operation.
/// @param userOpHash The user operation hash.
/// @return Packed validation data for validAfter (6 bytes), validUntil (6 bytes), and authorizer (20 bytes).
function preUserOpValidationHook(uint8 functionId, PackedUserOperation calldata userOp, bytes32 userOpHash)
external
returns (uint256);

/// @notice Run the pre runtime validation hook specified by the `functionId`.
/// @dev To indicate the entire call should revert, the function MUST revert.
/// @param functionId An identifier that routes the call to different internal implementations, should there be
/// more than one.
/// @param sender The caller address.
/// @param value The call value.
/// @param data The calldata sent.
function preRuntimeValidationHook(uint8 functionId, address sender, uint256 value, bytes calldata data)
external;
}
125 changes: 3 additions & 122 deletions src/plugins/BasePlugin.sol
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.25;

import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interfaces/PackedUserOperation.sol";
import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol";
import {ERC165, IERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol";

import {IPlugin, PluginManifest, PluginMetadata} from "../interfaces/IPlugin.sol";
import {IPlugin} from "../interfaces/IPlugin.sol";

/// @title Base contract for plugins
/// @dev Implements ERC-165 to support IPlugin's interface, which is a requirement
Expand All @@ -13,124 +12,6 @@ import {IPlugin, PluginManifest, PluginMetadata} from "../interfaces/IPlugin.sol
abstract contract BasePlugin is ERC165, IPlugin {
error NotImplemented();

/// @notice Initialize plugin data for the modular account.
/// @dev Called by the modular account during `installPlugin`.
/// @param data Optional bytes array to be decoded and used by the plugin to setup initial plugin data for the
/// modular account.
function onInstall(bytes calldata data) external virtual {
(data);
revert NotImplemented();
}

/// @notice Clear plugin data for the modular account.
/// @dev Called by the modular account during `uninstallPlugin`.
/// @param data Optional bytes array to be decoded and used by the plugin to clear plugin data for the modular
/// account.
function onUninstall(bytes calldata data) external virtual {
(data);
revert NotImplemented();
}

/// @notice Run the pre user operation validation hook specified by the `functionId`.
/// @dev Pre user operation validation hooks MUST NOT return an authorizer value other than 0 or 1.
/// @param functionId An identifier that routes the call to different internal implementations, should there be
/// more than one.
/// @param userOp The user operation.
/// @param userOpHash The user operation hash.
/// @return Packed validation data for validAfter (6 bytes), validUntil (6 bytes), and authorizer (20 bytes).
function preUserOpValidationHook(uint8 functionId, PackedUserOperation calldata userOp, bytes32 userOpHash)
external
virtual
returns (uint256)
{
(functionId, userOp, userOpHash);
revert NotImplemented();
}

/// @notice Run the user operation validationFunction specified by the `functionId`.
/// @param functionId An identifier that routes the call to different internal implementations, should there be
/// more than one.
/// @param userOp The user operation.
/// @param userOpHash The user operation hash.
/// @return Packed validation data for validAfter (6 bytes), validUntil (6 bytes), and authorizer (20 bytes).
function userOpValidationFunction(uint8 functionId, PackedUserOperation calldata userOp, bytes32 userOpHash)
external
virtual
returns (uint256)
{
(functionId, userOp, userOpHash);
revert NotImplemented();
}

/// @notice Run the pre runtime validation hook specified by the `functionId`.
/// @dev To indicate the entire call should revert, the function MUST revert.
/// @param functionId An identifier that routes the call to different internal implementations, should there be
/// more than one.
/// @param sender The caller address.
/// @param value The call value.
/// @param data The calldata sent.
function preRuntimeValidationHook(uint8 functionId, address sender, uint256 value, bytes calldata data)
external
virtual
{
(functionId, sender, value, data);
revert NotImplemented();
}

/// @notice Run the runtime validationFunction specified by the `functionId`.
/// @dev To indicate the entire call should revert, the function MUST revert.
/// @param functionId An identifier that routes the call to different internal implementations, should there be
/// more than one.
/// @param sender The caller address.
/// @param value The call value.
/// @param data The calldata sent.
function runtimeValidationFunction(uint8 functionId, address sender, uint256 value, bytes calldata data)
external
virtual
{
(functionId, sender, value, data);
revert NotImplemented();
}

/// @notice Run the pre execution hook specified by the `functionId`.
/// @dev To indicate the entire call should revert, the function MUST revert.
/// @param functionId An identifier that routes the call to different internal implementations, should there be
/// more than one.
/// @param sender The caller address.
/// @param value The call value.
/// @param data The calldata sent.
/// @return Context to pass to a post execution hook, if present. An empty bytes array MAY be returned.
function preExecutionHook(uint8 functionId, address sender, uint256 value, bytes calldata data)
external
virtual
returns (bytes memory)
{
(functionId, sender, value, data);
revert NotImplemented();
}

/// @notice Run the post execution hook specified by the `functionId`.
/// @dev To indicate the entire call should revert, the function MUST revert.
/// @param functionId An identifier that routes the call to different internal implementations, should there be
/// more than one.
/// @param preExecHookData The context returned by its associated pre execution hook.
function postExecutionHook(uint8 functionId, bytes calldata preExecHookData) external virtual {
(functionId, preExecHookData);
revert NotImplemented();
}

/// @notice Describe the contents and intended configuration of the plugin.
/// @dev This manifest MUST stay constant over time.
/// @return A manifest describing the contents and intended configuration of the plugin.
function pluginManifest() external pure virtual returns (PluginManifest memory) {
revert NotImplemented();
}

/// @notice Describe the metadata of the plugin.
/// @dev This metadata MUST stay constant over time.
/// @return A metadata struct describing the plugin.
function pluginMetadata() external pure virtual returns (PluginMetadata memory);

/// @dev Returns true if this contract implements the interface defined by
/// `interfaceId`. See the corresponding
/// https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
Expand All @@ -143,7 +24,7 @@ abstract contract BasePlugin is ERC165, IPlugin {
/// making calls to plugins.
/// @param interfaceId The interface ID to check for support.
/// @return True if the contract supports `interfaceId`.
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
return interfaceId == type(IPlugin).interfaceId || super.supportsInterface(interfaceId);
}
}
Loading

0 comments on commit ed804c3

Please sign in to comment.