diff --git a/.solhint-src.json b/.solhint-src.json
index 9e8685c..2fd5a0f 100644
--- a/.solhint-src.json
+++ b/.solhint-src.json
@@ -1,6 +1,7 @@
{
"extends": "solhint:recommended",
"rules": {
- "compiler-version": ["error", "0.8.24"]
+ "compiler-version": ["error", "0.8.24"],
+ "func-visibility": ["error", { "ignoreConstructors": true }]
}
}
diff --git a/.solhint-test.json b/.solhint-test.json
index 0e04dee..1c29916 100644
--- a/.solhint-test.json
+++ b/.solhint-test.json
@@ -4,6 +4,7 @@
"compiler-version": ["error", "0.8.24"],
"no-unused-vars": "off",
"no-console": "off",
- "func-name-mixedcase": "off"
+ "func-name-mixedcase": "off",
+ "func-visibility": ["error", { "ignoreConstructors": true }]
}
}
diff --git a/foundry.toml b/foundry.toml
index ee79208..4c58eeb 100644
--- a/foundry.toml
+++ b/foundry.toml
@@ -3,7 +3,7 @@ fs_permissions = [{ access = "read-write", path = "./gas"},
{ access = "read", path = "./test/fixtures"}]
src = 'src'
out = 'out'
-libs = ['lib']
+libs = ['lib', 'node_modules']
solc_version = "0.8.24"
test = 'test'
via_ir = true
diff --git a/package.json b/package.json
index b026039..8a197d8 100644
--- a/package.json
+++ b/package.json
@@ -5,7 +5,7 @@
"scripts": {
"clean": "rm -rf cache artifacts typechain-types",
"build": "forge build",
- "lint": "solhint -w 103 -c .solhint-src.json './src/**/*.sol' && solhint -w 241 -c .solhint-test.json './test/**/*.sol' && solhint -w 0 -c .solhint-script.json './script/**/*.sol'",
+ "lint": "solhint -w 0 -c .solhint-src.json './src/**/*.sol' && solhint -w 0 -c .solhint-test.json './test/**/*.sol' && solhint -w 0 -c .solhint-script.json './script/**/*.sol'",
"test": "forge test -vv",
"gasreport": "forge test --gas-report > gas/reports/gas-report.txt",
"coverage": "forge coverage --ir-minimum",
diff --git a/script/002_DeployUpgradableMSCAFactory.s.sol b/script/002_DeployUpgradableMSCAFactory.s.sol
index d24f3c6..e8e5b93 100644
--- a/script/002_DeployUpgradableMSCAFactory.s.sol
+++ b/script/002_DeployUpgradableMSCAFactory.s.sol
@@ -42,7 +42,7 @@ contract DeployUpgradableMSCAFactoryScript is Script {
factory = UpgradableMSCAFactory(EXPECTED_FACTORY_ADDRESS);
console.log("Found existing factory at expected address: %s", address(factory));
}
- console.log("Account implementation address: %s", address(factory.accountImplementation()));
+ console.log("Account implementation address: %s", address(factory.ACCOUNT_IMPLEMENTATION()));
vm.stopBroadcast();
}
}
diff --git a/script/003_DeploySingleOwnerMSCAFactory.s.sol b/script/003_DeploySingleOwnerMSCAFactory.s.sol
index bac1ba7..c5e2b49 100644
--- a/script/003_DeploySingleOwnerMSCAFactory.s.sol
+++ b/script/003_DeploySingleOwnerMSCAFactory.s.sol
@@ -38,7 +38,7 @@ contract DeploySingleOwnerMSCAFactoryScript is Script {
factory = SingleOwnerMSCAFactory(EXPECTED_FACTORY_ADDRESS);
console.log("Found existing single owner MSCA factory at expected address: %s", address(factory));
}
- console.log("Account implementation address: %s", address(factory.accountImplementation()));
+ console.log("Account implementation address: %s", address(factory.ACCOUNT_IMPLEMENTATION()));
vm.stopBroadcast();
}
}
diff --git a/script/005_DeployECDSAAccountFactory.s.sol b/script/005_DeployECDSAAccountFactory.s.sol
index 33b585a..6962d2b 100644
--- a/script/005_DeployECDSAAccountFactory.s.sol
+++ b/script/005_DeployECDSAAccountFactory.s.sol
@@ -40,7 +40,7 @@ contract DeployECDSAAccountFactoryScript is Script {
factory = ECDSAAccountFactory(EXPECTED_FACTORY_ADDRESS);
}
console.log("Factory address: %s", address(factory));
- console.log("Account implementation address: %s", address(factory.accountImplementation()));
+ console.log("Account implementation address: %s", address(factory.ACCOUNT_IMPLEMENTATION()));
vm.stopBroadcast();
}
}
diff --git a/src/account/CoreAccount.sol b/src/account/CoreAccount.sol
index 5c60722..f5f0ecb 100644
--- a/src/account/CoreAccount.sol
+++ b/src/account/CoreAccount.sol
@@ -19,6 +19,7 @@
pragma solidity 0.8.24;
import {DefaultCallbackHandler} from "../callback/DefaultCallbackHandler.sol";
+import {InvalidLength, UnauthorizedCaller} from "../common/Errors.sol";
import {ExecutionUtils} from "../utils/ExecutionUtils.sol";
import {BaseAccount} from "@account-abstraction/contracts/core/BaseAccount.sol";
import {IEntryPoint} from "@account-abstraction/contracts/interfaces/IEntryPoint.sol";
@@ -44,7 +45,7 @@ abstract contract CoreAccount is
{
// bytes4(keccak256("isValidSignature(bytes32,bytes)")
bytes4 internal constant EIP1271_MAGIC_VALUE = 0x1626ba7e;
- IEntryPoint public immutable entryPointAddress;
+ IEntryPoint public immutable ENTRY_POINT_ADDRESS;
/**
* @dev This empty reserved space is put in place to allow future versions to add new
@@ -57,18 +58,21 @@ abstract contract CoreAccount is
function _checkOwner() internal view override {
// directly from EOA owner, or through the account itself (which gets redirected through execute())
- require(msg.sender == owner() || msg.sender == address(this), "Caller is not the owner");
+ if (!(msg.sender == owner() || msg.sender == address(this))) {
+ revert UnauthorizedCaller();
+ }
}
/// @custom:oz-upgrades-unsafe-allow constructor
// for immutable values in implementations
constructor(IEntryPoint _newEntryPoint) {
- entryPointAddress = _newEntryPoint;
+ ENTRY_POINT_ADDRESS = _newEntryPoint;
// lock the implementation contract so it can only be called from proxies
_disableInitializers();
}
// for mutable values in proxies
+ // solhint-disable-next-line func-name-mixedcase
function __CoreAccount_init(address _newOwner) internal onlyInitializing {
__Ownable_init();
transferOwnership(_newOwner);
@@ -77,7 +81,7 @@ abstract contract CoreAccount is
/// @inheritdoc BaseAccount
function entryPoint() public view virtual override returns (IEntryPoint) {
- return entryPointAddress;
+ return ENTRY_POINT_ADDRESS;
}
/// @dev Please override this method
@@ -105,8 +109,9 @@ abstract contract CoreAccount is
whenNotPaused
{
_requireFromEntryPointOrOwner();
- require(dest.length == func.length, "wrong array lengths");
- require(dest.length == value.length, "wrong array lengths");
+ if (dest.length != func.length || dest.length != value.length) {
+ revert InvalidLength();
+ }
for (uint256 i = 0; i < dest.length; i++) {
ExecutionUtils.callAndRevert(dest[i], value[i], func[i]);
}
@@ -116,7 +121,9 @@ abstract contract CoreAccount is
* @dev Require the function call went through EntryPoint or owner.
*/
function _requireFromEntryPointOrOwner() internal view {
- require(msg.sender == address(entryPoint()) || msg.sender == owner(), "account: not EntryPoint or Owner");
+ if (!(msg.sender == address(entryPoint()) || msg.sender == owner())) {
+ revert UnauthorizedCaller();
+ }
}
/**
diff --git a/src/account/v1/ECDSAAccount.sol b/src/account/v1/ECDSAAccount.sol
index 45707ef..b7a42e7 100644
--- a/src/account/v1/ECDSAAccount.sol
+++ b/src/account/v1/ECDSAAccount.sol
@@ -47,6 +47,7 @@ contract ECDSAAccount is CoreAccount, UUPSUpgradeable, BaseERC712CompliantAccoun
/// @inheritdoc UUPSUpgradeable
// The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.
// Authorize the owner to upgrade the contract.
+ // solhint-disable-next-line no-empty-blocks
function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}
/// @custom:oz-upgrades-unsafe-allow constructor
diff --git a/src/account/v1/factory/ECDSAAccountFactory.sol b/src/account/v1/factory/ECDSAAccountFactory.sol
index abc1d41..455a0d5 100644
--- a/src/account/v1/factory/ECDSAAccountFactory.sol
+++ b/src/account/v1/factory/ECDSAAccountFactory.sol
@@ -18,9 +18,9 @@
*/
pragma solidity 0.8.24;
-import "../ECDSAAccount.sol";
-import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
-import "@openzeppelin/contracts/utils/Create2.sol";
+import {ECDSAAccount, IEntryPoint} from "../ECDSAAccount.sol";
+import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
+import {Create2} from "@openzeppelin/contracts/utils/Create2.sol";
/**
* @dev Account factory that creates the upgradeable account signed and verified by ECDSA.
@@ -29,10 +29,10 @@ contract ECDSAAccountFactory {
event AccountCreated(address indexed proxy, address indexed owner);
// logic implementation
- ECDSAAccount public immutable accountImplementation;
+ ECDSAAccount public immutable ACCOUNT_IMPLEMENTATION;
constructor(IEntryPoint _entryPoint) {
- accountImplementation = new ECDSAAccount(_entryPoint);
+ ACCOUNT_IMPLEMENTATION = new ECDSAAccount(_entryPoint);
}
/**
@@ -76,7 +76,7 @@ contract ECDSAAccountFactory {
account = ECDSAAccount(
payable(
new ERC1967Proxy{salt: _salt}(
- address(accountImplementation), abi.encodeCall(ECDSAAccount.initialize, (_owner))
+ address(ACCOUNT_IMPLEMENTATION), abi.encodeCall(ECDSAAccount.initialize, (_owner))
)
)
);
@@ -92,7 +92,7 @@ contract ECDSAAccountFactory {
bytes32 code = keccak256(
abi.encodePacked(
type(ERC1967Proxy).creationCode,
- abi.encode(address(accountImplementation), abi.encodeCall(ECDSAAccount.initialize, (_owner)))
+ abi.encode(address(ACCOUNT_IMPLEMENTATION), abi.encodeCall(ECDSAAccount.initialize, (_owner)))
)
);
// call computeAddress(salt, bytecodeHash, address(this))
diff --git a/src/callback/DefaultCallbackHandler.sol b/src/callback/DefaultCallbackHandler.sol
index 3e45766..5aaa44e 100644
--- a/src/callback/DefaultCallbackHandler.sol
+++ b/src/callback/DefaultCallbackHandler.sol
@@ -64,5 +64,7 @@ contract DefaultCallbackHandler is IERC721Receiver, IERC1155Receiver, IERC777Rec
uint256 amount,
bytes calldata userData,
bytes calldata operatorData
- ) external pure override {}
+ ) external pure override
+ // solhint-disable-next-line no-empty-blocks
+ {}
}
diff --git a/src/common/Errors.sol b/src/common/Errors.sol
new file mode 100644
index 0000000..7d1820d
--- /dev/null
+++ b/src/common/Errors.sol
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2024 Circle Internet Group, Inc. All rights reserved.
+
+ * SPDX-License-Identifier: GPL-3.0-or-later
+
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+pragma solidity 0.8.24;
+
+/**
+ * @notice Throws when the caller is unexpected.
+ */
+error UnauthorizedCaller();
+
+error InvalidLength();
+
+error Unsupported();
diff --git a/src/libs/CastLib.sol b/src/libs/CastLib.sol
index a962b47..5a59a82 100644
--- a/src/libs/CastLib.sol
+++ b/src/libs/CastLib.sol
@@ -28,6 +28,7 @@ library CastLib {
function toAddressArray(SetValue[] memory values) internal pure returns (address[] memory addresses) {
bytes32[] memory valuesBytes;
+ // solhint-disable-next-line no-inline-assembly
assembly ("memory-safe") {
valuesBytes := values
}
@@ -37,6 +38,7 @@ library CastLib {
valuesBytes[i] >>= 96;
}
+ // solhint-disable-next-line no-inline-assembly
assembly ("memory-safe") {
addresses := valuesBytes
}
diff --git a/src/libs/MessageHashUtils.sol b/src/libs/MessageHashUtils.sol
index e66b1b0..13c789b 100644
--- a/src/libs/MessageHashUtils.sol
+++ b/src/libs/MessageHashUtils.sol
@@ -38,6 +38,7 @@ library MessageHashUtils {
*/
function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 digest) {
/// @solidity memory-safe-assembly
+ // solhint-disable-next-line no-inline-assembly
assembly {
let ptr := mload(0x40)
mstore(ptr, hex"1901")
diff --git a/src/msca/6900/shared/common/Errors.sol b/src/msca/6900/shared/common/Errors.sol
index de8f196..1ff3372 100644
--- a/src/msca/6900/shared/common/Errors.sol
+++ b/src/msca/6900/shared/common/Errors.sol
@@ -18,11 +18,6 @@
*/
pragma solidity 0.8.24;
-/**
- * @notice Throws when the caller is unexpected.
- */
-error UnauthorizedCaller();
-
/**
* @notice Throws when the selector is not found.
*/
@@ -49,10 +44,6 @@ error InvalidInitializationInput();
error Create2FailedDeployment();
-error InvalidLength();
-
-error Unsupported();
-
error NotImplemented(bytes4 selector, uint8 functionId);
error InvalidItem();
diff --git a/src/msca/6900/shared/libs/AddressDLLLib.sol b/src/msca/6900/shared/libs/AddressDLLLib.sol
index cacbf91..1641270 100644
--- a/src/msca/6900/shared/libs/AddressDLLLib.sol
+++ b/src/msca/6900/shared/libs/AddressDLLLib.sol
@@ -117,6 +117,8 @@ library AddressDLLLib {
results[count] = current;
current = dll.next[current];
}
+
+ // solhint-disable-next-line no-inline-assembly
assembly ("memory-safe") {
mstore(results, count)
}
diff --git a/src/msca/6900/shared/libs/Bytes4DLLLib.sol b/src/msca/6900/shared/libs/Bytes4DLLLib.sol
index e9b40e1..79d8c3d 100644
--- a/src/msca/6900/shared/libs/Bytes4DLLLib.sol
+++ b/src/msca/6900/shared/libs/Bytes4DLLLib.sol
@@ -110,6 +110,7 @@ library Bytes4DLLLib {
results[count] = current;
current = dll.next[current];
}
+ // solhint-disable-next-line no-inline-assembly
assembly ("memory-safe") {
mstore(results, count)
}
diff --git a/src/msca/6900/v0.7/account/BaseMSCA.sol b/src/msca/6900/v0.7/account/BaseMSCA.sol
index a6dbdbc..974ae12 100644
--- a/src/msca/6900/v0.7/account/BaseMSCA.sol
+++ b/src/msca/6900/v0.7/account/BaseMSCA.sol
@@ -24,13 +24,14 @@ import {
WALLET_AUTHOR,
WALLET_VERSION_1
} from "../../../../common/Constants.sol";
+
+import {UnauthorizedCaller} from "../../../../common/Errors.sol";
import {ExecutionUtils} from "../../../../utils/ExecutionUtils.sol";
import {
InvalidAuthorizer,
InvalidExecutionFunction,
InvalidValidationFunctionId,
- NotFoundSelector,
- UnauthorizedCaller
+ NotFoundSelector
} from "../../shared/common/Errors.sol";
import {AddressDLL, ValidationData} from "../../shared/common/Structs.sol";
import {AddressDLLLib} from "../../shared/libs/AddressDLLLib.sol";
@@ -39,7 +40,16 @@ import {
PRE_HOOK_ALWAYS_DENY_FUNCTION_REFERENCE,
RUNTIME_VALIDATION_ALWAYS_ALLOW_FUNCTION_REFERENCE
} from "../common/Constants.sol";
-import "../common/Structs.sol";
+import {
+ Call,
+ ExecutionDetail,
+ ExecutionFunctionConfig,
+ ExecutionHooks,
+ FunctionReference,
+ HookGroup,
+ PostExecHookToRun,
+ RepeatableBytes21DLL
+} from "../common/Structs.sol";
import {IAccountLoupe} from "../interfaces/IAccountLoupe.sol";
import {IPlugin} from "../interfaces/IPlugin.sol";
import {IPluginExecutor} from "../interfaces/IPluginExecutor.sol";
@@ -86,11 +96,11 @@ abstract contract BaseMSCA is
using ValidationDataLib for ValidationData;
using SelectorRegistryLib for bytes4;
- string public constant author = WALLET_AUTHOR;
- string public constant version = WALLET_VERSION_1;
+ string public constant AUTHOR = WALLET_AUTHOR;
+ string public constant VERSION = WALLET_VERSION_1;
// 4337 related immutable storage
- IEntryPoint public immutable entryPoint;
- PluginManager public immutable pluginManager;
+ IEntryPoint public immutable ENTRY_POINT;
+ PluginManager public immutable PLUGIN_MANAGER;
error NotNativeFunctionSelector(bytes4 selector);
error InvalidHookFunctionId(uint8 functionId);
@@ -120,8 +130,8 @@ abstract contract BaseMSCA is
}
constructor(IEntryPoint _newEntryPoint, PluginManager _newPluginManager) {
- entryPoint = _newEntryPoint;
- pluginManager = _newPluginManager;
+ ENTRY_POINT = _newEntryPoint;
+ PLUGIN_MANAGER = _newPluginManager;
// lock the implementation contract so it can only be called from proxies
_disableWalletStorageInitializers();
}
@@ -131,10 +141,11 @@ abstract contract BaseMSCA is
/// @notice Manage fallback calls made to the plugins.
/// @dev Route calls to execution functions based on incoming msg.sig
/// If there's no plugin associated with this function selector, revert
+ // solhint-disable-next-line no-complex-fallback
fallback(bytes calldata) external payable returns (bytes memory result) {
// run runtime validation before we load the executionDetail because validation may update account state
- if (msg.sender != address(entryPoint)) {
- // entryPoint should go through validateUserOp flow which calls userOpValidationFunction
+ if (msg.sender != address(ENTRY_POINT)) {
+ // ENTRY_POINT should go through validateUserOp flow which calls userOpValidationFunction
_processPreRuntimeHooksAndValidation(msg.sig);
}
// load the executionDetail before we run the preExecHooks because they may modify the plugins
@@ -151,11 +162,11 @@ abstract contract BaseMSCA is
}
/**
- * @dev Return the entryPoint used by this account.
- * subclass should return the current entryPoint used by this account.
+ * @dev Return the ENTRY_POINT used by this account.
+ * subclass should return the current ENTRY_POINT used by this account.
*/
function getEntryPoint() external view returns (IEntryPoint) {
- return entryPoint;
+ return ENTRY_POINT;
}
/**
@@ -168,7 +179,7 @@ abstract contract BaseMSCA is
virtual
returns (uint256 validationData)
{
- if (msg.sender != address(entryPoint)) {
+ if (msg.sender != address(ENTRY_POINT)) {
revert UnauthorizedCaller();
}
validationData = _authenticateAndAuthorizeUserOp(userOp, userOpHash);
@@ -199,7 +210,7 @@ abstract contract BaseMSCA is
* For a nonce of a specific key, use `entrypoint.getNonce(account, key)`
*/
function getNonce() public view virtual returns (uint256) {
- return entryPoint.getNonce(address(this), 0);
+ return ENTRY_POINT.getNonce(address(this), 0);
}
function installPlugin(
@@ -211,7 +222,7 @@ abstract contract BaseMSCA is
bytes memory data = abi.encodeCall(
PluginManager.install, (plugin, manifestHash, pluginInstallData, dependencies, address(this))
);
- address(pluginManager).delegateCall(data);
+ address(PLUGIN_MANAGER).delegateCall(data);
emit PluginInstalled(plugin, manifestHash, dependencies);
}
@@ -221,7 +232,7 @@ abstract contract BaseMSCA is
validateNativeFunction
{
bytes memory data = abi.encodeCall(PluginManager.uninstall, (plugin, config, pluginUninstallData));
- address(pluginManager).delegateCall(data);
+ address(PLUGIN_MANAGER).delegateCall(data);
emit PluginUninstalled(plugin, true);
}
@@ -313,17 +324,17 @@ abstract contract BaseMSCA is
}
/**
- * Check current account deposit in the entryPoint.
+ * Check current account deposit in the ENTRY_POINT.
*/
function getDeposit() public view returns (uint256) {
- return entryPoint.balanceOf(address(this));
+ return ENTRY_POINT.balanceOf(address(this));
}
/**
- * Deposit more funds for this account in the entryPoint.
+ * Deposit more funds for this account in the ENTRY_POINT.
*/
function addDeposit() public payable {
- entryPoint.depositTo{value: msg.value}(address(this));
+ ENTRY_POINT.depositTo{value: msg.value}(address(this));
}
/**
@@ -332,7 +343,7 @@ abstract contract BaseMSCA is
* @param amount to withdraw
*/
function withdrawDepositTo(address payable withdrawAddress, uint256 amount) public onlyFromEntryPointOrSelf {
- entryPoint.withdrawTo(withdrawAddress, amount);
+ ENTRY_POINT.withdrawTo(withdrawAddress, amount);
}
/**
@@ -427,6 +438,7 @@ abstract contract BaseMSCA is
revert InvalidValidationFunctionId(preRuntimeValidationHooks[j].functionId);
}
IPlugin preRuntimeValidationHookPlugin = IPlugin(preRuntimeValidationHooks[j].plugin);
+ // solhint-disable no-empty-blocks
try preRuntimeValidationHookPlugin.preRuntimeValidationHook(
preRuntimeValidationHooks[j].functionId, msg.sender, msg.value, msg.data
) {} catch (bytes memory revertReason) {
@@ -434,6 +446,7 @@ abstract contract BaseMSCA is
preRuntimeValidationHooks[j].plugin, preRuntimeValidationHooks[j].functionId, revertReason
);
}
+ // solhint-enable no-empty-blocks
}
if (nextHook.pack() == SENTINEL_BYTES21) {
break;
@@ -442,11 +455,13 @@ abstract contract BaseMSCA is
}
// call runtimeValidationFunction if it's not always allowed
if (packedValidationFunction != RUNTIME_VALIDATION_ALWAYS_ALLOW_FUNCTION_REFERENCE) {
+ // solhint-disable no-empty-blocks
try IPlugin(validationFunction.plugin).runtimeValidationFunction(
validationFunction.functionId, msg.sender, msg.value, msg.data
) {} catch (bytes memory revertReason) {
revert RuntimeValidationFailed(validationFunction.plugin, validationFunction.functionId, revertReason);
}
+ // solhint-enable no-empty-blocks
}
}
@@ -455,8 +470,8 @@ abstract contract BaseMSCA is
if (!msg.sig._isNativeFunctionSelector()) {
revert NotNativeFunctionSelector(msg.sig);
}
- if (msg.sender != address(entryPoint)) {
- // entryPoint should go through validateUserOp flow which calls userOpValidationFunction
+ if (msg.sender != address(ENTRY_POINT)) {
+ // ENTRY_POINT should go through validateUserOp flow which calls userOpValidationFunction
_processPreRuntimeHooksAndValidation(msg.sig);
}
return WalletStorageV1Lib.getLayout().executionDetails[msg.sig].executionHooks._processPreExecHooks(msg.data);
@@ -507,7 +522,7 @@ abstract contract BaseMSCA is
}
function _checkAccessRuleFromEPOrAcctItself() internal view {
- if (msg.sender != address(entryPoint) && msg.sender != address(this)) {
+ if (msg.sender != address(ENTRY_POINT) && msg.sender != address(this)) {
revert UnauthorizedCaller();
}
}
diff --git a/src/msca/6900/v0.7/account/UpgradableMSCA.sol b/src/msca/6900/v0.7/account/UpgradableMSCA.sol
index fdaa09b..cc757bf 100644
--- a/src/msca/6900/v0.7/account/UpgradableMSCA.sol
+++ b/src/msca/6900/v0.7/account/UpgradableMSCA.sol
@@ -18,6 +18,7 @@
*/
pragma solidity 0.8.24;
+import {DefaultCallbackHandler} from "../../../../callback/DefaultCallbackHandler.sol";
import {ExecutionUtils} from "../../../../utils/ExecutionUtils.sol";
import {InvalidInitializationInput} from "../../shared/common/Errors.sol";
import {FunctionReference} from "../common/Structs.sol";
@@ -26,23 +27,24 @@ import {BaseMSCA} from "./BaseMSCA.sol";
import {IEntryPoint} from "@account-abstraction/contracts/interfaces/IEntryPoint.sol";
import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
+import {IERC1271} from "@openzeppelin/contracts/interfaces/IERC1271.sol";
+import {IERC1155Receiver} from "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol";
+import {IERC721Receiver} from "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
+
/**
* @dev Leverage {ERC1967Proxy} brought by UUPS proxies, when this contract is set as the implementation behind such a
* proxy.
* The {_authorizeUpgrade} function is overridden here so more granular ACLs to the upgrade mechanism should be enforced
* by plugins.
*/
-contract UpgradableMSCA is BaseMSCA, UUPSUpgradeable {
+contract UpgradableMSCA is BaseMSCA, DefaultCallbackHandler, UUPSUpgradeable {
using ExecutionUtils for address;
event UpgradableMSCAInitialized(address indexed account, address indexed entryPointAddress);
constructor(IEntryPoint _newEntryPoint, PluginManager _newPluginManager)
BaseMSCA(_newEntryPoint, _newPluginManager)
- {
- // lock the implementation contract so it can only be called from proxies
- _disableWalletStorageInitializers();
- }
+ {}
/// @notice Initializes the account with a set of plugins
/// @dev No dependencies can be injected with this installation. For a full installation, please use installPlugin.
@@ -66,10 +68,21 @@ contract UpgradableMSCA is BaseMSCA, UUPSUpgradeable {
PluginManager.install,
(plugins[i], manifestHashes[i], pluginInstallData[i], dependencies, address(this))
);
- address(pluginManager).delegateCall(data);
+ address(PLUGIN_MANAGER).delegateCall(data);
emit PluginInstalled(plugins[i], manifestHashes[i], dependencies);
}
- emit UpgradableMSCAInitialized(address(this), address(entryPoint));
+ emit UpgradableMSCAInitialized(address(this), address(ENTRY_POINT));
+ }
+
+ function supportsInterface(bytes4 interfaceId)
+ public
+ view
+ override(BaseMSCA, DefaultCallbackHandler)
+ returns (bool)
+ {
+ // BaseMSCA has already implemented ERC165
+ return BaseMSCA.supportsInterface(interfaceId) || interfaceId == type(IERC721Receiver).interfaceId
+ || interfaceId == type(IERC1155Receiver).interfaceId || interfaceId == type(IERC1271).interfaceId;
}
/// @inheritdoc UUPSUpgradeable
@@ -92,5 +105,6 @@ contract UpgradableMSCA is BaseMSCA, UUPSUpgradeable {
* @dev The function is overridden here so more granular ACLs to the upgrade mechanism should be enforced by
* plugins.
*/
+ // solhint-disable-next-line no-empty-blocks
function _authorizeUpgrade(address newImplementation) internal override {}
}
diff --git a/src/msca/6900/v0.7/account/WalletStorageInitializable.sol b/src/msca/6900/v0.7/account/WalletStorageInitializable.sol
index 2243d70..91dcaa0 100644
--- a/src/msca/6900/v0.7/account/WalletStorageInitializable.sol
+++ b/src/msca/6900/v0.7/account/WalletStorageInitializable.sol
@@ -43,7 +43,23 @@ abstract contract WalletStorageInitializable {
* Emits an {WalletStorageInitialized} event.
*/
modifier walletStorageInitializer() {
- bool isTopLevelCall = _setWalletStorageInitializing();
+ bool isTopLevelCall = !WalletStorageV1Lib.getLayout().initializing;
+ uint8 initialized = WalletStorageV1Lib.getLayout().initialized;
+
+ // Allowed calls:
+ // - initialSetup: the contract is not in the initializing state and no previous version was
+ // initialized
+ // - deploying: the contract is initialized at version 1 (no reininitialization) and the
+ // current contract is just being deployed
+ bool initialSetup = initialized == 0 && isTopLevelCall;
+ bool deploying = initialized == 1 && address(this).code.length == 0;
+ if (!initialSetup && !deploying) {
+ revert WalletStorageIsInitialized();
+ }
+ WalletStorageV1Lib.getLayout().initialized = 1;
+ if (isTopLevelCall) {
+ WalletStorageV1Lib.getLayout().initializing = true;
+ }
_;
if (isTopLevelCall) {
WalletStorageV1Lib.getLayout().initializing = false;
@@ -79,17 +95,4 @@ abstract contract WalletStorageInitializable {
emit WalletStorageInitialized();
}
}
-
- function _setWalletStorageInitializing() internal returns (bool) {
- bool isTopLevelCall = !WalletStorageV1Lib.getLayout().initializing;
- uint8 initialized = WalletStorageV1Lib.getLayout().initialized;
- if (!(isTopLevelCall && initialized < 1) || (address(this).code.length <= 0 && initialized == 1)) {
- revert WalletStorageIsInitialized();
- }
- WalletStorageV1Lib.getLayout().initialized = 1;
- if (isTopLevelCall) {
- WalletStorageV1Lib.getLayout().initializing = true;
- }
- return isTopLevelCall;
- }
}
diff --git a/src/msca/6900/v0.7/account/semi/SingleOwnerMSCA.sol b/src/msca/6900/v0.7/account/semi/SingleOwnerMSCA.sol
index 8b0f46f..cfd25f9 100644
--- a/src/msca/6900/v0.7/account/semi/SingleOwnerMSCA.sol
+++ b/src/msca/6900/v0.7/account/semi/SingleOwnerMSCA.sol
@@ -30,13 +30,10 @@ import {
SIG_VALIDATION_SUCCEEDED,
WALLET_VERSION_1
} from "../../../../../common/Constants.sol";
+
+import {UnauthorizedCaller} from "../../../../../common/Errors.sol";
import {ExecutionUtils} from "../../../../../utils/ExecutionUtils.sol";
-import {
- InvalidAuthorizer,
- InvalidValidationFunctionId,
- NotFoundSelector,
- UnauthorizedCaller
-} from "../../../shared/common/Errors.sol";
+import {InvalidAuthorizer, InvalidValidationFunctionId, NotFoundSelector} from "../../../shared/common/Errors.sol";
import {ValidationData} from "../../../shared/common/Structs.sol";
import {ValidationDataLib} from "../../../shared/libs/ValidationDataLib.sol";
import {
@@ -99,10 +96,7 @@ contract SingleOwnerMSCA is BaseMSCA, DefaultCallbackHandler, UUPSUpgradeable, I
constructor(IEntryPoint _newEntryPoint, PluginManager _newPluginManager)
BaseMSCA(_newEntryPoint, _newPluginManager)
- {
- // lock the implementation contract so it can only be called from proxies
- _disableWalletStorageInitializers();
- }
+ {}
/// @notice Initializes the account with a set of plugins
/// @dev No dependencies or hooks can be injected with this installation. For a full installation, please use
@@ -113,17 +107,22 @@ contract SingleOwnerMSCA is BaseMSCA, DefaultCallbackHandler, UUPSUpgradeable, I
revert InvalidOwnerForMSCA(address(this), owner);
}
_transferNativeOwnership(owner);
- emit SingleOwnerMSCAInitialized(address(this), address(entryPoint), owner);
+ emit SingleOwnerMSCAInitialized(address(this), address(ENTRY_POINT), owner);
}
/// @inheritdoc IERC1271
function isValidSignature(bytes32 hash, bytes memory signature) external view override returns (bytes4) {
address owner = WalletStorageV1Lib.getLayout().owner;
if (owner == address(0)) {
+ ExecutionDetail storage executionDetail =
+ WalletStorageV1Lib.getLayout().executionDetails[IERC1271.isValidSignature.selector];
+ // this is a sanity check only, as using address(0) as a plugin is not permitted during installation
+ if (executionDetail.plugin == address(0)) {
+ return EIP1271_INVALID_SIGNATURE;
+ }
// isValidSignature is installed via plugin, so it should fallback to the plugin
- (bool success, bytes memory returnData) = WalletStorageV1Lib.getLayout().executionDetails[IERC1271
- .isValidSignature
- .selector].plugin.staticcall(abi.encodeCall(IERC1271.isValidSignature, (hash, signature)));
+ (bool success, bytes memory returnData) =
+ executionDetail.plugin.staticcall(abi.encodeCall(IERC1271.isValidSignature, (hash, signature)));
if (!success) {
return EIP1271_INVALID_SIGNATURE;
}
@@ -258,8 +257,8 @@ contract SingleOwnerMSCA is BaseMSCA, DefaultCallbackHandler, UUPSUpgradeable, I
}
function _processPreRuntimeHooksAndValidation(bytes4 selector) internal override {
- if (msg.sender == address(entryPoint)) {
- // entryPoint should go through validateUserOp flow which calls userOpValidationFunction
+ if (msg.sender == address(ENTRY_POINT)) {
+ // ENTRY_POINT should go through validateUserOp flow which calls userOpValidationFunction
return;
}
ExecutionDetail storage executionDetail = WalletStorageV1Lib.getLayout().executionDetails[selector];
@@ -284,6 +283,7 @@ contract SingleOwnerMSCA is BaseMSCA, DefaultCallbackHandler, UUPSUpgradeable, I
revert InvalidValidationFunctionId(preRuntimeValidationHooks[j].functionId);
}
IPlugin preRuntimeValidationHookPlugin = IPlugin(preRuntimeValidationHooks[j].plugin);
+ // solhint-disable no-empty-blocks
try preRuntimeValidationHookPlugin.preRuntimeValidationHook(
preRuntimeValidationHooks[j].functionId, msg.sender, msg.value, msg.data
) {} catch (bytes memory revertReason) {
@@ -291,6 +291,7 @@ contract SingleOwnerMSCA is BaseMSCA, DefaultCallbackHandler, UUPSUpgradeable, I
preRuntimeValidationHooks[j].plugin, preRuntimeValidationHooks[j].functionId, revertReason
);
}
+ // solhint-enable no-empty-blocks
}
if (nextHook.pack() == SENTINEL_BYTES21) {
break;
@@ -309,6 +310,7 @@ contract SingleOwnerMSCA is BaseMSCA, DefaultCallbackHandler, UUPSUpgradeable, I
}
// call runtimeValidationFunction if it's not always allowed
if (packedValidationFunction != RUNTIME_VALIDATION_ALWAYS_ALLOW_FUNCTION_REFERENCE) {
+ // solhint-disable no-empty-blocks
try IPlugin(validationFunction.plugin).runtimeValidationFunction(
validationFunction.functionId, msg.sender, msg.value, msg.data
) {} catch (bytes memory revertReason) {
@@ -316,6 +318,7 @@ contract SingleOwnerMSCA is BaseMSCA, DefaultCallbackHandler, UUPSUpgradeable, I
validationFunction.plugin, validationFunction.functionId, revertReason
);
}
+ // solhint-enable no-empty-blocks
}
return;
} else {
@@ -350,6 +353,7 @@ contract SingleOwnerMSCA is BaseMSCA, DefaultCallbackHandler, UUPSUpgradeable, I
* @dev The function is overridden here so more granular ACLs to the upgrade mechanism should be enforced by
* plugins.
*/
+ // solhint-disable-next-line no-empty-blocks
function _authorizeUpgrade(address newImplementation) internal override {}
function _processPreUserOpValidationHooks(
@@ -399,7 +403,7 @@ contract SingleOwnerMSCA is BaseMSCA, DefaultCallbackHandler, UUPSUpgradeable, I
function _checkFromEPOrOwnerOrSelf() internal view {
// all need to go through validation first, which means being initiated by the owner or account
if (
- msg.sender != address(entryPoint) && msg.sender != WalletStorageV1Lib.getLayout().owner
+ msg.sender != address(ENTRY_POINT) && msg.sender != WalletStorageV1Lib.getLayout().owner
&& msg.sender != address(this)
) {
revert UnauthorizedCaller();
diff --git a/src/msca/6900/v0.7/factories/UpgradableMSCAFactory.sol b/src/msca/6900/v0.7/factories/UpgradableMSCAFactory.sol
index 0e0fc62..76a111b 100644
--- a/src/msca/6900/v0.7/factories/UpgradableMSCAFactory.sol
+++ b/src/msca/6900/v0.7/factories/UpgradableMSCAFactory.sol
@@ -18,7 +18,8 @@
*/
pragma solidity 0.8.24;
-import {Create2FailedDeployment, InvalidInitializationInput, InvalidLength} from "../../shared/common/Errors.sol";
+import {InvalidLength} from "../../../../common/Errors.sol";
+import {Create2FailedDeployment, InvalidInitializationInput} from "../../shared/common/Errors.sol";
import {UpgradableMSCA} from "../account/UpgradableMSCA.sol";
import {PluginManager} from "../managers/PluginManager.sol";
import {IEntryPoint} from "@account-abstraction/contracts/interfaces/IEntryPoint.sol";
@@ -35,8 +36,8 @@ import {Create2} from "@openzeppelin/contracts/utils/Create2.sol";
*/
contract UpgradableMSCAFactory is Ownable2Step {
// logic implementation
- UpgradableMSCA public immutable accountImplementation;
- IEntryPoint public immutable entryPoint;
+ UpgradableMSCA public immutable ACCOUNT_IMPLEMENTATION;
+ IEntryPoint public immutable ENTRY_POINT;
mapping(address => bool) public isPluginAllowed;
event FactoryDeployed(address indexed factory, address accountImplementation, address entryPoint);
@@ -45,11 +46,11 @@ contract UpgradableMSCAFactory is Ownable2Step {
error PluginIsNotAllowed(address plugin);
constructor(address _owner, address _entryPointAddr, address _pluginManagerAddr) {
- entryPoint = IEntryPoint(_entryPointAddr);
+ ENTRY_POINT = IEntryPoint(_entryPointAddr);
PluginManager _pluginManager = PluginManager(_pluginManagerAddr);
_transferOwnership(_owner);
- accountImplementation = new UpgradableMSCA(entryPoint, _pluginManager);
- emit FactoryDeployed(address(this), address(accountImplementation), _entryPointAddr);
+ ACCOUNT_IMPLEMENTATION = new UpgradableMSCA(ENTRY_POINT, _pluginManager);
+ emit FactoryDeployed(address(this), address(ACCOUNT_IMPLEMENTATION), _entryPointAddr);
}
function setPlugins(address[] calldata _plugins, bool[] calldata _permissions) external onlyOwner {
@@ -94,7 +95,7 @@ contract UpgradableMSCAFactory is Ownable2Step {
account = UpgradableMSCA(
payable(
new ERC1967Proxy{salt: mixedSalt}(
- address(accountImplementation),
+ address(ACCOUNT_IMPLEMENTATION),
abi.encodeCall(
UpgradableMSCA.initializeUpgradableMSCA, (_plugins, _manifestHashes, _pluginInstallData)
)
@@ -132,7 +133,7 @@ contract UpgradableMSCAFactory is Ownable2Step {
* @param _unstakeDelaySec - the unstake delay for this entity. Can only be increased.
*/
function addStake(uint32 _unstakeDelaySec) public payable onlyOwner {
- entryPoint.addStake{value: msg.value}(_unstakeDelaySec);
+ ENTRY_POINT.addStake{value: msg.value}(_unstakeDelaySec);
}
/**
@@ -140,7 +141,7 @@ contract UpgradableMSCAFactory is Ownable2Step {
* @notice This entity can't serve requests once unlocked, until it calls addStake again.
*/
function unlockStake() public onlyOwner {
- entryPoint.unlockStake();
+ ENTRY_POINT.unlockStake();
}
/**
@@ -149,7 +150,7 @@ contract UpgradableMSCAFactory is Ownable2Step {
* @param _withdrawAddress the address to send withdrawn value.
*/
function withdrawStake(address payable _withdrawAddress) public onlyOwner {
- entryPoint.withdrawStake(_withdrawAddress);
+ ENTRY_POINT.withdrawStake(_withdrawAddress);
}
/**
@@ -187,7 +188,7 @@ contract UpgradableMSCAFactory is Ownable2Step {
abi.encodePacked(
type(ERC1967Proxy).creationCode,
abi.encode(
- address(accountImplementation),
+ address(ACCOUNT_IMPLEMENTATION),
abi.encodeCall(
UpgradableMSCA.initializeUpgradableMSCA, (_plugins, _manifestHashes, _pluginInstallData)
)
diff --git a/src/msca/6900/v0.7/factories/semi/SingleOwnerMSCAFactory.sol b/src/msca/6900/v0.7/factories/semi/SingleOwnerMSCAFactory.sol
index a567fd2..12b3182 100644
--- a/src/msca/6900/v0.7/factories/semi/SingleOwnerMSCAFactory.sol
+++ b/src/msca/6900/v0.7/factories/semi/SingleOwnerMSCAFactory.sol
@@ -31,8 +31,8 @@ import {Create2} from "@openzeppelin/contracts/utils/Create2.sol";
*/
contract SingleOwnerMSCAFactory {
// logic implementation
- SingleOwnerMSCA public immutable accountImplementation;
- IEntryPoint public immutable entryPoint;
+ SingleOwnerMSCA public immutable ACCOUNT_IMPLEMENTATION;
+ IEntryPoint public immutable ENTRY_POINT;
event FactoryDeployed(address indexed factory, address accountImplementation, address entryPoint);
event AccountCreated(address indexed proxy, address sender, bytes32 salt);
@@ -46,10 +46,10 @@ contract SingleOwnerMSCAFactory {
* of more complicated plugins, please call installPlugin via a separate tx/userOp after account deployment.
*/
constructor(address _entryPointAddr, address _pluginManagerAddr) {
- entryPoint = IEntryPoint(_entryPointAddr);
+ ENTRY_POINT = IEntryPoint(_entryPointAddr);
PluginManager _pluginManager = PluginManager(_pluginManagerAddr);
- accountImplementation = new SingleOwnerMSCA(entryPoint, _pluginManager);
- emit FactoryDeployed(address(this), address(accountImplementation), _entryPointAddr);
+ ACCOUNT_IMPLEMENTATION = new SingleOwnerMSCA(ENTRY_POINT, _pluginManager);
+ emit FactoryDeployed(address(this), address(ACCOUNT_IMPLEMENTATION), _entryPointAddr);
}
/**
@@ -82,7 +82,7 @@ contract SingleOwnerMSCAFactory {
account = SingleOwnerMSCA(
payable(
new ERC1967Proxy{salt: mixedSalt}(
- address(accountImplementation), abi.encodeCall(SingleOwnerMSCA.initializeSingleOwnerMSCA, (owner))
+ address(ACCOUNT_IMPLEMENTATION), abi.encodeCall(SingleOwnerMSCA.initializeSingleOwnerMSCA, (owner))
)
)
);
@@ -136,7 +136,7 @@ contract SingleOwnerMSCAFactory {
abi.encodePacked(
type(ERC1967Proxy).creationCode,
abi.encode(
- address(accountImplementation), abi.encodeCall(SingleOwnerMSCA.initializeSingleOwnerMSCA, (_owner))
+ address(ACCOUNT_IMPLEMENTATION), abi.encodeCall(SingleOwnerMSCA.initializeSingleOwnerMSCA, (_owner))
)
)
);
diff --git a/src/msca/6900/v0.7/interfaces/IAccountLoupe.sol b/src/msca/6900/v0.7/interfaces/IAccountLoupe.sol
index 6647ad5..aa80e55 100644
--- a/src/msca/6900/v0.7/interfaces/IAccountLoupe.sol
+++ b/src/msca/6900/v0.7/interfaces/IAccountLoupe.sol
@@ -18,7 +18,7 @@
*/
pragma solidity 0.8.24;
-import "../common/Structs.sol";
+import {ExecutionFunctionConfig, ExecutionHooks, FunctionReference} from "../common/Structs.sol";
/**
* @dev Implements https://eips.ethereum.org/EIPS/eip-6900. MSCAs may implement this interface to support visibility in
diff --git a/src/msca/6900/v0.7/interfaces/IPlugin.sol b/src/msca/6900/v0.7/interfaces/IPlugin.sol
index b932ec6..80ec369 100644
--- a/src/msca/6900/v0.7/interfaces/IPlugin.sol
+++ b/src/msca/6900/v0.7/interfaces/IPlugin.sol
@@ -18,8 +18,7 @@
*/
pragma solidity 0.8.24;
-import "../common/PluginManifest.sol";
-import "../common/Structs.sol";
+import {PluginManifest, PluginMetadata} from "../common/PluginManifest.sol";
import {UserOperation} from "@account-abstraction/contracts/interfaces/UserOperation.sol";
/**
diff --git a/src/msca/6900/v0.7/interfaces/IPluginManager.sol b/src/msca/6900/v0.7/interfaces/IPluginManager.sol
index 0d816bd..e6de207 100644
--- a/src/msca/6900/v0.7/interfaces/IPluginManager.sol
+++ b/src/msca/6900/v0.7/interfaces/IPluginManager.sol
@@ -18,7 +18,7 @@
*/
pragma solidity 0.8.24;
-import "../common/Structs.sol";
+import {FunctionReference} from "../common/Structs.sol";
/**
* @dev Implements https://eips.ethereum.org/EIPS/eip-6900. MSCAs must implement this interface to support installing
diff --git a/src/msca/6900/v0.7/interfaces/IStandardExecutor.sol b/src/msca/6900/v0.7/interfaces/IStandardExecutor.sol
index 9878c53..b932515 100644
--- a/src/msca/6900/v0.7/interfaces/IStandardExecutor.sol
+++ b/src/msca/6900/v0.7/interfaces/IStandardExecutor.sol
@@ -18,7 +18,7 @@
*/
pragma solidity 0.8.24;
-import "../common/Structs.sol";
+import {Call} from "../common/Structs.sol";
/**
* @dev Implements https://eips.ethereum.org/EIPS/eip-6900. MSCAs must implement this interface to support open-ended
diff --git a/src/msca/6900/v0.7/libs/ExecutionHookLib.sol b/src/msca/6900/v0.7/libs/ExecutionHookLib.sol
index f6461d6..a55f3f6 100644
--- a/src/msca/6900/v0.7/libs/ExecutionHookLib.sol
+++ b/src/msca/6900/v0.7/libs/ExecutionHookLib.sol
@@ -24,7 +24,13 @@ import {
PRE_HOOK_ALWAYS_DENY_FUNCTION_REFERENCE,
RUNTIME_VALIDATION_ALWAYS_ALLOW_FUNCTION_REFERENCE
} from "../common/Constants.sol";
-import "../common/Structs.sol";
+import {
+ ExecutionHooks,
+ FunctionReference,
+ HookGroup,
+ PostExecHookToRun,
+ RepeatableBytes21DLL
+} from "../common/Structs.sol";
import {IPlugin} from "../interfaces/IPlugin.sol";
import {FunctionReferenceLib} from "./FunctionReferenceLib.sol";
import {RepeatableFunctionReferenceDLLLib} from "./RepeatableFunctionReferenceDLLLib.sol";
@@ -74,6 +80,7 @@ library ExecutionHookLib {
input.totalPostExecHooksToRunCount = totalPostExecHooksToRunCount;
input.postExecHooksToRun = postExecHooksToRun;
(totalPostExecHooksToRunCount, postExecHooksToRun) = _setPostExecHooksFromPreHooks(hookGroup, data, input);
+ // solhint-disable-next-line no-inline-assembly
assembly ("memory-safe") {
mstore(postExecHooksToRun, totalPostExecHooksToRunCount)
}
@@ -97,11 +104,13 @@ library ExecutionHookLib {
uint256 length = postExecHooksToRun.length;
for (uint256 i = 0; i < length; ++i) {
FunctionReference memory postExecHook = postExecHooksToRun[i].postExecHook;
+ // solhint-disable no-empty-blocks
try IPlugin(postExecHook.plugin).postExecutionHook(
postExecHook.functionId, postExecHooksToRun[i].preExecHookReturnData
) {} catch (bytes memory revertReason) {
revert PostExecHookFailed(postExecHook.plugin, postExecHook.functionId, revertReason);
}
+ // solhint-enable no-empty-blocks
}
}
@@ -152,6 +161,7 @@ library ExecutionHookLib {
}
startHook = nextHook;
}
+ // solhint-disable-next-line no-inline-assembly
assembly ("memory-safe") {
mstore(hooks, totalExecHooksCount)
}
diff --git a/src/msca/6900/v0.7/libs/FunctionReferenceDLLLib.sol b/src/msca/6900/v0.7/libs/FunctionReferenceDLLLib.sol
index f81c743..ff42498 100644
--- a/src/msca/6900/v0.7/libs/FunctionReferenceDLLLib.sol
+++ b/src/msca/6900/v0.7/libs/FunctionReferenceDLLLib.sol
@@ -22,7 +22,7 @@ import {EMPTY_FUNCTION_REFERENCE, SENTINEL_BYTES21} from "../../../../common/Con
import {
InvalidFunctionReference, InvalidLimit, ItemAlreadyExists, ItemDoesNotExist
} from "../../shared/common/Errors.sol";
-import "../common/Structs.sol";
+import {Bytes21DLL, FunctionReference} from "../common/Structs.sol";
import {FunctionReferenceLib} from "./FunctionReferenceLib.sol";
/**
@@ -130,6 +130,7 @@ library FunctionReferenceDLLLib {
results[count] = current.unpack();
current = dll.next[current];
}
+ // solhint-disable-next-line no-inline-assembly
assembly ("memory-safe") {
mstore(results, count)
}
diff --git a/src/msca/6900/v0.7/libs/FunctionReferenceLib.sol b/src/msca/6900/v0.7/libs/FunctionReferenceLib.sol
index 018b9ff..f63e3d1 100644
--- a/src/msca/6900/v0.7/libs/FunctionReferenceLib.sol
+++ b/src/msca/6900/v0.7/libs/FunctionReferenceLib.sol
@@ -18,7 +18,7 @@
*/
pragma solidity 0.8.24;
-import "../common/Structs.sol";
+import {FunctionReference} from "../common/Structs.sol";
library FunctionReferenceLib {
function unpack(bytes21 frBytes) internal pure returns (FunctionReference memory) {
diff --git a/src/msca/6900/v0.7/libs/RepeatableFunctionReferenceDLLLib.sol b/src/msca/6900/v0.7/libs/RepeatableFunctionReferenceDLLLib.sol
index a6a219e..7936790 100644
--- a/src/msca/6900/v0.7/libs/RepeatableFunctionReferenceDLLLib.sol
+++ b/src/msca/6900/v0.7/libs/RepeatableFunctionReferenceDLLLib.sol
@@ -20,7 +20,7 @@ pragma solidity 0.8.24;
import {EMPTY_FUNCTION_REFERENCE, SENTINEL_BYTES21} from "../../../../common/Constants.sol";
import {InvalidFunctionReference, InvalidLimit, ItemDoesNotExist} from "../../shared/common/Errors.sol";
-import "../common/Structs.sol";
+import {FunctionReference, RepeatableBytes21DLL} from "../common/Structs.sol";
import {FunctionReferenceLib} from "./FunctionReferenceLib.sol";
/**
@@ -176,6 +176,7 @@ library RepeatableFunctionReferenceDLLLib {
results[count] = current.unpack();
current = dll.next[current];
}
+ // solhint-disable-next-line no-inline-assembly
assembly ("memory-safe") {
mstore(results, count)
}
diff --git a/src/msca/6900/v0.7/libs/SelectorRegistryLib.sol b/src/msca/6900/v0.7/libs/SelectorRegistryLib.sol
index b5bde17..376009f 100644
--- a/src/msca/6900/v0.7/libs/SelectorRegistryLib.sol
+++ b/src/msca/6900/v0.7/libs/SelectorRegistryLib.sol
@@ -28,6 +28,9 @@ import {IAggregator} from "@account-abstraction/contracts/interfaces/IAggregator
import {IPaymaster} from "@account-abstraction/contracts/interfaces/IPaymaster.sol";
import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
+import {IERC777Recipient} from "@openzeppelin/contracts/interfaces/IERC777Recipient.sol";
+import {IERC1155Receiver} from "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol";
+import {IERC721Receiver} from "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
library SelectorRegistryLib {
@@ -62,7 +65,10 @@ library SelectorRegistryLib {
|| selector == IAccountLoupe.getInstalledPlugins.selector || selector == VALIDATE_USER_OP
|| selector == GET_ENTRYPOINT || selector == GET_NONCE || selector == INITIALIZE_UPGRADABLE_MSCA
|| selector == INITIALIZE_SINGLE_OWNER_MSCA || selector == TRANSFER_NATIVE_OWNERSHIP
- || selector == RENOUNCE_NATIVE_OWNERSHIP || selector == GET_NATIVE_OWNER;
+ || selector == RENOUNCE_NATIVE_OWNERSHIP || selector == GET_NATIVE_OWNER
+ || selector == IERC1155Receiver.onERC1155Received.selector
+ || selector == IERC1155Receiver.onERC1155BatchReceived.selector
+ || selector == IERC721Receiver.onERC721Received.selector || selector == IERC777Recipient.tokensReceived.selector;
}
function _isErc4337FunctionSelector(bytes4 selector) internal pure returns (bool) {
diff --git a/src/msca/6900/v0.7/libs/WalletStorageV1Lib.sol b/src/msca/6900/v0.7/libs/WalletStorageV1Lib.sol
index 282c7e3..69c72c5 100644
--- a/src/msca/6900/v0.7/libs/WalletStorageV1Lib.sol
+++ b/src/msca/6900/v0.7/libs/WalletStorageV1Lib.sol
@@ -19,7 +19,7 @@
pragma solidity 0.8.24;
import {AddressDLL} from "../../shared/common/Structs.sol";
-import "../common/Structs.sol";
+import {ExecutionDetail, PermittedExternalCall, PluginDetail} from "../common/Structs.sol";
/// @dev The same storage will be used for v1.x.y of MSCAs.
library WalletStorageV1Lib {
@@ -54,6 +54,7 @@ library WalletStorageV1Lib {
* @dev Function to read structured wallet storage.
*/
function getLayout() internal pure returns (Layout storage walletStorage) {
+ // solhint-disable-next-line no-inline-assembly
assembly ("memory-safe") {
walletStorage.slot := WALLET_STORAGE_SLOT
}
diff --git a/src/msca/6900/v0.7/managers/PluginExecutor.sol b/src/msca/6900/v0.7/managers/PluginExecutor.sol
index 3c61668..431d70d 100644
--- a/src/msca/6900/v0.7/managers/PluginExecutor.sol
+++ b/src/msca/6900/v0.7/managers/PluginExecutor.sol
@@ -20,7 +20,7 @@ pragma solidity 0.8.24;
import {ExecutionUtils} from "../../../../utils/ExecutionUtils.sol";
import {InvalidExecutionFunction, NotFoundSelector} from "../../shared/common/Errors.sol";
-import "../common/Structs.sol";
+import {ExecutionDetail, HookGroup, PermittedExternalCall, PostExecHookToRun} from "../common/Structs.sol";
import {IPlugin} from "../interfaces/IPlugin.sol";
import {IPluginExecutor} from "../interfaces/IPluginExecutor.sol";
import {ExecutionHookLib} from "../libs/ExecutionHookLib.sol";
diff --git a/src/msca/6900/v0.7/managers/PluginManager.sol b/src/msca/6900/v0.7/managers/PluginManager.sol
index 81d77ad..3ead74a 100644
--- a/src/msca/6900/v0.7/managers/PluginManager.sol
+++ b/src/msca/6900/v0.7/managers/PluginManager.sol
@@ -26,8 +26,20 @@ import {
PRE_HOOK_ALWAYS_DENY_FUNCTION_REFERENCE,
RUNTIME_VALIDATION_ALWAYS_ALLOW_FUNCTION_REFERENCE
} from "../common/Constants.sol";
-import "../common/PluginManifest.sol";
-import "../common/Structs.sol";
+import {
+ ManifestAssociatedFunctionType,
+ ManifestExecutionHook,
+ ManifestExternalCallPermission,
+ ManifestFunction,
+ PluginManifest
+} from "../common/PluginManifest.sol";
+import {
+ Bytes21DLL,
+ FunctionReference,
+ HookGroup,
+ PermittedExternalCall,
+ RepeatableBytes21DLL
+} from "../common/Structs.sol";
import {IPlugin} from "../interfaces/IPlugin.sol";
import {FunctionReferenceDLLLib} from "../libs/FunctionReferenceDLLLib.sol";
import {FunctionReferenceLib} from "../libs/FunctionReferenceLib.sol";
@@ -49,7 +61,7 @@ contract PluginManager {
using SelectorRegistryLib for bytes4;
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment
- address private immutable __self = address(this);
+ address private immutable SELF = address(this);
enum AssociatedFunctionType {
HOOK,
@@ -71,7 +83,7 @@ contract PluginManager {
error InvalidExecutionSelector(address plugin, bytes4 selector);
modifier onlyDelegated() {
- if (address(this) == __self) {
+ if (address(this) == SELF) {
revert OnlyDelegated();
}
_;
diff --git a/src/msca/6900/v0.7/managers/StandardExecutor.sol b/src/msca/6900/v0.7/managers/StandardExecutor.sol
index 0ac85bf..57625a3 100644
--- a/src/msca/6900/v0.7/managers/StandardExecutor.sol
+++ b/src/msca/6900/v0.7/managers/StandardExecutor.sol
@@ -19,7 +19,7 @@
pragma solidity 0.8.24;
import {ExecutionUtils} from "../../../../utils/ExecutionUtils.sol";
-import "../common/Structs.sol";
+import {Call} from "../common/Structs.sol";
import {IPlugin} from "../interfaces/IPlugin.sol";
import {ERC165Checker} from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol";
diff --git a/src/msca/6900/v0.7/plugins/BasePlugin.sol b/src/msca/6900/v0.7/plugins/BasePlugin.sol
index f343934..7b3af4b 100644
--- a/src/msca/6900/v0.7/plugins/BasePlugin.sol
+++ b/src/msca/6900/v0.7/plugins/BasePlugin.sol
@@ -19,8 +19,7 @@
pragma solidity 0.8.24;
import {NotImplemented} from "../../shared/common/Errors.sol";
-import "../common/PluginManifest.sol";
-import "../common/Structs.sol";
+import {PluginManifest, PluginMetadata} from "../common/PluginManifest.sol";
import {IPlugin} from "../interfaces/IPlugin.sol";
import {UserOperation} from "@account-abstraction/contracts/interfaces/UserOperation.sol";
import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol";
diff --git a/src/msca/6900/v0.7/plugins/v1_0_0/acl/SingleOwnerPlugin.sol b/src/msca/6900/v0.7/plugins/v1_0_0/acl/SingleOwnerPlugin.sol
index 9439a87..2950709 100644
--- a/src/msca/6900/v0.7/plugins/v1_0_0/acl/SingleOwnerPlugin.sol
+++ b/src/msca/6900/v0.7/plugins/v1_0_0/acl/SingleOwnerPlugin.sol
@@ -26,9 +26,17 @@ import {
SIG_VALIDATION_FAILED,
SIG_VALIDATION_SUCCEEDED
} from "../../../../../../common/Constants.sol";
-import {InvalidValidationFunctionId, UnauthorizedCaller} from "../../../../shared/common/Errors.sol";
-import "../../../common/PluginManifest.sol";
-import "../../../common/Structs.sol";
+
+import {UnauthorizedCaller} from "../../../../../../common/Errors.sol";
+import {InvalidValidationFunctionId} from "../../../../shared/common/Errors.sol";
+import {
+ ManifestAssociatedFunction,
+ ManifestAssociatedFunctionType,
+ ManifestFunction,
+ PluginManifest,
+ PluginMetadata,
+ SelectorPermission
+} from "../../../common/PluginManifest.sol";
import {IPluginManager} from "../../../interfaces/IPluginManager.sol";
import {IStandardExecutor} from "../../../interfaces/IStandardExecutor.sol";
import {BasePlugin} from "../../BasePlugin.sol";
diff --git a/src/msca/6900/v0.7/plugins/v1_0_0/addressbook/AddressBookPlugin.sol b/src/msca/6900/v0.7/plugins/v1_0_0/addressbook/AddressBookPlugin.sol
index 232c2c8..96f5f04 100644
--- a/src/msca/6900/v0.7/plugins/v1_0_0/addressbook/AddressBookPlugin.sol
+++ b/src/msca/6900/v0.7/plugins/v1_0_0/addressbook/AddressBookPlugin.sol
@@ -24,10 +24,17 @@ import {
SIG_VALIDATION_FAILED,
SIG_VALIDATION_SUCCEEDED
} from "../../../../../../common/Constants.sol";
+
+import {InvalidLength, Unsupported} from "../../../../../../common/Errors.sol";
import {CastLib} from "../../../../../../libs/CastLib.sol";
-import {InvalidLength, Unsupported} from "../../../../shared/common/Errors.sol";
-import "../../../common/PluginManifest.sol";
-import "../../../common/Structs.sol";
+import {
+ ManifestAssociatedFunction,
+ ManifestAssociatedFunctionType,
+ ManifestFunction,
+ PluginManifest,
+ PluginMetadata,
+ SelectorPermission
+} from "../../../common/PluginManifest.sol";
import {IPlugin} from "../../../interfaces/IPlugin.sol";
import {IPluginExecutor} from "../../../interfaces/IPluginExecutor.sol";
import {IStandardExecutor} from "../../../interfaces/IStandardExecutor.sol";
diff --git a/src/msca/6900/v0.7/plugins/v1_0_0/addressbook/ColdStorageAddressBookPlugin.sol b/src/msca/6900/v0.7/plugins/v1_0_0/addressbook/ColdStorageAddressBookPlugin.sol
index 951d127..a75426e 100644
--- a/src/msca/6900/v0.7/plugins/v1_0_0/addressbook/ColdStorageAddressBookPlugin.sol
+++ b/src/msca/6900/v0.7/plugins/v1_0_0/addressbook/ColdStorageAddressBookPlugin.sol
@@ -18,6 +18,7 @@
*/
pragma solidity 0.8.24;
+import {Unsupported} from "../../../../../../common//Errors.sol";
import {
PLUGIN_AUTHOR,
PLUGIN_VERSION_1,
@@ -26,7 +27,6 @@ import {
} from "../../../../../../common/Constants.sol";
import {CastLib} from "../../../../../../libs/CastLib.sol";
import {RecipientAddressLib} from "../../../../../../libs/RecipientAddressLib.sol";
-import {Unsupported} from "../../../../shared/common/Errors.sol";
import {
ManifestAssociatedFunction,
ManifestAssociatedFunctionType,
diff --git a/src/msca/6900/v0.7/plugins/v1_0_0/multisig/BaseMultisigPlugin.sol b/src/msca/6900/v0.7/plugins/v1_0_0/multisig/BaseMultisigPlugin.sol
index acec908..3b0a495 100644
--- a/src/msca/6900/v0.7/plugins/v1_0_0/multisig/BaseMultisigPlugin.sol
+++ b/src/msca/6900/v0.7/plugins/v1_0_0/multisig/BaseMultisigPlugin.sol
@@ -124,6 +124,7 @@ abstract contract BaseMultisigPlugin is BasePlugin {
/// @return minimal user op hash
function _getMinimalUserOpDigest(UserOperation calldata userOp) internal view returns (bytes32) {
address sender;
+ // solhint-disable-next-line no-inline-assembly
assembly ("memory-safe") {
sender := calldataload(userOp)
}
@@ -151,6 +152,7 @@ abstract contract BaseMultisigPlugin is BasePlugin {
/// @param data calldata to hash
function _calldataKeccak(bytes calldata data) internal pure returns (bytes32 ret) {
+ // solhint-disable-next-line no-inline-assembly
assembly ("memory-safe") {
let mem := mload(0x40)
let len := data.length
@@ -176,6 +178,7 @@ abstract contract BaseMultisigPlugin is BasePlugin {
pure
returns (uint8 v, bytes32 r, bytes32 s)
{
+ // solhint-disable-next-line no-inline-assembly
assembly ("memory-safe") {
let signaturePos := mul(0x41, pos)
r := mload(add(signatures, add(signaturePos, 0x20)))
diff --git a/src/msca/6900/v0.7/plugins/v1_0_0/multisig/WeightedWebauthnMultisigPlugin.sol b/src/msca/6900/v0.7/plugins/v1_0_0/multisig/WeightedWebauthnMultisigPlugin.sol
index e5b8066..a59d393 100644
--- a/src/msca/6900/v0.7/plugins/v1_0_0/multisig/WeightedWebauthnMultisigPlugin.sol
+++ b/src/msca/6900/v0.7/plugins/v1_0_0/multisig/WeightedWebauthnMultisigPlugin.sol
@@ -412,6 +412,7 @@ contract WeightedWebauthnMultisigPlugin is BaseWeightedMultisigPlugin, BaseERC71
uint256 sigDynamicPartTotalLen;
// 1. load contractSignature content starting from the correct memory offset
// 2. calculate total length including the content and the prefix storing the length
+ // solhint-disable-next-line no-inline-assembly
assembly ("memory-safe") {
contractSignature := add(add(signatures, sigDynamicPartOffset), 0x20)
sigDynamicPartTotalLen := add(mload(contractSignature), 0x20)
@@ -452,6 +453,7 @@ contract WeightedWebauthnMultisigPlugin is BaseWeightedMultisigPlugin, BaseERC71
uint256 sigDynamicPartTotalLen;
// 1. load the content starting from the correct memory offset
// 2. calculate total length including the content and the prefix storing the length
+ // solhint-disable-next-line no-inline-assembly
assembly ("memory-safe") {
sigDynamicPartBytes := add(add(signatures, sigDynamicPartOffset), 0x20)
sigDynamicPartTotalLen := add(mload(sigDynamicPartBytes), 0x20)
diff --git a/src/msca/6900/v0.7/plugins/v1_0_0/utility/DefaultTokenCallbackPlugin.sol b/src/msca/6900/v0.7/plugins/v1_0_0/utility/DefaultTokenCallbackPlugin.sol
index 6cefb43..f0dd712 100644
--- a/src/msca/6900/v0.7/plugins/v1_0_0/utility/DefaultTokenCallbackPlugin.sol
+++ b/src/msca/6900/v0.7/plugins/v1_0_0/utility/DefaultTokenCallbackPlugin.sol
@@ -78,7 +78,9 @@ contract DefaultTokenCallbackPlugin is BasePlugin, IERC721Receiver, IERC1155Rece
uint256 amount,
bytes calldata userData,
bytes calldata operatorData
- ) external pure override {}
+ ) external pure override
+ // solhint-disable-next-line no-empty-blocks
+ {}
/// @inheritdoc BasePlugin
function pluginManifest() external pure override returns (PluginManifest memory) {
diff --git a/src/paymaster/BasePaymaster.sol b/src/paymaster/BasePaymaster.sol
index 5d1990f..9425eed 100644
--- a/src/paymaster/BasePaymaster.sol
+++ b/src/paymaster/BasePaymaster.sol
@@ -18,6 +18,7 @@
*/
pragma solidity 0.8.24;
+import {UnauthorizedCaller} from "../common/Errors.sol";
import {IEntryPoint} from "@account-abstraction/contracts/interfaces/IEntryPoint.sol";
import {IPaymaster} from "@account-abstraction/contracts/interfaces/IPaymaster.sol";
@@ -46,7 +47,7 @@ abstract contract BasePaymaster is
PausableUpgradeable
{
// global entry point
- IEntryPoint public immutable entryPoint;
+ IEntryPoint public immutable ENTRY_POINT;
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
@@ -57,16 +58,18 @@ abstract contract BasePaymaster is
/// @inheritdoc UUPSUpgradeable
// The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.
// Authorize the owner to upgrade the contract.
+ // solhint-disable-next-line no-empty-blocks
function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}
/// @custom:oz-upgrades-unsafe-allow constructor
// for immutable values in implementations
constructor(IEntryPoint _newEntryPoint) {
- entryPoint = _newEntryPoint;
+ ENTRY_POINT = _newEntryPoint;
// lock the implementation contract so it can only be called from proxies
_disableInitializers();
}
+ // solhint-disable-next-line func-name-mixedcase
function __BasePaymaster_init(address _newOwner) internal onlyInitializing {
__UUPSUpgradeable_init();
__Ownable_init();
@@ -96,27 +99,28 @@ abstract contract BasePaymaster is
_postOp(mode, context, actualGasCost);
}
+ // solhint-disable-next-line no-empty-blocks
function _postOp(PostOpMode mode, bytes calldata context, uint256 actualGasCost) internal virtual {}
/**
* add a deposit for this paymaster, used for paying for transaction fees
*/
function deposit() public payable whenNotPaused {
- entryPoint.depositTo{value: msg.value}(address(this));
+ ENTRY_POINT.depositTo{value: msg.value}(address(this));
}
/**
- * return current paymaster's deposit on the entryPoint.
+ * return current paymaster's deposit on the ENTRY_POINT.
*/
function getDeposit() public view returns (uint256) {
- return entryPoint.balanceOf(address(this));
+ return ENTRY_POINT.balanceOf(address(this));
}
/**
- * return current paymaster's full deposit&stake information on the entryPoint.
+ * return current paymaster's full deposit&stake information on the ENTRY_POINT.
*/
function getDepositInfo() public view returns (IStakeManager.DepositInfo memory info) {
- return entryPoint.getDepositInfo(address(this));
+ return ENTRY_POINT.getDepositInfo(address(this));
}
/**
@@ -125,7 +129,7 @@ abstract contract BasePaymaster is
* @param unstakeDelaySec - the unstake delay for this paymaster. Can only be increased.
*/
function addStake(uint32 unstakeDelaySec) public payable onlyOwner whenNotPaused {
- entryPoint.addStake{value: msg.value}(unstakeDelaySec);
+ ENTRY_POINT.addStake{value: msg.value}(unstakeDelaySec);
}
/**
@@ -133,7 +137,7 @@ abstract contract BasePaymaster is
* The paymaster can't serve requests once unlocked, until it calls addStake again
*/
function unlockStake() public onlyOwner whenNotPaused {
- entryPoint.unlockStake();
+ ENTRY_POINT.unlockStake();
}
/**
@@ -142,12 +146,14 @@ abstract contract BasePaymaster is
* @param withdrawAddress the address to send withdrawn value.
*/
function withdrawStake(address payable withdrawAddress) public onlyOwner whenNotPaused {
- entryPoint.withdrawStake(withdrawAddress);
+ ENTRY_POINT.withdrawStake(withdrawAddress);
}
/// validate the call is made from a valid entrypoint
function _requireFromEntryPoint() internal view {
- require(msg.sender == address(entryPoint), "Sender not EntryPoint");
+ if (msg.sender != address(ENTRY_POINT)) {
+ revert UnauthorizedCaller();
+ }
}
function pause() public onlyOwner whenNotPaused {
@@ -159,13 +165,13 @@ abstract contract BasePaymaster is
}
function withdrawTo(address payable withdrawAddress, uint256 amount) public onlyOwner whenNotPaused {
- entryPoint.withdrawTo(withdrawAddress, amount);
+ ENTRY_POINT.withdrawTo(withdrawAddress, amount);
}
/**
* automatically deposit received native token to entrypoint
*/
receive() external payable whenNotPaused {
- entryPoint.depositTo{value: msg.value}(address(this));
+ ENTRY_POINT.depositTo{value: msg.value}(address(this));
}
}
diff --git a/src/paymaster/v1/permissioned/SponsorPaymaster.sol b/src/paymaster/v1/permissioned/SponsorPaymaster.sol
index 7e1f054..c2105d1 100644
--- a/src/paymaster/v1/permissioned/SponsorPaymaster.sol
+++ b/src/paymaster/v1/permissioned/SponsorPaymaster.sol
@@ -18,15 +18,12 @@
*/
pragma solidity 0.8.24;
-/* solhint-disable reason-string */
+import {PaymasterUtils, UserOperationLib} from "../../../utils/PaymasterUtils.sol";
-import "../../../utils/PaymasterUtils.sol";
-
-import "../../BasePaymaster.sol";
+import {BasePaymaster, UserOperation} from "../../BasePaymaster.sol";
import {_packValidationData} from "@account-abstraction/contracts/core/Helpers.sol";
-import "@account-abstraction/contracts/interfaces/IEntryPoint.sol";
-import "@account-abstraction/contracts/interfaces/IPaymaster.sol";
-import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
+import {IEntryPoint} from "@account-abstraction/contracts/interfaces/IEntryPoint.sol";
+import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
/**
diff --git a/src/utils/ExecutionUtils.sol b/src/utils/ExecutionUtils.sol
index 1ccd934..c431648 100644
--- a/src/utils/ExecutionUtils.sol
+++ b/src/utils/ExecutionUtils.sol
@@ -18,8 +18,6 @@
*/
pragma solidity 0.8.24;
-// solhint-disable no-inline-assembly
-
/**
* Utility functions helpful when making different kinds of contract calls in Solidity.
* For inline assembly, please refer to https://docs.soliditylang.org/en/latest/assembly.html
@@ -30,6 +28,7 @@ library ExecutionUtils {
internal
returns (bool success, bytes memory returnData)
{
+ // solhint-disable-next-line no-inline-assembly
assembly {
success := call(gas(), to, value, add(data, 0x20), mload(data), 0, 0)
let len := returndatasize()
@@ -42,6 +41,7 @@ library ExecutionUtils {
}
function revertWithData(bytes memory returnData) internal pure {
+ // solhint-disable-next-line no-inline-assembly
assembly {
revert(add(returnData, 32), mload(returnData))
}
@@ -65,6 +65,7 @@ library ExecutionUtils {
/// @dev Return data or revert.
function delegateCall(address to, bytes memory data) internal returns (bytes memory) {
+ // solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returnData) = to.delegatecall(data);
if (!success) {
// bubble up revert reason
@@ -83,6 +84,7 @@ library ExecutionUtils {
/// ensuring the memory is pushed to the nearest multiple of 32 bytes. This avoids unaligned memory access,
/// which can lead to inefficiencies.
function fetchReturnData() internal pure returns (bytes memory returnData) {
+ // solhint-disable-next-line no-inline-assembly
assembly ("memory-safe") {
// allocate memory for the return data starting at the free memory pointer
returnData := mload(0x40)
diff --git a/src/utils/PaymasterUtils.sol b/src/utils/PaymasterUtils.sol
index a5005b6..a42505c 100644
--- a/src/utils/PaymasterUtils.sol
+++ b/src/utils/PaymasterUtils.sol
@@ -18,9 +18,6 @@
*/
pragma solidity 0.8.24;
-/* solhint-disable reason-string */
-/* solhint-disable no-inline-assembly */
-
import {UserOperation, UserOperationLib} from "@account-abstraction/contracts/interfaces/UserOperation.sol";
enum ChargeMode {
@@ -99,6 +96,7 @@ library PaymasterUtils {
* do it.
*/
function calldataKeccak(bytes calldata data) internal pure returns (bytes32 ret) {
+ // solhint-disable-next-line no-inline-assembly
assembly {
let mem := mload(0x40)
let len := data.length
diff --git a/test/ECDSAAccountAndFactory.t.sol b/test/ECDSAAccountAndFactory.t.sol
index 4af446d..55cce64 100644
--- a/test/ECDSAAccountAndFactory.t.sol
+++ b/test/ECDSAAccountAndFactory.t.sol
@@ -21,6 +21,7 @@ pragma solidity 0.8.24;
import {ECDSAAccountFactory} from "../src/account/v1/factory/ECDSAAccountFactory.sol";
import {ECDSAAccount} from "../src/account/v1/ECDSAAccount.sol";
+import {InvalidLength, UnauthorizedCaller} from "../src/common/Errors.sol";
import {TestERC1155} from "./util/TestERC1155.sol";
import {TestERC721} from "./util/TestERC721.sol";
import {TestLiquidityPool} from "./util/TestLiquidityPool.sol";
@@ -63,7 +64,7 @@ contract ECDSAAccountAndFactoryTest is TestUtils {
uint256 internal eoaPrivateKey;
address private ownerAddr;
ECDSAAccountFactory private ecdsaAccountFactory;
- address payable beneficiary; // e.g. bundler
+ address payable private beneficiary; // e.g. bundler
TestLiquidityPool private testLiquidityPool;
TestERC1155 private testERC1155;
TestERC721 private testERC721;
@@ -403,7 +404,7 @@ contract ECDSAAccountAndFactoryTest is TestUtils {
// upgrade via random address
vm.startPrank(address(1));
- vm.expectRevert(bytes("Caller is not the owner"));
+ vm.expectRevert(UnauthorizedCaller.selector);
proxy.upgradeToAndCall(v2ImplAddr, "");
vm.stopPrank();
}
@@ -459,7 +460,7 @@ contract ECDSAAccountAndFactoryTest is TestUtils {
value[1] = 10;
vm.startPrank(ownerAddr);
- vm.expectRevert(bytes("wrong array lengths"));
+ vm.expectRevert(InvalidLength.selector);
proxy.executeBatch(dest, value, func);
vm.stopPrank();
@@ -473,7 +474,7 @@ contract ECDSAAccountAndFactoryTest is TestUtils {
func2[1] = transferCallData;
vm.startPrank(ownerAddr);
- vm.expectRevert(bytes("wrong array lengths"));
+ vm.expectRevert(InvalidLength.selector);
proxy.executeBatch(dest2, value2, func2);
vm.stopPrank();
}
@@ -612,7 +613,7 @@ contract ECDSAAccountAndFactoryTest is TestUtils {
// only owner can withdraw
vm.startPrank(randomAddr);
- vm.expectRevert("Caller is not the owner");
+ vm.expectRevert(UnauthorizedCaller.selector);
proxy.withdrawDepositTo(payable(randomAddr), 1);
vm.stopPrank();
}
@@ -660,7 +661,7 @@ contract ECDSAAccountAndFactoryTest is TestUtils {
address sender = address(proxy);
(address randomAddr) = makeAddr("randomAccount");
vm.startPrank(randomAddr);
- vm.expectRevert("Caller is not the owner");
+ vm.expectRevert(UnauthorizedCaller.selector);
proxy.pause();
vm.stopPrank();
@@ -759,7 +760,7 @@ contract ECDSAAccountAndFactoryTest is TestUtils {
assertEq(sender.balance, 900000000000000000);
// hacker
vm.startPrank(vm.addr(123));
- vm.expectRevert(bytes("account: not EntryPoint or Owner"));
+ vm.expectRevert(UnauthorizedCaller.selector);
senderAccount.execute(recipient, 100, "");
vm.stopPrank();
}
@@ -781,7 +782,7 @@ contract ECDSAAccountAndFactoryTest is TestUtils {
assertEq(sender.balance, 900000000000000000);
// hacker
vm.startPrank(vm.addr(456));
- vm.expectRevert(bytes("account: not EntryPoint or Owner"));
+ vm.expectRevert(UnauthorizedCaller.selector);
senderAccount.execute(recipient, 100, "");
vm.stopPrank();
}
@@ -806,7 +807,7 @@ contract ECDSAAccountAndFactoryTest is TestUtils {
// hacker
vm.startPrank(vm.addr(123));
- vm.expectRevert(bytes("account: not EntryPoint or Owner"));
+ vm.expectRevert(UnauthorizedCaller.selector);
senderAccount.execute(liquidityPoolSpenderAddr, 0, transferCallData);
vm.stopPrank();
}
@@ -831,7 +832,7 @@ contract ECDSAAccountAndFactoryTest is TestUtils {
// hacker
vm.startPrank(vm.addr(123));
- vm.expectRevert(bytes("account: not EntryPoint or Owner"));
+ vm.expectRevert(UnauthorizedCaller.selector);
senderAccount.execute(liquidityPoolSpenderAddr, 0, transferCallData);
vm.stopPrank();
}
@@ -856,7 +857,7 @@ contract ECDSAAccountAndFactoryTest is TestUtils {
// hacker
vm.startPrank(vm.addr(123));
- vm.expectRevert(bytes("account: not EntryPoint or Owner"));
+ vm.expectRevert(UnauthorizedCaller.selector);
senderAccount.execute(liquidityPoolSpenderAddr, 0, transferCallData);
vm.stopPrank();
}
diff --git a/test/SponsorPaymaster.t.sol b/test/SponsorPaymaster.t.sol
index 63b2d12..1170e13 100644
--- a/test/SponsorPaymaster.t.sol
+++ b/test/SponsorPaymaster.t.sol
@@ -18,13 +18,16 @@
*/
pragma solidity 0.8.24;
-import "../src/paymaster/v1/permissioned/SponsorPaymaster.sol";
+import {SponsorPaymaster} from "../src/paymaster/v1/permissioned/SponsorPaymaster.sol";
+import {_packValidationData} from "@account-abstraction/contracts/core/Helpers.sol";
+import {IEntryPoint} from "@account-abstraction/contracts/interfaces/IEntryPoint.sol";
+import {UserOperation, UserOperationLib} from "@account-abstraction/contracts/interfaces/UserOperation.sol";
+import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
-import "./util/TestUtils.sol";
+import {TestUtils} from "./util/TestUtils.sol";
-import "@account-abstraction/contracts/core/EntryPoint.sol";
-import "@account-abstraction/contracts/interfaces/IPaymaster.sol";
-import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
+import {EntryPoint} from "@account-abstraction/contracts/core/EntryPoint.sol";
+import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
contract SponsorPaymasterTest is TestUtils {
using UserOperationLib for UserOperation;
@@ -38,9 +41,9 @@ contract SponsorPaymasterTest is TestUtils {
uint256 internal verifyingSigner2PrivateKey = 0xdef;
address internal verifyingSigner1;
address internal verifyingSigner2;
- uint48 internal MOCK_VALID_UNTIL = 1691493273;
- uint48 internal MOCK_VALID_AFTER = 1681493273;
- bytes internal MOCK_OFFCHAIN_SIG = "0x123456";
+ uint48 internal constant MOCK_VALID_UNTIL = 1691493273;
+ uint48 internal constant MOCK_VALID_AFTER = 1681493273;
+ bytes internal constant MOCK_OFFCHAIN_SIG = "0x123456";
function setUp() public {
verifyingSigner1 = vm.addr(verifyingSigner1PrivateKey);
diff --git a/test/WalletMigration.t.sol b/test/WalletMigration.t.sol
index 4d9119d..87ef86d 100644
--- a/test/WalletMigration.t.sol
+++ b/test/WalletMigration.t.sol
@@ -21,14 +21,16 @@ pragma solidity 0.8.24;
import {ECDSAAccount} from "../src/account/v1/ECDSAAccount.sol";
import {ECDSAAccountFactory} from "../src/account/v1/factory/ECDSAAccountFactory.sol";
import {FunctionReference} from "../src/msca/6900/v0.7/common/Structs.sol";
-import "../src/msca/6900/v0.7/factories/semi/SingleOwnerMSCAFactory.sol";
-import "../src/msca/6900/v0.7/interfaces/IStandardExecutor.sol";
-import "../src/msca/6900/v0.7/libs/FunctionReferenceLib.sol";
-import "../src/msca/6900/v0.7/plugins/v1_0_0/acl/SingleOwnerPlugin.sol";
-import "./util/TestERC1155.sol";
-import "./util/TestERC721.sol";
-
-import "./util/TestLiquidityPool.sol";
+import {SingleOwnerMSCAFactory} from "../src/msca/6900/v0.7/factories/semi/SingleOwnerMSCAFactory.sol";
+import {FunctionReferenceLib} from "../src/msca/6900/v0.7/libs/FunctionReferenceLib.sol";
+import {TestERC1155} from "./util/TestERC1155.sol";
+import {TestERC721} from "./util/TestERC721.sol";
+import {IEntryPoint} from "@account-abstraction/contracts/interfaces/IEntryPoint.sol";
+import {UserOperation} from "@account-abstraction/contracts/interfaces/UserOperation.sol";
+import {SingleOwnerMSCA} from "src/msca/6900/v0.7/account/semi/SingleOwnerMSCA.sol";
+import {PluginManager} from "src/msca/6900/v0.7/managers/PluginManager.sol";
+
+import {TestLiquidityPool} from "./util/TestLiquidityPool.sol";
import {TestUtils} from "./util/TestUtils.sol";
import {EntryPoint} from "@account-abstraction/contracts/core/EntryPoint.sol";
diff --git a/test/gas/6900/v0.7/plugins/addressbook/SingleOwnerMSCAWithAddressBookPlugin.t.sol b/test/gas/6900/v0.7/plugins/addressbook/SingleOwnerMSCAWithAddressBookPlugin.t.sol
index cc748a6..b160d8a 100644
--- a/test/gas/6900/v0.7/plugins/addressbook/SingleOwnerMSCAWithAddressBookPlugin.t.sol
+++ b/test/gas/6900/v0.7/plugins/addressbook/SingleOwnerMSCAWithAddressBookPlugin.t.sol
@@ -20,9 +20,16 @@ pragma solidity 0.8.24;
import {FunctionReference} from "../../../../../../src/msca/6900/v0.7/common/Structs.sol";
-import "../../../../../../src/msca/6900/v0.7/factories/semi/SingleOwnerMSCAFactory.sol";
-import "../../../../../../src/msca/6900/v0.7/plugins/v1_0_0/addressbook/AddressBookPlugin.sol";
-import "../../../../../../src/utils/ExecutionUtils.sol";
+import {
+ PluginManager,
+ SingleOwnerMSCA,
+ SingleOwnerMSCAFactory
+} from "../../../../../../src/msca/6900/v0.7/factories/semi/SingleOwnerMSCAFactory.sol";
+import {
+ AddressBookPlugin,
+ IAddressBookPlugin,
+ UserOperation
+} from "../../../../../../src/msca/6900/v0.7/plugins/v1_0_0/addressbook/AddressBookPlugin.sol";
import {PluginGasProfileBaseTest} from "../../../../PluginGasProfileBase.t.sol";
contract SingleOwnerMSCAWithAddressBookPluginTest is PluginGasProfileBaseTest {
diff --git a/test/gas/6900/v0.7/plugins/singleowner/SingleOwnerMSCAWithSingleOwnerPlugin.t.sol b/test/gas/6900/v0.7/plugins/singleowner/SingleOwnerMSCAWithSingleOwnerPlugin.t.sol
index dab78b7..f17d304 100644
--- a/test/gas/6900/v0.7/plugins/singleowner/SingleOwnerMSCAWithSingleOwnerPlugin.t.sol
+++ b/test/gas/6900/v0.7/plugins/singleowner/SingleOwnerMSCAWithSingleOwnerPlugin.t.sol
@@ -18,12 +18,15 @@
*/
pragma solidity 0.8.24;
-import "../../../../../../src/msca/6900/v0.7/common/Structs.sol";
-
-import "../../../../../../src/msca/6900/v0.7/factories/semi/SingleOwnerMSCAFactory.sol";
-import "../../../../../../src/msca/6900/v0.7/plugins/v1_0_0/acl/SingleOwnerPlugin.sol";
-import "../../../../../../src/utils/ExecutionUtils.sol";
-import "../../../../PluginGasProfileBase.t.sol";
+import {FunctionReference} from "../../../../../../src/msca/6900/v0.7/common/Structs.sol";
+
+import {
+ PluginManager,
+ SingleOwnerMSCA,
+ SingleOwnerMSCAFactory
+} from "../../../../../../src/msca/6900/v0.7/factories/semi/SingleOwnerMSCAFactory.sol";
+import {SingleOwnerPlugin} from "../../../../../../src/msca/6900/v0.7/plugins/v1_0_0/acl/SingleOwnerPlugin.sol";
+import {PluginGasProfileBaseTest, UserOperation} from "../../../../PluginGasProfileBase.t.sol";
contract SingleOwnerMSCAWithSingleOwnerPluginTest is PluginGasProfileBaseTest {
event PluginInstalled(address indexed plugin, bytes32 manifestHash, FunctionReference[] dependencies);
diff --git a/test/gas/6900/v0.7/plugins/singleowner/UpgradableMSCAWithSingleOwnerPlugin.t.sol b/test/gas/6900/v0.7/plugins/singleowner/UpgradableMSCAWithSingleOwnerPlugin.t.sol
index 3b7f6cb..3d4f14d 100644
--- a/test/gas/6900/v0.7/plugins/singleowner/UpgradableMSCAWithSingleOwnerPlugin.t.sol
+++ b/test/gas/6900/v0.7/plugins/singleowner/UpgradableMSCAWithSingleOwnerPlugin.t.sol
@@ -18,13 +18,18 @@
*/
pragma solidity 0.8.24;
-import "../../../../../../src/msca/6900/v0.7/common/Structs.sol";
-
-import "../../../../../../src/msca/6900/v0.7/factories/UpgradableMSCAFactory.sol";
-import "../../../../../../src/msca/6900/v0.7/plugins/v1_0_0/acl/SingleOwnerPlugin.sol";
-import "../../../../../../src/utils/ExecutionUtils.sol";
+import {FunctionReference} from "../../../../../../src/msca/6900/v0.7/common/Structs.sol";
+import {console} from "forge-std/src/console.sol";
+
+import {
+ PluginManager,
+ UpgradableMSCA,
+ UpgradableMSCAFactory
+} from "../../../../../../src/msca/6900/v0.7/factories/UpgradableMSCAFactory.sol";
+import {SingleOwnerPlugin} from "../../../../../../src/msca/6900/v0.7/plugins/v1_0_0/acl/SingleOwnerPlugin.sol";
+import {ExecutionUtils} from "../../../../../../src/utils/ExecutionUtils.sol";
import {TestUserOpAllPassValidator} from "../../../../../msca/6900/v0.7/TestUserOpAllPassValidator.sol";
-import "../../../../PluginGasProfileBase.t.sol";
+import {PluginGasProfileBaseTest, UserOperation} from "../../../../PluginGasProfileBase.t.sol";
contract UpgradableMSCAWithSingleOwnerPluginTest is PluginGasProfileBaseTest {
event PluginInstalled(address indexed plugin, bytes32 manifestHash, FunctionReference[] dependencies);
diff --git a/test/gas/PluginGasProfileBase.t.sol b/test/gas/PluginGasProfileBase.t.sol
index ee01641..b09fab0 100644
--- a/test/gas/PluginGasProfileBase.t.sol
+++ b/test/gas/PluginGasProfileBase.t.sol
@@ -25,12 +25,12 @@ import {UserOperation} from "@account-abstraction/contracts/interfaces/UserOpera
import {console} from "forge-std/src/console.sol";
abstract contract PluginGasProfileBaseTest is TestUtils {
- uint256 constant OV_PER_ZERO_BYTE = 4;
- uint256 constant OV_PER_NONZERO_BYTE = 16;
+ uint256 private constant OV_PER_ZERO_BYTE = 4;
+ uint256 private constant OV_PER_NONZERO_BYTE = 16;
IEntryPoint public entryPoint = new EntryPoint();
address payable public beneficiary = payable(address(makeAddr("bundler")));
- string jsonObj;
- uint256 sum;
+ string internal jsonObj;
+ uint256 internal sum;
bool public writeGasProfileToFile;
function testBenchmarkAll() external virtual;
diff --git a/test/msca/6900/shared/libs/Bytes32DLLLib.t.sol b/test/msca/6900/shared/libs/Bytes32DLLLib.t.sol
index 5580298..f1d1781 100644
--- a/test/msca/6900/shared/libs/Bytes32DLLLib.t.sol
+++ b/test/msca/6900/shared/libs/Bytes32DLLLib.t.sol
@@ -18,60 +18,17 @@
*/
pragma solidity 0.8.24;
-/* solhint-disable one-contract-per-file */
-
import {SENTINEL_BYTES32} from "../../../../../src/common/Constants.sol";
import {Bytes32DLL} from "../../../../../src/msca/6900/shared/common/Structs.sol";
import {Bytes32DLLLib} from "../../../../../src/msca/6900/shared/libs/Bytes32DLLLib.sol";
import {TestUtils} from "../../../../util/TestUtils.sol";
-
-contract TestDLL {
- using Bytes32DLLLib for Bytes32DLL;
-
- Bytes32DLL private bytes32DLL;
-
- function append(bytes32 valueToAdd) external returns (bool) {
- return bytes32DLL.append(valueToAdd);
- }
-
- function remove(bytes32 valueToRemove) external returns (bool) {
- return bytes32DLL.remove(valueToRemove);
- }
-
- function size() external view returns (uint256) {
- return bytes32DLL.size();
- }
-
- function contains(bytes32 value) external view returns (bool) {
- return bytes32DLL.contains(value);
- }
-
- function getAll() external view returns (bytes32[] memory results) {
- return bytes32DLL.getAll();
- }
-
- function getPaginated(bytes32 start, uint256 limit)
- external
- view
- returns (bytes32[] memory results, bytes32 next)
- {
- return bytes32DLL.getPaginated(start, limit);
- }
-
- function getHead() external view returns (bytes32) {
- return bytes32DLL.getHead();
- }
-
- function getTail() external view returns (bytes32) {
- return bytes32DLL.getTail();
- }
-}
+import {TestBytes32DLL} from "./TestBytes32DLL.sol";
contract Bytes32DLLLibTest is TestUtils {
using Bytes32DLLLib for Bytes32DLL;
function testAddRemoveGetBytes32Values() public {
- TestDLL values = new TestDLL();
+ TestBytes32DLL values = new TestBytes32DLL();
// sentinel value is initialized
assertEq(values.size(), 0);
// try to remove sentinel stupidly
@@ -152,14 +109,14 @@ contract Bytes32DLLLibTest is TestUtils {
// try out different limits, even bigger than totalValues
bound(limit, 1, 30);
bound(totalValues, 3, 30);
- TestDLL dll = new TestDLL();
+ TestBytes32DLL dll = new TestBytes32DLL();
for (uint32 i = 1; i <= totalValues; i++) {
dll.append(bytes32(uint256(i)));
}
bulkGetAndVerifyValues(dll, totalValues, limit);
}
- function bulkGetAndVerifyValues(TestDLL dll, uint256 totalValues, uint256 limit) private view {
+ function bulkGetAndVerifyValues(TestBytes32DLL dll, uint256 totalValues, uint256 limit) private view {
bytes32[] memory results = new bytes32[](totalValues);
bytes32 start = SENTINEL_BYTES32;
uint32 count = 0;
diff --git a/test/msca/6900/shared/libs/Bytes4DLLLib.t.sol b/test/msca/6900/shared/libs/Bytes4DLLLib.t.sol
index 5da7524..2c087ac 100644
--- a/test/msca/6900/shared/libs/Bytes4DLLLib.t.sol
+++ b/test/msca/6900/shared/libs/Bytes4DLLLib.t.sol
@@ -24,50 +24,13 @@ import {SENTINEL_BYTES4} from "../../../../../src/common/Constants.sol";
import {Bytes4DLL} from "../../../../../src/msca/6900/shared/common/Structs.sol";
import {Bytes4DLLLib} from "../../../../../src/msca/6900/shared/libs/Bytes4DLLLib.sol";
import {TestUtils} from "../../../../util/TestUtils.sol";
-
-contract TestDLL {
- using Bytes4DLLLib for Bytes4DLL;
-
- Bytes4DLL private bytes4DLL;
-
- function append(bytes4 valueToAdd) external returns (bool) {
- return bytes4DLL.append(valueToAdd);
- }
-
- function remove(bytes4 valueToRemove) external returns (bool) {
- return bytes4DLL.remove(valueToRemove);
- }
-
- function size() external view returns (uint256) {
- return bytes4DLL.size();
- }
-
- function contains(bytes4 value) external returns (bool) {
- return bytes4DLL.contains(value);
- }
-
- function getAll() external view returns (bytes4[] memory results) {
- return bytes4DLL.getAll();
- }
-
- function getPaginated(bytes4 start, uint256 limit) external view returns (bytes4[] memory results, bytes4 next) {
- return bytes4DLL.getPaginated(start, limit);
- }
-
- function getHead() external view returns (bytes4) {
- return bytes4DLL.getHead();
- }
-
- function getTail() external view returns (bytes4) {
- return bytes4DLL.getTail();
- }
-}
+import {TestBytes4DLL} from "./TestBytes4DLL.sol";
contract Bytes4DLLLibTest is TestUtils {
using Bytes4DLLLib for Bytes4DLL;
function testAddRemoveGetBytes4Values() public {
- TestDLL values = new TestDLL();
+ TestBytes4DLL values = new TestBytes4DLL();
// sentinel value is initialized
assertEq(values.size(), 0);
// try to remove sentinel stupidly
@@ -148,14 +111,14 @@ contract Bytes4DLLLibTest is TestUtils {
// try out different limits, even bigger than totalValues
bound(limit, 1, 30);
bound(totalValues, 3, 30);
- TestDLL dll = new TestDLL();
+ TestBytes4DLL dll = new TestBytes4DLL();
for (uint32 i = 1; i <= totalValues; i++) {
dll.append(bytes4(i));
}
bulkGetAndVerifyValues(dll, totalValues, limit);
}
- function bulkGetAndVerifyValues(TestDLL dll, uint256 totalValues, uint256 limit) private view {
+ function bulkGetAndVerifyValues(TestBytes4DLL dll, uint256 totalValues, uint256 limit) private view {
bytes4[] memory results = new bytes4[](totalValues);
bytes4 start = SENTINEL_BYTES4;
uint32 count = 0;
diff --git a/test/msca/6900/shared/libs/TestBytes32DLL.sol b/test/msca/6900/shared/libs/TestBytes32DLL.sol
new file mode 100644
index 0000000..22568c1
--- /dev/null
+++ b/test/msca/6900/shared/libs/TestBytes32DLL.sol
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2024 Circle Internet Group, Inc. All rights reserved.
+
+ * SPDX-License-Identifier: GPL-3.0-or-later
+
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+pragma solidity 0.8.24;
+
+import {Bytes32DLL} from "../../../../../src/msca/6900/shared/common/Structs.sol";
+import {Bytes32DLLLib} from "../../../../../src/msca/6900/shared/libs/Bytes32DLLLib.sol";
+
+contract TestBytes32DLL {
+ using Bytes32DLLLib for Bytes32DLL;
+
+ Bytes32DLL private bytes32DLL;
+
+ function append(bytes32 valueToAdd) external returns (bool) {
+ return bytes32DLL.append(valueToAdd);
+ }
+
+ function remove(bytes32 valueToRemove) external returns (bool) {
+ return bytes32DLL.remove(valueToRemove);
+ }
+
+ function size() external view returns (uint256) {
+ return bytes32DLL.size();
+ }
+
+ function contains(bytes32 value) external view returns (bool) {
+ return bytes32DLL.contains(value);
+ }
+
+ function getAll() external view returns (bytes32[] memory results) {
+ return bytes32DLL.getAll();
+ }
+
+ function getPaginated(bytes32 start, uint256 limit)
+ external
+ view
+ returns (bytes32[] memory results, bytes32 next)
+ {
+ return bytes32DLL.getPaginated(start, limit);
+ }
+
+ function getHead() external view returns (bytes32) {
+ return bytes32DLL.getHead();
+ }
+
+ function getTail() external view returns (bytes32) {
+ return bytes32DLL.getTail();
+ }
+}
diff --git a/test/msca/6900/shared/libs/TestBytes4DLL.sol b/test/msca/6900/shared/libs/TestBytes4DLL.sol
new file mode 100644
index 0000000..ac74e89
--- /dev/null
+++ b/test/msca/6900/shared/libs/TestBytes4DLL.sol
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2024 Circle Internet Group, Inc. All rights reserved.
+
+ * SPDX-License-Identifier: GPL-3.0-or-later
+
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+pragma solidity 0.8.24;
+
+import {Bytes4DLL} from "../../../../../src/msca/6900/shared/common/Structs.sol";
+import {Bytes4DLLLib} from "../../../../../src/msca/6900/shared/libs/Bytes4DLLLib.sol";
+
+contract TestBytes4DLL {
+ using Bytes4DLLLib for Bytes4DLL;
+
+ Bytes4DLL private bytes4DLL;
+
+ function append(bytes4 valueToAdd) external returns (bool) {
+ return bytes4DLL.append(valueToAdd);
+ }
+
+ function remove(bytes4 valueToRemove) external returns (bool) {
+ return bytes4DLL.remove(valueToRemove);
+ }
+
+ function size() external view returns (uint256) {
+ return bytes4DLL.size();
+ }
+
+ function contains(bytes4 value) external returns (bool) {
+ return bytes4DLL.contains(value);
+ }
+
+ function getAll() external view returns (bytes4[] memory results) {
+ return bytes4DLL.getAll();
+ }
+
+ function getPaginated(bytes4 start, uint256 limit) external view returns (bytes4[] memory results, bytes4 next) {
+ return bytes4DLL.getPaginated(start, limit);
+ }
+
+ function getHead() external view returns (bytes4) {
+ return bytes4DLL.getHead();
+ }
+
+ function getTail() external view returns (bytes4) {
+ return bytes4DLL.getTail();
+ }
+}
diff --git a/test/msca/6900/v0.7/ChildConstructorInitializableMock.sol b/test/msca/6900/v0.7/ChildConstructorInitializableMock.sol
new file mode 100644
index 0000000..1ccd5ec
--- /dev/null
+++ b/test/msca/6900/v0.7/ChildConstructorInitializableMock.sol
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2024 Circle Internet Group, Inc. All rights reserved.
+
+ * SPDX-License-Identifier: GPL-3.0-or-later
+
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+pragma solidity 0.8.24;
+
+import {ConstructorInitializableMock} from "./ConstructorInitializableMock.sol";
+
+contract ChildConstructorInitializableMock is ConstructorInitializableMock {
+ bool public childInitializerRan;
+
+ constructor() walletStorageInitializer {
+ childInitialize();
+ }
+
+ function childInitialize() public walletStorageInitializer {
+ childInitializerRan = true;
+ }
+}
diff --git a/test/msca/6900/v0.7/ConstructorInitializableMock.sol b/test/msca/6900/v0.7/ConstructorInitializableMock.sol
new file mode 100644
index 0000000..1383c5a
--- /dev/null
+++ b/test/msca/6900/v0.7/ConstructorInitializableMock.sol
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2024 Circle Internet Group, Inc. All rights reserved.
+
+ * SPDX-License-Identifier: GPL-3.0-or-later
+
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+pragma solidity 0.8.24;
+
+import {WalletStorageInitializable} from "../../../../src/msca/6900/v0.7/account/WalletStorageInitializable.sol";
+import {console} from "forge-std/src/console.sol";
+
+contract ConstructorInitializableMock is WalletStorageInitializable {
+ bool public initializerRan;
+ bool public onlyInitializingRan;
+
+ constructor() walletStorageInitializer {
+ console.logString("ConstructorInitializableMock constructor");
+ initialize();
+ initializeOnlyInitializing();
+ }
+
+ function initialize() public walletStorageInitializer {
+ initializerRan = true;
+ }
+
+ function initializeOnlyInitializing() public onlyWalletStorageInitializing {
+ onlyInitializingRan = true;
+ }
+}
diff --git a/test/msca/6900/v0.7/DisableInitializingWalletStorageMock.sol b/test/msca/6900/v0.7/DisableInitializingWalletStorageMock.sol
new file mode 100644
index 0000000..20d75e2
--- /dev/null
+++ b/test/msca/6900/v0.7/DisableInitializingWalletStorageMock.sol
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2024 Circle Internet Group, Inc. All rights reserved.
+
+ * SPDX-License-Identifier: GPL-3.0-or-later
+
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+pragma solidity 0.8.24;
+
+import {WalletStorageInitializable} from "../../../../src/msca/6900/v0.7/account/WalletStorageInitializable.sol";
+import {console} from "forge-std/src/console.sol";
+
+// 1. call walletStorageInitializer before constructor, initializing is set to true
+// 2. call _disableWalletStorageInitializers in the same constructor, we can't disable initializer in the middle of
+// initialization
+contract DisableInitializingWalletStorageMock is WalletStorageInitializable {
+ constructor() walletStorageInitializer {
+ console.logString("DisableInitializingWalletStorageMock constructor");
+ _disableWalletStorageInitializers();
+ }
+}
diff --git a/test/msca/6900/v0.7/DisableWalletStorageInitializerMock.sol b/test/msca/6900/v0.7/DisableWalletStorageInitializerMock.sol
new file mode 100644
index 0000000..323307b
--- /dev/null
+++ b/test/msca/6900/v0.7/DisableWalletStorageInitializerMock.sol
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2024 Circle Internet Group, Inc. All rights reserved.
+
+ * SPDX-License-Identifier: GPL-3.0-or-later
+
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+pragma solidity 0.8.24;
+
+import {WalletStorageInitializable} from "../../../../src/msca/6900/v0.7/account/WalletStorageInitializable.sol";
+import {console} from "forge-std/src/console.sol";
+
+contract DisableWalletStorageInitializerMock is WalletStorageInitializable {
+ constructor() {
+ console.logString("DisableWalletStorageInitializerMock constructor");
+ _disableWalletStorageInitializers();
+ }
+}
diff --git a/test/msca/6900/v0.7/HookFunctionReferenceDLL.t.sol b/test/msca/6900/v0.7/HookFunctionReferenceDLL.t.sol
index 3726be6..b92b55c 100644
--- a/test/msca/6900/v0.7/HookFunctionReferenceDLL.t.sol
+++ b/test/msca/6900/v0.7/HookFunctionReferenceDLL.t.sol
@@ -18,10 +18,11 @@
*/
pragma solidity 0.8.24;
-import "../../../../src/msca/6900/v0.7/common/Structs.sol";
-import "../../../util/TestUtils.sol";
-import "./TestRepeatableFunctionReferenceDLL.sol";
-import "forge-std/src/console.sol";
+import {SENTINEL_BYTES21} from "../../../../src/common/Constants.sol";
+import {FunctionReference} from "../../../../src/msca/6900/v0.7/common/Structs.sol";
+import {TestUtils} from "../../../util/TestUtils.sol";
+import {TestRepeatableFunctionReferenceDLL} from "./TestRepeatableFunctionReferenceDLL.sol";
+import {FunctionReferenceLib} from "src/msca/6900/v0.7/libs/FunctionReferenceLib.sol";
contract HookFunctionReferenceDLLTest is TestUtils {
using FunctionReferenceLib for bytes21;
diff --git a/test/msca/6900/v0.7/LockWalletStorageAfterInitializationMock.sol b/test/msca/6900/v0.7/LockWalletStorageAfterInitializationMock.sol
new file mode 100644
index 0000000..58c383e
--- /dev/null
+++ b/test/msca/6900/v0.7/LockWalletStorageAfterInitializationMock.sol
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2024 Circle Internet Group, Inc. All rights reserved.
+
+ * SPDX-License-Identifier: GPL-3.0-or-later
+
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+pragma solidity 0.8.24;
+
+import {ConstructorInitializableMock} from "./ConstructorInitializableMock.sol";
+import {DisableWalletStorageInitializerMock} from "./DisableWalletStorageInitializerMock.sol";
+
+// 1. call walletStorageInitializer before 1st constructor, initialization is done and initializing is set to false
+// after 1st constructor
+// 2. call _disableWalletStorageInitializers in 2nd constructor to prevent any future reinitialization
+// solhint-disable-next-line no-empty-blocks
+contract LockWalletStorageAfterInitializationMock is
+ ConstructorInitializableMock,
+ DisableWalletStorageInitializerMock
+{}
diff --git a/test/msca/6900/v0.7/LockedWalletStorageMock.sol b/test/msca/6900/v0.7/LockedWalletStorageMock.sol
new file mode 100644
index 0000000..12c1e50
--- /dev/null
+++ b/test/msca/6900/v0.7/LockedWalletStorageMock.sol
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2024 Circle Internet Group, Inc. All rights reserved.
+
+ * SPDX-License-Identifier: GPL-3.0-or-later
+
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+pragma solidity 0.8.24;
+
+import {ConstructorInitializableMock} from "./ConstructorInitializableMock.sol";
+import {DisableWalletStorageInitializerMock} from "./DisableWalletStorageInitializerMock.sol";
+
+// 1. call _disableWalletStorageInitializers, initialized is set to type(uint8).max to prevent any future
+// reinitialization
+// 2. call walletStorageInitializer, the locked contract should not work because it's neither initialSetup nor deploying
+// solhint-disable-next-line no-empty-blocks
+contract LockedWalletStorageMock is DisableWalletStorageInitializerMock, ConstructorInitializableMock {}
diff --git a/test/msca/6900/v0.7/PluginExecutor.t.sol b/test/msca/6900/v0.7/PluginExecutor.t.sol
index 290e69f..a3e3307 100644
--- a/test/msca/6900/v0.7/PluginExecutor.t.sol
+++ b/test/msca/6900/v0.7/PluginExecutor.t.sol
@@ -18,26 +18,37 @@
*/
pragma solidity 0.8.24;
-import "../../../../src/msca/6900/v0.7/common/Structs.sol";
-
-import "../../../../src/msca/6900/v0.7/plugins/v1_0_0/acl/SingleOwnerPlugin.sol";
-import "../../../util/TestLiquidityPool.sol";
-import "../../../util/TestUtils.sol";
-import "./TestCircleMSCA.sol";
-
-import "./TestCircleMSCAFactory.sol";
-import "./TestPermitAnyExternalAddressPlugin.sol";
-
-import "./TestPermitAnyExternalAddressWithPostHookOnlyPlugin.sol";
-
-import "./TestPermitAnyExternalAddressWithPreHookOnlyPlugin.sol";
-import "./TestTokenPlugin.sol";
-import "./TestTokenWithPostHookOnlyPlugin.sol";
-import "./TestTokenWithPreHookOnlyPlugin.sol";
-import "./TestUserOpValidator.sol";
-import "./TestUserOpValidatorHook.sol";
+import {PLUGIN_AUTHOR, PLUGIN_VERSION_1} from "../../../../src/common/Constants.sol";
+import {PluginMetadata} from "../../../../src/msca/6900/v0.7/common/PluginManifest.sol";
+import {Call, FunctionReference} from "../../../../src/msca/6900/v0.7/common/Structs.sol";
+import {IPlugin} from "../../../../src/msca/6900/v0.7/interfaces/IPlugin.sol";
+
+import {IPluginExecutor} from "../../../../src/msca/6900/v0.7/interfaces/IPluginExecutor.sol";
+import {IPluginManager} from "../../../../src/msca/6900/v0.7/interfaces/IPluginManager.sol";
+import {IStandardExecutor} from "../../../../src/msca/6900/v0.7/interfaces/IStandardExecutor.sol";
+import {ISingleOwnerPlugin} from "../../../../src/msca/6900/v0.7/plugins/v1_0_0/acl/ISingleOwnerPlugin.sol";
+import {SingleOwnerPlugin} from "../../../../src/msca/6900/v0.7/plugins/v1_0_0/acl/SingleOwnerPlugin.sol";
+import {TestLiquidityPool} from "../../../util/TestLiquidityPool.sol";
+import {TestUtils} from "../../../util/TestUtils.sol";
+import {PluginManager} from "src/msca/6900/v0.7/managers/PluginManager.sol";
+
+import {FunctionReferenceLib} from "../../../../src/msca/6900/v0.7/libs/FunctionReferenceLib.sol";
+import {IEntryPoint, TestCircleMSCA, TestCircleMSCAFactory} from "./TestCircleMSCAFactory.sol";
+import {TestPermitAnyExternalAddressPlugin} from "./TestPermitAnyExternalAddressPlugin.sol";
+
+import {TestPermitAnyExternalAddressWithPostHookOnlyPlugin} from
+ "./TestPermitAnyExternalAddressWithPostHookOnlyPlugin.sol";
+
+import {TestPermitAnyExternalAddressWithPreHookOnlyPlugin} from
+ "./TestPermitAnyExternalAddressWithPreHookOnlyPlugin.sol";
+import {TestTokenPlugin} from "./TestTokenPlugin.sol";
+import {TestTokenWithPostHookOnlyPlugin} from "./TestTokenWithPostHookOnlyPlugin.sol";
+import {TestTokenWithPreHookOnlyPlugin} from "./TestTokenWithPreHookOnlyPlugin.sol";
import {EntryPoint} from "@account-abstraction/contracts/core/EntryPoint.sol";
-import "forge-std/src/console.sol";
+import {UserOperation} from "@account-abstraction/contracts/interfaces/UserOperation.sol";
+import {console} from "forge-std/src/console.sol";
+
+/* solhint-disable max-states-count */
contract PluginExecutorTest is TestUtils {
using FunctionReferenceLib for bytes21;
@@ -67,7 +78,7 @@ contract PluginExecutorTest is TestUtils {
PluginManager private pluginManager = new PluginManager();
uint256 internal ownerPrivateKey;
address private ownerAddr;
- address payable beneficiary; // e.g. bundler
+ address payable private beneficiary; // e.g. bundler
TestCircleMSCAFactory private factory;
SingleOwnerPlugin private singleOwnerPlugin;
TestCircleMSCA private msca;
diff --git a/test/msca/6900/v0.7/PluginManager.t.sol b/test/msca/6900/v0.7/PluginManager.t.sol
index a295619..0bd1b94 100644
--- a/test/msca/6900/v0.7/PluginManager.t.sol
+++ b/test/msca/6900/v0.7/PluginManager.t.sol
@@ -18,21 +18,29 @@
*/
pragma solidity 0.8.24;
-import {EMPTY_FUNCTION_REFERENCE} from "../../../../src/common/Constants.sol";
-import "../../../../src/msca/6900/v0.7/common/Structs.sol";
-import "../../../../src/msca/6900/v0.7/plugins/v1_0_0/acl/SingleOwnerPlugin.sol";
-import "../../../util/TestLiquidityPool.sol";
-import "../../../util/TestUtils.sol";
-import "./TestCircleMSCA.sol";
+import {EMPTY_FUNCTION_REFERENCE, PLUGIN_AUTHOR, PLUGIN_VERSION_1} from "../../../../src/common/Constants.sol";
+import {UnauthorizedCaller} from "../../../../src/common/Errors.sol";
+import {PluginMetadata} from "../../../../src/msca/6900/v0.7/common/PluginManifest.sol";
+import {FunctionReference} from "../../../../src/msca/6900/v0.7/common/Structs.sol";
+import {IPluginManager} from "../../../../src/msca/6900/v0.7/interfaces/IPluginManager.sol";
+import {FunctionReferenceLib} from "../../../../src/msca/6900/v0.7/libs/FunctionReferenceLib.sol";
-import "./TestCircleMSCAFactory.sol";
-import "./TestTokenPlugin.sol";
-import "./TestUserOpValidator.sol";
-import "./TestUserOpValidatorHook.sol";
+import {PluginManager} from "../../../../src/msca/6900/v0.7/managers/PluginManager.sol";
-import "./TestUserOpValidatorWithDependencyHook.sol";
+import {ISingleOwnerPlugin} from "../../../../src/msca/6900/v0.7/plugins/v1_0_0/acl/ISingleOwnerPlugin.sol";
+import {SingleOwnerPlugin} from "../../../../src/msca/6900/v0.7/plugins/v1_0_0/acl/SingleOwnerPlugin.sol";
+import {TestLiquidityPool} from "../../../util/TestLiquidityPool.sol";
+import {TestUtils} from "../../../util/TestUtils.sol";
+import {TestCircleMSCA} from "./TestCircleMSCA.sol";
+
+import {TestCircleMSCAFactory} from "./TestCircleMSCAFactory.sol";
+import {TestTokenPlugin} from "./TestTokenPlugin.sol";
+
+import {TestUserOpValidatorWithDependencyHook} from "./TestUserOpValidatorWithDependencyHook.sol";
import {EntryPoint} from "@account-abstraction/contracts/core/EntryPoint.sol";
-import "forge-std/src/console.sol";
+import {IEntryPoint} from "@account-abstraction/contracts/interfaces/IEntryPoint.sol";
+import {UserOperation} from "@account-abstraction/contracts/interfaces/UserOperation.sol";
+import {console} from "forge-std/src/console.sol";
/// Tests for install/uninstall
contract PluginManagerTest is TestUtils {
@@ -56,7 +64,7 @@ contract PluginManagerTest is TestUtils {
PluginManager private pluginManager = new PluginManager();
uint256 internal eoaPrivateKey;
address private ownerAddr;
- address payable beneficiary; // e.g. bundler
+ address payable private beneficiary; // e.g. bundler
TestCircleMSCAFactory private factory;
SingleOwnerPlugin private singleOwnerPlugin;
TestCircleMSCA private msca;
@@ -120,7 +128,7 @@ contract PluginManagerTest is TestUtils {
// install from a random address, should be rejected
// UnauthorizedCaller is caught by the caller and converted to RuntimeValidationFailed
vm.startPrank(address(1));
- bytes memory revertReason = abi.encodeWithSelector(bytes4(keccak256("UnauthorizedCaller()")));
+ bytes memory revertReason = abi.encodeWithSelector(UnauthorizedCaller.selector);
// function id from manifest
uint8 functionId = uint8(ISingleOwnerPlugin.FunctionId.RUNTIME_VALIDATION_OWNER_OR_SELF);
vm.expectRevert(
diff --git a/test/msca/6900/v0.7/RepeatableFunctionReferenceDLLLib.t.sol b/test/msca/6900/v0.7/RepeatableFunctionReferenceDLLLib.t.sol
index 2cf340e..a86ccb2 100644
--- a/test/msca/6900/v0.7/RepeatableFunctionReferenceDLLLib.t.sol
+++ b/test/msca/6900/v0.7/RepeatableFunctionReferenceDLLLib.t.sol
@@ -18,10 +18,12 @@
*/
pragma solidity 0.8.24;
-import "../../../../src/msca/6900/v0.7/common/Structs.sol";
-import "../../../util/TestUtils.sol";
-import "./TestRepeatableFunctionReferenceDLL.sol";
-import "forge-std/src/console.sol";
+import {SENTINEL_BYTES21} from "../../../../src/common/Constants.sol";
+
+import {FunctionReference} from "../../../../src/msca/6900/v0.7/common/Structs.sol";
+import {FunctionReferenceLib} from "../../../../src/msca/6900/v0.7/libs/FunctionReferenceLib.sol";
+import {TestUtils} from "../../../util/TestUtils.sol";
+import {TestRepeatableFunctionReferenceDLL} from "./TestRepeatableFunctionReferenceDLL.sol";
contract RepeatableFunctionReferenceDLLibTest is TestUtils {
using FunctionReferenceLib for bytes21;
diff --git a/test/msca/6900/v0.7/SingleOwnerMSCA.t.sol b/test/msca/6900/v0.7/SingleOwnerMSCA.t.sol
index 64e107b..3ee3d81 100644
--- a/test/msca/6900/v0.7/SingleOwnerMSCA.t.sol
+++ b/test/msca/6900/v0.7/SingleOwnerMSCA.t.sol
@@ -18,31 +18,45 @@
*/
pragma solidity 0.8.24;
+import {EIP1271_INVALID_SIGNATURE, EIP1271_VALID_SIGNATURE} from "../../../../src/common/Constants.sol";
+
+import {UnauthorizedCaller} from "../../../../src/common/Errors.sol";
+import {InvalidInitializationInput} from "../../../../src/msca/6900/shared/common/Errors.sol";
+import {InvalidValidationFunctionId} from "../../../../src/msca/6900/shared/common/Errors.sol";
import {InvalidExecutionFunction} from "../../../../src/msca/6900/shared/common/Errors.sol";
-import "../../../../src/msca/6900/v0.7/common/Structs.sol";
-import "../../../../src/msca/6900/v0.7/factories/semi/SingleOwnerMSCAFactory.sol";
-import "../../../../src/msca/6900/v0.7/interfaces/IStandardExecutor.sol";
-import "../../../../src/msca/6900/v0.7/libs/FunctionReferenceLib.sol";
-import "../../../../src/msca/6900/v0.7/plugins/v1_0_0/acl/SingleOwnerPlugin.sol";
-import "../../../../src/utils/ExecutionUtils.sol";
-import "../../../util/Mock1820Registry.sol";
-import "../../../util/TestERC1155.sol";
-import "../../../util/TestERC721.sol";
-import "../../../util/TestERC777.sol";
-import "../../../util/TestLiquidityPool.sol";
-import "../../../util/TestUtils.sol";
+import {ValidationData} from "../../../../src/msca/6900/shared/common/Structs.sol";
+import {SingleOwnerMSCA} from "../../../../src/msca/6900/v0.7/account/semi/SingleOwnerMSCA.sol";
+import {
+ Call,
+ ExecutionFunctionConfig,
+ ExecutionHooks,
+ FunctionReference
+} from "../../../../src/msca/6900/v0.7/common/Structs.sol";
+import {SingleOwnerMSCAFactory} from "../../../../src/msca/6900/v0.7/factories/semi/SingleOwnerMSCAFactory.sol";
+import {IPluginManager} from "../../../../src/msca/6900/v0.7/interfaces/IPluginManager.sol";
+import {IStandardExecutor} from "../../../../src/msca/6900/v0.7/interfaces/IStandardExecutor.sol";
+import {FunctionReferenceLib} from "../../../../src/msca/6900/v0.7/libs/FunctionReferenceLib.sol";
+import {PluginManager} from "../../../../src/msca/6900/v0.7/managers/PluginManager.sol";
+import {ISingleOwnerPlugin} from "../../../../src/msca/6900/v0.7/plugins/v1_0_0/acl/ISingleOwnerPlugin.sol";
+
+import {SingleOwnerPlugin} from "../../../../src/msca/6900/v0.7/plugins/v1_0_0/acl/SingleOwnerPlugin.sol";
+import {ExecutionUtils} from "../../../../src/utils/ExecutionUtils.sol";
+import {MockERC1820Registry} from "../../../util/Mock1820Registry.sol";
+import {TestERC1155} from "../../../util/TestERC1155.sol";
+import {TestERC721} from "../../../util/TestERC721.sol";
+import {TestERC777} from "../../../util/TestERC777.sol";
+import {TestLiquidityPool} from "../../../util/TestLiquidityPool.sol";
+import {TestUtils} from "../../../util/TestUtils.sol";
+import {IEntryPoint} from "@account-abstraction/contracts/interfaces/IEntryPoint.sol";
+import {UserOperation} from "@account-abstraction/contracts/interfaces/UserOperation.sol";
+import {IERC1820Registry} from "@openzeppelin/contracts/interfaces/IERC1820Registry.sol";
import {TestTokenPlugin} from "./TestTokenPlugin.sol";
-import {DefaultTokenCallbackPlugin} from
- "../../../../src/msca/6900/v0.7/plugins/v1_0_0/utility/DefaultTokenCallbackPlugin.sol";
import {TestUserOpAllPassValidator} from "./TestUserOpAllPassValidator.sol";
-import "./TestUserOpValidator.sol";
-import "./TestUserOpValidatorHook.sol";
import {EntryPoint} from "@account-abstraction/contracts/core/EntryPoint.sol";
import {IERC721Receiver} from "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
-import "forge-std/src/console.sol";
contract SingleOwnerMSCATest is TestUtils {
using FunctionReferenceLib for bytes21;
@@ -504,22 +518,17 @@ contract SingleOwnerMSCATest is TestUtils {
bytes memory initializingData = abi.encode(sendingOwnerAddr);
SingleOwnerMSCA sender = factory.createAccount(sendingOwnerAddr, salt, initializingData);
vm.deal(address(sender), 1 ether);
- DefaultTokenCallbackPlugin defaultTokenCallbackPlugin = new DefaultTokenCallbackPlugin();
// call from owner
vm.startPrank(sendingOwnerAddr);
- bytes32 manifest = keccak256(abi.encode(defaultTokenCallbackPlugin.pluginManifest()));
- FunctionReference[] memory emptyFR = new FunctionReference[](0);
- sender.installPlugin(address(defaultTokenCallbackPlugin), manifest, "", emptyFR);
-
ExecutionFunctionConfig memory executionFunctionConfig =
sender.getExecutionFunctionConfig(IERC721Receiver.onERC721Received.selector);
- assertEq(executionFunctionConfig.plugin, address(defaultTokenCallbackPlugin));
+ assertEq(executionFunctionConfig.plugin, address(sender));
vm.stopPrank();
// okay to use a random address to view
vm.startPrank(vm.addr(123));
executionFunctionConfig = sender.getExecutionFunctionConfig(IERC721Receiver.onERC721Received.selector);
- assertEq(executionFunctionConfig.plugin, address(defaultTokenCallbackPlugin));
+ assertEq(executionFunctionConfig.plugin, address(sender));
vm.stopPrank();
}
@@ -569,9 +578,13 @@ contract SingleOwnerMSCATest is TestUtils {
bytes32 salt = 0x0000000000000000000000000000000000000000000000000000000000000000;
address sendingOwnerAddr = makeAddr("testGetPreValidationHooksWithRuntimeValidation");
bytes memory initializingData = abi.encode(sendingOwnerAddr);
+ // initialSetup: true
+ // construction: false
SingleOwnerMSCA sender = factory.createAccount(sendingOwnerAddr, salt, initializingData);
vm.deal(address(sender), 1 ether);
// init from owner again
+ // initialSetup: false
+ // construction: false
vm.startPrank(sendingOwnerAddr);
vm.expectRevert(WalletStorageIsInitialized.selector);
sender.initializeSingleOwnerMSCA(sendingOwnerAddr);
@@ -775,6 +788,7 @@ contract SingleOwnerMSCATest is TestUtils {
vm.startPrank(address(sender));
calls[0].target = address(testERC777);
calls[0].value = 0;
+ // solhint-disable-next-line check-send-result
calls[0].data = abi.encodeCall(testERC777.send, (recipientAddr, 9, ""));
sender.executeBatch(calls);
vm.stopPrank();
diff --git a/test/msca/6900/v0.7/SingleOwnerMSCAFactory.t.sol b/test/msca/6900/v0.7/SingleOwnerMSCAFactory.t.sol
index ae294fa..39283f5 100644
--- a/test/msca/6900/v0.7/SingleOwnerMSCAFactory.t.sol
+++ b/test/msca/6900/v0.7/SingleOwnerMSCAFactory.t.sol
@@ -18,16 +18,19 @@
*/
pragma solidity 0.8.24;
-import "../../../../src/msca/6900/v0.7/common/Structs.sol";
+import {InvalidInitializationInput} from "../../../../src/msca/6900/shared/common/Errors.sol";
+import {SingleOwnerMSCA} from "../../../../src/msca/6900/v0.7/account/semi/SingleOwnerMSCA.sol";
-import "../../../../src/msca/6900/v0.7/factories/semi/SingleOwnerMSCAFactory.sol";
-import "../../../../src/msca/6900/v0.7/interfaces/IStandardExecutor.sol";
+import {FunctionReference} from "../../../../src/msca/6900/v0.7/common/Structs.sol";
+import {IEntryPoint} from "@account-abstraction/contracts/interfaces/IEntryPoint.sol";
+
+import {SingleOwnerMSCAFactory} from "../../../../src/msca/6900/v0.7/factories/semi/SingleOwnerMSCAFactory.sol";
+import {IStandardExecutor} from "../../../../src/msca/6900/v0.7/interfaces/IStandardExecutor.sol";
import {PluginManager} from "../../../../src/msca/6900/v0.7/managers/PluginManager.sol";
-import "../../../util/TestLiquidityPool.sol";
-import "../../../util/TestUtils.sol";
+import {TestLiquidityPool} from "../../../util/TestLiquidityPool.sol";
+import {TestUtils} from "../../../util/TestUtils.sol";
import {EntryPoint} from "@account-abstraction/contracts/core/EntryPoint.sol";
-import "@account-abstraction/contracts/interfaces/UserOperation.sol";
-import "forge-std/src/console.sol";
+import {UserOperation} from "@account-abstraction/contracts/interfaces/UserOperation.sol";
contract SingleOwnerMSCAFactoryTest is TestUtils {
event AccountCreated(address indexed proxy, address sender, bytes32 salt);
@@ -50,7 +53,7 @@ contract SingleOwnerMSCAFactoryTest is TestUtils {
address private ownerAddr;
SingleOwnerMSCAFactory private factory;
TestLiquidityPool private testLiquidityPool;
- address payable beneficiary; // e.g. bundler
+ address payable private beneficiary; // e.g. bundler
function setUp() public {
factory = new SingleOwnerMSCAFactory(address(entryPoint), address(pluginManager));
@@ -75,7 +78,7 @@ contract SingleOwnerMSCAFactoryTest is TestUtils {
vm.expectEmit(true, true, false, false);
emit AccountCreated(counterfactualAddr, ownerAddr, salt);
SingleOwnerMSCA accountCreated = factory.createAccount(ownerAddr, salt, initializingData);
- assertEq(address(accountCreated.entryPoint()), address(entryPoint));
+ assertEq(address(accountCreated.ENTRY_POINT()), address(entryPoint));
assertEq(accountCreated.getNativeOwner(), ownerAddr);
// verify the address does not change
assertEq(address(accountCreated), counterfactualAddr);
diff --git a/test/msca/6900/v0.7/TestCircleMSCAFactory.sol b/test/msca/6900/v0.7/TestCircleMSCAFactory.sol
index 808b4eb..8b8ed04 100644
--- a/test/msca/6900/v0.7/TestCircleMSCAFactory.sol
+++ b/test/msca/6900/v0.7/TestCircleMSCAFactory.sol
@@ -18,12 +18,15 @@
*/
pragma solidity 0.8.24;
-import {Create2FailedDeployment, InvalidLength} from "../../../../src/msca/6900/shared/common/Errors.sol";
-import "./TestCircleMSCA.sol";
+import {InvalidLength} from "../../../../src/common/Errors.sol";
+import {Create2FailedDeployment} from "../../../../src/msca/6900/shared/common/Errors.sol";
+import {TestCircleMSCA} from "./TestCircleMSCA.sol";
import {IEntryPoint} from "@account-abstraction/contracts/interfaces/IEntryPoint.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
-import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
-import "@openzeppelin/contracts/utils/Create2.sol";
+import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
+import {Create2} from "@openzeppelin/contracts/utils/Create2.sol";
+import {UpgradableMSCA} from "src/msca/6900/v0.7/account/UpgradableMSCA.sol";
+import {PluginManager} from "src/msca/6900/v0.7/managers/PluginManager.sol";
/**
* @dev Only for testing purpose. Account factory that creates the TestCircleMSCA with a set of plugins to be installed.
@@ -32,8 +35,8 @@ import "@openzeppelin/contracts/utils/Create2.sol";
*/
contract TestCircleMSCAFactory is Ownable {
// logic implementation
- TestCircleMSCA public immutable accountImplementation;
- IEntryPoint public immutable entryPoint;
+ TestCircleMSCA public immutable ACCOUNT_IMPLEMENTATION;
+ IEntryPoint public immutable ENTRY_POINT;
mapping(address => bool) public isPluginAllowed;
event AccountCreated(address indexed proxy, address sender, bytes32 salt);
@@ -43,8 +46,8 @@ contract TestCircleMSCAFactory is Ownable {
constructor(address _owner, IEntryPoint _entryPoint, PluginManager _pluginManager) {
transferOwnership(_owner);
- accountImplementation = new TestCircleMSCA(_entryPoint, _pluginManager);
- entryPoint = _entryPoint;
+ ACCOUNT_IMPLEMENTATION = new TestCircleMSCA(_entryPoint, _pluginManager);
+ ENTRY_POINT = _entryPoint;
}
function setPlugins(address[] calldata _plugins, bool[] calldata _permissions) external onlyOwner {
@@ -94,7 +97,7 @@ contract TestCircleMSCAFactory is Ownable {
account = TestCircleMSCA(
payable(
new ERC1967Proxy{salt: mixedSalt}(
- address(accountImplementation),
+ address(ACCOUNT_IMPLEMENTATION),
abi.encodeCall(
UpgradableMSCA.initializeUpgradableMSCA, (_plugins, _manifestHashes, _pluginInstallData)
)
@@ -131,7 +134,7 @@ contract TestCircleMSCAFactory is Ownable {
* @param _unstakeDelaySec - the unstake delay for this entity. Can only be increased.
*/
function addStake(uint32 _unstakeDelaySec) public payable onlyOwner {
- entryPoint.addStake{value: msg.value}(_unstakeDelaySec);
+ ENTRY_POINT.addStake{value: msg.value}(_unstakeDelaySec);
}
/**
@@ -139,7 +142,7 @@ contract TestCircleMSCAFactory is Ownable {
* @notice This entity can't serve requests once unlocked, until it calls addStake again.
*/
function unlockStake() public onlyOwner {
- entryPoint.unlockStake();
+ ENTRY_POINT.unlockStake();
}
/**
@@ -148,7 +151,7 @@ contract TestCircleMSCAFactory is Ownable {
* @param _withdrawAddress the address to send withdrawn value.
*/
function withdrawStake(address payable _withdrawAddress) public onlyOwner {
- entryPoint.withdrawStake(_withdrawAddress);
+ ENTRY_POINT.withdrawStake(_withdrawAddress);
}
/**
@@ -179,7 +182,7 @@ contract TestCircleMSCAFactory is Ownable {
abi.encodePacked(
type(ERC1967Proxy).creationCode,
abi.encode(
- address(accountImplementation),
+ address(ACCOUNT_IMPLEMENTATION),
abi.encodeCall(
UpgradableMSCA.initializeUpgradableMSCA, (_plugins, _manifestHashes, _pluginInstallData)
)
diff --git a/test/msca/6900/v0.7/TestPermitAnyExternalAddressPlugin.sol b/test/msca/6900/v0.7/TestPermitAnyExternalAddressPlugin.sol
index 77bc320..bcf5736 100644
--- a/test/msca/6900/v0.7/TestPermitAnyExternalAddressPlugin.sol
+++ b/test/msca/6900/v0.7/TestPermitAnyExternalAddressPlugin.sol
@@ -18,17 +18,24 @@
*/
pragma solidity 0.8.24;
+import {SIG_VALIDATION_SUCCEEDED} from "../../../../src/common/Constants.sol";
import {PLUGIN_AUTHOR, PLUGIN_VERSION_1, SIG_VALIDATION_SUCCEEDED} from "../../../../src/common/Constants.sol";
-import "../../../../src/msca/6900/v0.7/common/Structs.sol";
+import {NotImplemented} from "../../../../src/msca/6900/shared/common/Errors.sol";
+import {
+ ManifestAssociatedFunction,
+ ManifestAssociatedFunctionType,
+ ManifestExecutionHook,
+ ManifestFunction,
+ PluginManifest,
+ PluginMetadata
+} from "../../../../src/msca/6900/v0.7/common/PluginManifest.sol";
-import "../../../../src/msca/6900/v0.7/interfaces/IPluginExecutor.sol";
-import "../../../../src/msca/6900/v0.7/interfaces/IPluginManager.sol";
-import "../../../../src/msca/6900/v0.7/interfaces/IStandardExecutor.sol";
+import {IPluginExecutor} from "../../../../src/msca/6900/v0.7/interfaces/IPluginExecutor.sol";
-import "../../../../src/msca/6900/v0.7/plugins/BasePlugin.sol";
-import "../../../util/TestLiquidityPool.sol";
-import "@account-abstraction/contracts/interfaces/UserOperation.sol";
-import "forge-std/src/console.sol";
+import {BasePlugin} from "../../../../src/msca/6900/v0.7/plugins/BasePlugin.sol";
+import {TestLiquidityPool} from "../../../util/TestLiquidityPool.sol";
+import {UserOperation} from "@account-abstraction/contracts/interfaces/UserOperation.sol";
+import {console} from "forge-std/src/console.sol";
/**
* @dev Plugin for tests only. This plugin permits any external contract calls.
diff --git a/test/msca/6900/v0.7/TestPermitAnyExternalAddressWithPostHookOnlyPlugin.sol b/test/msca/6900/v0.7/TestPermitAnyExternalAddressWithPostHookOnlyPlugin.sol
index 6a8a492..be3b07a 100644
--- a/test/msca/6900/v0.7/TestPermitAnyExternalAddressWithPostHookOnlyPlugin.sol
+++ b/test/msca/6900/v0.7/TestPermitAnyExternalAddressWithPostHookOnlyPlugin.sol
@@ -18,17 +18,25 @@
*/
pragma solidity 0.8.24;
+import {SIG_VALIDATION_SUCCEEDED} from "../../../../src/common/Constants.sol";
import {PLUGIN_AUTHOR, PLUGIN_VERSION_1, SIG_VALIDATION_SUCCEEDED} from "../../../../src/common/Constants.sol";
-import "../../../../src/msca/6900/v0.7/common/Structs.sol";
-
-import "../../../../src/msca/6900/v0.7/interfaces/IPluginExecutor.sol";
-import "../../../../src/msca/6900/v0.7/interfaces/IPluginManager.sol";
-import "../../../../src/msca/6900/v0.7/interfaces/IStandardExecutor.sol";
-
-import "../../../../src/msca/6900/v0.7/plugins/BasePlugin.sol";
-import "../../../util/TestLiquidityPool.sol";
-import "@account-abstraction/contracts/interfaces/UserOperation.sol";
-import "forge-std/src/console.sol";
+import {InvalidLength} from "../../../../src/common/Errors.sol";
+import {
+ ManifestAssociatedFunction,
+ ManifestAssociatedFunctionType,
+ ManifestExecutionHook,
+ ManifestFunction,
+ PluginManifest,
+ PluginMetadata
+} from "../../../../src/msca/6900/v0.7/common/PluginManifest.sol";
+
+import {IPluginExecutor} from "../../../../src/msca/6900/v0.7/interfaces/IPluginExecutor.sol";
+
+import {NotImplemented} from "../../../../src/msca/6900/shared/common/Errors.sol";
+import {BasePlugin} from "../../../../src/msca/6900/v0.7/plugins/BasePlugin.sol";
+import {TestLiquidityPool} from "../../../util/TestLiquidityPool.sol";
+import {UserOperation} from "@account-abstraction/contracts/interfaces/UserOperation.sol";
+import {console} from "forge-std/src/console.sol";
/**
* @dev Plugin for tests only. This plugin permits any external contract calls with post hook only.
@@ -99,7 +107,9 @@ contract TestPermitAnyExternalAddressWithPostHookOnlyPlugin is BasePlugin {
function postExecutionHook(uint8 functionId, bytes calldata preExecHookData) external view override {
console.logString("postExecutionHook data:");
console.logBytes(preExecHookData);
- require(preExecHookData.length == 0, "postOnlyHook should not have data");
+ if (preExecHookData.length != 0) {
+ revert InvalidLength();
+ }
if (functionId == uint8(FunctionId.POST_EXECUTION_HOOK)) {
return;
} else if (functionId == uint8(FunctionId.POST_PERMITTED_CALL_EXECUTION_HOOK)) {
diff --git a/test/msca/6900/v0.7/TestPermitAnyExternalAddressWithPreHookOnlyPlugin.sol b/test/msca/6900/v0.7/TestPermitAnyExternalAddressWithPreHookOnlyPlugin.sol
index 316705c..f737c69 100644
--- a/test/msca/6900/v0.7/TestPermitAnyExternalAddressWithPreHookOnlyPlugin.sol
+++ b/test/msca/6900/v0.7/TestPermitAnyExternalAddressWithPreHookOnlyPlugin.sol
@@ -19,16 +19,22 @@
pragma solidity 0.8.24;
import {PLUGIN_AUTHOR, PLUGIN_VERSION_1, SIG_VALIDATION_SUCCEEDED} from "../../../../src/common/Constants.sol";
-import "../../../../src/msca/6900/v0.7/common/Structs.sol";
-
-import "../../../../src/msca/6900/v0.7/interfaces/IPluginExecutor.sol";
-import "../../../../src/msca/6900/v0.7/interfaces/IPluginManager.sol";
-import "../../../../src/msca/6900/v0.7/interfaces/IStandardExecutor.sol";
-
-import "../../../../src/msca/6900/v0.7/plugins/BasePlugin.sol";
-import "../../../util/TestLiquidityPool.sol";
-import "@account-abstraction/contracts/interfaces/UserOperation.sol";
-import "forge-std/src/console.sol";
+import {NotImplemented} from "../../../../src/msca/6900/shared/common/Errors.sol";
+import {
+ ManifestAssociatedFunction,
+ ManifestAssociatedFunctionType,
+ ManifestExecutionHook,
+ ManifestFunction,
+ PluginManifest,
+ PluginMetadata
+} from "../../../../src/msca/6900/v0.7/common/PluginManifest.sol";
+
+import {IPluginExecutor} from "../../../../src/msca/6900/v0.7/interfaces/IPluginExecutor.sol";
+
+import {BasePlugin} from "../../../../src/msca/6900/v0.7/plugins/BasePlugin.sol";
+import {TestLiquidityPool} from "../../../util/TestLiquidityPool.sol";
+import {UserOperation} from "@account-abstraction/contracts/interfaces/UserOperation.sol";
+import {console} from "forge-std/src/console.sol";
/**
* @dev Plugin for tests only. This plugin permits any external contract calls with pre hook only.
diff --git a/test/msca/6900/v0.7/TestRepeatableFunctionReferenceDLL.sol b/test/msca/6900/v0.7/TestRepeatableFunctionReferenceDLL.sol
index 720a918..643383f 100644
--- a/test/msca/6900/v0.7/TestRepeatableFunctionReferenceDLL.sol
+++ b/test/msca/6900/v0.7/TestRepeatableFunctionReferenceDLL.sol
@@ -18,13 +18,14 @@
*/
pragma solidity 0.8.24;
-import "../../../../src/msca/6900/v0.7/common/Structs.sol";
-import "../../../../src/msca/6900/v0.7/libs/RepeatableFunctionReferenceDLLLib.sol";
+import {FunctionReference, RepeatableBytes21DLL} from "../../../../src/msca/6900/v0.7/common/Structs.sol";
+import {RepeatableFunctionReferenceDLLLib} from
+ "../../../../src/msca/6900/v0.7/libs/RepeatableFunctionReferenceDLLLib.sol";
contract TestRepeatableFunctionReferenceDLL {
using RepeatableFunctionReferenceDLLLib for RepeatableBytes21DLL;
- RepeatableBytes21DLL preValidationHooks;
+ RepeatableBytes21DLL private preValidationHooks;
function appendPreValidationHook(FunctionReference memory hookToAdd) external returns (uint256) {
return preValidationHooks.append(hookToAdd);
diff --git a/test/msca/6900/v0.7/TestTokenPlugin.sol b/test/msca/6900/v0.7/TestTokenPlugin.sol
index fb43c80..9eab5fe 100644
--- a/test/msca/6900/v0.7/TestTokenPlugin.sol
+++ b/test/msca/6900/v0.7/TestTokenPlugin.sol
@@ -19,17 +19,26 @@
pragma solidity 0.8.24;
import {PLUGIN_AUTHOR, PLUGIN_VERSION_1, SIG_VALIDATION_SUCCEEDED} from "../../../../src/common/Constants.sol";
-import "../../../../src/msca/6900/v0.7/common/Structs.sol";
-
-import "../../../../src/msca/6900/v0.7/interfaces/IPluginExecutor.sol";
-import "../../../../src/msca/6900/v0.7/interfaces/IPluginManager.sol";
-import "../../../../src/msca/6900/v0.7/interfaces/IStandardExecutor.sol";
-
-import "../../../../src/msca/6900/v0.7/plugins/BasePlugin.sol";
-import "../../../../src/msca/6900/v0.7/plugins/v1_0_0/acl/ISingleOwnerPlugin.sol";
-import "../../../util/TestLiquidityPool.sol";
-import "@account-abstraction/contracts/interfaces/UserOperation.sol";
-import "forge-std/src/console.sol";
+import {NotImplemented} from "../../../../src/msca/6900/shared/common/Errors.sol";
+import {
+ ManifestAssociatedFunction,
+ ManifestAssociatedFunctionType,
+ ManifestExecutionHook,
+ ManifestExternalCallPermission,
+ ManifestFunction,
+ PluginManifest,
+ PluginMetadata,
+ SelectorPermission
+} from "src/msca/6900/v0.7/common/PluginManifest.sol";
+
+import {IPluginExecutor} from "../../../../src/msca/6900/v0.7/interfaces/IPluginExecutor.sol";
+import {IStandardExecutor} from "../../../../src/msca/6900/v0.7/interfaces/IStandardExecutor.sol";
+
+import {BasePlugin} from "../../../../src/msca/6900/v0.7/plugins/BasePlugin.sol";
+import {ISingleOwnerPlugin} from "../../../../src/msca/6900/v0.7/plugins/v1_0_0/acl/ISingleOwnerPlugin.sol";
+import {TestLiquidityPool} from "../../../util/TestLiquidityPool.sol";
+import {UserOperation} from "@account-abstraction/contracts/interfaces/UserOperation.sol";
+import {console} from "forge-std/src/console.sol";
/**
* @dev Plugin for tests only. This plugin implements everything in manifest.
@@ -57,12 +66,12 @@ contract TestTokenPlugin is BasePlugin {
}
string public constant NAME = "Test Token Plugin";
- string constant NOT_FROZEN_PERM = "NOT_FROZEN_PERM"; // msg.sender should be able to
+ string private constant NOT_FROZEN_PERM = "NOT_FROZEN_PERM"; // msg.sender should be able to
mapping(address => uint256) internal _balances;
// use constants generated from tests here so manifest can stay pure
- address public constant longLiquidityPoolAddr = 0x7bff7C664bFeF913FB04473CC610D41F35E2A3F9;
- address public constant shortLiquidityPoolAddr = 0x241BB07f7eBB2CDC08Ccb8130088a8C3761cf197;
+ address public constant LONG_LIQUIDITY_POOL_ADDR = 0x7bff7C664bFeF913FB04473CC610D41F35E2A3F9;
+ address public constant SHORT_LIQUIDITY_POOL_ADDR = 0x241BB07f7eBB2CDC08Ccb8130088a8C3761cf197;
/// executeFromPlugin is allowed
/// airdrop from wallet to owner
@@ -98,10 +107,10 @@ contract TestTokenPlugin is BasePlugin {
// mint to both liquidity pools
function mintToken(uint256 value) external returns (bool) {
IPluginExecutor(msg.sender).executeFromPluginExternal(
- longLiquidityPoolAddr, 0, abi.encodeCall(TestLiquidityPool.mint, (msg.sender, value))
+ LONG_LIQUIDITY_POOL_ADDR, 0, abi.encodeCall(TestLiquidityPool.mint, (msg.sender, value))
);
IPluginExecutor(msg.sender).executeFromPluginExternal(
- shortLiquidityPoolAddr, 0, abi.encodeCall(TestLiquidityPool.mint, (msg.sender, value))
+ SHORT_LIQUIDITY_POOL_ADDR, 0, abi.encodeCall(TestLiquidityPool.mint, (msg.sender, value))
);
return true;
}
@@ -110,14 +119,14 @@ contract TestTokenPlugin is BasePlugin {
// supply to only long liquidity pool
function supplyLiquidity(address to, uint256 value) external {
IPluginExecutor(msg.sender).executeFromPluginExternal(
- longLiquidityPoolAddr, 0, abi.encodeCall(TestLiquidityPool.supplyLiquidity, (msg.sender, to, value))
+ LONG_LIQUIDITY_POOL_ADDR, 0, abi.encodeCall(TestLiquidityPool.supplyLiquidity, (msg.sender, to, value))
);
}
// externalFromPluginExternal is not allowed
function supplyLiquidityBad(address to, uint256 value) external {
IPluginExecutor(msg.sender).executeFromPluginExternal(
- shortLiquidityPoolAddr, 0, abi.encodeCall(TestLiquidityPool.supplyLiquidity, (msg.sender, to, value))
+ SHORT_LIQUIDITY_POOL_ADDR, 0, abi.encodeCall(TestLiquidityPool.supplyLiquidity, (msg.sender, to, value))
);
}
@@ -260,13 +269,13 @@ contract TestTokenPlugin is BasePlugin {
manifest.permittedExternalCalls = new ManifestExternalCallPermission[](2);
// access only mint function in shortLiquidityPool
manifest.permittedExternalCalls[0] = ManifestExternalCallPermission({
- externalAddress: shortLiquidityPoolAddr,
+ externalAddress: SHORT_LIQUIDITY_POOL_ADDR,
permitAnySelector: false,
selectors: permittedExternalCallsSelectors
});
// access all the functions in longLiquidityPool
manifest.permittedExternalCalls[1] = ManifestExternalCallPermission({
- externalAddress: longLiquidityPoolAddr,
+ externalAddress: LONG_LIQUIDITY_POOL_ADDR,
permitAnySelector: true,
selectors: new bytes4[](0)
});
diff --git a/test/msca/6900/v0.7/TestTokenWithPostHookOnlyPlugin.sol b/test/msca/6900/v0.7/TestTokenWithPostHookOnlyPlugin.sol
index bc98be5..c23e79f 100644
--- a/test/msca/6900/v0.7/TestTokenWithPostHookOnlyPlugin.sol
+++ b/test/msca/6900/v0.7/TestTokenWithPostHookOnlyPlugin.sol
@@ -19,17 +19,26 @@
pragma solidity 0.8.24;
import {PLUGIN_AUTHOR, PLUGIN_VERSION_1, SIG_VALIDATION_SUCCEEDED} from "../../../../src/common/Constants.sol";
-import "../../../../src/msca/6900/v0.7/common/Structs.sol";
-
-import "../../../../src/msca/6900/v0.7/interfaces/IPluginExecutor.sol";
-import "../../../../src/msca/6900/v0.7/interfaces/IPluginManager.sol";
-import "../../../../src/msca/6900/v0.7/interfaces/IStandardExecutor.sol";
-
-import "../../../../src/msca/6900/v0.7/plugins/BasePlugin.sol";
-import "../../../../src/msca/6900/v0.7/plugins/v1_0_0/acl/ISingleOwnerPlugin.sol";
-import "../../../util/TestLiquidityPool.sol";
-import "@account-abstraction/contracts/interfaces/UserOperation.sol";
-import "forge-std/src/console.sol";
+import {InvalidLength} from "../../../../src/common/Errors.sol";
+import {NotImplemented} from "../../../../src/msca/6900/shared/common/Errors.sol";
+import {
+ ManifestAssociatedFunction,
+ ManifestAssociatedFunctionType,
+ ManifestExecutionHook,
+ ManifestExternalCallPermission,
+ ManifestFunction,
+ PluginManifest,
+ PluginMetadata,
+ SelectorPermission
+} from "../../../../src/msca/6900/v0.7/common/PluginManifest.sol";
+
+import {IPluginExecutor} from "../../../../src/msca/6900/v0.7/interfaces/IPluginExecutor.sol";
+
+import {BasePlugin} from "../../../../src/msca/6900/v0.7/plugins/BasePlugin.sol";
+import {ISingleOwnerPlugin} from "../../../../src/msca/6900/v0.7/plugins/v1_0_0/acl/ISingleOwnerPlugin.sol";
+import {TestLiquidityPool} from "../../../util/TestLiquidityPool.sol";
+import {UserOperation} from "@account-abstraction/contracts/interfaces/UserOperation.sol";
+import {console} from "forge-std/src/console.sol";
/**
* @dev Plugin that only has post hooks.
@@ -46,12 +55,12 @@ contract TestTokenWithPostHookOnlyPlugin is BasePlugin {
}
string public constant NAME = "Test Token Plugin With Post Hook Only";
- string constant NOT_FROZEN_PERM = "NOT_FROZEN_PERM"; // msg.sender should be able to
+ string private constant NOT_FROZEN_PERM = "NOT_FROZEN_PERM"; // msg.sender should be able to
mapping(address => uint256) internal _balances;
// use constants generated from tests here so manifest can stay pure
- address public constant longLiquidityPoolAddr = 0x7bff7C664bFeF913FB04473CC610D41F35E2A3F9;
- address public constant shortLiquidityPoolAddr = 0x241BB07f7eBB2CDC08Ccb8130088a8C3761cf197;
+ address public constant LONG_LIQUIDITY_POOL_ADDR = 0x7bff7C664bFeF913FB04473CC610D41F35E2A3F9;
+ address public constant SHORT_LIQUIDITY_POOL_ADDR = 0x241BB07f7eBB2CDC08Ccb8130088a8C3761cf197;
/// executeFromPlugin is allowed
/// airdrop from wallet to owner
@@ -87,10 +96,10 @@ contract TestTokenWithPostHookOnlyPlugin is BasePlugin {
// mint to both liquidity pools
function mintToken(uint256 value) external {
IPluginExecutor(msg.sender).executeFromPluginExternal(
- longLiquidityPoolAddr, 0, abi.encodeCall(TestLiquidityPool.mint, (msg.sender, value))
+ LONG_LIQUIDITY_POOL_ADDR, 0, abi.encodeCall(TestLiquidityPool.mint, (msg.sender, value))
);
IPluginExecutor(msg.sender).executeFromPluginExternal(
- shortLiquidityPoolAddr, 0, abi.encodeCall(TestLiquidityPool.mint, (msg.sender, value))
+ SHORT_LIQUIDITY_POOL_ADDR, 0, abi.encodeCall(TestLiquidityPool.mint, (msg.sender, value))
);
}
@@ -98,14 +107,14 @@ contract TestTokenWithPostHookOnlyPlugin is BasePlugin {
// supply to only long liquidity pool
function supplyLiquidity(address to, uint256 value) external {
IPluginExecutor(msg.sender).executeFromPluginExternal(
- longLiquidityPoolAddr, 0, abi.encodeCall(TestLiquidityPool.supplyLiquidity, (msg.sender, to, value))
+ LONG_LIQUIDITY_POOL_ADDR, 0, abi.encodeCall(TestLiquidityPool.supplyLiquidity, (msg.sender, to, value))
);
}
// externalFromPluginExternal is not allowed
function supplyLiquidityBad(address to, uint256 value) external {
IPluginExecutor(msg.sender).executeFromPluginExternal(
- shortLiquidityPoolAddr, 0, abi.encodeCall(TestLiquidityPool.supplyLiquidity, (msg.sender, to, value))
+ SHORT_LIQUIDITY_POOL_ADDR, 0, abi.encodeCall(TestLiquidityPool.supplyLiquidity, (msg.sender, to, value))
);
}
@@ -161,7 +170,9 @@ contract TestTokenWithPostHookOnlyPlugin is BasePlugin {
function postExecutionHook(uint8 functionId, bytes calldata preExecHookData) external view override {
console.logString("postExecutionHook data:");
console.logBytes(preExecHookData);
- require(preExecHookData.length == 0, "postOnlyHook should not have data");
+ if (preExecHookData.length != 0) {
+ revert InvalidLength();
+ }
if (functionId == uint8(FunctionId.POST_EXECUTION_HOOK)) {
return;
} else if (functionId == uint8(FunctionId.POST_EXECUTION_HOOK)) {
@@ -198,13 +209,13 @@ contract TestTokenWithPostHookOnlyPlugin is BasePlugin {
manifest.permittedExternalCalls = new ManifestExternalCallPermission[](2);
// access only mint function in shortLiquidityPool
manifest.permittedExternalCalls[0] = ManifestExternalCallPermission({
- externalAddress: shortLiquidityPoolAddr,
+ externalAddress: SHORT_LIQUIDITY_POOL_ADDR,
permitAnySelector: false,
selectors: permittedExternalCallsSelectors
});
// access all the functions in longLiquidityPool
manifest.permittedExternalCalls[1] = ManifestExternalCallPermission({
- externalAddress: longLiquidityPoolAddr,
+ externalAddress: LONG_LIQUIDITY_POOL_ADDR,
permitAnySelector: true,
selectors: new bytes4[](0)
});
diff --git a/test/msca/6900/v0.7/TestTokenWithPreHookOnlyPlugin.sol b/test/msca/6900/v0.7/TestTokenWithPreHookOnlyPlugin.sol
index 5eff70b..7ee1a54 100644
--- a/test/msca/6900/v0.7/TestTokenWithPreHookOnlyPlugin.sol
+++ b/test/msca/6900/v0.7/TestTokenWithPreHookOnlyPlugin.sol
@@ -19,17 +19,26 @@
pragma solidity 0.8.24;
import {PLUGIN_AUTHOR, PLUGIN_VERSION_1, SIG_VALIDATION_SUCCEEDED} from "../../../../src/common/Constants.sol";
-import "../../../../src/msca/6900/v0.7/common/Structs.sol";
-
-import "../../../../src/msca/6900/v0.7/interfaces/IPluginExecutor.sol";
-import "../../../../src/msca/6900/v0.7/interfaces/IPluginManager.sol";
-import "../../../../src/msca/6900/v0.7/interfaces/IStandardExecutor.sol";
-
-import "../../../../src/msca/6900/v0.7/plugins/BasePlugin.sol";
-import "../../../../src/msca/6900/v0.7/plugins/v1_0_0/acl/ISingleOwnerPlugin.sol";
-import "../../../util/TestLiquidityPool.sol";
-import "@account-abstraction/contracts/interfaces/UserOperation.sol";
-import "forge-std/src/console.sol";
+import {NotImplemented} from "../../../../src/msca/6900/shared/common/Errors.sol";
+import {
+ ManifestAssociatedFunction,
+ ManifestAssociatedFunctionType,
+ ManifestExecutionHook,
+ ManifestExternalCallPermission,
+ ManifestFunction,
+ PluginManifest,
+ PluginMetadata,
+ SelectorPermission
+} from "../../../../src/msca/6900/v0.7/common/PluginManifest.sol";
+
+import {IPluginExecutor} from "../../../../src/msca/6900/v0.7/interfaces/IPluginExecutor.sol";
+import {IStandardExecutor} from "../../../../src/msca/6900/v0.7/interfaces/IStandardExecutor.sol";
+
+import {BasePlugin} from "../../../../src/msca/6900/v0.7/plugins/BasePlugin.sol";
+import {ISingleOwnerPlugin} from "../../../../src/msca/6900/v0.7/plugins/v1_0_0/acl/ISingleOwnerPlugin.sol";
+import {TestLiquidityPool} from "../../../util/TestLiquidityPool.sol";
+import {UserOperation} from "@account-abstraction/contracts/interfaces/UserOperation.sol";
+import {console} from "forge-std/src/console.sol";
/**
* @dev Plugin for tests only with only pre hooks.
@@ -50,12 +59,12 @@ contract TestTokenWithPreHookOnlyPlugin is BasePlugin {
}
string public constant NAME = "Test Token Plugin With Pre Hook Only";
- string constant NOT_FROZEN_PERM = "NOT_FROZEN_PERM"; // msg.sender should be able to
+ string private constant NOT_FROZEN_PERM = "NOT_FROZEN_PERM"; // msg.sender should be able to
mapping(address => uint256) internal _balances;
// use constants generated from tests here so manifest can stay pure
- address public constant longLiquidityPoolAddr = 0x7bff7C664bFeF913FB04473CC610D41F35E2A3F9;
- address public constant shortLiquidityPoolAddr = 0x241BB07f7eBB2CDC08Ccb8130088a8C3761cf197;
+ address public constant LONG_LIQUIDITY_POOL_ADDR = 0x7bff7C664bFeF913FB04473CC610D41F35E2A3F9;
+ address public constant SHORT_LIQUIDITY_POOL_ADDR = 0x241BB07f7eBB2CDC08Ccb8130088a8C3761cf197;
/// executeFromPlugin is allowed
/// airdrop from wallet to owner
@@ -91,10 +100,10 @@ contract TestTokenWithPreHookOnlyPlugin is BasePlugin {
// mint to both liquidity pools
function mintToken(uint256 value) external {
IPluginExecutor(msg.sender).executeFromPluginExternal(
- longLiquidityPoolAddr, 0, abi.encodeCall(TestLiquidityPool.mint, (msg.sender, value))
+ LONG_LIQUIDITY_POOL_ADDR, 0, abi.encodeCall(TestLiquidityPool.mint, (msg.sender, value))
);
IPluginExecutor(msg.sender).executeFromPluginExternal(
- shortLiquidityPoolAddr, 0, abi.encodeCall(TestLiquidityPool.mint, (msg.sender, value))
+ SHORT_LIQUIDITY_POOL_ADDR, 0, abi.encodeCall(TestLiquidityPool.mint, (msg.sender, value))
);
}
@@ -102,14 +111,14 @@ contract TestTokenWithPreHookOnlyPlugin is BasePlugin {
// supply to only long liquidity pool
function supplyLiquidity(address to, uint256 value) external {
IPluginExecutor(msg.sender).executeFromPluginExternal(
- longLiquidityPoolAddr, 0, abi.encodeCall(TestLiquidityPool.supplyLiquidity, (msg.sender, to, value))
+ LONG_LIQUIDITY_POOL_ADDR, 0, abi.encodeCall(TestLiquidityPool.supplyLiquidity, (msg.sender, to, value))
);
}
// externalFromPluginExternal is not allowed
function supplyLiquidityBad(address to, uint256 value) external {
IPluginExecutor(msg.sender).executeFromPluginExternal(
- shortLiquidityPoolAddr, 0, abi.encodeCall(TestLiquidityPool.supplyLiquidity, (msg.sender, to, value))
+ SHORT_LIQUIDITY_POOL_ADDR, 0, abi.encodeCall(TestLiquidityPool.supplyLiquidity, (msg.sender, to, value))
);
}
@@ -235,13 +244,13 @@ contract TestTokenWithPreHookOnlyPlugin is BasePlugin {
manifest.permittedExternalCalls = new ManifestExternalCallPermission[](2);
// access only mint function in shortLiquidityPool
manifest.permittedExternalCalls[0] = ManifestExternalCallPermission({
- externalAddress: shortLiquidityPoolAddr,
+ externalAddress: SHORT_LIQUIDITY_POOL_ADDR,
permitAnySelector: false,
selectors: permittedExternalCallsSelectors
});
// access all the functions in longLiquidityPool
manifest.permittedExternalCalls[1] = ManifestExternalCallPermission({
- externalAddress: longLiquidityPoolAddr,
+ externalAddress: LONG_LIQUIDITY_POOL_ADDR,
permitAnySelector: true,
selectors: new bytes4[](0)
});
diff --git a/test/msca/6900/v0.7/TestUserOpAllPassValidator.sol b/test/msca/6900/v0.7/TestUserOpAllPassValidator.sol
index 8acebe8..7af1712 100644
--- a/test/msca/6900/v0.7/TestUserOpAllPassValidator.sol
+++ b/test/msca/6900/v0.7/TestUserOpAllPassValidator.sol
@@ -18,13 +18,15 @@
*/
pragma solidity 0.8.24;
+/* solhint-disable no-empty-blocks */
+
import {ValidationData} from "../../../../src/msca/6900/shared/common/Structs.sol";
import {PluginManifest} from "../../../../src/msca/6900/v0.7/common/PluginManifest.sol";
import {BasePlugin} from "../../../../src/msca/6900/v0.7/plugins/BasePlugin.sol";
import {UserOperation} from "@account-abstraction/contracts/interfaces/UserOperation.sol";
contract TestUserOpAllPassValidator is BasePlugin {
- ValidationData expectedValidationData;
+ ValidationData private expectedValidationData;
constructor() {
ValidationData memory expectToPass = ValidationData(0, 0xFFFFFFFFFFFF, address(0));
diff --git a/test/msca/6900/v0.7/TestUserOpValidatorHook.sol b/test/msca/6900/v0.7/TestUserOpValidatorHook.sol
index c5570c3..3c70431 100644
--- a/test/msca/6900/v0.7/TestUserOpValidatorHook.sol
+++ b/test/msca/6900/v0.7/TestUserOpValidatorHook.sol
@@ -23,7 +23,7 @@ import {BasePlugin} from "../../../../src/msca/6900/v0.7/plugins/BasePlugin.sol"
import {UserOperation} from "@account-abstraction/contracts/interfaces/UserOperation.sol";
contract TestValidatorHook is BasePlugin {
- ValidationData expectedValidationData;
+ ValidationData private expectedValidationData;
constructor(ValidationData memory _expectedValidationData) {
expectedValidationData = _expectedValidationData;
diff --git a/test/msca/6900/v0.7/TestUserOpValidatorWithDependencyHook.sol b/test/msca/6900/v0.7/TestUserOpValidatorWithDependencyHook.sol
index 74862ab..dbdbf12 100644
--- a/test/msca/6900/v0.7/TestUserOpValidatorWithDependencyHook.sol
+++ b/test/msca/6900/v0.7/TestUserOpValidatorWithDependencyHook.sol
@@ -19,8 +19,14 @@
pragma solidity 0.8.24;
import {ValidationData} from "../../../../src/msca/6900/shared/common/Structs.sol";
-import "../../../../src/msca/6900/v0.7/plugins/BasePlugin.sol";
-import "../../../../src/msca/6900/v0.7/plugins/v1_0_0/acl/ISingleOwnerPlugin.sol";
+import {BasePlugin} from "../../../../src/msca/6900/v0.7/plugins/BasePlugin.sol";
+import {ISingleOwnerPlugin} from "../../../../src/msca/6900/v0.7/plugins/v1_0_0/acl/ISingleOwnerPlugin.sol";
+import {
+ ManifestAssociatedFunction,
+ ManifestAssociatedFunctionType,
+ ManifestFunction,
+ PluginManifest
+} from "src/msca/6900/v0.7/common/PluginManifest.sol";
/// This hook cannot be installed due to expecting being installed with hook dependencies
contract TestUserOpValidatorWithDependencyHook is BasePlugin {
diff --git a/test/msca/6900/v0.7/UpgradableMSCA.t.sol b/test/msca/6900/v0.7/UpgradableMSCA.t.sol
index 8bdf423..29e49b1 100644
--- a/test/msca/6900/v0.7/UpgradableMSCA.t.sol
+++ b/test/msca/6900/v0.7/UpgradableMSCA.t.sol
@@ -23,7 +23,6 @@ import {EMPTY_FUNCTION_REFERENCE} from "../../../../src/common/Constants.sol";
import {ValidationData} from "../../../../src/msca/6900/shared/common/Structs.sol";
import {UpgradableMSCA} from "../../../../src/msca/6900/v0.7/account/UpgradableMSCA.sol";
-import {InvalidValidationFunctionId} from "../../../../src/msca/6900/shared/common/Errors.sol";
import {
PRE_HOOK_ALWAYS_DENY_FUNCTION_REFERENCE,
RUNTIME_VALIDATION_ALWAYS_ALLOW_FUNCTION_REFERENCE
@@ -47,8 +46,6 @@ import {TestERC721} from "../../../util/TestERC721.sol";
import {TestLiquidityPool} from "../../../util/TestLiquidityPool.sol";
import {TestUtils} from "../../../util/TestUtils.sol";
-import {DefaultTokenCallbackPlugin} from
- "../../../../src/msca/6900/v0.7/plugins/v1_0_0/utility/DefaultTokenCallbackPlugin.sol";
import {TestValidatorHook} from "../v0.7/TestUserOpValidatorHook.sol";
import {TestCircleMSCA} from "./TestCircleMSCA.sol";
import {TestCircleMSCAFactory} from "./TestCircleMSCAFactory.sol";
@@ -95,7 +92,6 @@ contract UpgradableMSCATest is TestUtils {
TestCircleMSCAFactory private factory;
address private factoryOwner;
SingleOwnerPlugin private singleOwnerPlugin;
- DefaultTokenCallbackPlugin private defaultTokenCallbackPlugin;
function setUp() public {
factoryOwner = makeAddr("factoryOwner");
@@ -105,13 +101,10 @@ contract UpgradableMSCATest is TestUtils {
testLiquidityPool = new TestLiquidityPool("getrich", "$$$");
factory = new TestCircleMSCAFactory(factoryOwner, entryPoint, pluginManager);
singleOwnerPlugin = new SingleOwnerPlugin();
- defaultTokenCallbackPlugin = new DefaultTokenCallbackPlugin();
- address[] memory _plugins = new address[](2);
+ address[] memory _plugins = new address[](1);
_plugins[0] = address(singleOwnerPlugin);
- _plugins[1] = address(defaultTokenCallbackPlugin);
- bool[] memory _permissions = new bool[](2);
+ bool[] memory _permissions = new bool[](1);
_permissions[0] = true;
- _permissions[1] = true;
vm.startPrank(factoryOwner);
factory.setPlugins(_plugins, _permissions);
vm.stopPrank();
@@ -889,10 +882,10 @@ contract UpgradableMSCATest is TestUtils {
assertEq(testLiquidityPool.balanceOf(senderAddr), 1000000);
}
- // should not be able to receive ERC1155 token w/o token callback plugin
- function testSendAndReceiveERC1155TokenWithoutDefaultCallbackPlugin() public {
+ // should be able to receive ERC1155 token with token callback enshrined
+ function testSendAndReceiveERC1155TokenNatively() public {
bytes32 salt = 0x0000000000000000000000000000000000000000000000000000000000000000;
- (ownerAddr, eoaPrivateKey) = makeAddrAndKey("testSendAndReceiveERC1155TokenWithoutDefaultCallbackPlugin_sender");
+ (ownerAddr, eoaPrivateKey) = makeAddrAndKey("testSendAndReceiveERC1155TokenNatively_sender");
address[] memory plugins = new address[](1);
bytes32[] memory manifestHashes = new bytes32[](1);
bytes[] memory pluginInstallData = new bytes[](1);
@@ -903,14 +896,14 @@ contract UpgradableMSCATest is TestUtils {
factory.createAccount(ownerAddr, salt, initializingData);
(address senderAddr,) = factory.getAddress(ownerAddr, salt, initializingData);
vm.deal(senderAddr, 1 ether);
- vm.expectRevert("ERC1155: transfer to non-ERC1155Receiver implementer");
testERC1155.mint(senderAddr, 0, 2, "");
+ assertEq(testERC1155.balanceOf(senderAddr, 0), 2);
}
- // should not be able to receive ERC721 token w/o token callback plugin
- function testSendAndReceiveERC721TokenWithoutDefaultCallbackPlugin() public {
+ // should not be able to receive ERC721 token with token callback enshrined
+ function testSendAndReceiveERC721TokenNatively() public {
bytes32 salt = 0x0000000000000000000000000000000000000000000000000000000000000000;
- (ownerAddr, eoaPrivateKey) = makeAddrAndKey("testSendAndReceiveERC721TokenWithoutDefaultCallbackPlugin_sender");
+ (ownerAddr, eoaPrivateKey) = makeAddrAndKey("testSendAndReceiveERC721TokenNatively_sender");
address[] memory plugins = new address[](1);
bytes32[] memory manifestHashes = new bytes32[](1);
bytes[] memory pluginInstallData = new bytes[](1);
@@ -921,24 +914,20 @@ contract UpgradableMSCATest is TestUtils {
factory.createAccount(ownerAddr, salt, initializingData);
(address senderAddr,) = factory.getAddress(ownerAddr, salt, initializingData);
vm.deal(senderAddr, 1 ether);
- // we do the runtime validation now first, so it would not even pass that due to missing of onERC721Received
- vm.expectRevert(abi.encodeWithSelector(bytes4(keccak256("InvalidValidationFunctionId(uint8)")), uint8(0)));
testERC721.safeMint(senderAddr, 0);
+ assertEq(testERC721.balanceOf(senderAddr), 1);
}
- // should be able to send/receive ERC1155 token with token callback plugin
- function testSendAndReceiveERC1155TokenWithDefaultCallbackPlugin() public {
+ // should be able to send/receive ERC1155 token with token callback handler
+ function testSendAndReceiveERC1155TokenWithDefaultCallbackHandler() public {
bytes32 salt = 0x0000000000000000000000000000000000000000000000000000000000000000;
- (ownerAddr, eoaPrivateKey) = makeAddrAndKey("testSendAndReceiveERC1155TokenWithDefaultCallbackPlugin_sender");
- address[] memory plugins = new address[](2);
- bytes32[] memory manifestHashes = new bytes32[](2);
- bytes[] memory pluginInstallData = new bytes[](2);
- plugins[0] = address(defaultTokenCallbackPlugin);
- manifestHashes[0] = keccak256(abi.encode(defaultTokenCallbackPlugin.pluginManifest()));
- pluginInstallData[0] = "";
- plugins[1] = address(singleOwnerPlugin);
- manifestHashes[1] = keccak256(abi.encode(singleOwnerPlugin.pluginManifest()));
- pluginInstallData[1] = abi.encode(ownerAddr);
+ (ownerAddr, eoaPrivateKey) = makeAddrAndKey("testSendAndReceiveERC1155TokenWithDefaultCallbackHandler_sender");
+ address[] memory plugins = new address[](1);
+ bytes32[] memory manifestHashes = new bytes32[](1);
+ bytes[] memory pluginInstallData = new bytes[](1);
+ plugins[0] = address(singleOwnerPlugin);
+ manifestHashes[0] = keccak256(abi.encode(singleOwnerPlugin.pluginManifest()));
+ pluginInstallData[0] = abi.encode(ownerAddr);
bytes memory initializingData = abi.encode(plugins, manifestHashes, pluginInstallData);
factory.createAccount(ownerAddr, salt, initializingData);
(address senderAddr,) = factory.getAddress(ownerAddr, salt, initializingData);
@@ -986,19 +975,16 @@ contract UpgradableMSCATest is TestUtils {
assertEq(testERC1155.balanceOf(senderAddr, 0), 1);
}
- // should be able to send/receive ERC721 token with token callback plugin
- function testSendAndReceiveERC721TokenWithDefaultCallbackPlugin() public {
+ // should be able to send/receive ERC721 token with token callback handler
+ function testSendAndReceiveERC721TokenWithDefaultCallbackHandler() public {
bytes32 salt = 0x0000000000000000000000000000000000000000000000000000000000000000;
- (ownerAddr, eoaPrivateKey) = makeAddrAndKey("testSendAndReceiveERC721TokenWithDefaultCallbackPlugin_sender");
- address[] memory plugins = new address[](2);
- bytes32[] memory manifestHashes = new bytes32[](2);
- bytes[] memory pluginInstallData = new bytes[](2);
- plugins[0] = address(defaultTokenCallbackPlugin);
- manifestHashes[0] = keccak256(abi.encode(defaultTokenCallbackPlugin.pluginManifest()));
- pluginInstallData[0] = "";
- plugins[1] = address(singleOwnerPlugin);
- manifestHashes[1] = keccak256(abi.encode(singleOwnerPlugin.pluginManifest()));
- pluginInstallData[1] = abi.encode(ownerAddr);
+ (ownerAddr, eoaPrivateKey) = makeAddrAndKey("testSendAndReceiveERC721TokenWithDefaultCallbackHandler_sender");
+ address[] memory plugins = new address[](1);
+ bytes32[] memory manifestHashes = new bytes32[](1);
+ bytes[] memory pluginInstallData = new bytes[](1);
+ plugins[0] = address(singleOwnerPlugin);
+ manifestHashes[0] = keccak256(abi.encode(singleOwnerPlugin.pluginManifest()));
+ pluginInstallData[0] = abi.encode(ownerAddr);
bytes memory initializingData = abi.encode(plugins, manifestHashes, pluginInstallData);
factory.createAccount(ownerAddr, salt, initializingData);
(address senderAddr,) = factory.getAddress(ownerAddr, salt, initializingData);
diff --git a/test/msca/6900/v0.7/UpgradableMSCAFactory.t.sol b/test/msca/6900/v0.7/UpgradableMSCAFactory.t.sol
index d62c9bd..875b700 100644
--- a/test/msca/6900/v0.7/UpgradableMSCAFactory.t.sol
+++ b/test/msca/6900/v0.7/UpgradableMSCAFactory.t.sol
@@ -117,7 +117,7 @@ contract UpgradableMSCAFactoryTest is TestUtils {
vm.expectEmit(true, true, false, false);
emit AccountCreated(counterfactualAddr, addressToBytes32(ownerAddr), salt);
UpgradableMSCA accountCreated = factory.createAccount(addressToBytes32(ownerAddr), salt, initializingData);
- assertEq(address(accountCreated.entryPoint()), address(entryPoint));
+ assertEq(address(accountCreated.ENTRY_POINT()), address(entryPoint));
assertEq(singleOwnerPlugin.getOwnerOf(address(accountCreated)), ownerAddr);
// verify the address does not change
assertEq(address(accountCreated), counterfactualAddr);
diff --git a/test/msca/6900/v0.7/WalletStorageInitializable.t.sol b/test/msca/6900/v0.7/WalletStorageInitializable.t.sol
new file mode 100644
index 0000000..1b781e9
--- /dev/null
+++ b/test/msca/6900/v0.7/WalletStorageInitializable.t.sol
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2024 Circle Internet Group, Inc. All rights reserved.
+
+ * SPDX-License-Identifier: GPL-3.0-or-later
+
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+pragma solidity 0.8.24;
+
+import {TestUtils} from "../../../util/TestUtils.sol";
+import {ChildConstructorInitializableMock} from "./ChildConstructorInitializableMock.sol";
+import {ConstructorInitializableMock} from "./ConstructorInitializableMock.sol";
+import {DisableInitializingWalletStorageMock} from "./DisableInitializingWalletStorageMock.sol";
+import {LockWalletStorageAfterInitializationMock} from "./LockWalletStorageAfterInitializationMock.sol";
+import {LockedWalletStorageMock} from "./LockedWalletStorageMock.sol";
+
+import {WalletStorageInitializableMock} from "./WalletStorageInitializableMock.sol";
+
+contract WalletStorageInitializableTest is TestUtils {
+ event WalletStorageInitialized();
+
+ error WalletStorageIsInitialized();
+ error WalletStorageIsNotInitializing();
+ error WalletStorageIsInitializing();
+
+ function testBeforeInitialize() public {
+ WalletStorageInitializableMock wallet = new WalletStorageInitializableMock();
+ assertFalse(wallet.initializerRan());
+ assertFalse(wallet.isInitializing());
+
+ // cannot call initializeOnlyInitializing function outside the scope of an initializable function
+ vm.expectRevert(WalletStorageIsNotInitializing.selector);
+ wallet.initializeOnlyInitializing();
+ }
+
+ function testAfterInitialize() public {
+ WalletStorageInitializableMock wallet = new WalletStorageInitializableMock();
+ wallet.initialize();
+ assertTrue(wallet.initializerRan());
+ assertFalse(wallet.isInitializing());
+ vm.expectRevert(WalletStorageIsInitialized.selector);
+ wallet.initialize();
+
+ // cannot call initializeOnlyInitializing function outside the scope of an initializable function
+ vm.expectRevert(WalletStorageIsNotInitializing.selector);
+ wallet.initializeOnlyInitializing();
+ }
+
+ function testNestedUnderAnInitializer() public {
+ WalletStorageInitializableMock wallet = new WalletStorageInitializableMock();
+ vm.expectRevert(WalletStorageIsInitialized.selector);
+ wallet.initializerNested();
+
+ wallet.onlyInitializingNested();
+ assertTrue(wallet.onlyInitializingRan());
+
+ // cannot call initializeOnlyInitializing function outside the scope of an initializable function
+ vm.expectRevert(WalletStorageIsNotInitializing.selector);
+ wallet.initializeOnlyInitializing();
+ }
+
+ function testNestedInitializerCanRunDuringConstruction() public {
+ ConstructorInitializableMock mock = new ConstructorInitializableMock();
+ assertTrue(mock.initializerRan());
+ assertTrue(mock.onlyInitializingRan());
+ }
+
+ function testMultipleConstructorLevelsCanBeInitializers() public {
+ ChildConstructorInitializableMock mock = new ChildConstructorInitializableMock();
+ assertTrue(mock.initializerRan());
+ assertTrue(mock.onlyInitializingRan());
+ assertTrue(mock.childInitializerRan());
+ }
+
+ function testInitLockedWalletStorage() public {
+ // the wallet is disabled/locked from initializing,
+ // so it should not be able to initialize in walletStorageInitializer
+ vm.expectRevert(WalletStorageIsInitialized.selector);
+ new LockedWalletStorageMock();
+ }
+
+ function testDisableInitializationInMiddleOfInitializing() public {
+ // the wallet is the middle of initializing
+ // so it should not be able to disable the process
+ vm.expectRevert(WalletStorageIsInitializing.selector);
+ new DisableInitializingWalletStorageMock();
+ }
+
+ function testDisableInitializationAfterInit() public {
+ vm.expectEmit(true, true, true, true);
+ emit WalletStorageInitialized();
+ new LockWalletStorageAfterInitializationMock();
+ }
+}
diff --git a/test/msca/6900/v0.7/WalletStorageInitializableMock.sol b/test/msca/6900/v0.7/WalletStorageInitializableMock.sol
new file mode 100644
index 0000000..51f0e23
--- /dev/null
+++ b/test/msca/6900/v0.7/WalletStorageInitializableMock.sol
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2024 Circle Internet Group, Inc. All rights reserved.
+
+ * SPDX-License-Identifier: GPL-3.0-or-later
+
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+pragma solidity 0.8.24;
+
+import {WalletStorageInitializable} from "../../../../src/msca/6900/v0.7/account/WalletStorageInitializable.sol";
+import {WalletStorageV1Lib} from "../../../../src/msca/6900/v0.7/libs/WalletStorageV1Lib.sol";
+
+/**
+ * @title InitializableMock, forked from OpenZeppelin
+ * @dev This contract is a mock to test WalletStorageInitializable functionality. It is not intended for production.
+ * There are some use cases we don't use in our protocol, such as the contract is initialized at version 1 (no
+ * reininitialization) and the current contract is just being deployed,
+ * but we still want to test them.
+ */
+contract WalletStorageInitializableMock is WalletStorageInitializable {
+ bool public initializerRan;
+ bool public onlyInitializingRan;
+
+ function isInitializing() public view returns (bool) {
+ return WalletStorageV1Lib.getLayout().initializing;
+ }
+
+ function initialize() public walletStorageInitializer {
+ initializerRan = true;
+ }
+
+ function initializeOnlyInitializing() public onlyWalletStorageInitializing {
+ onlyInitializingRan = true;
+ }
+
+ function initializerNested() public walletStorageInitializer {
+ initialize();
+ }
+
+ function onlyInitializingNested() public walletStorageInitializer {
+ initializeOnlyInitializing();
+ }
+}
diff --git a/test/msca/6900/v0.7/WalletStorageV1Lib.t.sol b/test/msca/6900/v0.7/WalletStorageV1Lib.t.sol
index d0f7f9e..971bae5 100644
--- a/test/msca/6900/v0.7/WalletStorageV1Lib.t.sol
+++ b/test/msca/6900/v0.7/WalletStorageV1Lib.t.sol
@@ -19,14 +19,16 @@
pragma solidity 0.8.24;
import {SENTINEL_BYTES21} from "../../../../src/common/Constants.sol";
-import "../../../../src/msca/6900/v0.7/account/UpgradableMSCA.sol";
-import "../../../../src/msca/6900/v0.7/common/Structs.sol";
-import "../../../util/TestUtils.sol";
-import "./TestCircleMSCA.sol";
-import "./TestUserOpValidator.sol";
-import "./TestUserOpValidatorHook.sol";
+import {FunctionReference, RepeatableBytes21DLL} from "../../../../src/msca/6900/v0.7/common/Structs.sol";
+import {FunctionReferenceLib} from "../../../../src/msca/6900/v0.7/libs/FunctionReferenceLib.sol";
+import {RepeatableFunctionReferenceDLLLib} from
+ "../../../../src/msca/6900/v0.7/libs/RepeatableFunctionReferenceDLLLib.sol";
+
+import {TestUtils} from "../../../util/TestUtils.sol";
+import {TestCircleMSCA} from "./TestCircleMSCA.sol";
import {EntryPoint} from "@account-abstraction/contracts/core/EntryPoint.sol";
-import "forge-std/src/console.sol";
+import {IEntryPoint} from "@account-abstraction/contracts/interfaces/IEntryPoint.sol";
+import {PluginManager} from "src/msca/6900/v0.7/managers/PluginManager.sol";
contract WalletStorageV1LibTest is TestUtils {
using RepeatableFunctionReferenceDLLLib for RepeatableBytes21DLL;
diff --git a/test/msca/6900/v0.7/plugins/AddressBookPluginWithFullMSCA.t.sol b/test/msca/6900/v0.7/plugins/AddressBookPluginWithFullMSCA.t.sol
index 0622367..3ca4939 100644
--- a/test/msca/6900/v0.7/plugins/AddressBookPluginWithFullMSCA.t.sol
+++ b/test/msca/6900/v0.7/plugins/AddressBookPluginWithFullMSCA.t.sol
@@ -18,20 +18,34 @@
*/
pragma solidity 0.8.24;
-import "../../../../../src/msca/6900/v0.7/account/BaseMSCA.sol";
+import {UnauthorizedCaller} from "../../../../../src/common/Errors.sol";
+import {BaseMSCA} from "../../../../../src/msca/6900/v0.7/account/BaseMSCA.sol";
+
+import {UpgradableMSCA} from "../../../../../src/msca/6900/v0.7/account/UpgradableMSCA.sol";
import {PRE_HOOK_ALWAYS_DENY_FUNCTION_REFERENCE} from "../../../../../src/msca/6900/v0.7/common/Constants.sol";
-import "../../../../../src/msca/6900/v0.7/common/Structs.sol";
-import "../../../../../src/msca/6900/v0.7/factories/UpgradableMSCAFactory.sol";
-import "../../../../../src/msca/6900/v0.7/libs/FunctionReferenceLib.sol";
-import "../../../../../src/msca/6900/v0.7/plugins/v1_0_0/acl/SingleOwnerPlugin.sol";
-
-import "../../../../../src/msca/6900/v0.7/plugins/v1_0_0/addressbook/AddressBookPlugin.sol";
-import "../../../../../src/msca/6900/v0.7/plugins/v1_0_0/addressbook/IAddressBookPlugin.sol";
-import "../../../../../src/utils/ExecutionUtils.sol";
-import "../../../../util/TestLiquidityPool.sol";
-import "../../../../util/TestUtils.sol";
+import {
+ Call,
+ ExecutionFunctionConfig,
+ ExecutionHooks,
+ FunctionReference
+} from "../../../../../src/msca/6900/v0.7/common/Structs.sol";
+import {UpgradableMSCAFactory} from "../../../../../src/msca/6900/v0.7/factories/UpgradableMSCAFactory.sol";
+import {IStandardExecutor} from "../../../../../src/msca/6900/v0.7/interfaces/IStandardExecutor.sol";
+import {FunctionReferenceLib} from "../../../../../src/msca/6900/v0.7/libs/FunctionReferenceLib.sol";
+import {PluginManager} from "../../../../../src/msca/6900/v0.7/managers/PluginManager.sol";
+import {ISingleOwnerPlugin} from "../../../../../src/msca/6900/v0.7/plugins/v1_0_0/acl/ISingleOwnerPlugin.sol";
+import {SingleOwnerPlugin} from "../../../../../src/msca/6900/v0.7/plugins/v1_0_0/acl/SingleOwnerPlugin.sol";
+import {IPluginManager} from "src/msca/6900/v0.7/interfaces/IPluginManager.sol";
+
+import {AddressBookPlugin} from "../../../../../src/msca/6900/v0.7/plugins/v1_0_0/addressbook/AddressBookPlugin.sol";
+import {IAddressBookPlugin} from "../../../../../src/msca/6900/v0.7/plugins/v1_0_0/addressbook/IAddressBookPlugin.sol";
+import {ExecutionUtils} from "../../../../../src/utils/ExecutionUtils.sol";
+import {TestLiquidityPool} from "../../../../util/TestLiquidityPool.sol";
+import {TestUtils} from "../../../../util/TestUtils.sol";
import {EntryPoint} from "@account-abstraction/contracts/core/EntryPoint.sol";
-import "forge-std/src/console.sol";
+import {IEntryPoint} from "@account-abstraction/contracts/interfaces/IEntryPoint.sol";
+import {UserOperation} from "@account-abstraction/contracts/interfaces/UserOperation.sol";
+import {console} from "forge-std/src/console.sol";
// some common test cases related to plugin itself is covered in AddressBookPluginWithSemiMSCATest
contract AddressBookPluginWithFullMSCATest is TestUtils {
@@ -56,14 +70,14 @@ contract AddressBookPluginWithFullMSCATest is TestUtils {
PluginManager private pluginManager = new PluginManager();
uint256 internal eoaPrivateKey;
address private ownerAddr;
- address payable beneficiary; // e.g. bundler
+ address payable private beneficiary; // e.g. bundler
UpgradableMSCAFactory private factory;
AddressBookPlugin private addressBookPlugin;
TestLiquidityPool private testLiquidityPool;
address private addressBookPluginAddr;
UpgradableMSCA private msca;
address private mscaAddr;
- bytes32 addressBookPluginManifest;
+ bytes32 private addressBookPluginManifest;
SingleOwnerPlugin private singleOwnerPlugin;
address private factoryOwner;
@@ -1044,7 +1058,7 @@ contract AddressBookPluginWithFullMSCATest is TestUtils {
msca = factory.createAccount(addressToBytes32(ownerAddr), bytes32(0), _initializingData);
console.log("address(msca) -> %s", address(msca));
(bool sent,) = address(msca).call{value: 10e18}("");
- require(sent, "Failed to send Ether");
+ assertTrue(sent);
FunctionReference[] memory dependencies = new FunctionReference[](2);
dependencies[0] = FunctionReference(
address(singleOwnerPlugin), uint8(ISingleOwnerPlugin.FunctionId.RUNTIME_VALIDATION_OWNER_OR_SELF)
diff --git a/test/msca/6900/v0.7/plugins/AddressBookPluginWithSemiMSCA.t.sol b/test/msca/6900/v0.7/plugins/AddressBookPluginWithSemiMSCA.t.sol
index 448f671..5e405c1 100644
--- a/test/msca/6900/v0.7/plugins/AddressBookPluginWithSemiMSCA.t.sol
+++ b/test/msca/6900/v0.7/plugins/AddressBookPluginWithSemiMSCA.t.sol
@@ -18,20 +18,39 @@
*/
pragma solidity 0.8.24;
+import {PLUGIN_AUTHOR, PLUGIN_VERSION_1} from "../../../../../src/common/Constants.sol";
+import {UnauthorizedCaller} from "../../../../../src/common/Errors.sol";
+import {InvalidValidationFunctionId} from "../../../../../src/msca/6900/shared/common/Errors.sol";
+
import {NotImplemented} from "../../../../../src/msca/6900/shared/common/Errors.sol";
-import "../../../../../src/msca/6900/v0.7/account/semi/SingleOwnerMSCA.sol";
-import "../../../../../src/msca/6900/v0.7/common/Structs.sol";
-import "../../../../../src/msca/6900/v0.7/factories/semi/SingleOwnerMSCAFactory.sol";
-import "../../../../../src/msca/6900/v0.7/interfaces/IPluginManager.sol";
-import "../../../../../src/msca/6900/v0.7/interfaces/IStandardExecutor.sol";
-import "../../../../../src/msca/6900/v0.7/libs/FunctionReferenceLib.sol";
-import "../../../../../src/msca/6900/v0.7/plugins/v1_0_0/addressbook/AddressBookPlugin.sol";
-import "../../../../../src/msca/6900/v0.7/plugins/v1_0_0/addressbook/IAddressBookPlugin.sol";
-import "../../../../../src/utils/ExecutionUtils.sol";
-import "../../../../util/TestLiquidityPool.sol";
-import "../../../../util/TestUtils.sol";
+import {BaseMSCA} from "../../../../../src/msca/6900/v0.7/account/BaseMSCA.sol";
+import {SingleOwnerMSCA} from "../../../../../src/msca/6900/v0.7/account/semi/SingleOwnerMSCA.sol";
+import {PluginMetadata} from "../../../../../src/msca/6900/v0.7/common/PluginManifest.sol";
+import {
+ Call,
+ ExecutionFunctionConfig,
+ ExecutionHooks,
+ FunctionReference
+} from "../../../../../src/msca/6900/v0.7/common/Structs.sol";
+import {SingleOwnerMSCAFactory} from "../../../../../src/msca/6900/v0.7/factories/semi/SingleOwnerMSCAFactory.sol";
+
+import {IPluginManager} from "../../../../../src/msca/6900/v0.7/interfaces/IPluginManager.sol";
+import {IStandardExecutor} from "../../../../../src/msca/6900/v0.7/interfaces/IStandardExecutor.sol";
+import {FunctionReferenceLib} from "../../../../../src/msca/6900/v0.7/libs/FunctionReferenceLib.sol";
+import {PluginManager} from "../../../../../src/msca/6900/v0.7/managers/PluginManager.sol";
+import {BasePlugin} from "../../../../../src/msca/6900/v0.7/plugins/BasePlugin.sol";
+
+import {AddressBookPlugin} from "../../../../../src/msca/6900/v0.7/plugins/v1_0_0/addressbook/AddressBookPlugin.sol";
+import {IAddressBookPlugin} from "../../../../../src/msca/6900/v0.7/plugins/v1_0_0/addressbook/IAddressBookPlugin.sol";
+import {ExecutionUtils} from "../../../../../src/utils/ExecutionUtils.sol";
+import {TestLiquidityPool} from "../../../../util/TestLiquidityPool.sol";
+import {TestUtils} from "../../../../util/TestUtils.sol";
import {EntryPoint} from "@account-abstraction/contracts/core/EntryPoint.sol";
-import "forge-std/src/console.sol";
+import {IEntryPoint} from "@account-abstraction/contracts/interfaces/IEntryPoint.sol";
+import {UserOperation} from "@account-abstraction/contracts/interfaces/UserOperation.sol";
+
+import {console} from "forge-std/src/console.sol";
+import {PRE_HOOK_ALWAYS_DENY_FUNCTION_REFERENCE} from "src/msca/6900/v0.7/common/Constants.sol";
contract AddressBookPluginWithSemiMSCATest is TestUtils {
using FunctionReferenceLib for bytes21;
@@ -55,14 +74,14 @@ contract AddressBookPluginWithSemiMSCATest is TestUtils {
PluginManager private pluginManager = new PluginManager();
uint256 internal eoaPrivateKey;
address private ownerAddr;
- address payable beneficiary; // e.g. bundler
+ address payable private beneficiary; // e.g. bundler
SingleOwnerMSCAFactory private factory;
AddressBookPlugin private addressBookPlugin;
SingleOwnerMSCA private msca;
TestLiquidityPool private testLiquidityPool;
address private addressBookPluginAddr;
address private mscaAddr;
- bytes32 addressBookPluginManifest;
+ bytes32 private addressBookPluginManifest;
function setUp() public {
beneficiary = payable(address(makeAddr("bundler")));
@@ -1245,7 +1264,7 @@ contract AddressBookPluginWithSemiMSCATest is TestUtils {
msca = factory.createAccount(ownerAddr, bytes32(0), _initializingData);
console.log("address(msca) -> %s", address(msca));
(bool sent,) = address(msca).call{value: 10e18}("");
- require(sent, "Failed to send Ether");
+ assertTrue(sent);
FunctionReference[] memory dependencies = new FunctionReference[](2);
dependencies[0] =
FunctionReference(mscaAddr, uint8(SingleOwnerMSCA.FunctionId.NATIVE_RUNTIME_VALIDATION_OWNER_OR_SELF));
diff --git a/test/msca/6900/v0.7/plugins/ColdStorageAddressBookPluginWithFullMSCA.t.sol b/test/msca/6900/v0.7/plugins/ColdStorageAddressBookPluginWithFullMSCA.t.sol
index ad59376..201591a 100644
--- a/test/msca/6900/v0.7/plugins/ColdStorageAddressBookPluginWithFullMSCA.t.sol
+++ b/test/msca/6900/v0.7/plugins/ColdStorageAddressBookPluginWithFullMSCA.t.sol
@@ -19,7 +19,7 @@
pragma solidity 0.8.24;
import {EMPTY_FUNCTION_REFERENCE} from "../../../../../src/common/Constants.sol";
-import {UnauthorizedCaller} from "../../../../../src/msca/6900/shared/common/Errors.sol";
+import {UnauthorizedCaller} from "../../../../../src/common/Errors.sol";
import {BaseMSCA} from "../../../../../src/msca/6900/v0.7/account/BaseMSCA.sol";
import {UpgradableMSCA} from "../../../../../src/msca/6900/v0.7/account/UpgradableMSCA.sol";
diff --git a/test/msca/6900/v0.7/plugins/ColdStorageAddressBookPluginWithSemiMSCA.t.sol b/test/msca/6900/v0.7/plugins/ColdStorageAddressBookPluginWithSemiMSCA.t.sol
index 8ea0958..d56bf5c 100644
--- a/test/msca/6900/v0.7/plugins/ColdStorageAddressBookPluginWithSemiMSCA.t.sol
+++ b/test/msca/6900/v0.7/plugins/ColdStorageAddressBookPluginWithSemiMSCA.t.sol
@@ -19,7 +19,8 @@
pragma solidity 0.8.24;
import {EMPTY_FUNCTION_REFERENCE, PLUGIN_AUTHOR, PLUGIN_VERSION_1} from "../../../../../src/common/Constants.sol";
-import {NotImplemented, UnauthorizedCaller, Unsupported} from "../../../../../src/msca/6900/shared/common/Errors.sol";
+import {UnauthorizedCaller, Unsupported} from "../../../../../src/common/Errors.sol";
+import {NotImplemented} from "../../../../../src/msca/6900/shared/common/Errors.sol";
import {BaseMSCA} from "../../../../../src/msca/6900/v0.7/account/BaseMSCA.sol";
import {SingleOwnerMSCA} from "../../../../../src/msca/6900/v0.7/account/semi/SingleOwnerMSCA.sol";
diff --git a/test/util/Mock1820Registry.sol b/test/util/Mock1820Registry.sol
index 17c237d..967dfe0 100644
--- a/test/util/Mock1820Registry.sol
+++ b/test/util/Mock1820Registry.sol
@@ -18,6 +18,7 @@
*/
pragma solidity 0.8.24;
+import {Unsupported} from "../../src/common/Errors.sol";
import {IERC1820Registry} from "@openzeppelin/contracts/interfaces/IERC1820Registry.sol";
// IV is value needed to have a vanity address starting with '0x1820'.
@@ -81,13 +82,16 @@ contract MockERC1820Registry is IERC1820Registry {
// we don't check this for the convenience of testing
// require(getManager(addr) == msg.sender, "Not the manager");
- require(!isERC165Interface(_interfaceHash), "Must not be an ERC165 hash");
+ if (isERC165Interface(_interfaceHash)) {
+ revert Unsupported();
+ }
if (_implementer != address(0) && _implementer != msg.sender) {
- require(
+ if (
ERC1820ImplementerInterface(_implementer).canImplementInterfaceForAddress(_interfaceHash, addr)
- == ERC1820_ACCEPT_MAGIC,
- "Does not implement the interface"
- );
+ != ERC1820_ACCEPT_MAGIC
+ ) {
+ revert Unsupported();
+ }
}
interfaces[addr][_interfaceHash] = _implementer;
emit InterfaceImplementerSet(addr, _interfaceHash, _implementer);
@@ -179,6 +183,7 @@ contract MockERC1820Registry is IERC1820Registry {
{
bytes4 erc165ID = ERC165ID;
+ // solhint-disable-next-line no-inline-assembly
assembly {
let x := mload(0x40) // Find empty storage location using "free memory pointer"
mstore(x, erc165ID) // Place signature at beginning of empty storage