Skip to content
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
8 changes: 4 additions & 4 deletions src/account/AccountStorage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@ struct SelectorData {
// Note that even if this is set to true, user op validation will still be required, otherwise anyone could
// drain the account of native tokens by wasting gas.
bool isPublic;
// Whether or not a default validation function may be used to validate this function.
bool allowDefaultValidation;
// Whether or not a global validation function may be used to validate this function.
bool allowGlobalValidation;
// The execution hooks for this function selector.
EnumerableSet.Bytes32Set executionHooks;
}

struct ValidationData {
// Whether or not this validation can be used as a default validation function.
bool isDefault;
// Whether or not this validation can be used as a global validation function.
bool isGlobal;
// Whether or not this validation is a signature validator.
bool isSignatureValidation;
// How many execution hooks require the UO context.
Expand Down
14 changes: 7 additions & 7 deletions src/account/PluginManager2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ abstract contract PluginManager2 {
// Index marking the start of the data for the validation function.
uint8 internal constant _RESERVED_VALIDATION_DATA_INDEX = 255;

error DefaultValidationAlreadySet(FunctionReference validationFunction);
error GlobalValidationAlreadySet(FunctionReference validationFunction);
error PreValidationAlreadySet(FunctionReference validationFunction, FunctionReference preValidationFunction);
error ValidationAlreadySet(bytes4 selector, FunctionReference validationFunction);
error ValidationNotSet(bytes4 selector, FunctionReference validationFunction);
Expand All @@ -25,7 +25,7 @@ abstract contract PluginManager2 {

function _installValidation(
FunctionReference validationFunction,
bool isDefault,
bool isGlobal,
bytes4[] memory selectors,
bytes calldata installData,
bytes memory preValidationHooks,
Expand Down Expand Up @@ -80,11 +80,11 @@ abstract contract PluginManager2 {
}
}

if (isDefault) {
if (_storage.validationData[validationFunction].isDefault) {
revert DefaultValidationAlreadySet(validationFunction);
if (isGlobal) {
if (_storage.validationData[validationFunction].isGlobal) {
revert GlobalValidationAlreadySet(validationFunction);
}
_storage.validationData[validationFunction].isDefault = true;
_storage.validationData[validationFunction].isGlobal = true;
}

for (uint256 i = 0; i < selectors.length; ++i) {
Expand All @@ -108,7 +108,7 @@ abstract contract PluginManager2 {
) internal {
AccountStorage storage _storage = getAccountStorage();

_storage.validationData[validationFunction].isDefault = false;
_storage.validationData[validationFunction].isGlobal = false;
_storage.validationData[validationFunction].isSignatureValidation = false;

{
Expand Down
14 changes: 7 additions & 7 deletions src/account/PluginManagerInternals.sol
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ abstract contract PluginManagerInternals is IPluginManager {

// Storage update operations

function _setExecutionFunction(bytes4 selector, bool isPublic, bool allowDefaultValidation, address plugin)
function _setExecutionFunction(bytes4 selector, bool isPublic, bool allowGlobalValidation, address plugin)
internal
{
SelectorData storage _selectorData = getAccountStorage().selectorData[selector];
Expand Down Expand Up @@ -64,15 +64,15 @@ abstract contract PluginManagerInternals is IPluginManager {

_selectorData.plugin = plugin;
_selectorData.isPublic = isPublic;
_selectorData.allowDefaultValidation = allowDefaultValidation;
_selectorData.allowGlobalValidation = allowGlobalValidation;
}

function _removeExecutionFunction(bytes4 selector) internal {
SelectorData storage _selectorData = getAccountStorage().selectorData[selector];

_selectorData.plugin = address(0);
_selectorData.isPublic = false;
_selectorData.allowDefaultValidation = false;
_selectorData.allowGlobalValidation = false;
}

function _addValidationFunction(address plugin, ManifestValidation memory mv) internal {
Expand All @@ -81,7 +81,7 @@ abstract contract PluginManagerInternals is IPluginManager {
FunctionReference validationFunction = FunctionReferenceLib.pack(plugin, mv.functionId);

if (mv.isDefault) {
_storage.validationData[validationFunction].isDefault = true;
_storage.validationData[validationFunction].isGlobal = true;
}

if (mv.isSignatureValidation) {
Expand All @@ -101,7 +101,7 @@ abstract contract PluginManagerInternals is IPluginManager {

FunctionReference validationFunction = FunctionReferenceLib.pack(plugin, mv.functionId);

_storage.validationData[validationFunction].isDefault = false;
_storage.validationData[validationFunction].isGlobal = false;
_storage.validationData[validationFunction].isSignatureValidation = false;

// Clear the selectors
Expand Down Expand Up @@ -168,8 +168,8 @@ abstract contract PluginManagerInternals is IPluginManager {
for (uint256 i = 0; i < length; ++i) {
bytes4 selector = manifest.executionFunctions[i].executionSelector;
bool isPublic = manifest.executionFunctions[i].isPublic;
bool allowDefaultValidation = manifest.executionFunctions[i].allowDefaultValidation;
_setExecutionFunction(selector, isPublic, allowDefaultValidation, plugin);
bool allowGlobalValidation = manifest.executionFunctions[i].allowGlobalValidation;
_setExecutionFunction(selector, isPublic, allowGlobalValidation, plugin);
}

length = manifest.validationFunctions.length;
Expand Down
55 changes: 28 additions & 27 deletions src/account/UpgradeableModularAccount.sol
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ contract UpgradeableModularAccount is
error UnexpectedAggregator(address plugin, uint8 functionId, address aggregator);
error UnrecognizedFunction(bytes4 selector);
error UserOpValidationFunctionMissing(bytes4 selector);
error ValidationDoesNotApply(bytes4 selector, address plugin, uint8 functionId, bool isDefault);
error ValidationDoesNotApply(bytes4 selector, address plugin, uint8 functionId, bool isGlobal);
error ValidationSignatureSegmentMissing();
error SignatureSegmentOutOfOrder();

Expand Down Expand Up @@ -180,7 +180,7 @@ contract UpgradeableModularAccount is
}

/// @inheritdoc IStandardExecutor
/// @notice May be validated by a default validation.
/// @notice May be validated by a global validation.
function execute(address target, uint256 value, bytes calldata data)
external
payable
Expand All @@ -192,7 +192,7 @@ contract UpgradeableModularAccount is
}

/// @inheritdoc IStandardExecutor
/// @notice May be validated by a default validation function.
/// @notice May be validated by a global validation function.
function executeBatch(Call[] calldata calls)
external
payable
Expand All @@ -218,8 +218,8 @@ contract UpgradeableModularAccount is
FunctionReference runtimeValidationFunction = FunctionReference.wrap(bytes21(authorization[:21]));

// Check if the runtime validation function is allowed to be called
bool isDefaultValidation = uint8(authorization[21]) == 1;
_checkIfValidationAppliesCallData(data, runtimeValidationFunction, isDefaultValidation);
bool isGlobalValidation = uint8(authorization[21]) == 1;
_checkIfValidationAppliesCallData(data, runtimeValidationFunction, isGlobalValidation);

_doRuntimeValidation(runtimeValidationFunction, data, authorization[22:]);

Expand All @@ -242,7 +242,7 @@ contract UpgradeableModularAccount is
}

/// @inheritdoc IPluginManager
/// @notice May be validated by a default validation.
/// @notice May be validated by a global validation.
function installPlugin(address plugin, bytes32 manifestHash, bytes calldata pluginInstallData)
external
override
Expand All @@ -252,7 +252,7 @@ contract UpgradeableModularAccount is
}

/// @inheritdoc IPluginManager
/// @notice May be validated by a default validation.
/// @notice May be validated by a global validation.
function uninstallPlugin(address plugin, bytes calldata config, bytes calldata pluginUninstallData)
external
override
Expand All @@ -269,40 +269,41 @@ contract UpgradeableModularAccount is
_uninstallPlugin(plugin, manifest, pluginUninstallData);
}

/// @notice Initializes the account with a validation function added to the default pool.
/// @notice Initializes the account with a validation function added to the global pool.
/// TODO: remove and merge with regular initialization, after we figure out a better install/uninstall workflow
/// with user install configs.
/// @dev This function is only callable once, and only by the EntryPoint.

function initializeWithValidation(
FunctionReference validationFunction,
bool shared,
bool isGlobal,
bytes4[] memory selectors,
bytes calldata installData,
bytes calldata preValidationHooks,
bytes calldata permissionHooks
) external initializer {
_installValidation(validationFunction, shared, selectors, installData, preValidationHooks, permissionHooks);
_installValidation(
validationFunction, isGlobal, selectors, installData, preValidationHooks, permissionHooks
);
emit ModularAccountInitialized(_ENTRY_POINT);
}

/// @inheritdoc IPluginManager
/// @notice May be validated by a default validation.
/// @notice May be validated by a global validation.
function installValidation(
FunctionReference validationFunction,
bool isDefault,
bool isGlobal,
bytes4[] memory selectors,
bytes calldata installData,
bytes calldata preValidationHooks,
bytes calldata permissionHooks
) external wrapNativeFunction {
_installValidation(
validationFunction, isDefault, selectors, installData, preValidationHooks, permissionHooks
validationFunction, isGlobal, selectors, installData, preValidationHooks, permissionHooks
);
}

/// @inheritdoc IPluginManager
/// @notice May be validated by a default validation.
/// @notice May be validated by a global validation.
function uninstallValidation(
FunctionReference validationFunction,
bytes calldata uninstallData,
Expand Down Expand Up @@ -330,7 +331,7 @@ contract UpgradeableModularAccount is
}

/// @inheritdoc UUPSUpgradeable
/// @notice May be validated by a default validation.
/// @notice May be validated by a global validation.
function upgradeToAndCall(address newImplementation, bytes memory data)
public
payable
Expand Down Expand Up @@ -381,9 +382,9 @@ contract UpgradeableModularAccount is

// Revert if the provided `authorization` less than 21 bytes long, rather than right-padding.
FunctionReference userOpValidationFunction = FunctionReference.wrap(bytes21(userOp.signature[:21]));
bool isDefaultValidation = uint8(userOp.signature[21]) == 1;
bool isGlobalValidation = uint8(userOp.signature[21]) == 1;

_checkIfValidationAppliesCallData(userOp.callData, userOpValidationFunction, isDefaultValidation);
_checkIfValidationAppliesCallData(userOp.callData, userOpValidationFunction, isGlobalValidation);

// Check if there are permission hooks associated with the validator, and revert if the call isn't to
// `executeUserOp`
Expand Down Expand Up @@ -612,7 +613,7 @@ contract UpgradeableModularAccount is
function _checkIfValidationAppliesCallData(
bytes calldata callData,
FunctionReference validationFunction,
bool isDefault
bool isGlobal
) internal view {
bytes4 outerSelector = bytes4(callData[:4]);
if (outerSelector == this.executeUserOp.selector) {
Expand All @@ -622,7 +623,7 @@ contract UpgradeableModularAccount is
outerSelector = bytes4(callData[:4]);
}

_checkIfValidationAppliesSelector(outerSelector, validationFunction, isDefault);
_checkIfValidationAppliesSelector(outerSelector, validationFunction, isGlobal);

if (outerSelector == IStandardExecutor.execute.selector) {
(address target,,) = abi.decode(callData[4:], (address, uint256, bytes));
Expand Down Expand Up @@ -656,7 +657,7 @@ contract UpgradeableModularAccount is
revert SelfCallRecursionDepthExceeded();
}

_checkIfValidationAppliesSelector(nestedSelector, validationFunction, isDefault);
_checkIfValidationAppliesSelector(nestedSelector, validationFunction, isGlobal);
}
}
}
Expand All @@ -665,24 +666,24 @@ contract UpgradeableModularAccount is
function _checkIfValidationAppliesSelector(
bytes4 selector,
FunctionReference validationFunction,
bool isDefault
bool isGlobal
) internal view {
AccountStorage storage _storage = getAccountStorage();

// Check that the provided validation function is applicable to the selector
if (isDefault) {
if (!_defaultValidationAllowed(selector) || !_storage.validationData[validationFunction].isDefault) {
if (isGlobal) {
if (!_globalValidationAllowed(selector) || !_storage.validationData[validationFunction].isGlobal) {
revert UserOpValidationFunctionMissing(selector);
}
} else {
// Not default validation, but per-selector
// Not global validation, but per-selector
if (!getAccountStorage().validationData[validationFunction].selectors.contains(toSetValue(selector))) {
revert UserOpValidationFunctionMissing(selector);
}
}
}

function _defaultValidationAllowed(bytes4 selector) internal view returns (bool) {
function _globalValidationAllowed(bytes4 selector) internal view returns (bool) {
if (
selector == this.execute.selector || selector == this.executeBatch.selector
|| selector == this.installPlugin.selector || selector == this.uninstallPlugin.selector
Expand All @@ -692,7 +693,7 @@ contract UpgradeableModularAccount is
return true;
}

return getAccountStorage().selectorData[selector].allowDefaultValidation;
return getAccountStorage().selectorData[selector].allowGlobalValidation;
}

function _checkPermittedCallerIfNotFromEP() internal view {
Expand Down
4 changes: 2 additions & 2 deletions src/interfaces/IPlugin.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ struct ManifestExecutionFunction {
bytes4 executionSelector;
// If true, the function won't need runtime validation, and can be called by anyone.
bool isPublic;
// If true, the function can be validated by a default validation function.
bool allowDefaultValidation;
// If true, the function can be validated by a global validation function.
bool allowGlobalValidation;
}

// todo: do we need these at all? Or do we fully switch to `installValidation`?
Expand Down
6 changes: 3 additions & 3 deletions src/interfaces/IPluginManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,19 @@ interface IPluginManager {

/// @notice Temporary install function - pending a different user-supplied install config & manifest validation
/// path.
/// Installs a validation function across a set of execution selectors, and optionally mark it as a default
/// Installs a validation function across a set of execution selectors, and optionally mark it as a global
/// validation.
/// TODO: remove or update.
/// @dev This does not validate anything against the manifest - the caller must ensure validity.
/// @param validationFunction The validation function to install.
/// @param isDefault Whether the validation function applies for all selectors in the default pool.
/// @param isGlobal Whether the validation function applies for all selectors in the global pool.
/// @param selectors The selectors to install the validation function for.
/// @param installData Optional data to be decoded and used by the plugin to setup initial plugin state.
/// @param preValidationHooks Optional pre-validation hooks to install for the validation function.
/// @param permissionHooks Optional permission hooks to install for the validation function.
function installValidation(
FunctionReference validationFunction,
bool isDefault,
bool isGlobal,
bytes4[] memory selectors,
bytes calldata installData,
bytes calldata preValidationHooks,
Expand Down
6 changes: 3 additions & 3 deletions src/plugins/TokenReceiverPlugin.sol
Original file line number Diff line number Diff line change
Expand Up @@ -62,17 +62,17 @@ contract TokenReceiverPlugin is BasePlugin, IERC721Receiver, IERC1155Receiver {
manifest.executionFunctions[0] = ManifestExecutionFunction({
executionSelector: this.onERC721Received.selector,
isPublic: true,
allowDefaultValidation: false
allowGlobalValidation: false
});
manifest.executionFunctions[1] = ManifestExecutionFunction({
executionSelector: this.onERC1155Received.selector,
isPublic: true,
allowDefaultValidation: false
allowGlobalValidation: false
});
manifest.executionFunctions[2] = ManifestExecutionFunction({
executionSelector: this.onERC1155BatchReceived.selector,
isPublic: true,
allowDefaultValidation: false
allowGlobalValidation: false
});

manifest.interfaceIds = new bytes4[](2);
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/owner/SingleOwnerPlugin.sol
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ contract SingleOwnerPlugin is ISingleOwnerPlugin, BasePlugin {
function pluginManifest() external pure override returns (PluginManifest memory) {
PluginManifest memory manifest;

// TODO: use default validation instead
// TODO: use global validation instead
bytes4[] memory accountSelectors = new bytes4[](5);
accountSelectors[0] = IStandardExecutor.execute.selector;
accountSelectors[1] = IStandardExecutor.executeBatch.selector;
Expand Down
2 changes: 1 addition & 1 deletion test/account/AccountExecHooks.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ contract AccountExecHooksTest is AccountTestBase {
ManifestExecutionFunction({
executionSelector: _EXEC_SELECTOR,
isPublic: true,
allowDefaultValidation: false
allowGlobalValidation: false
})
);
}
Expand Down
Loading