Skip to content

Commit

Permalink
fix: [Quantstamp-ALC-14] fix execution data view for native functions
Browse files Browse the repository at this point in the history
  • Loading branch information
fangting-alchemy committed Nov 15, 2024
1 parent 357cb8c commit 6fa612a
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 36 deletions.
36 changes: 14 additions & 22 deletions src/account/ModularAccountBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ import {UUPSUpgradeable} from "solady/utils/UUPSUpgradeable.sol";

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

import {IModularAccountBase} from "../interfaces/IModularAccountBase.sol";
import {
DensePostHookData,
ExecutionLib,
Expand All @@ -50,6 +52,7 @@ import {TokenReceiver} from "./TokenReceiver.sol";
/// deferred actions during validation.
abstract contract ModularAccountBase is
IModularAccount,
IModularAccountBase,
ModularAccountView,
AccountStorageInitializable,
AccountBase,
Expand Down Expand Up @@ -147,14 +150,12 @@ abstract contract ModularAccountBase is
return execReturnData;
}

/// @notice Create a contract.
/// @param value The value to send to the new contract constructor
/// @param initCode The initCode to deploy.
/// @return createdAddr The created contract address.
/// @inheritdoc IModularAccountBase
function performCreate(uint256 value, bytes calldata initCode, bool isCreate2, bytes32 salt)
external
payable
virtual
override
wrapNativeFunction
returns (address createdAddr)
{
Expand Down Expand Up @@ -338,8 +339,8 @@ abstract contract ModularAccountBase is
_uninstallValidation(validationFunction, uninstallData, hookUninstallData);
}

/// @notice May be validated by a global validation
function invalidateDeferredValidationInstallNonce(uint256 nonce) external wrapNativeFunction {
/// @inheritdoc IModularAccountBase
function invalidateDeferredValidationInstallNonce(uint256 nonce) external override wrapNativeFunction {
getAccountStorage().deferredActionNonceUsed[nonce] = true;
emit DeferredActionNonceInvalidated(nonce);
}
Expand Down Expand Up @@ -378,7 +379,8 @@ abstract contract ModularAccountBase is
super.upgradeToAndCall(newImplementation, data);
}

function isValidSignature(bytes32 hash, bytes calldata signature) public view returns (bytes4) {
/// @inheritdoc IERC1271
function isValidSignature(bytes32 hash, bytes calldata signature) public view override returns (bytes4) {
ModuleEntity sigValidation = ModuleEntity.wrap(bytes24(signature));
signature = signature[24:];
return _isValidSignature(sigValidation, hash, signature);
Expand Down Expand Up @@ -770,21 +772,6 @@ abstract contract ModularAccountBase is
return _1271_INVALID;
}

function _globalValidationAllowed(bytes4 selector) internal view virtual returns (bool) {
if (
selector == this.execute.selector || selector == this.executeBatch.selector
|| selector == this.installExecution.selector || selector == this.uninstallExecution.selector
|| selector == this.installValidation.selector || selector == this.uninstallValidation.selector
|| selector == this.upgradeToAndCall.selector
|| selector == this.invalidateDeferredValidationInstallNonce.selector
|| selector == this.performCreate.selector
) {
return true;
}

return getAccountStorage().executionStorage[selector].allowGlobalValidation;
}

function _isValidationGlobal(ModuleEntity validationFunction) internal view virtual returns (bool) {
return getAccountStorage().validationStorage[validationFunction].isGlobal;
}
Expand Down Expand Up @@ -1015,6 +1002,11 @@ abstract contract ModularAccountBase is
return _globalValidationAllowed(selector) && _isValidationGlobal(validationFunction);
}

function _globalValidationAllowed(bytes4 selector) internal view virtual returns (bool) {
return _isGlobalValidationAllowedNativeFunction(selector)
|| getAccountStorage().executionStorage[selector].allowGlobalValidation;
}

function _selectorValidationApplies(bytes4 selector, ModuleEntity validationFunction)
internal
view
Expand Down
30 changes: 29 additions & 1 deletion src/account/ModularAccountView.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@ import {
ValidationDataView
} from "@erc6900/reference-implementation/interfaces/IModularAccountView.sol";

import {IModularAccount} from "@erc6900/reference-implementation/interfaces/IModularAccount.sol";
import {IModularAccountView} from "@erc6900/reference-implementation/interfaces/IModularAccountView.sol";
import {IAccountExecute} from "@eth-infinitism/account-abstraction/interfaces/IAccountExecute.sol";
import {UUPSUpgradeable} from "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol";

import {NativeFunctionDelegate} from "../helpers/NativeFunctionDelegate.sol";
import {IModularAccountBase} from "../interfaces/IModularAccountBase.sol";
import {MemManagementLib} from "../libraries/MemManagementLib.sol";
import {ExecutionStorage, ValidationStorage, getAccountStorage} from "./AccountStorage.sol";

Expand All @@ -28,9 +34,13 @@ abstract contract ModularAccountView is IModularAccountView {
// return ModularAccountViewLib.getExecutionData(selector, _isNativeFunction(selector));
ExecutionStorage storage executionStorage = getAccountStorage().executionStorage[selector];

if (_isNativeFunction(uint32(selector))) {
if (_isGlobalValidationAllowedNativeFunction(selector)) {
data.module = address(this);
data.allowGlobalValidation = true;
} else if (_isNativeFunction(uint32(selector))) {
// native view functions
data.module = address(this);
data.skipRuntimeValidation = true;
} else {
data.module = executionStorage.module;
data.skipRuntimeValidation = executionStorage.skipRuntimeValidation;
Expand Down Expand Up @@ -68,4 +78,22 @@ abstract contract ModularAccountView is IModularAccountView {
function _isNativeFunction(uint32 selector) internal view virtual returns (bool) {
return _NATIVE_FUNCTION_DELEGATE.isNativeFunction(selector);
}

function _isGlobalValidationAllowedNativeFunction(bytes4 selector) internal view virtual returns (bool) {
if (
selector == IModularAccount.execute.selector || selector == IModularAccount.executeBatch.selector
|| selector == IAccountExecute.executeUserOp.selector
|| selector == IModularAccount.executeWithRuntimeValidation.selector
|| selector == IModularAccount.installExecution.selector
|| selector == IModularAccount.uninstallExecution.selector
|| selector == IModularAccount.installValidation.selector
|| selector == IModularAccount.uninstallValidation.selector
|| selector == UUPSUpgradeable.upgradeToAndCall.selector
|| selector == IModularAccountBase.invalidateDeferredValidationInstallNonce.selector
|| selector == IModularAccountBase.performCreate.selector
) {
return true;
}
return false;
}
}
29 changes: 16 additions & 13 deletions src/helpers/NativeFunctionDelegate.sol
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.26;

import {IModularAccount} from "@erc6900/reference-implementation/interfaces/IModularAccount.sol";
import {IModularAccountView} from "@erc6900/reference-implementation/interfaces/IModularAccountView.sol";
import {IAccount} from "@eth-infinitism/account-abstraction/interfaces/IAccount.sol";
import {IAccountExecute} from "@eth-infinitism/account-abstraction/interfaces/IAccountExecute.sol";
import {IERC1155Receiver} from "@openzeppelin/contracts/interfaces/IERC1155Receiver.sol";
import {IERC1271} from "@openzeppelin/contracts/interfaces/IERC1271.sol";
import {UUPSUpgradeable} from "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol";
import {IERC721Receiver} from "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";

import {ModularAccountBase} from "../account/ModularAccountBase.sol";
import {IModularAccountBase} from "../interfaces/IModularAccountBase.sol";

/// @title Native Function Delegate
/// @author Alchemy
Expand All @@ -20,18 +23,18 @@ contract NativeFunctionDelegate {
// check against IAccount methods
selector == uint32(IAccount.validateUserOp.selector)
// check against ModularAccount methods
|| selector == uint32(ModularAccountBase.installExecution.selector)
|| selector == uint32(ModularAccountBase.uninstallExecution.selector)
|| selector == uint32(ModularAccountBase.installValidation.selector)
|| selector == uint32(ModularAccountBase.uninstallValidation.selector)
|| selector == uint32(ModularAccountBase.execute.selector)
|| selector == uint32(ModularAccountBase.executeBatch.selector)
|| selector == uint32(ModularAccountBase.executeWithRuntimeValidation.selector)
|| selector == uint32(ModularAccountBase.accountId.selector)
|| selector == uint32(ModularAccountBase.performCreate.selector)
|| selector == uint32(ModularAccountBase.invalidateDeferredValidationInstallNonce.selector)
|| selector == uint32(ModularAccountBase.executeUserOp.selector)
|| selector == uint32(ModularAccountBase.isValidSignature.selector)
|| selector == uint32(IModularAccount.installExecution.selector)
|| selector == uint32(IModularAccount.uninstallExecution.selector)
|| selector == uint32(IModularAccount.installValidation.selector)
|| selector == uint32(IModularAccount.uninstallValidation.selector)
|| selector == uint32(IModularAccount.execute.selector)
|| selector == uint32(IModularAccount.executeBatch.selector)
|| selector == uint32(IModularAccount.executeWithRuntimeValidation.selector)
|| selector == uint32(IModularAccount.accountId.selector)
|| selector == uint32(IAccountExecute.executeUserOp.selector)
|| selector == uint32(IModularAccountBase.performCreate.selector)
|| selector == uint32(IModularAccountBase.invalidateDeferredValidationInstallNonce.selector)
|| selector == uint32(IERC1271.isValidSignature.selector)
// check against IModularAccountView methods
|| selector == uint32(IModularAccountView.getExecutionData.selector)
|| selector == uint32(IModularAccountView.getValidationData.selector)
Expand Down
19 changes: 19 additions & 0 deletions src/interfaces/IModularAccountBase.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.26;

interface IModularAccountBase {
/// @notice Create a contract.
/// @param value The value to send to the new contract constructor
/// @param initCode The initCode to deploy.
/// @param isCreate2 The bool to indicate which method to use to deploy.
/// @param salt The salt for deployment.
/// @return createdAddr The created contract address.
function performCreate(uint256 value, bytes calldata initCode, bool isCreate2, bytes32 salt)
external
payable
returns (address createdAddr);

/// @notice Invalidate a nonce for deferred actions
/// @param nonce the nonce to invalidate.
function invalidateDeferredValidationInstallNonce(uint256 nonce) external;
}

0 comments on commit 6fa612a

Please sign in to comment.