From 9d431ad9a02624abf51bbe21b0d985e339867f8c Mon Sep 17 00:00:00 2001 From: zeroknots Date: Tue, 20 Feb 2024 12:59:07 +0700 Subject: [PATCH 1/8] cleaned safe account --- accounts/safe7579/package.json | 4 + accounts/safe7579/remappings.txt | 4 + accounts/safe7579/src/Account.sol | 49 --- accounts/safe7579/src/SafeERC7579.sol | 94 ++++- .../safe7579/src/{ => core}/AccessControl.sol | 0 .../src/{ => core}/ExecutionHelper.sol | 3 +- .../safe7579/src/{ => core}/HookManager.sol | 2 +- .../safe7579/src/{ => core}/ModuleManager.sol | 185 ++++----- .../src/core/ValidatorStorageHelper.sol | 123 ++++++ accounts/safe7579/src/interfaces/ISafe.sol | 2 +- accounts/safe7579/src/utils/Boostrap.sol | 69 ++++ accounts/safe7579/test/Base.t.sol | 100 +++++ accounts/safe7579/test/Foo.t.sol | 8 - accounts/safe7579/test/SafeERC7579.t.sol | 110 ++++++ .../safe7579/test/dependencies/EntryPoint.sol | 76 ++++ accounts/safe7579/test/mocks/MockExecutor.sol | 49 +++ accounts/safe7579/test/mocks/MockHook.sol | 29 ++ accounts/safe7579/test/mocks/MockRegistry.sol | 54 +++ accounts/safe7579/test/mocks/MockTarget.sol | 11 + .../safe7579/test/mocks/MockValidator.sol | 49 +++ create_scaffolding.sh | 24 -- package.json | 8 +- packages/SessionKeyManager/bytecode.sh | 2 +- .../src/SessionKeyManagerBytecode.sol | 3 +- pnpm-lock.yaml | 370 +++++++++++------- remappings.txt | 1 + src/Modules.sol | 6 + src/modules/ERC7579HookDestruct.sol | 43 +- src/test/RhinestoneModuleKit.sol | 196 ++-------- test/Diff.t.sol | 324 --------------- test/MakeAccount.t.sol | 36 -- 31 files changed, 1114 insertions(+), 920 deletions(-) delete mode 100644 accounts/safe7579/src/Account.sol rename accounts/safe7579/src/{ => core}/AccessControl.sol (100%) rename accounts/safe7579/src/{ => core}/ExecutionHelper.sol (96%) rename accounts/safe7579/src/{ => core}/HookManager.sol (100%) rename accounts/safe7579/src/{ => core}/ModuleManager.sol (57%) create mode 100644 accounts/safe7579/src/core/ValidatorStorageHelper.sol create mode 100644 accounts/safe7579/src/utils/Boostrap.sol create mode 100644 accounts/safe7579/test/Base.t.sol delete mode 100644 accounts/safe7579/test/Foo.t.sol create mode 100644 accounts/safe7579/test/SafeERC7579.t.sol create mode 100644 accounts/safe7579/test/dependencies/EntryPoint.sol create mode 100644 accounts/safe7579/test/mocks/MockExecutor.sol create mode 100644 accounts/safe7579/test/mocks/MockHook.sol create mode 100644 accounts/safe7579/test/mocks/MockRegistry.sol create mode 100644 accounts/safe7579/test/mocks/MockTarget.sol create mode 100644 accounts/safe7579/test/mocks/MockValidator.sol delete mode 100644 create_scaffolding.sh delete mode 100644 test/Diff.t.sol delete mode 100644 test/MakeAccount.t.sol diff --git a/accounts/safe7579/package.json b/accounts/safe7579/package.json index 0a9b0931..6959b81e 100644 --- a/accounts/safe7579/package.json +++ b/accounts/safe7579/package.json @@ -12,9 +12,13 @@ }, "devDependencies": { "@rhinestone/modulekit": "workspace:*", + "@rhinestone/sessionkeymanager": "workspace:*", "@safe-global/safe-contracts": "^1.4.1", "@openzeppelin/contracts": "5.0.1", "@ERC4337/account-abstraction": "github:kopy-kat/account-abstraction#develop", + "@ERC4337/account-abstraction-v0.6": "github:eth-infinitism/account-abstraction#v0.6.0", + "erc4337-validation": "github:rhinestonewtf/erc4337-validation", + "@prb/math": "^4.0.2", "forge-std": "github:foundry-rs/forge-std", "ds-test": "github:dapphub/ds-test", "erc7579": "github:erc7579/erc7579-implementation", diff --git a/accounts/safe7579/remappings.txt b/accounts/safe7579/remappings.txt index 4b78f3ad..24b26f77 100644 --- a/accounts/safe7579/remappings.txt +++ b/accounts/safe7579/remappings.txt @@ -1,6 +1,7 @@ ds-test/=node_modules/ds-test/src/ forge-std/=node_modules/forge-std/src/ account-abstraction/=node_modules/@ERC4337/account-abstraction/contracts/ +account-abstraction-v0.6/=node_modules/@ERC4337/account-abstraction-v0.6/contracts/ erc7579/=node_modules/erc7579/src/ sentinellist/=node_modules/sentinellist/src/ solmate/=node_modules/solmate/src/ @@ -9,3 +10,6 @@ solarray/=node_modules/solarray/src/ @rhinestone/=node_modules/@rhinestone/ @safe-global/=node_modules/@safe-global/ @ERC4337/=node_modules/@ERC4337/ +@openzeppelin/=node_modules/@openzeppelin/ +@prb/math/=node_modules/@prb/math/ +erc4337-validation/=node_modules/erc4337-validation/src/ diff --git a/accounts/safe7579/src/Account.sol b/accounts/safe7579/src/Account.sol deleted file mode 100644 index 006666e5..00000000 --- a/accounts/safe7579/src/Account.sol +++ /dev/null @@ -1,49 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.23; - -import "forge-std/Test.sol"; -import { SafeERC7579 } from "./SafeERC7579.sol"; - -import "@safe-global/safe-contracts/contracts/Safe.sol"; -import { LibClone } from "solady/src/utils/LibClone.sol"; - -contract AccountFactory is Test { - // singletons - SafeERC7579 erc7579Mod = new SafeERC7579(); - Safe safeImpl = new Safe(); - Safe safe; - - function safeSetup( - address[] memory signers, - uint256 threshold, - address defaultValidator, - address defaultExecutor - ) - public - returns (address _clone) - { - Safe clone = Safe(payable(LibClone.clone(address(safeImpl)))); - _clone = address(clone); - - clone.setup({ - _owners: signers, - _threshold: threshold, - to: address(0), // optional delegatecall - data: "", - fallbackHandler: address(erc7579Mod), - paymentToken: address(0), // optional payment token - payment: 0, - paymentReceiver: payable(address(0)) // optional payment receiver - }); - - vm.startPrank(address(clone)); - clone.enableModule(address(erc7579Mod)); - address[] memory validators = new address[](1); - validators[0] = address(defaultValidator); - - address[] memory executors = new address[](1); - executors[0] = address(defaultExecutor); - erc7579Mod.initializeAccount(abi.encode(validators, executors)); - vm.stopPrank(); - } -} diff --git a/accounts/safe7579/src/SafeERC7579.sol b/accounts/safe7579/src/SafeERC7579.sol index 578f694e..51913f6e 100644 --- a/accounts/safe7579/src/SafeERC7579.sol +++ b/accounts/safe7579/src/SafeERC7579.sol @@ -1,19 +1,36 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.8.0 <0.9.0; -import "erc7579/interfaces/IERC7579Account.sol"; -import "erc7579/interfaces/IMSA.sol"; -import "erc7579/lib/ModeLib.sol"; -import "erc7579/lib/ExecutionLib.sol"; -import "erc7579/interfaces/IERC7579Module.sol"; -import "./AccessControl.sol"; -import "./HookManager.sol"; -import "./ExecutionHelper.sol"; -import "./ModuleManager.sol"; -import "./interfaces/ISafeOp.sol"; -import { UserOperationLib } from "@ERC4337/account-abstraction/contracts/core/UserOperationLib.sol"; +import { IERC7579Account, Execution } from "erc7579/interfaces/IERC7579Account.sol"; +import { IMSA } from "erc7579/interfaces/IMSA.sol"; +import { + CallType, ModeCode, ModeLib, CALLTYPE_SINGLE, CALLTYPE_BATCH +} from "erc7579/lib/ModeLib.sol"; +import { ExecutionLib } from "erc7579/lib/ExecutionLib.sol"; +import { + IValidator, + MODULE_TYPE_VALIDATOR, + MODULE_TYPE_HOOK, + MODULE_TYPE_EXECUTOR, + MODULE_TYPE_FALLBACK +} from "erc7579/interfaces/IERC7579Module.sol"; +import { AccessControl } from "./core/AccessControl.sol"; +import { HookManager } from "./core/HookManager.sol"; +import { ExecutionHelper } from "./core/ExecutionHelper.sol"; +import { ISafeOp, SAFE_OP_TYPEHASH } from "./interfaces/ISafeOp.sol"; +import { ISafe } from "./interfaces/ISafe.sol"; +import { + PackedUserOperation, + UserOperationLib +} from "@ERC4337/account-abstraction/contracts/core/UserOperationLib.sol"; import { _packValidationData } from "@ERC4337/account-abstraction/contracts/core/Helpers.sol"; +/** + * @title ERC7579 Adapter for Safe accounts. + * By using Safe's Fallback and Execution modules, + * this contract creates full ERC7579 compliance to Safe accounts + * @author zeroknots.eth | rhinestone.wtf + */ contract SafeERC7579 is ISafeOp, IERC7579Account, @@ -26,9 +43,14 @@ contract SafeERC7579 is using ModeLib for ModeCode; using ExecutionLib for bytes; + error Unsupported(); + bytes32 private constant DOMAIN_SEPARATOR_TYPEHASH = 0x47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a79469218; + /** + * @inheritdoc IERC7579Account + */ function execute( ModeCode mode, bytes calldata executionCalldata @@ -53,6 +75,9 @@ contract SafeERC7579 is } } + /** + * @inheritdoc IERC7579Account + */ function executeFromExecutor( ModeCode mode, bytes calldata executionCalldata @@ -79,13 +104,21 @@ contract SafeERC7579 is } } + /** + * @inheritdoc IERC7579Account + */ function executeUserOp(PackedUserOperation calldata userOp) external payable override onlyEntryPointOrSelf - { } + { + revert Unsupported(); + } + /** + * @inheritdoc IERC7579Account + */ function validateUserOp( PackedUserOperation calldata userOp, bytes32 userOpHash, @@ -142,8 +175,14 @@ contract SafeERC7579 is } } + /** + * @inheritdoc IERC7579Account + */ function isValidSignature(bytes32 hash, bytes calldata data) external view returns (bytes4) { } + /** + * @inheritdoc IERC7579Account + */ function installModule( uint256 moduleType, address module, @@ -162,6 +201,9 @@ contract SafeERC7579 is emit ModuleInstalled(moduleType, module); } + /** + * @inheritdoc IERC7579Account + */ function uninstallModule( uint256 moduleType, address module, @@ -180,6 +222,9 @@ contract SafeERC7579 is emit ModuleUninstalled(moduleType, module); } + /** + * @inheritdoc IERC7579Account + */ function supportsAccountMode(ModeCode encodedMode) external pure override returns (bool) { CallType callType = encodedMode.getCallType(); if (callType == CALLTYPE_BATCH) return true; @@ -187,6 +232,9 @@ contract SafeERC7579 is else return false; } + /** + * @inheritdoc IERC7579Account + */ function supportsModule(uint256 moduleTypeId) external pure override returns (bool) { if (moduleTypeId == MODULE_TYPE_VALIDATOR) return true; else if (moduleTypeId == MODULE_TYPE_EXECUTOR) return true; @@ -194,6 +242,9 @@ contract SafeERC7579 is else return false; } + /** + * @inheritdoc IERC7579Account + */ function isModuleInstalled( uint256 moduleType, address module, @@ -211,8 +262,11 @@ contract SafeERC7579 is else return false; } + /** + * @inheritdoc IERC7579Account + */ function accountId() external pure override returns (string memory accountImplementationId) { - return "safe-erc7579.v0.0.1"; + return "safe-erc7579.v0.0.0"; } /** @@ -293,20 +347,18 @@ contract SafeERC7579 is } } + /** + * Domain Separator for EIP-712. + */ function domainSeparator() public view returns (bytes32) { return keccak256(abi.encode(DOMAIN_SEPARATOR_TYPEHASH, block.chainid, this)); } function initializeAccount(bytes calldata data) external payable { _initModuleManager(); - (address[] memory validators, address[] memory executors) = - abi.decode(data, (address[], address[])); - for (uint256 i = 0; i < validators.length; i++) { - _installValidator(validators[i], data); - } - for (uint256 i = 0; i < executors.length; i++) { - _installExecutor(executors[i], data); - } + (address bootstrap, bytes memory bootstrapCall) = abi.decode(data, (address, bytes)); + (bool success,) = bootstrap.delegatecall(bootstrapCall); + if (!success) revert AccountInitializationFailed(); } } diff --git a/accounts/safe7579/src/AccessControl.sol b/accounts/safe7579/src/core/AccessControl.sol similarity index 100% rename from accounts/safe7579/src/AccessControl.sol rename to accounts/safe7579/src/core/AccessControl.sol diff --git a/accounts/safe7579/src/ExecutionHelper.sol b/accounts/safe7579/src/core/ExecutionHelper.sol similarity index 96% rename from accounts/safe7579/src/ExecutionHelper.sol rename to accounts/safe7579/src/core/ExecutionHelper.sol index b2d12bd6..727f6a05 100644 --- a/accounts/safe7579/src/ExecutionHelper.sol +++ b/accounts/safe7579/src/core/ExecutionHelper.sol @@ -2,8 +2,7 @@ pragma solidity >=0.8.0 <0.9.0; import { Execution } from "erc7579/interfaces/IERC7579Account.sol"; -import "./interfaces/ISafe.sol"; -import "forge-std/console2.sol"; +import "../interfaces/ISafe.sol"; contract ExecutionHelper { function _execute( diff --git a/accounts/safe7579/src/HookManager.sol b/accounts/safe7579/src/core/HookManager.sol similarity index 100% rename from accounts/safe7579/src/HookManager.sol rename to accounts/safe7579/src/core/HookManager.sol index 56088dc7..253001ac 100644 --- a/accounts/safe7579/src/HookManager.sol +++ b/accounts/safe7579/src/core/HookManager.sol @@ -4,11 +4,11 @@ pragma solidity ^0.8.23; import "./ModuleManager.sol"; import "erc7579/interfaces/IERC7579Account.sol"; import "erc7579/interfaces/IERC7579Module.sol"; + /** * @title reference implementation of HookManager * @author zeroknots.eth | rhinestone.wtf */ - abstract contract HookManager is ModuleManager { /// @custom:storage-location erc7201:hookmanager.storage.msa struct HookManagerStorage { diff --git a/accounts/safe7579/src/ModuleManager.sol b/accounts/safe7579/src/core/ModuleManager.sol similarity index 57% rename from accounts/safe7579/src/ModuleManager.sol rename to accounts/safe7579/src/core/ModuleManager.sol index bc1114e6..05084f77 100644 --- a/accounts/safe7579/src/ModuleManager.sol +++ b/accounts/safe7579/src/core/ModuleManager.sol @@ -2,18 +2,13 @@ pragma solidity ^0.8.23; import { SentinelListLib, SENTINEL } from "sentinellist/SentinelList.sol"; -import { AccountBase } from "erc7579/core/AccountBase.sol"; -import "erc7579/interfaces/IERC7579Module.sol"; +import { IExecutor, IValidator, IFallback } from "erc7579/interfaces/IERC7579Module.sol"; import { Receiver } from "erc7579/core/Receiver.sol"; -import "./AccessControl.sol"; -import "./interfaces/ISafe.sol"; - -import "forge-std/console2.sol"; - -struct ValidatorManagerStorage { - // linked list of validators. List is initialized by initializeAccount() - SentinelListLib.SentinelList _validators; -} +import { AccessControl } from "./AccessControl.sol"; +import { ISafe } from "../interfaces/ISafe.sol"; +import { + ValidatorStorageHelper, ValidatorStorageLib, $validator +} from "./ValidatorStorageHelper.sol"; struct ModuleManagerStorage { // linked list of executors. List is initialized by initializeAccount() @@ -21,68 +16,33 @@ struct ModuleManagerStorage { // single fallback handler for all fallbacks // account vendors may implement this differently. This is just a reference implementation address fallbackHandler; - // single hook - address hook; } // keccak256("modulemanager.storage.msa"); bytes32 constant MODULEMANAGER_STORAGE_LOCATION = 0xf88ce1fdb7fb1cbd3282e49729100fa3f2d6ee9f797961fe4fb1871cea89ea02; -function _getValidatorStorage() pure returns (ValidatorManagerStorage storage ims) { - bytes32 position = MODULEMANAGER_STORAGE_LOCATION; - assembly { - ims.slot := position - } -} - -contract ModuleStorage { - using SentinelListLib for SentinelListLib.SentinelList; - - function initModuleManager() external virtual { - ValidatorManagerStorage storage ims = _getValidatorStorage(); - ims._validators.init(); - } - ///////////////////////////////////////////////////// - // Manage Validators - //////////////////////////////////////////////////// - - function installValidator(address validator, bytes calldata data) external virtual { - SentinelListLib.SentinelList storage _validators = _getValidatorStorage()._validators; - _validators.push(validator); - IValidator(validator).onInstall(data); - } - - function uninstallValidator(address validator, bytes calldata data) external { - // TODO: check if its the last validator. this might brick the account - SentinelListLib.SentinelList storage _validators = _getValidatorStorage()._validators; - (address prev, bytes memory disableModuleData) = abi.decode(data, (address, bytes)); - _validators.pop(prev, validator); - IValidator(validator).onUninstall(disableModuleData); - } - - function isValidatorInstalled(address validator) external view virtual returns (bool) { - SentinelListLib.SentinelList storage _validators = _getValidatorStorage()._validators; - return _validators.contains(validator); - } -} - /** * @title ModuleManager + * Contract that implements ERC7579 Module compatibility for Safe accounts * @author zeroknots.eth | rhinestone.wtf */ abstract contract ModuleManager is AccessControl, Receiver { using SentinelListLib for SentinelListLib.SentinelList; + using ValidatorStorageLib for SentinelListLib.SentinelList; error InvalidModule(address module); + error LinkedListError(); error CannotRemoveLastValidator(); + error InitializerError(); + error ValidatorStorageHelperError(); - ModuleStorage immutable STORAGE_MANAGER; + ValidatorStorageHelper internal immutable VALIDATOR_STORAGE; - mapping(address smartAccount => ModuleManagerStorage) private _moduleManagerStorage; + mapping(address smartAccount => ModuleManagerStorage) private $moduleManager; constructor() { - STORAGE_MANAGER = new ModuleStorage(); + VALIDATOR_STORAGE = new ValidatorStorageHelper(); } function _getModuleManagerStorage(address account) @@ -90,7 +50,7 @@ abstract contract ModuleManager is AccessControl, Receiver { view returns (ModuleManagerStorage storage ims) { - return _moduleManagerStorage[account]; + return $moduleManager[account]; } modifier onlyExecutorModule() { @@ -98,67 +58,71 @@ abstract contract ModuleManager is AccessControl, Receiver { _; } + /** + * Initializes linked list that handles installed Validator and Executor + * For Validators: + * The Safe Account will call VALIDATOR_STORAGE via DELEGTATECALL. + * Due to the storage restrictions of ERC-4337 of the validation phase, + * Validators are stored within the Safe's account storage. + */ function _initModuleManager() internal { bool success = ISafe(msg.sender).execTransactionFromModule({ - to: address(STORAGE_MANAGER), + to: address(VALIDATOR_STORAGE), value: 0, - data: abi.encodeCall(ModuleStorage.initModuleManager, ()), - operation: 1 - }); - require(success, "ModuleManager: failed to initialize module manager"); + data: abi.encodeCall(ValidatorStorageHelper.initModuleManager, ()), + operation: 1 // <--- DELEGATECALL + }); + // this will be false if the list is already initialized + if (!success) revert InitializerError(); ModuleManagerStorage storage ims = _getModuleManagerStorage(msg.sender); + // this will revert if list is already initialized ims._executors.init(); } ///////////////////////////////////////////////////// // Manage Validators //////////////////////////////////////////////////// - function _installValidator(address validator, bytes calldata data) internal virtual { + /** + * Write into validator linked list via ValidatorStorageHelper DELEGATECALL + */ + function _installValidator(address validator, bytes memory data) internal virtual { bool success = ISafe(msg.sender).execTransactionFromModule({ - to: address(STORAGE_MANAGER), + to: address(VALIDATOR_STORAGE), value: 0, - data: abi.encodeCall(ModuleStorage.installValidator, (validator, data)), - operation: 1 - }); - require(success, "ModuleManager: failed to install validator"); + data: abi.encodeCall(ValidatorStorageHelper.installValidator, (validator, data)), + operation: 1 // <-- DELEGATECALL + }); + if (!success) revert ValidatorStorageHelperError(); } - function _uninstallValidator(address validator, bytes calldata data) internal { + function _uninstallValidator(address validator, bytes memory data) internal { bool success = ISafe(msg.sender).execTransactionFromModule({ - to: address(STORAGE_MANAGER), + to: address(VALIDATOR_STORAGE), value: 0, - data: abi.encodeCall(ModuleStorage.uninstallValidator, (validator, data)), + data: abi.encodeCall(ValidatorStorageHelper.uninstallValidator, (validator, data)), operation: 1 }); - require(success, "ModuleManager: failed to uninstall validator"); + if (!success) revert ValidatorStorageHelperError(); } - function getKeyEncodedWithMappingIndex( - SentinelListLib.SentinelList storage linkedList, - address key - ) - private - pure - returns (bytes32 hash) + /** + * Helper function that will calculate storage slot for + * validator address within the linked list in ValidatorStorageHelper + * and use Safe's getStorageAt() to read 32bytes from Safe's storage + */ + function _isValidatorInstalled(address validator) + internal + view + virtual + returns (bool isInstalled) { - bytes32 slot; - assembly { - slot := linkedList.slot - mstore(0, key) - mstore(0x20, slot) - hash := keccak256(0, 0x40) - } - } - - function _isValidatorInstalled(address validator) internal view virtual returns (bool) { // calculate slot for linked list - SentinelListLib.SentinelList storage _validators = _getValidatorStorage()._validators; - bytes32 slot = getKeyEncodedWithMappingIndex(_validators, validator); - bytes32 value = bytes32(ISafe(msg.sender).getStorageAt(uint256(slot), 1)); - address link = address(uint160(uint256(value))); - bool ok = SENTINEL != validator && link != address(0); - return ok; + SentinelListLib.SentinelList storage $validators = $validator()._validators; + // predict slot for validator in ValidatorStorageHelper linked list + address link = $validators.getNextEntry(validator); + // See https://github.com/zeroknots/sentinellist/blob/main/src/SentinelList.sol#L52 + isInstalled = SENTINEL != validator && link != address(0); } /** @@ -174,45 +138,27 @@ abstract contract ModuleManager is AccessControl, Receiver { virtual returns (address[] memory array, address next) { - if (start != SENTINEL && _isExecutorInstalled(start)) revert(); - if (pageSize == 0) revert(); + if (start != SENTINEL && _isExecutorInstalled(start)) revert LinkedListError(); + if (pageSize == 0) revert LinkedListError(); array = new address[](pageSize); // Populate return array - uint256 entryCount = 0; - SentinelListLib.SentinelList storage _validators = _getValidatorStorage()._validators; - bytes32 slot = getKeyEncodedWithMappingIndex(_validators, start); - bytes32 value = bytes32(ISafe(msg.sender).getStorageAt(uint256(slot), 1)); - address next = address(uint160(uint256(value))); + uint256 entryCount; + SentinelListLib.SentinelList storage $validators = $validator()._validators; + next = $validators.getNextEntry(start); while (next != address(0) && next != SENTINEL && entryCount < pageSize) { array[entryCount] = next; - bytes32 slot = getKeyEncodedWithMappingIndex(_validators, next); - bytes32 value = bytes32(ISafe(msg.sender).getStorageAt(uint256(slot), 1)); - address next = address(uint160(uint256(value))); + next = $validators.getNextEntry(next); entryCount++; } - /** - * Because of the argument validation, we can assume that the loop will always iterate over - * the valid entry list values - * and the `next` variable will either be an enabled entry or a sentinel address - * (signalling the end). - * - * If we haven't reached the end inside the loop, we need to set the next pointer to - * the last element of the entry array - * because the `next` variable (which is a entry by itself) acting as a pointer to the - * start of the next page is neither - * incSENTINELrent page, nor will it be included in the next one if you pass it as a - * start. - */ if (next != SENTINEL) { next = array[entryCount - 1]; } // Set correct size of returned array // solhint-disable-next-line no-inline-assembly - /// @solidity memory-safe-assembly - assembly { + assembly ("memory-safe") { mstore(array, entryCount) } } @@ -221,7 +167,7 @@ abstract contract ModuleManager is AccessControl, Receiver { // Manage Executors //////////////////////////////////////////////////// - function _installExecutor(address executor, bytes calldata data) internal { + function _installExecutor(address executor, bytes memory data) internal { SentinelListLib.SentinelList storage _executors = _getModuleManagerStorage(msg.sender)._executors; _executors.push(executor); @@ -295,6 +241,7 @@ abstract contract ModuleManager is AccessControl, Receiver { if (handler == address(0)) revert(); /* solhint-disable no-inline-assembly */ /// @solidity memory-safe-assembly + // solhint-disable-next-line no-inline-assembly assembly { // When compiled with the optimizer, the compiler relies on a certain assumptions on how // the diff --git a/accounts/safe7579/src/core/ValidatorStorageHelper.sol b/accounts/safe7579/src/core/ValidatorStorageHelper.sol new file mode 100644 index 00000000..2db5bfe4 --- /dev/null +++ b/accounts/safe7579/src/core/ValidatorStorageHelper.sol @@ -0,0 +1,123 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.23; + +import { SentinelListLib, SENTINEL } from "sentinellist/SentinelList.sol"; +import { IValidator } from "erc7579/interfaces/IERC7579Module.sol"; +import { ISafe } from "../interfaces/ISafe.sol"; + +struct ValidatorStorage { + // linked list of validators. List is initialized by initializeAccount() + SentinelListLib.SentinelList _validators; +} + +// keccak256("modulemanager.storage.msa"); +// TODO: change this +bytes32 constant VALIDATORMANAGER_STORAGE_LOCATION = + 0xf88ce1fdb7fb1cbd3282e49729100fa3f2d6ee9f797961fe4fb1871cea89ea02; + +function $validator() pure returns (ValidatorStorage storage $validators) { + bytes32 position = VALIDATORMANAGER_STORAGE_LOCATION; + // solhint-disable-next-line no-inline-assembly + assembly { + $validators.slot := position + } +} + +/** + * @title ValidatorStorage - Storage for ModuleManager + * Due to the storage restrictions of ERC4337, + * storing a linked list outside of the ERC-4337 UserOp.sender account is not possible + * In order to make storage of the linked list possible, the Safe account with DELEGATECALL + * the functions within ModuleStorage and thus write into its own storage. + * ModuleStorage is using MODULEMANAGER_STORAGE_LOCATION to store data, to ensure no storage slot + * conflicts + */ +contract ValidatorStorageHelper { + using SentinelListLib for SentinelListLib.SentinelList; + + error Unauthorized(); + + // Ensures that the functions are only interacted with via delegatecall + modifier onlyDelegateCall() { + // if (msg.sender != address(this)) revert Unauthorized(); + _; + } + + /** + * Initializes the module manager storage + * Due to the nature of SentinelListLib, + * a linked list first has to be initialized before it can be used + */ + function initModuleManager() external virtual onlyDelegateCall { + ValidatorStorage storage $v = $validator(); + $v._validators.init(); + } + ///////////////////////////////////////////////////// + // Manage Validators + //////////////////////////////////////////////////// + + /** + * Installs Validator to ModuleStorage + * @param validator address of ERC7579 Validator module + * @param data init data that will be passed to Validator Module + */ + function installValidator( + address validator, + bytes calldata data + ) + external + virtual + onlyDelegateCall + { + SentinelListLib.SentinelList storage $validators = $validator()._validators; + $validators.push(validator); + IValidator(validator).onInstall(data); + } + + /** + * Uninstalls Validator module from ModuleStorage + * @param validator address of ERC7579 Validator Module + * @param data deinitialization data that will be passed to the validator module + */ + function uninstallValidator(address validator, bytes calldata data) external onlyDelegateCall { + SentinelListLib.SentinelList storage _validators = $validator()._validators; + (address prev, bytes memory disableModuleData) = abi.decode(data, (address, bytes)); + _validators.pop(prev, validator); + IValidator(validator).onUninstall(disableModuleData); + } +} + +library ValidatorStorageLib { + using ValidatorStorageLib for SentinelListLib.SentinelList; + + function getSlot( + SentinelListLib.SentinelList storage linkedList, + address key + ) + internal + pure + returns (bytes32 hash) + { + bytes32 slot; + // solhint-disable-next-line no-inline-assembly + assembly { + slot := linkedList.slot + mstore(0, key) + mstore(0x20, slot) + hash := keccak256(0, 0x40) + } + } + + function getNextEntry( + SentinelListLib.SentinelList storage $validators, + address key + ) + internal + view + returns (address next) + { + bytes32 slot = $validators.getSlot(key); + bytes32 value = bytes32(ISafe(msg.sender).getStorageAt(uint256(slot), 1)); + next = address(uint160(uint256(value))); + } +} diff --git a/accounts/safe7579/src/interfaces/ISafe.sol b/accounts/safe7579/src/interfaces/ISafe.sol index bcd310d8..04c6b4a5 100644 --- a/accounts/safe7579/src/interfaces/ISafe.sol +++ b/accounts/safe7579/src/interfaces/ISafe.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: LGPL-3.0-only -pragma solidity >=0.7.0 <0.9.0; +pragma solidity ^0.8.0; interface ISafe { /** diff --git a/accounts/safe7579/src/utils/Boostrap.sol b/accounts/safe7579/src/utils/Boostrap.sol new file mode 100644 index 00000000..89d73c3d --- /dev/null +++ b/accounts/safe7579/src/utils/Boostrap.sol @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.21; + +import "../core/ModuleManager.sol"; +import "../core/HookManager.sol"; + +import "erc7579/interfaces/IERC7579Module.sol"; + +struct BootstrapConfig { + address module; + bytes data; +} + +contract Bootstrap is ModuleManager, HookManager { + function singleInitMSA(IModule validator, bytes calldata data) external { + // init validator + _installValidator(address(validator), data); + } + + /** + * This function is intended to be called by the MSA with a delegatecall. + * Make sure that the MSA already initilazed the linked lists in the ModuleManager prior to + * calling this function + */ + function initMSA( + BootstrapConfig[] calldata _validators, + BootstrapConfig[] calldata _executors, + BootstrapConfig calldata _hook, + BootstrapConfig calldata _fallback + ) + external + { + // init validators + for (uint256 i; i < _validators.length; i++) { + _installValidator(_validators[i].module, _validators[i].data); + } + + // init executors + for (uint256 i; i < _executors.length; i++) { + if (_executors[i].module == address(0)) continue; + _installExecutor(_executors[i].module, _executors[i].data); + } + + // init hook + if (_hook.module != address(0)) { + _installHook(_hook.module, _hook.data); + } + + // init fallback + if (_fallback.module != address(0)) { + _installFallbackHandler(_fallback.module, _fallback.data); + } + } + + function _getInitMSACalldata( + BootstrapConfig[] calldata _validators, + BootstrapConfig[] calldata _executors, + BootstrapConfig calldata _hook, + BootstrapConfig calldata _fallback + ) + external + view + returns (bytes memory init) + { + init = abi.encode( + address(this), abi.encodeCall(this.initMSA, (_validators, _executors, _hook, _fallback)) + ); + } +} diff --git a/accounts/safe7579/test/Base.t.sol b/accounts/safe7579/test/Base.t.sol new file mode 100644 index 00000000..5bc41054 --- /dev/null +++ b/accounts/safe7579/test/Base.t.sol @@ -0,0 +1,100 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.23; + +import "forge-std/Test.sol"; +import { SafeERC7579 } from "src/SafeERC7579.sol"; +import { MockValidator } from "./mocks/MockValidator.sol"; +import { MockExecutor } from "./mocks/MockExecutor.sol"; +import { MockTarget } from "./mocks/MockTarget.sol"; + +import "@safe-global/safe-contracts/contracts/Safe.sol"; +import { LibClone } from "solady/src/utils/LibClone.sol"; + +import "./dependencies/EntryPoint.sol"; + +contract TestBaseUtil is Test { + // singletons + SafeERC7579 internal erc7579Mod; + Safe internal safeImpl; + Safe internal safe; + IEntryPoint internal entrypoint = IEntryPoint(ENTRYPOINT_ADDR); + + MockValidator internal defaultValidator; + MockExecutor internal defaultExecutor; + + MockTarget internal target; + + Account internal signer1; + Account internal signer2; + + function setUp() public virtual { + // Set up EntryPoint + etchEntrypoint(); + + // Set up MSA and Factory + erc7579Mod = new SafeERC7579(); + safeImpl = new Safe(); + + signer1 = makeAccount("signer1"); + signer2 = makeAccount("signer2"); + + // Set up Modules + defaultExecutor = new MockExecutor(); + defaultValidator = new MockValidator(); + + // Set up Target for testing + target = new MockTarget(); + + (safe,) = safeSetup(); + vm.deal(address(safe), 100 ether); + } + + function safeSetup() internal returns (Safe clone, address _defaultValidator) { + clone = Safe(payable(LibClone.clone(address(safeImpl)))); + _defaultValidator = address(defaultValidator); + + address[] memory signers = new address[](2); + signers[0] = signer1.addr; + signers[1] = signer2.addr; + + clone.setup({ + _owners: signers, + _threshold: 2, + to: address(0), // optional delegatecall + data: "", + fallbackHandler: address(erc7579Mod), + paymentToken: address(0), // optional payment token + payment: 0, + paymentReceiver: payable(address(0)) // optional payment receiver + }); + + vm.startPrank(address(clone)); + clone.enableModule(address(erc7579Mod)); + address[] memory validators = new address[](1); + validators[0] = address(defaultValidator); + + address[] memory executors = new address[](1); + executors[0] = address(defaultExecutor); + erc7579Mod.initializeAccount(abi.encode(validators, executors)); + vm.stopPrank(); + } + + function getNonce(address account, address validator) internal view returns (uint256 nonce) { + uint192 key = uint192(bytes24(bytes20(address(validator)))); + nonce = entrypoint.getNonce(address(account), key); + } + + function getDefaultUserOp() internal pure returns (PackedUserOperation memory userOp) { + userOp = PackedUserOperation({ + sender: address(0), + nonce: 0, + initCode: "", + callData: "", + accountGasLimits: bytes32(abi.encodePacked(uint128(2e6), uint128(2e6))), + preVerificationGas: 2e6, + gasFees: bytes32(abi.encodePacked(uint128(2e6), uint128(2e6))), + paymasterAndData: bytes(""), + signature: abi.encodePacked(hex"41414141") + }); + } +} diff --git a/accounts/safe7579/test/Foo.t.sol b/accounts/safe7579/test/Foo.t.sol deleted file mode 100644 index 274b52eb..00000000 --- a/accounts/safe7579/test/Foo.t.sol +++ /dev/null @@ -1,8 +0,0 @@ -import "forge-std/Test.sol"; - -contract FooTest is Test { - function setUp() public { } - function test_foo() public { - // This is a test - } -} diff --git a/accounts/safe7579/test/SafeERC7579.t.sol b/accounts/safe7579/test/SafeERC7579.t.sol new file mode 100644 index 00000000..84406973 --- /dev/null +++ b/accounts/safe7579/test/SafeERC7579.t.sol @@ -0,0 +1,110 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.23; + +import "erc7579/interfaces/IERC7579Account.sol"; +import "erc7579/lib/ModeLib.sol"; +import "erc7579/lib/ExecutionLib.sol"; +import { MockTarget } from "./mocks/MockTarget.sol"; +import "./Base.t.sol"; + +contract MSATest is TestBaseUtil { + function setUp() public override { + super.setUp(); + } + + function test_execSingle() public { + // Create calldata for the account to execute + bytes memory setValueOnTarget = abi.encodeCall(MockTarget.setValue, 1337); + + // Encode the call into the calldata for the userOp + bytes memory userOpCalldata = abi.encodeCall( + IERC7579Account.execute, + ( + ModeLib.encodeSimpleSingle(), + ExecutionLib.encodeSingle(address(target), uint256(0), setValueOnTarget) + ) + ); + + // Get the account, initcode and nonce + uint256 nonce = getNonce(address(safe), address(defaultValidator)); + + // Create the userOp and add the data + PackedUserOperation memory userOp = getDefaultUserOp(); + userOp.sender = address(safe); + userOp.nonce = nonce; + userOp.initCode = ""; + userOp.callData = userOpCalldata; + + // Create userOps array + PackedUserOperation[] memory userOps = new PackedUserOperation[](1); + userOps[0] = userOp; + + // Send the userOp to the entrypoint + console2.log("userOps"); + entrypoint.handleOps(userOps, payable(address(0x69))); + + // Assert that the value was set ie that execution was successful + assertTrue(target.value() == 1337); + } + + function test_execBatch() public { + // Create calldata for the account to execute + bytes memory setValueOnTarget = abi.encodeCall(MockTarget.setValue, 1337); + address target2 = address(0x420); + uint256 target2Amount = 1 wei; + + // Create the executions + Execution[] memory executions = new Execution[](2); + executions[0] = Execution({ target: address(target), value: 0, callData: setValueOnTarget }); + executions[1] = Execution({ target: address(target), value: 0, callData: setValueOnTarget }); + + // Encode the call into the calldata for the userOp + bytes memory userOpCalldata = abi.encodeCall( + IERC7579Account.execute, + (ModeLib.encodeSimpleBatch(), ExecutionLib.encodeBatch(executions)) + ); + + address account = address(safe); + uint256 nonce = getNonce(account, address(defaultValidator)); + + // Create the userOp and add the data + PackedUserOperation memory userOp = getDefaultUserOp(); + userOp.sender = address(account); + userOp.nonce = nonce; + userOp.initCode = ""; + userOp.callData = userOpCalldata; + + // Create userOps array + PackedUserOperation[] memory userOps = new PackedUserOperation[](1); + userOps[0] = userOp; + + // Send the userOp to the entrypoint + entrypoint.handleOps(userOps, payable(address(0x69))); + + // Assert that the value was set ie that execution was successful + assertTrue(target.value() == 1337); + } + + function test_execViaExecutor() public { + defaultExecutor.executeViaAccount( + IERC7579Account(address(safe)), + address(target), + 0, + abi.encodeWithSelector(MockTarget.setValue.selector, 1337) + ); + } + + function test_execBatchFromExecutor() public { + bytes memory setValueOnTarget = abi.encodeCall(MockTarget.setValue, 1338); + Execution[] memory executions = new Execution[](2); + executions[0] = Execution({ target: address(target), value: 0, callData: setValueOnTarget }); + executions[1] = Execution({ target: address(target), value: 0, callData: setValueOnTarget }); + bytes[] memory ret = defaultExecutor.execBatch({ + account: IERC7579Account(address(safe)), + execs: executions + }); + + assertEq(ret.length, 2); + assertEq(abi.decode(ret[0], (uint256)), 1338); + } +} diff --git a/accounts/safe7579/test/dependencies/EntryPoint.sol b/accounts/safe7579/test/dependencies/EntryPoint.sol new file mode 100644 index 00000000..07a81587 --- /dev/null +++ b/accounts/safe7579/test/dependencies/EntryPoint.sol @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.21; + +import "account-abstraction/interfaces/IEntryPoint.sol"; +import { IEntryPoint } from "account-abstraction/interfaces/IEntryPoint.sol"; +import { EntryPoint, SenderCreator } from "account-abstraction/core/EntryPoint.sol"; +import { EntryPointSimulations } from "account-abstraction/core/EntryPointSimulations.sol"; + +contract EntryPointSimulationsPatch is EntryPointSimulations { + address _entrypointAddr = address(this); + + SenderCreator _newSenderCreator; + + function init(address entrypointAddr) public { + _entrypointAddr = entrypointAddr; + initSenderCreator(); + } + + function initSenderCreator() internal override { + //this is the address of the first contract created with CREATE by this address. + address createdObj = address( + uint160(uint256(keccak256(abi.encodePacked(hex"d694", _entrypointAddr, hex"01")))) + ); + _newSenderCreator = SenderCreator(createdObj); + } + + function senderCreator() internal view virtual override returns (SenderCreator) { + return _newSenderCreator; + } +} + +address constant ENTRYPOINT_ADDR = 0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789; + +function etchEntrypoint() returns (IEntryPoint) { + address payable entryPoint = payable(address(new EntryPointSimulationsPatch())); + etch(ENTRYPOINT_ADDR, entryPoint.code); + EntryPointSimulationsPatch(payable(ENTRYPOINT_ADDR)).init(entryPoint); + + return IEntryPoint(ENTRYPOINT_ADDR); +} + +import "forge-std/Vm.sol"; + +address constant VM_ADDR = 0x7109709ECfa91a80626fF3989D68f67F5b1DD12D; + +function getAddr(uint256 pk) pure returns (address) { + return Vm(VM_ADDR).addr(pk); +} + +function sign(uint256 pk, bytes32 msgHash) pure returns (uint8 v, bytes32 r, bytes32 s) { + return Vm(VM_ADDR).sign(pk, msgHash); +} + +function etch(address target, bytes memory runtimeBytecode) { + Vm(VM_ADDR).etch(target, runtimeBytecode); +} + +function label(address _addr, string memory _label) { + Vm(VM_ADDR).label(_addr, _label); +} + +function expectEmit() { + Vm(VM_ADDR).expectEmit(); +} + +function recordLogs() { + Vm(VM_ADDR).recordLogs(); +} + +function getRecordedLogs() returns (VmSafe.Log[] memory) { + return Vm(VM_ADDR).getRecordedLogs(); +} + +function prank(address _addr) { + Vm(VM_ADDR).prank(_addr); +} diff --git a/accounts/safe7579/test/mocks/MockExecutor.sol b/accounts/safe7579/test/mocks/MockExecutor.sol new file mode 100644 index 00000000..38d311c7 --- /dev/null +++ b/accounts/safe7579/test/mocks/MockExecutor.sol @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.23; + +import { IExecutor, EncodedModuleTypes } from "erc7579/interfaces/IERC7579Module.sol"; +import { IERC7579Account, Execution } from "erc7579/interfaces/IERC7579Account.sol"; +import { ExecutionLib } from "erc7579/lib/ExecutionLib.sol"; +import { ModeLib } from "erc7579/lib/ModeLib.sol"; + +contract MockExecutor is IExecutor { + function onInstall(bytes calldata data) external override { } + + function onUninstall(bytes calldata data) external override { } + + function executeViaAccount( + IERC7579Account account, + address target, + uint256 value, + bytes calldata callData + ) + external + returns (bytes[] memory returnData) + { + return account.executeFromExecutor( + ModeLib.encodeSimpleSingle(), ExecutionLib.encodeSingle(target, value, callData) + ); + } + + function execBatch( + IERC7579Account account, + Execution[] calldata execs + ) + external + returns (bytes[] memory returnData) + { + return account.executeFromExecutor( + ModeLib.encodeSimpleBatch(), ExecutionLib.encodeBatch(execs) + ); + } + + function isModuleType(uint256 typeID) external view returns (bool) { + return typeID == 2; + } + + function getModuleTypes() external view returns (EncodedModuleTypes) { } + + function isInitialized(address smartAccount) external view returns (bool) { + return false; + } +} diff --git a/accounts/safe7579/test/mocks/MockHook.sol b/accounts/safe7579/test/mocks/MockHook.sol new file mode 100644 index 00000000..47e424e7 --- /dev/null +++ b/accounts/safe7579/test/mocks/MockHook.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.23; + +import { IHook, EncodedModuleTypes } from "erc7579/interfaces/IERC7579Module.sol"; + +contract MockHook is IHook { + function onInstall(bytes calldata data) external override { } + + function onUninstall(bytes calldata data) external override { } + + function preCheck( + address msgSender, + bytes calldata msgData + ) + external + returns (bytes memory hookData) + { } + function postCheck(bytes calldata hookData) external returns (bool success) { } + + function isModuleType(uint256 typeID) external view returns (bool) { + return typeID == 4; + } + + function getModuleTypes() external view returns (EncodedModuleTypes) { } + + function isInitialized(address smartAccount) external view returns (bool) { + return false; + } +} diff --git a/accounts/safe7579/test/mocks/MockRegistry.sol b/accounts/safe7579/test/mocks/MockRegistry.sol new file mode 100644 index 00000000..4e5c674a --- /dev/null +++ b/accounts/safe7579/test/mocks/MockRegistry.sol @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +/** + * @title MockRegistry + * @author zeroknots + * @notice Mock registry for testing purposes + */ +contract MockRegistry { + function check( + address plugin, + address trustedEntity + ) + external + view + returns (uint256 listedAt) + { + return uint256(1234); + } + + function checkN( + address module, + address[] memory attesters, + uint256 threshold + ) + external + view + returns (uint256[] memory) + { + uint256 attestersLength = attesters.length; + uint256[] memory attestedAtArray = new uint256[](attestersLength); + for (uint256 i; i < attestersLength; ++i) { + attestedAtArray[i] = uint256(1234); + } + return attestedAtArray; + } + + function checkNUnsafe( + address module, + address[] memory attesters, + uint256 threshold + ) + external + view + returns (uint256[] memory) + { + uint256 attestersLength = attesters.length; + uint256[] memory attestedAtArray = new uint256[](attestersLength); + for (uint256 i; i < attestersLength; ++i) { + attestedAtArray[i] = uint256(1234); + } + return attestedAtArray; + } +} diff --git a/accounts/safe7579/test/mocks/MockTarget.sol b/accounts/safe7579/test/mocks/MockTarget.sol new file mode 100644 index 00000000..6e8f4b77 --- /dev/null +++ b/accounts/safe7579/test/mocks/MockTarget.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.23; + +contract MockTarget { + uint256 public value; + + function setValue(uint256 _value) public returns (uint256) { + value = _value; + return _value; + } +} diff --git a/accounts/safe7579/test/mocks/MockValidator.sol b/accounts/safe7579/test/mocks/MockValidator.sol new file mode 100644 index 00000000..16530216 --- /dev/null +++ b/accounts/safe7579/test/mocks/MockValidator.sol @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.23; + +import { + IValidator, + PackedUserOperation, + VALIDATION_SUCCESS, + EncodedModuleTypes +} from "erc7579/interfaces/IERC7579Module.sol"; + +contract MockValidator is IValidator { + function onInstall(bytes calldata data) external override { } + + function onUninstall(bytes calldata data) external override { } + + function validateUserOp( + PackedUserOperation calldata userOp, + bytes32 userOpHash + ) + external + override + returns (uint256) + { + bytes4 execSelector = bytes4(userOp.callData[:4]); + + return VALIDATION_SUCCESS; + } + + function isValidSignatureWithSender( + address sender, + bytes32 hash, + bytes calldata data + ) + external + view + override + returns (bytes4) + { } + + function isModuleType(uint256 typeID) external view returns (bool) { + return typeID == 1; + } + + function getModuleTypes() external view returns (EncodedModuleTypes) { } + + function isInitialized(address smartAccount) external view returns (bool) { + return false; + } +} diff --git a/create_scaffolding.sh b/create_scaffolding.sh deleted file mode 100644 index 9d331da7..00000000 --- a/create_scaffolding.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/bash - -# Check if directory path is provided -if [ -z "$1" ]; then - echo "Usage: ./create_project.sh " - exit 1 -fi - -# Create the directory if it doesn't exist -mkdir -p $1 - -# Navigate to the directory -cd $1 - -# Download package.json using wget from a fixed URL -wget -O package.json - -# Create src and test folders -mkdir src test - -# Write "modulekit/=../." into remappings.txt -echo "modulekit/=../." > remappings.txt - -echo "Project scaffolding created successfully." diff --git a/package.json b/package.json index 55a392ad..34b5b8c0 100644 --- a/package.json +++ b/package.json @@ -12,18 +12,18 @@ }, "workspaces": [ "packages/**", - "examples/", - "accounts/**" + "accounts/**", + "examples/" ], "dependencies": {}, "devDependencies": { + "@rhinestone/sessionkeymanager": "workspace:*", + "@rhinestone/safe7579": "workspace:*", "ds-test": "github:dapphub/ds-test", "forge-std": "github:foundry-rs/forge-std", "@openzeppelin/contracts": "5.0.1", "@prb/math": "^4.0.2", - "@rhinestone/sessionkeymanager": "workspace:*", "erc4337-validation": "github:rhinestonewtf/erc4337-validation", - "@rhinestone/safe7579": "workspace:*", "@ERC4337/account-abstraction": "github:kopy-kat/account-abstraction#develop", "@ERC4337/account-abstraction-v0.6": "github:eth-infinitism/account-abstraction#v0.6.0", "@safe-global/safe-contracts": "^1.4.1", diff --git a/packages/SessionKeyManager/bytecode.sh b/packages/SessionKeyManager/bytecode.sh index 9f59e8d1..67714640 100755 --- a/packages/SessionKeyManager/bytecode.sh +++ b/packages/SessionKeyManager/bytecode.sh @@ -3,5 +3,5 @@ bytecode=$(jq ".bytecode" out/SessionKeyManager.sol/SessionKeyManager.json | jq echo "// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; - +/* solhint-disable-nextline max-line-length */ bytes constant SESSIONKEYMANAGER_BYTECODE = $bytecode;" > src/SessionKeyManagerBytecode.sol diff --git a/packages/SessionKeyManager/src/SessionKeyManagerBytecode.sol b/packages/SessionKeyManager/src/SessionKeyManagerBytecode.sol index e1fa5407..1d078379 100644 --- a/packages/SessionKeyManager/src/SessionKeyManagerBytecode.sol +++ b/packages/SessionKeyManager/src/SessionKeyManagerBytecode.sol @@ -1,5 +1,6 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; +/* solhint-disable max-line-length */ bytes constant SESSIONKEYMANAGER_BYTECODE = - hex"6080806040523461001657610cfe908161001c8239f35b600080fdfe60806040908082526004918236101561001757600080fd5b600091823560e01c90816306fdde03146106025750806354fd4d50146105be5780636d61fe70146105b95780638a91b0e3146105b95780639700320314610563578063cb9b272c14610308578063d4511ee9146102e7578063d60b347f146102c2578063d6cc1aa4146102a8578063df73e60e146101cb578063ecd05961146101a6578063f42c859d146100ff5763f551e2ee146100b457600080fd5b346100fb5760603660031901126100fb576100cd610727565b5060443567ffffffffffffffff81116100f7576020936100ef9136910161068f565b505051908152f35b8280fd5b5080fd5b508183346100fb5760203660031901126100fb576001903592838352826020528083203384526020528220828155016101388154610807565b80610169575b505050337f10103b778a5e09e8bcc680439d97711489525190a1fe679251002e893f9ea5638380a380f35b82601f8211600114610181575050555b81838061013e565b909180825261019f601f60208420940160051c840160018501610841565b5555610179565b509190346101c85760203660031901126101c857506001602092519135148152f35b80fd5b50346100fb57806003193601126100fb576102a460016101e9610727565b838051956101f68761073d565b808752606080602098838a820152838582015201526024358152808752818120848060a01b038094168252875220948451946102318661073d565b86549165ffffffffffff9788918285168952610271818a0192848760301c168452858b019660601c875261026a8651809a81930161088c565b038861078b565b606089019687528351998a99828b52511690890152511690860152511660608401525160808084015260a083019061064f565b0390f35b50346100fb57816003193601126100fb5751908152602090f35b50346100fb5760203660031901126100fb57906020916102e0610727565b5051908152f35b50346100fb576020906103016102fc366106f5565b610c34565b9051908152f35b5082346100f757610318366106f5565b9061032282610c34565b92838552602092858452818620338752845281862065ffffffffffff9283610349846107e0565b1690868401946bffffffffffff000000000000610365876107e0565b60301b16828601936bffffffffffffffffffffffff19610384866107f3565b60601b169117178455600180940160608601946103a186886107ad565b919067ffffffffffffffff9a8b841161055057509082918e8d6103c48754610807565b90601f8211610517575b90508193601f86116001146104ad575050926104a2575b50508160011b916000199060031b1c19161790555b6104178251968988528261040d88610858565b168a890152610858565b1690850152356001600160a01b0381169081900361049e57606084015235601e198236030181121561049a57018035930191831161049657823603821361049657806104907f57aa9b35aca9ac2ac77db1278fe563afa57004616360740e680d89bc674ebd1e93608080840152339560a084019161086b565b0390a380f35b8480fd5b8680fd5b8780fd5b013590508d806103e5565b8783528183209550929392601f19871692915b8383106104ff575050509084600195949392106104e5575b505050811b0190556103fa565b0135600019600384901b60f8161c191690558d80806104d8565b8185978293949688013581550196019301908f6104c0565b87835280832061053f92601f880160051c8201928810610546575b601f0160051c0190610841565b388e6103ce565b9091508190610532565b634e487b7160e01b8f526041905260248efd5b5090346101c8576003199282843601126100fb57803567ffffffffffffffff81116100f7576101208183019582360301126100f75760646105a59101856107ad565b919050116101c85750610301602092610922565b6106c2565b50346100fb57816003193601126100fb5780516102a4916105de8261076f565b6005825264302e302e3160d81b60208301525191829160208352602083019061064f565b919050346100f757826003193601126100f7576102a492506106238261076f565b601182527029b2b9b9b4b7b725b2bca6b0b730b3b2b960791b6020830152519182916020835260208301905b919082519283825260005b84811061067b575050826000602080949584010152601f8019910116010190565b60208183018101518483018201520161065a565b9181601f840112156106bd5782359167ffffffffffffffff83116106bd57602083818601950101116106bd57565b600080fd5b346106bd5760203660031901126106bd5760043567ffffffffffffffff81116106bd576106f390369060040161068f565b005b600319906020818301126106bd576004359167ffffffffffffffff83116106bd57826080920301126106bd5760040190565b600435906001600160a01b03821682036106bd57565b6080810190811067ffffffffffffffff82111761075957604052565b634e487b7160e01b600052604160045260246000fd5b6040810190811067ffffffffffffffff82111761075957604052565b90601f8019910116810190811067ffffffffffffffff82111761075957604052565b903590601e19813603018212156106bd570180359067ffffffffffffffff82116106bd576020019181360383136106bd57565b3565ffffffffffff811681036106bd5790565b356001600160a01b03811681036106bd5790565b90600182811c92168015610837575b602083101461082157565b634e487b7160e01b600052602260045260246000fd5b91607f1691610816565b81811061084c575050565b60008155600101610841565b359065ffffffffffff821682036106bd57565b908060209392818452848401376000828201840152601f01601f1916010190565b80546000939261089b82610807565b9182825260209360019160018116908160001461090357506001146108c2575b5050505050565b90939495506000929192528360002092846000945b8386106108ef575050505001019038808080806108bb565b8054858701830152940193859082016108d7565b60ff19168685015250505090151560051b0101915038808080806108bb565b6109306101008201826107ad565b5060018101356000526000602052604060002060018060a01b0383351660005260205261096660406000209260608101906107ad565b9290836004116106bd576003198401806020116106bd57806040116106bd57601f198501858111610c1e57806080116106bd57116106bd576109f7602091610a0c956000855460601c92610a2c604051998a968795869463c20bccb960e01b8652601081013560601c60048701526024810135602487015260a06044870152608460a4870192609f1901910161086b565b83810360031901606485015260018a0161088c565b82810360031901608484015260218a8101358b016001810135910161086b565b03925af1928315610c1257600093610bce575b5054916000916001600160a01b038216610a80575b505015610a7a5760a01b65ffffffffffff60d01b81169065ffffffffffff60a01b161790565b50600190565b9091506040519160018201356000526040600160218401358401013514610b6f575b6041600160218401358401013514610b25575b60006060526040838152630b135d3f60e11b8085526001848101356004870152602486019283526021808601358601808301356044890181905294979396602096899690959460649490930184860137602181013501013501916001600160a01b03165afa915114163880610a54565b6021828101358301606181013560001a6020526040910181376020600160806000825afa516001600160a01b038216183d1517610ab5575050600060605260405260013880610a54565b6021828101358301604181013560ff81901c601b01602090815291909201356040526001600160ff1b03909116606052600160806000825afa516001600160a01b038216183d1517610aa2575050600060605260405260013880610a54565b9092506020813d602011610c0a575b81610bea6020938361078b565b810103126106bd57516001600160a01b03811681036106bd579138610a3f565b3d9150610bdd565b6040513d6000823e3d90fd5b634e487b7160e01b600052601160045260246000fd5b610c3d816107e0565b90610cc26040610c4f602084016107e0565b93610c69610c5e8386016107f3565b9460608101906107ad565b80918451968794602086019965ffffffffffff60d01b809260d01b168b5260d01b1660268601526bffffffffffffffffffffffff199060601b16602c85015284840137810160008382015203602081018452018261078b565b5190209056fea2646970667358221220382b31db820b9e5359a6e195c39a621efa0137a06c8ea2d2183ef52d7060226264736f6c63430008180033"; + hex"6080806040523461001657610cfe908161001c8239f35b600080fdfe60806040908082526004918236101561001757600080fd5b600091823560e01c90816306fdde03146106025750806354fd4d50146105be5780636d61fe70146105b95780638a91b0e3146105b95780639700320314610563578063cb9b272c14610308578063d4511ee9146102e7578063d60b347f146102c2578063d6cc1aa4146102a8578063df73e60e146101cb578063ecd05961146101a6578063f42c859d146100ff5763f551e2ee146100b457600080fd5b346100fb5760603660031901126100fb576100cd610727565b5060443567ffffffffffffffff81116100f7576020936100ef9136910161068f565b505051908152f35b8280fd5b5080fd5b508183346100fb5760203660031901126100fb576001903592838352826020528083203384526020528220828155016101388154610807565b80610169575b505050337f10103b778a5e09e8bcc680439d97711489525190a1fe679251002e893f9ea5638380a380f35b82601f8211600114610181575050555b81838061013e565b909180825261019f601f60208420940160051c840160018501610841565b5555610179565b509190346101c85760203660031901126101c857506001602092519135148152f35b80fd5b50346100fb57806003193601126100fb576102a460016101e9610727565b838051956101f68761073d565b808752606080602098838a820152838582015201526024358152808752818120848060a01b038094168252875220948451946102318661073d565b86549165ffffffffffff9788918285168952610271818a0192848760301c168452858b019660601c875261026a8651809a81930161088c565b038861078b565b606089019687528351998a99828b52511690890152511690860152511660608401525160808084015260a083019061064f565b0390f35b50346100fb57816003193601126100fb5751908152602090f35b50346100fb5760203660031901126100fb57906020916102e0610727565b5051908152f35b50346100fb576020906103016102fc366106f5565b610c34565b9051908152f35b5082346100f757610318366106f5565b9061032282610c34565b92838552602092858452818620338752845281862065ffffffffffff9283610349846107e0565b1690868401946bffffffffffff000000000000610365876107e0565b60301b16828601936bffffffffffffffffffffffff19610384866107f3565b60601b169117178455600180940160608601946103a186886107ad565b919067ffffffffffffffff9a8b841161055057509082918e8d6103c48754610807565b90601f8211610517575b90508193601f86116001146104ad575050926104a2575b50508160011b916000199060031b1c19161790555b6104178251968988528261040d88610858565b168a890152610858565b1690850152356001600160a01b0381169081900361049e57606084015235601e198236030181121561049a57018035930191831161049657823603821361049657806104907f57aa9b35aca9ac2ac77db1278fe563afa57004616360740e680d89bc674ebd1e93608080840152339560a084019161086b565b0390a380f35b8480fd5b8680fd5b8780fd5b013590508d806103e5565b8783528183209550929392601f19871692915b8383106104ff575050509084600195949392106104e5575b505050811b0190556103fa565b0135600019600384901b60f8161c191690558d80806104d8565b8185978293949688013581550196019301908f6104c0565b87835280832061053f92601f880160051c8201928810610546575b601f0160051c0190610841565b388e6103ce565b9091508190610532565b634e487b7160e01b8f526041905260248efd5b5090346101c8576003199282843601126100fb57803567ffffffffffffffff81116100f7576101208183019582360301126100f75760646105a59101856107ad565b919050116101c85750610301602092610922565b6106c2565b50346100fb57816003193601126100fb5780516102a4916105de8261076f565b6005825264302e302e3160d81b60208301525191829160208352602083019061064f565b919050346100f757826003193601126100f7576102a492506106238261076f565b601182527029b2b9b9b4b7b725b2bca6b0b730b3b2b960791b6020830152519182916020835260208301905b919082519283825260005b84811061067b575050826000602080949584010152601f8019910116010190565b60208183018101518483018201520161065a565b9181601f840112156106bd5782359167ffffffffffffffff83116106bd57602083818601950101116106bd57565b600080fd5b346106bd5760203660031901126106bd5760043567ffffffffffffffff81116106bd576106f390369060040161068f565b005b600319906020818301126106bd576004359167ffffffffffffffff83116106bd57826080920301126106bd5760040190565b600435906001600160a01b03821682036106bd57565b6080810190811067ffffffffffffffff82111761075957604052565b634e487b7160e01b600052604160045260246000fd5b6040810190811067ffffffffffffffff82111761075957604052565b90601f8019910116810190811067ffffffffffffffff82111761075957604052565b903590601e19813603018212156106bd570180359067ffffffffffffffff82116106bd576020019181360383136106bd57565b3565ffffffffffff811681036106bd5790565b356001600160a01b03811681036106bd5790565b90600182811c92168015610837575b602083101461082157565b634e487b7160e01b600052602260045260246000fd5b91607f1691610816565b81811061084c575050565b60008155600101610841565b359065ffffffffffff821682036106bd57565b908060209392818452848401376000828201840152601f01601f1916010190565b80546000939261089b82610807565b9182825260209360019160018116908160001461090357506001146108c2575b5050505050565b90939495506000929192528360002092846000945b8386106108ef575050505001019038808080806108bb565b8054858701830152940193859082016108d7565b60ff19168685015250505090151560051b0101915038808080806108bb565b6109306101008201826107ad565b5060018101356000526000602052604060002060018060a01b0383351660005260205261096660406000209260608101906107ad565b9290836004116106bd576003198401806020116106bd57806040116106bd57601f198501858111610c1e57806080116106bd57116106bd576109f7602091610a0c956000855460601c92610a2c604051998a968795869463c20bccb960e01b8652601081013560601c60048701526024810135602487015260a06044870152608460a4870192609f1901910161086b565b83810360031901606485015260018a0161088c565b82810360031901608484015260218a8101358b016001810135910161086b565b03925af1928315610c1257600093610bce575b5054916000916001600160a01b038216610a80575b505015610a7a5760a01b65ffffffffffff60d01b81169065ffffffffffff60a01b161790565b50600190565b9091506040519160018201356000526040600160218401358401013514610b6f575b6041600160218401358401013514610b25575b60006060526040838152630b135d3f60e11b8085526001848101356004870152602486019283526021808601358601808301356044890181905294979396602096899690959460649490930184860137602181013501013501916001600160a01b03165afa915114163880610a54565b6021828101358301606181013560001a6020526040910181376020600160806000825afa516001600160a01b038216183d1517610ab5575050600060605260405260013880610a54565b6021828101358301604181013560ff81901c601b01602090815291909201356040526001600160ff1b03909116606052600160806000825afa516001600160a01b038216183d1517610aa2575050600060605260405260013880610a54565b9092506020813d602011610c0a575b81610bea6020938361078b565b810103126106bd57516001600160a01b03811681036106bd579138610a3f565b3d9150610bdd565b6040513d6000823e3d90fd5b634e487b7160e01b600052601160045260246000fd5b610c3d816107e0565b90610cc26040610c4f602084016107e0565b93610c69610c5e8386016107f3565b9460608101906107ad565b80918451968794602086019965ffffffffffff60d01b809260d01b168b5260d01b1660268601526bffffffffffffffffffffffff199060601b16602c85015284840137810160008382015203602081018452018261078b565b5190209056fea264697066735822122026a81cd670005fcd561638caf42a14771310b8b3023b89447085b3f5739e2d3364736f6c63430008180033"; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 737fb704..6f41b3f6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -62,18 +62,30 @@ importers: '@ERC4337/account-abstraction': specifier: github:kopy-kat/account-abstraction#develop version: github.com/kopy-kat/account-abstraction/aafae2a1f974e4c05f7025b3303d0d4aba85fa76(ethers@5.4.0)(hardhat@2.20.1)(lodash@4.17.21)(typechain@5.2.0) + '@ERC4337/account-abstraction-v0.6': + specifier: github:eth-infinitism/account-abstraction#v0.6.0 + version: github.com/eth-infinitism/account-abstraction/7174d6d845618dbd11cee68eefa715f5263690b6(ethers@5.4.0)(hardhat@2.20.1)(lodash@4.17.21)(typechain@5.2.0) '@openzeppelin/contracts': specifier: 5.0.1 version: 5.0.1 + '@prb/math': + specifier: ^4.0.2 + version: 4.0.2 '@rhinestone/modulekit': specifier: workspace:* version: link:../.. + '@rhinestone/sessionkeymanager': + specifier: workspace:* + version: link:../../packages/SessionKeyManager '@safe-global/safe-contracts': specifier: ^1.4.1 version: 1.4.1(ethers@5.4.0) ds-test: specifier: github:dapphub/ds-test version: github.com/dapphub/ds-test/e282159d5170298eb2455a6c05280ab5a73a4ef0 + erc4337-validation: + specifier: github:rhinestonewtf/erc4337-validation + version: github.com/rhinestonewtf/erc4337-validation/19a97d86f8f29709664334078925b2a843be19e0 erc7579: specifier: github:erc7579/erc7579-implementation version: github.com/erc7579/erc7579-implementation/be581c908df73f1554f466cb6b47c8ce8777e50f @@ -150,6 +162,48 @@ importers: specifier: github:transmissions11/solmate version: github.com/transmissions11/solmate/c892309933b25c03d32b1b0d674df7ae292ba925 + packages/AccountFactory: + devDependencies: + '@ERC4337/account-abstraction': + specifier: github:kopy-kat/account-abstraction#develop + version: github.com/kopy-kat/account-abstraction/aafae2a1f974e4c05f7025b3303d0d4aba85fa76(ethers@5.4.0)(hardhat@2.20.1)(lodash@4.17.21)(typechain@5.2.0) + '@ERC4337/account-abstraction-v0.6': + specifier: github:eth-infinitism/account-abstraction#v0.6.0 + version: github.com/eth-infinitism/account-abstraction/7174d6d845618dbd11cee68eefa715f5263690b6(ethers@5.4.0)(hardhat@2.20.1)(lodash@4.17.21)(typechain@5.2.0) + '@openzeppelin/contracts': + specifier: 5.0.1 + version: 5.0.1 + '@rhinestone/modulekit': + specifier: workspace:* + version: link:../.. + '@rhinestone/safe7579': + specifier: workspace:* + version: link:../../accounts/safe7579 + '@safe-global/safe-contracts': + specifier: ^1.4.1 + version: 1.4.1(ethers@5.4.0) + ds-test: + specifier: github:dapphub/ds-test + version: github.com/dapphub/ds-test/e282159d5170298eb2455a6c05280ab5a73a4ef0 + erc7579: + specifier: github:erc7579/erc7579-implementation + version: github.com/erc7579/erc7579-implementation/957cd05deeab6a9a85343bb8d1c9701705ed4ecf + forge-std: + specifier: github:foundry-rs/forge-std + version: github.com/foundry-rs/forge-std/1d0766bc5d814f117c7b1e643828f7d85024fb51 + prettier: + specifier: ^2.8.8 + version: 2.8.8 + sentinellist: + specifier: github:zeroknots/sentinellist + version: github.com/zeroknots/sentinellist/1f9ec0250f1b3f14ba5d200629e3d9f3264fde61 + solady: + specifier: github:vectorized/solady + version: github.com/vectorized/solady/1372606383445c0a247e6c58eb255a529734258a + solhint: + specifier: ^4.1.1 + version: 4.1.1(typescript@5.3.3) + packages/SessionKeyManager: devDependencies: '@ERC4337/account-abstraction': @@ -225,15 +279,15 @@ packages: /@ethersproject/abi@5.4.0: resolution: {integrity: sha512-9gU2H+/yK1j2eVMdzm6xvHSnMxk8waIHQGYCZg5uvAyH0rsAzxkModzBSpbAkAuhKFEovC2S9hM4nPuLym8IZw==} dependencies: - '@ethersproject/address': 5.4.0 - '@ethersproject/bignumber': 5.4.0 - '@ethersproject/bytes': 5.4.0 - '@ethersproject/constants': 5.4.0 - '@ethersproject/hash': 5.4.0 - '@ethersproject/keccak256': 5.4.0 - '@ethersproject/logger': 5.4.0 - '@ethersproject/properties': 5.4.0 - '@ethersproject/strings': 5.4.0 + '@ethersproject/address': 5.7.0 + '@ethersproject/bignumber': 5.7.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/constants': 5.7.0 + '@ethersproject/hash': 5.7.0 + '@ethersproject/keccak256': 5.7.0 + '@ethersproject/logger': 5.7.0 + '@ethersproject/properties': 5.7.0 + '@ethersproject/strings': 5.7.0 dev: true /@ethersproject/abi@5.7.0: @@ -253,13 +307,13 @@ packages: /@ethersproject/abstract-provider@5.4.0: resolution: {integrity: sha512-vPBR7HKUBY0lpdllIn7tLIzNN7DrVnhCLKSzY0l8WAwxz686m/aL7ASDzrVxV93GJtIub6N2t4dfZ29CkPOxgA==} dependencies: - '@ethersproject/bignumber': 5.4.0 - '@ethersproject/bytes': 5.4.0 - '@ethersproject/logger': 5.4.0 - '@ethersproject/networks': 5.4.0 - '@ethersproject/properties': 5.4.0 - '@ethersproject/transactions': 5.4.0 - '@ethersproject/web': 5.4.0 + '@ethersproject/bignumber': 5.7.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/logger': 5.7.0 + '@ethersproject/networks': 5.7.1 + '@ethersproject/properties': 5.7.0 + '@ethersproject/transactions': 5.7.0 + '@ethersproject/web': 5.7.1 dev: true /@ethersproject/abstract-provider@5.7.0: @@ -277,11 +331,11 @@ packages: /@ethersproject/abstract-signer@5.4.0: resolution: {integrity: sha512-AieQAzt05HJZS2bMofpuxMEp81AHufA5D6M4ScKwtolj041nrfIbIi8ciNW7+F59VYxXq+V4c3d568Q6l2m8ew==} dependencies: - '@ethersproject/abstract-provider': 5.4.0 - '@ethersproject/bignumber': 5.4.0 - '@ethersproject/bytes': 5.4.0 - '@ethersproject/logger': 5.4.0 - '@ethersproject/properties': 5.4.0 + '@ethersproject/abstract-provider': 5.7.0 + '@ethersproject/bignumber': 5.7.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/logger': 5.7.0 + '@ethersproject/properties': 5.7.0 dev: true /@ethersproject/abstract-signer@5.7.0: @@ -297,11 +351,11 @@ packages: /@ethersproject/address@5.4.0: resolution: {integrity: sha512-SD0VgOEkcACEG/C6xavlU1Hy3m5DGSXW3CUHkaaEHbAPPsgi0coP5oNPsxau8eTlZOk/bpa/hKeCNoK5IzVI2Q==} dependencies: - '@ethersproject/bignumber': 5.4.0 - '@ethersproject/bytes': 5.4.0 - '@ethersproject/keccak256': 5.4.0 - '@ethersproject/logger': 5.4.0 - '@ethersproject/rlp': 5.4.0 + '@ethersproject/bignumber': 5.7.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/keccak256': 5.7.0 + '@ethersproject/logger': 5.7.0 + '@ethersproject/rlp': 5.7.0 dev: true /@ethersproject/address@5.7.0: @@ -317,7 +371,7 @@ packages: /@ethersproject/base64@5.4.0: resolution: {integrity: sha512-CjQw6E17QDSSC5jiM9YpF7N1aSCHmYGMt9bWD8PWv6YPMxjsys2/Q8xLrROKI3IWJ7sFfZ8B3flKDTM5wlWuZQ==} dependencies: - '@ethersproject/bytes': 5.4.0 + '@ethersproject/bytes': 5.7.0 dev: true /@ethersproject/base64@5.7.0: @@ -329,8 +383,8 @@ packages: /@ethersproject/basex@5.4.0: resolution: {integrity: sha512-J07+QCVJ7np2bcpxydFVf/CuYo9mZ7T73Pe7KQY4c1lRlrixMeblauMxHXD0MPwFmUHZIILDNViVkykFBZylbg==} dependencies: - '@ethersproject/bytes': 5.4.0 - '@ethersproject/properties': 5.4.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/properties': 5.7.0 dev: true /@ethersproject/basex@5.7.0: @@ -343,8 +397,8 @@ packages: /@ethersproject/bignumber@5.4.0: resolution: {integrity: sha512-OXUu9f9hO3vGRIPxU40cignXZVaYyfx6j9NNMjebKdnaCL3anCLSSy8/b8d03vY6dh7duCC0kW72GEC4tZer2w==} dependencies: - '@ethersproject/bytes': 5.4.0 - '@ethersproject/logger': 5.4.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/logger': 5.7.0 bn.js: 4.12.0 dev: true @@ -359,7 +413,7 @@ packages: /@ethersproject/bytes@5.4.0: resolution: {integrity: sha512-H60ceqgTHbhzOj4uRc/83SCN9d+BSUnOkrr2intevqdtEMO1JFVZ1XL84OEZV+QjV36OaZYxtnt4lGmxcGsPfA==} dependencies: - '@ethersproject/logger': 5.4.0 + '@ethersproject/logger': 5.7.0 dev: true /@ethersproject/bytes@5.7.0: @@ -371,7 +425,7 @@ packages: /@ethersproject/constants@5.4.0: resolution: {integrity: sha512-tzjn6S7sj9+DIIeKTJLjK9WGN2Tj0P++Z8ONEIlZjyoTkBuODN+0VfhAyYksKi43l1Sx9tX2VlFfzjfmr5Wl3Q==} dependencies: - '@ethersproject/bignumber': 5.4.0 + '@ethersproject/bignumber': 5.7.0 dev: true /@ethersproject/constants@5.7.0: @@ -383,16 +437,16 @@ packages: /@ethersproject/contracts@5.4.0: resolution: {integrity: sha512-hkO3L3IhS1Z3ZtHtaAG/T87nQ7KiPV+/qnvutag35I0IkiQ8G3ZpCQ9NNOpSCzn4pWSW4CfzmtE02FcqnLI+hw==} dependencies: - '@ethersproject/abi': 5.4.0 - '@ethersproject/abstract-provider': 5.4.0 - '@ethersproject/abstract-signer': 5.4.0 - '@ethersproject/address': 5.4.0 - '@ethersproject/bignumber': 5.4.0 - '@ethersproject/bytes': 5.4.0 - '@ethersproject/constants': 5.4.0 - '@ethersproject/logger': 5.4.0 - '@ethersproject/properties': 5.4.0 - '@ethersproject/transactions': 5.4.0 + '@ethersproject/abi': 5.7.0 + '@ethersproject/abstract-provider': 5.7.0 + '@ethersproject/abstract-signer': 5.7.0 + '@ethersproject/address': 5.7.0 + '@ethersproject/bignumber': 5.7.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/constants': 5.7.0 + '@ethersproject/logger': 5.7.0 + '@ethersproject/properties': 5.7.0 + '@ethersproject/transactions': 5.7.0 dev: true /@ethersproject/contracts@5.7.0: @@ -413,14 +467,14 @@ packages: /@ethersproject/hash@5.4.0: resolution: {integrity: sha512-xymAM9tmikKgbktOCjW60Z5sdouiIIurkZUr9oW5NOex5uwxrbsYG09kb5bMcNjlVeJD3yPivTNzViIs1GCbqA==} dependencies: - '@ethersproject/abstract-signer': 5.4.0 - '@ethersproject/address': 5.4.0 - '@ethersproject/bignumber': 5.4.0 - '@ethersproject/bytes': 5.4.0 - '@ethersproject/keccak256': 5.4.0 - '@ethersproject/logger': 5.4.0 - '@ethersproject/properties': 5.4.0 - '@ethersproject/strings': 5.4.0 + '@ethersproject/abstract-signer': 5.7.0 + '@ethersproject/address': 5.7.0 + '@ethersproject/bignumber': 5.7.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/keccak256': 5.7.0 + '@ethersproject/logger': 5.7.0 + '@ethersproject/properties': 5.7.0 + '@ethersproject/strings': 5.7.0 dev: true /@ethersproject/hash@5.7.0: @@ -440,18 +494,18 @@ packages: /@ethersproject/hdnode@5.4.0: resolution: {integrity: sha512-pKxdS0KAaeVGfZPp1KOiDLB0jba11tG6OP1u11QnYfb7pXn6IZx0xceqWRr6ygke8+Kw74IpOoSi7/DwANhy8Q==} dependencies: - '@ethersproject/abstract-signer': 5.4.0 - '@ethersproject/basex': 5.4.0 - '@ethersproject/bignumber': 5.4.0 - '@ethersproject/bytes': 5.4.0 - '@ethersproject/logger': 5.4.0 - '@ethersproject/pbkdf2': 5.4.0 - '@ethersproject/properties': 5.4.0 - '@ethersproject/sha2': 5.4.0 - '@ethersproject/signing-key': 5.4.0 - '@ethersproject/strings': 5.4.0 - '@ethersproject/transactions': 5.4.0 - '@ethersproject/wordlists': 5.4.0 + '@ethersproject/abstract-signer': 5.7.0 + '@ethersproject/basex': 5.7.0 + '@ethersproject/bignumber': 5.7.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/logger': 5.7.0 + '@ethersproject/pbkdf2': 5.7.0 + '@ethersproject/properties': 5.7.0 + '@ethersproject/sha2': 5.7.0 + '@ethersproject/signing-key': 5.7.0 + '@ethersproject/strings': 5.7.0 + '@ethersproject/transactions': 5.7.0 + '@ethersproject/wordlists': 5.7.0 dev: true /@ethersproject/hdnode@5.7.0: @@ -474,17 +528,17 @@ packages: /@ethersproject/json-wallets@5.4.0: resolution: {integrity: sha512-igWcu3fx4aiczrzEHwG1xJZo9l1cFfQOWzTqwRw/xcvxTk58q4f9M7cjh51EKphMHvrJtcezJ1gf1q1AUOfEQQ==} dependencies: - '@ethersproject/abstract-signer': 5.4.0 - '@ethersproject/address': 5.4.0 - '@ethersproject/bytes': 5.4.0 - '@ethersproject/hdnode': 5.4.0 - '@ethersproject/keccak256': 5.4.0 - '@ethersproject/logger': 5.4.0 - '@ethersproject/pbkdf2': 5.4.0 - '@ethersproject/properties': 5.4.0 - '@ethersproject/random': 5.4.0 - '@ethersproject/strings': 5.4.0 - '@ethersproject/transactions': 5.4.0 + '@ethersproject/abstract-signer': 5.7.0 + '@ethersproject/address': 5.7.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/hdnode': 5.7.0 + '@ethersproject/keccak256': 5.7.0 + '@ethersproject/logger': 5.7.0 + '@ethersproject/pbkdf2': 5.7.0 + '@ethersproject/properties': 5.7.0 + '@ethersproject/random': 5.7.0 + '@ethersproject/strings': 5.7.0 + '@ethersproject/transactions': 5.7.0 aes-js: 3.0.0 scrypt-js: 3.0.1 dev: true @@ -510,7 +564,7 @@ packages: /@ethersproject/keccak256@5.4.0: resolution: {integrity: sha512-FBI1plWet+dPUvAzPAeHzRKiPpETQzqSUWR1wXJGHVWi4i8bOSrpC3NwpkPjgeXG7MnugVc1B42VbfnQikyC/A==} dependencies: - '@ethersproject/bytes': 5.4.0 + '@ethersproject/bytes': 5.7.0 js-sha3: 0.5.7 dev: true @@ -532,7 +586,7 @@ packages: /@ethersproject/networks@5.4.0: resolution: {integrity: sha512-5fywtKRDcnaVeA5SjxXH3DOQqe/IbeD/plwydi94SdPps1fbDUrnO6SzDExaruBZXxpxJcO9upG9UComsei4bg==} dependencies: - '@ethersproject/logger': 5.4.0 + '@ethersproject/logger': 5.7.0 dev: true /@ethersproject/networks@5.7.1: @@ -544,8 +598,8 @@ packages: /@ethersproject/pbkdf2@5.4.0: resolution: {integrity: sha512-x94aIv6tiA04g6BnazZSLoRXqyusawRyZWlUhKip2jvoLpzJuLb//KtMM6PEovE47pMbW+Qe1uw+68ameJjB7g==} dependencies: - '@ethersproject/bytes': 5.4.0 - '@ethersproject/sha2': 5.4.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/sha2': 5.7.0 dev: true /@ethersproject/pbkdf2@5.7.0: @@ -558,7 +612,7 @@ packages: /@ethersproject/properties@5.4.0: resolution: {integrity: sha512-7jczalGVRAJ+XSRvNA6D5sAwT4gavLq3OXPuV/74o3Rd2wuzSL035IMpIMgei4CYyBdialJMrTqkOnzccLHn4A==} dependencies: - '@ethersproject/logger': 5.4.0 + '@ethersproject/logger': 5.7.0 dev: true /@ethersproject/properties@5.7.0: @@ -570,23 +624,23 @@ packages: /@ethersproject/providers@5.4.0: resolution: {integrity: sha512-XRmI9syLnkNdLA8ikEeg0duxmwSWTTt9S+xabnTOyI51JPJyhQ0QUNT+wvmod218ebb7rLupHDPQ7UVe2/+Tjg==} dependencies: - '@ethersproject/abstract-provider': 5.4.0 - '@ethersproject/abstract-signer': 5.4.0 - '@ethersproject/address': 5.4.0 - '@ethersproject/basex': 5.4.0 - '@ethersproject/bignumber': 5.4.0 - '@ethersproject/bytes': 5.4.0 - '@ethersproject/constants': 5.4.0 - '@ethersproject/hash': 5.4.0 - '@ethersproject/logger': 5.4.0 - '@ethersproject/networks': 5.4.0 - '@ethersproject/properties': 5.4.0 - '@ethersproject/random': 5.4.0 - '@ethersproject/rlp': 5.4.0 - '@ethersproject/sha2': 5.4.0 - '@ethersproject/strings': 5.4.0 - '@ethersproject/transactions': 5.4.0 - '@ethersproject/web': 5.4.0 + '@ethersproject/abstract-provider': 5.7.0 + '@ethersproject/abstract-signer': 5.7.0 + '@ethersproject/address': 5.7.0 + '@ethersproject/basex': 5.7.0 + '@ethersproject/bignumber': 5.7.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/constants': 5.7.0 + '@ethersproject/hash': 5.7.0 + '@ethersproject/logger': 5.7.0 + '@ethersproject/networks': 5.7.1 + '@ethersproject/properties': 5.7.0 + '@ethersproject/random': 5.7.0 + '@ethersproject/rlp': 5.7.0 + '@ethersproject/sha2': 5.7.0 + '@ethersproject/strings': 5.7.0 + '@ethersproject/transactions': 5.7.0 + '@ethersproject/web': 5.7.1 bech32: 1.1.4 ws: 7.4.6 transitivePeerDependencies: @@ -625,8 +679,8 @@ packages: /@ethersproject/random@5.4.0: resolution: {integrity: sha512-pnpWNQlf0VAZDEOVp1rsYQosmv2o0ITS/PecNw+mS2/btF8eYdspkN0vIXrCMtkX09EAh9bdk8GoXmFXM1eAKw==} dependencies: - '@ethersproject/bytes': 5.4.0 - '@ethersproject/logger': 5.4.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/logger': 5.7.0 dev: true /@ethersproject/random@5.7.0: @@ -639,8 +693,8 @@ packages: /@ethersproject/rlp@5.4.0: resolution: {integrity: sha512-0I7MZKfi+T5+G8atId9QaQKHRvvasM/kqLyAH4XxBCBchAooH2EX5rL9kYZWwcm3awYV+XC7VF6nLhfeQFKVPg==} dependencies: - '@ethersproject/bytes': 5.4.0 - '@ethersproject/logger': 5.4.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/logger': 5.7.0 dev: true /@ethersproject/rlp@5.7.0: @@ -653,8 +707,8 @@ packages: /@ethersproject/sha2@5.4.0: resolution: {integrity: sha512-siheo36r1WD7Cy+bDdE1BJ8y0bDtqXCOxRMzPa4bV1TGt/eTUUt03BHoJNB6reWJD8A30E/pdJ8WFkq+/uz4Gg==} dependencies: - '@ethersproject/bytes': 5.4.0 - '@ethersproject/logger': 5.4.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/logger': 5.7.0 hash.js: 1.1.7 dev: true @@ -669,9 +723,9 @@ packages: /@ethersproject/signing-key@5.4.0: resolution: {integrity: sha512-q8POUeywx6AKg2/jX9qBYZIAmKSB4ubGXdQ88l40hmATj29JnG5pp331nAWwwxPn2Qao4JpWHNZsQN+bPiSW9A==} dependencies: - '@ethersproject/bytes': 5.4.0 - '@ethersproject/logger': 5.4.0 - '@ethersproject/properties': 5.4.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/logger': 5.7.0 + '@ethersproject/properties': 5.7.0 bn.js: 4.12.0 elliptic: 6.5.4 hash.js: 1.1.7 @@ -691,11 +745,11 @@ packages: /@ethersproject/solidity@5.4.0: resolution: {integrity: sha512-XFQTZ7wFSHOhHcV1DpcWj7VXECEiSrBuv7JErJvB9Uo+KfCdc3QtUZV+Vjh/AAaYgezUEKbCtE6Khjm44seevQ==} dependencies: - '@ethersproject/bignumber': 5.4.0 - '@ethersproject/bytes': 5.4.0 - '@ethersproject/keccak256': 5.4.0 - '@ethersproject/sha2': 5.4.0 - '@ethersproject/strings': 5.4.0 + '@ethersproject/bignumber': 5.7.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/keccak256': 5.7.0 + '@ethersproject/sha2': 5.7.0 + '@ethersproject/strings': 5.7.0 dev: true /@ethersproject/solidity@5.7.0: @@ -712,9 +766,9 @@ packages: /@ethersproject/strings@5.4.0: resolution: {integrity: sha512-k/9DkH5UGDhv7aReXLluFG5ExurwtIpUfnDNhQA29w896Dw3i4uDTz01Quaptbks1Uj9kI8wo9tmW73wcIEaWA==} dependencies: - '@ethersproject/bytes': 5.4.0 - '@ethersproject/constants': 5.4.0 - '@ethersproject/logger': 5.4.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/constants': 5.7.0 + '@ethersproject/logger': 5.7.0 dev: true /@ethersproject/strings@5.7.0: @@ -728,15 +782,15 @@ packages: /@ethersproject/transactions@5.4.0: resolution: {integrity: sha512-s3EjZZt7xa4BkLknJZ98QGoIza94rVjaEed0rzZ/jB9WrIuu/1+tjvYCWzVrystXtDswy7TPBeIepyXwSYa4WQ==} dependencies: - '@ethersproject/address': 5.4.0 - '@ethersproject/bignumber': 5.4.0 - '@ethersproject/bytes': 5.4.0 - '@ethersproject/constants': 5.4.0 - '@ethersproject/keccak256': 5.4.0 - '@ethersproject/logger': 5.4.0 - '@ethersproject/properties': 5.4.0 - '@ethersproject/rlp': 5.4.0 - '@ethersproject/signing-key': 5.4.0 + '@ethersproject/address': 5.7.0 + '@ethersproject/bignumber': 5.7.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/constants': 5.7.0 + '@ethersproject/keccak256': 5.7.0 + '@ethersproject/logger': 5.7.0 + '@ethersproject/properties': 5.7.0 + '@ethersproject/rlp': 5.7.0 + '@ethersproject/signing-key': 5.7.0 dev: true /@ethersproject/transactions@5.7.0: @@ -756,9 +810,9 @@ packages: /@ethersproject/units@5.4.0: resolution: {integrity: sha512-Z88krX40KCp+JqPCP5oPv5p750g+uU6gopDYRTBGcDvOASh6qhiEYCRatuM/suC4S2XW9Zz90QI35MfSrTIaFg==} dependencies: - '@ethersproject/bignumber': 5.4.0 - '@ethersproject/constants': 5.4.0 - '@ethersproject/logger': 5.4.0 + '@ethersproject/bignumber': 5.7.0 + '@ethersproject/constants': 5.7.0 + '@ethersproject/logger': 5.7.0 dev: true /@ethersproject/units@5.7.0: @@ -772,21 +826,21 @@ packages: /@ethersproject/wallet@5.4.0: resolution: {integrity: sha512-wU29majLjM6AjCjpat21mPPviG+EpK7wY1+jzKD0fg3ui5fgedf2zEu1RDgpfIMsfn8fJHJuzM4zXZ2+hSHaSQ==} dependencies: - '@ethersproject/abstract-provider': 5.4.0 - '@ethersproject/abstract-signer': 5.4.0 - '@ethersproject/address': 5.4.0 - '@ethersproject/bignumber': 5.4.0 - '@ethersproject/bytes': 5.4.0 - '@ethersproject/hash': 5.4.0 - '@ethersproject/hdnode': 5.4.0 - '@ethersproject/json-wallets': 5.4.0 - '@ethersproject/keccak256': 5.4.0 - '@ethersproject/logger': 5.4.0 - '@ethersproject/properties': 5.4.0 - '@ethersproject/random': 5.4.0 - '@ethersproject/signing-key': 5.4.0 - '@ethersproject/transactions': 5.4.0 - '@ethersproject/wordlists': 5.4.0 + '@ethersproject/abstract-provider': 5.7.0 + '@ethersproject/abstract-signer': 5.7.0 + '@ethersproject/address': 5.7.0 + '@ethersproject/bignumber': 5.7.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/hash': 5.7.0 + '@ethersproject/hdnode': 5.7.0 + '@ethersproject/json-wallets': 5.7.0 + '@ethersproject/keccak256': 5.7.0 + '@ethersproject/logger': 5.7.0 + '@ethersproject/properties': 5.7.0 + '@ethersproject/random': 5.7.0 + '@ethersproject/signing-key': 5.7.0 + '@ethersproject/transactions': 5.7.0 + '@ethersproject/wordlists': 5.7.0 dev: true /@ethersproject/wallet@5.7.0: @@ -812,11 +866,11 @@ packages: /@ethersproject/web@5.4.0: resolution: {integrity: sha512-1bUusGmcoRLYgMn6c1BLk1tOKUIFuTg8j+6N8lYlbMpDesnle+i3pGSagGNvwjaiLo4Y5gBibwctpPRmjrh4Og==} dependencies: - '@ethersproject/base64': 5.4.0 - '@ethersproject/bytes': 5.4.0 - '@ethersproject/logger': 5.4.0 - '@ethersproject/properties': 5.4.0 - '@ethersproject/strings': 5.4.0 + '@ethersproject/base64': 5.7.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/logger': 5.7.0 + '@ethersproject/properties': 5.7.0 + '@ethersproject/strings': 5.7.0 dev: true /@ethersproject/web@5.7.1: @@ -832,11 +886,11 @@ packages: /@ethersproject/wordlists@5.4.0: resolution: {integrity: sha512-FemEkf6a+EBKEPxlzeVgUaVSodU7G0Na89jqKjmWMlDB0tomoU8RlEMgUvXyqtrg8N4cwpLh8nyRnm1Nay1isA==} dependencies: - '@ethersproject/bytes': 5.4.0 - '@ethersproject/hash': 5.4.0 - '@ethersproject/logger': 5.4.0 - '@ethersproject/properties': 5.4.0 - '@ethersproject/strings': 5.4.0 + '@ethersproject/bytes': 5.7.0 + '@ethersproject/hash': 5.7.0 + '@ethersproject/logger': 5.7.0 + '@ethersproject/properties': 5.7.0 + '@ethersproject/strings': 5.7.0 dev: true /@ethersproject/wordlists@5.7.0: @@ -3748,7 +3802,7 @@ packages: resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} hasBin: true dependencies: - glob: 7.2.0 + glob: 7.2.3 dev: true /ripemd160@2.0.2: @@ -4426,6 +4480,14 @@ packages: version: 1.0.0 dev: true + github.com/erc7579/erc7579-implementation/957cd05deeab6a9a85343bb8d1c9701705ed4ecf: + resolution: {tarball: https://codeload.github.com/erc7579/erc7579-implementation/tar.gz/957cd05deeab6a9a85343bb8d1c9701705ed4ecf} + name: micro-msa + version: 0.3.1 + dependencies: + '@openzeppelin/contracts': 5.0.1 + dev: true + github.com/erc7579/erc7579-implementation/be581c908df73f1554f466cb6b47c8ce8777e50f: resolution: {tarball: https://codeload.github.com/erc7579/erc7579-implementation/tar.gz/be581c908df73f1554f466cb6b47c8ce8777e50f} name: micro-msa @@ -4583,6 +4645,12 @@ packages: version: 6.2.0 dev: true + github.com/vectorized/solady/1372606383445c0a247e6c58eb255a529734258a: + resolution: {tarball: https://codeload.github.com/vectorized/solady/tar.gz/1372606383445c0a247e6c58eb255a529734258a} + name: solady + version: 0.0.168 + dev: true + github.com/vectorized/solady/9deb9ed36a27261a8745db5b7cd7f4cdc3b1cd4e: resolution: {tarball: https://codeload.github.com/vectorized/solady/tar.gz/9deb9ed36a27261a8745db5b7cd7f4cdc3b1cd4e} name: solady diff --git a/remappings.txt b/remappings.txt index e80e0742..11d91084 100644 --- a/remappings.txt +++ b/remappings.txt @@ -12,3 +12,4 @@ solady/=node_modules/solady/ solarray/=node_modules/solarray/src/ @prb/math/=node_modules/@prb/math/ erc4337-validation/=node_modules/erc4337-validation/src/ + diff --git a/src/Modules.sol b/src/Modules.sol index 1992c006..5222b7a3 100644 --- a/src/Modules.sol +++ b/src/Modules.sol @@ -9,3 +9,9 @@ import { ERC7579HookBase } from "./modules/ERC7579HookBase.sol"; import { ERC7579HookDestruct } from "./modules/ERC7579HookDestruct.sol"; import { ERC7579FallbackBase } from "./modules/ERC7579FallbackBase.sol"; import { ExtensibleFallbackHandler } from "./core/ExtensibleFallbackHandler.sol"; +import { + IERC7579Validator, + IERC7579Executor, + IERC7579Fallback, + IERC7579Hook +} from "./external/ERC7579.sol"; diff --git a/src/modules/ERC7579HookDestruct.sol b/src/modules/ERC7579HookDestruct.sol index 0adcbaea..330363e7 100644 --- a/src/modules/ERC7579HookDestruct.sol +++ b/src/modules/ERC7579HookDestruct.sol @@ -13,6 +13,8 @@ import { CALLTYPE_DELEGATECALL } from "erc7579/lib/ModeLib.sol"; +import "forge-std/console2.sol"; + abstract contract ERC7579HookDestruct is ERC7579HookBase { error HookInvalidSelector(); @@ -20,6 +22,29 @@ abstract contract ERC7579HookDestruct is ERC7579HookBase { CALLDATA DECODING //////////////////////////////////////////////////////////////////////////*/ + // import "../interfaces/IERC7579Account.sol"; + // + // library HookOffsetLib { + // function offset() internal pure returns (uint256 offset) { + // bytes4 functionSig = bytes4(msg.data[:4]); + // if ( + // functionSig == IERC7579Account.execute.selector + // || functionSig == IERC7579Account.executeFromExecutor.selector + // ) { + // return 100 + uint256(bytes32(msg.data[68:100])); + // } + // + // if ( + // functionSig == IERC7579Account.installModule.selector + // || functionSig == IERC7579Account.uninstallModule.selector + // ) { + // return 132 + uint256(bytes32(msg.data[100:132])); + // } else { + // return msg.data.length; + // } + // } + // } + function preCheck( address msgSender, bytes calldata msgData @@ -33,9 +58,10 @@ abstract contract ERC7579HookDestruct is ERC7579HookBase { if (selector == IERC7579Account.execute.selector) { ModeCode mode = ModeCode.wrap(bytes32(msgData[4:36])); CallType calltype = ModeLib.getCallType(mode); + uint256 offset = 100 + uint256(bytes32(msgData[68:100])); if (calltype == CALLTYPE_SINGLE) { (address to, uint256 value, bytes calldata callData) = - ExecutionLib.decodeSingle(msgData[36:]); + ExecutionLib.decodeSingle(msgData[36:offset]); return onExecute(msgSender, to, value, callData); } else if (calltype == CALLTYPE_BATCH) { Execution[] calldata execs = ExecutionLib.decodeBatch(msgData[36:]); @@ -44,27 +70,34 @@ abstract contract ERC7579HookDestruct is ERC7579HookBase { revert HookInvalidSelector(); } } else if (selector == IERC7579Account.executeFromExecutor.selector) { + console2.logBytes(msgData); + + uint256 offset = 100 + uint256(bytes32(msgData[68:100])); + console2.log("offset: ", offset); + console2.logBytes(msgData[:offset]); ModeCode mode = ModeCode.wrap(bytes32(msgData[4:36])); CallType calltype = ModeLib.getCallType(mode); if (calltype == CALLTYPE_SINGLE) { (address to, uint256 value, bytes calldata callData) = - ExecutionLib.decodeSingle(msgData[36:]); + ExecutionLib.decodeSingle(msgData[36:offset]); return onExecuteFromExecutor(msgSender, to, value, callData); } else if (calltype == CALLTYPE_BATCH) { - Execution[] calldata execs = ExecutionLib.decodeBatch(msgData[36:]); + Execution[] calldata execs = ExecutionLib.decodeBatch(msgData[36:offset]); return onExecuteBatchFromExecutor(msgSender, execs); } else { revert HookInvalidSelector(); } } else if (selector == IERC7579Account.installModule.selector) { + uint256 offset = 132 + uint256(bytes32(msgData[100:132])); uint256 moduleType = uint256(bytes32(msgData[4:24])); address module = address(bytes20(msgData[24:36])); - bytes calldata initData = msgData[36:]; + bytes calldata initData = msgData[36:offset]; onInstallModule(msgSender, moduleType, module, initData); } else if (selector == IERC7579Account.uninstallModule.selector) { + uint256 offset = 132 + uint256(bytes32(msgData[100:132])); uint256 moduleType = uint256(bytes32(msgData[4:24])); address module = address(bytes20(msgData[24:36])); - bytes calldata initData = msgData[36:]; + bytes calldata initData = msgData[36:offset]; onUninstallModule(msgSender, moduleType, module, initData); } else { revert HookInvalidSelector(); diff --git a/src/test/RhinestoneModuleKit.sol b/src/test/RhinestoneModuleKit.sol index 355f911d..afedc21a 100644 --- a/src/test/RhinestoneModuleKit.sol +++ b/src/test/RhinestoneModuleKit.sol @@ -17,6 +17,9 @@ import { import { ModuleKitUserOp } from "./ModuleKitUserOp.sol"; import { ModuleKitHelpers } from "./ModuleKitHelpers.sol"; import { MockValidator } from "../Mocks.sol"; +import { MultiAccountFactory } from "./MultiAccountFactory.sol"; +import { AccountDetection } from "./utils/AccountDetection.sol"; +import { IAccountFactory } from "../IAccountFactory.sol"; import "./utils/Vm.sol"; import "./utils/ModuleKitCache.sol"; @@ -36,12 +39,9 @@ struct UserOpData { bytes32 userOpHash; } -contract RhinestoneModuleKit is AuxiliaryFactory { - ERC7579AccountFactory public accountFactory; - IERC7579Account public accountImplementationSingleton; - +contract RhinestoneModuleKit is AccountDetection, AuxiliaryFactory, MultiAccountFactory { + IAccountFactory public accountFactory; bool internal isInit; - MockValidator public defaultValidator; constructor() { @@ -59,120 +59,34 @@ contract RhinestoneModuleKit is AuxiliaryFactory { } isInit = true; - - // Deploy default contracts - accountImplementationSingleton = new ERC7579Account(); - label(address(accountImplementationSingleton), "ERC7579AccountImpl"); - accountFactory = new ERC7579AccountFactory(address(accountImplementationSingleton)); - label(address(accountFactory), "ERC7579AccountFactory"); defaultValidator = new MockValidator(); label(address(defaultValidator), "DefaultValidator"); - // Stake factory on EntryPoint - deal(address(accountFactory), 10 ether); - prank(address(accountFactory)); - IStakeManager(ENTRYPOINT_ADDR).addStake{ value: 10 ether }(100_000); + // // Deploy default contracts + // accountImplementationSingleton = new ERC7579Account(); + // label(address(accountImplementationSingleton), "ERC7579AccountImpl"); + // accountFactory = new ERC7579AccountFactory(address(accountImplementationSingleton)); + // label(address(accountFactory), "ERC7579AccountFactory"); + // defaultValidator = new MockValidator(); + // label(address(defaultValidator), "DefaultValidator"); + // + // // Stake factory on EntryPoint + // deal(address(accountFactory), 10 ether); + // prank(address(accountFactory)); + // IStakeManager(ENTRYPOINT_ADDR).addStake{ value: 10 ether }(100_000); } - /** - * create new AccountInstance with initCode - * @param salt account salt / name - * @param counterFactualAddress of the account - * @param initCode4337 to be added to userOp:initCode - */ - function makeAccountInstance( - bytes32 salt, - address counterFactualAddress, - bytes memory initCode4337 - ) - internal - returns (AccountInstance memory instance) - { - // Create AccountInstance struct with counterFactualAddress and initCode - // The initcode will be set to 0, once the account was created by EntryPoint.sol + function makeAccountInstance(bytes32 salt) internal returns (AccountInstance memory instance) { + address account = makeAccount(accountFlavor, salt, address(defaultValidator), ""); + instance = AccountInstance({ - account: counterFactualAddress, + account: account, aux: auxiliary, salt: salt, defaultValidator: IERC7579Validator(address(defaultValidator)), - initCode: initCode4337, + initCode: "", gasLog: false }); - - ModuleKitCache.logEntrypoint(instance.account, auxiliary.entrypoint); - } - - /** - * create new AccountInstance with ERC7579BootstrapConfig - * - * @param salt account salt / name - * @param validators ERC7549 validators to be installed on the account - * @param executors ERC7549 executors to be installed on the account - * @param hook ERC7549 hook to be installed on the account - * @param fallBack ERC7549 fallbackHandler to be installed on the account - */ - function makeAccountInstance( - bytes32 salt, - ERC7579BootstrapConfig[] memory validators, - ERC7579BootstrapConfig[] memory executors, - ERC7579BootstrapConfig memory hook, - ERC7579BootstrapConfig memory fallBack - ) - internal - returns (AccountInstance memory instance) - { - init(); - - if (validators.length == 0) validators = new ERC7579BootstrapConfig[](1); - - // inject the defaultValidator if it is not already in the list - // defaultValidator is used a lot in ModuleKit, to make it easier to use - // if defaultValidator isnt available on the account, a lot of ModuleKit Abstractions would - // break - if (validators[0].module != address(0) && validators[0].module != address(defaultValidator)) - { - ERC7579BootstrapConfig[] memory _validators = - new ERC7579BootstrapConfig[](validators.length + 1); - _validators[0] = ERC7579BootstrapConfig({ module: address(defaultValidator), data: "" }); - for (uint256 i = 0; i < validators.length; i++) { - _validators[i + 1] = validators[i]; - } - validators = _validators; - } - - bytes memory bootstrapCalldata = - auxiliary.bootstrap._getInitMSACalldata(validators, executors, hook, fallBack); - address account = accountFactory.getAddress(salt, bootstrapCalldata); - - // using MSAFactory from ERC7579 repo. - bytes memory createAccountOnFactory = - abi.encodeCall(accountFactory.createAccount, (salt, bootstrapCalldata)); - - address factory = address(accountFactory); - // encode pack factory and account initCode to comply with SenderCreater (EntryPoint.sol) - bytes memory initCode4337 = abi.encodePacked(factory, createAccountOnFactory); - label(address(account), bytes32ToString(salt)); - deal(account, 1 ether); - - instance = makeAccountInstance(salt, account, initCode4337); - } - - /** - * create new AccountInstance with modulekit defaults - * - * @param salt account salt / name - */ - function makeAccountInstance(bytes32 salt) internal returns (AccountInstance memory instance) { - init(); - ERC7579BootstrapConfig[] memory validators = - makeBootstrapConfig(address(defaultValidator), ""); - - ERC7579BootstrapConfig[] memory executors = _emptyConfigs(); - - ERC7579BootstrapConfig memory hook = _emptyConfig(); - - ERC7579BootstrapConfig memory fallBack = _emptyConfig(); - instance = makeAccountInstance(salt, validators, executors, hook, fallBack); } function makeAccountInstance( @@ -183,69 +97,5 @@ contract RhinestoneModuleKit is AuxiliaryFactory { ) internal returns (AccountInstance memory instance) - { - init(); - - instance = AccountInstance({ - account: account, - aux: auxiliary, - salt: salt, - defaultValidator: IERC7579Validator(address(defaultValidator)), - initCode: initCode, - gasLog: false - }); - - ModuleKitCache.logEntrypoint(instance.account, auxiliary.entrypoint); - } - - function bytes32ToString(bytes32 _bytes32) public pure returns (string memory) { - bytes memory _bytes = new bytes(32); - for (uint256 i = 0; i < 32; i++) { - _bytes[i] = _bytes32[i]; - } - return string(_bytes); - } - - function _emptyConfig() internal pure returns (ERC7579BootstrapConfig memory config) { } - function _emptyConfigs() internal pure returns (ERC7579BootstrapConfig[] memory config) { } - - function _makeBootstrapConfig( - address module, - bytes memory data - ) - public - pure - returns (ERC7579BootstrapConfig memory config) - { - config.module = module; - config.data = data; - } - - function makeBootstrapConfig( - address module, - bytes memory data - ) - public - pure - returns (ERC7579BootstrapConfig[] memory config) - { - config = new ERC7579BootstrapConfig[](1); - config[0].module = module; - config[0].data = data; - } - - function makeBootstrapConfig( - address[] memory modules, - bytes[] memory datas - ) - public - pure - returns (ERC7579BootstrapConfig[] memory configs) - { - configs = new ERC7579BootstrapConfig[](modules.length); - - for (uint256 i; i < modules.length; i++) { - configs[i] = _makeBootstrapConfig(modules[i], datas[i]); - } - } + { } } diff --git a/test/Diff.t.sol b/test/Diff.t.sol deleted file mode 100644 index 56b9e9f8..00000000 --- a/test/Diff.t.sol +++ /dev/null @@ -1,324 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.23; - -/* solhint-disable no-global-import */ -import "src/ModuleKit.sol"; -import "./MakeAccount.t.sol"; -import "src/Mocks.sol"; -import { writeSimulateUserOp } from "src/test/utils/Log.sol"; -import { - MODULE_TYPE_VALIDATOR, MODULE_TYPE_EXECUTOR, MODULE_TYPE_HOOK -} from "src/external/ERC7579.sol"; -/* solhint-enable no-global-import */ - -contract ERC7579DifferentialModuleKitLibTest is BaseTest { - using ModuleKitHelpers for *; - using ModuleKitUserOp for *; - - MockValidator internal validator; - MockHook internal hook; - MockExecutor internal executor; - MockTarget internal mockTarget; - - MockERC20 internal token; - - function setUp() public override { - super.setUp(); - // Setup account - instance = makeAccountInstance("1"); - - // Setup modules - validator = new MockValidator(); - hook = new MockHook(); - executor = new MockExecutor(); - mockTarget = new MockTarget(); - - // Setup aux - token = new MockERC20(); - token.initialize("Mock Token", "MTK", 18); - deal(address(token), instance.account, 100 ether); - vm.deal(instance.account, 1000 ether); - } - - // function fund() internal { - // for (uint256 i; i < diffAccounts.length; i++) { - // instance = diffAccounts[i]; - // deal(address(token), instance.account, 100 ether); - // vm.deal(instance.account, 1000 ether); - // } - // } - // - // modifier () { - // uint256 snapshot = vm.snapshot(); // saves the state - // for (uint256 i; i < diffAccounts.length; i++) { - // instance = diffAccounts[i]; - // _; - // vm.revertTo(snapshot); - // } - // } - - /*////////////////////////////////////////////////////////////////////////// - exec - //////////////////////////////////////////////////////////////////////////*/ - - function testexec__Given__TwoInputs() public { - // Create userOperation fields - address receiver = makeAddr("receiver"); - uint256 value = 10 gwei; - bytes memory callData = - abi.encodeWithSignature("transfer(address,uint256)", receiver, value); - - // Create userOperation - instance.exec({ target: address(token), callData: callData }); - - // Validate userOperation - assertEq(token.balanceOf(receiver), value, "Receiver should have 10 gwei in tokens"); - } - - function testexec__Given__ThreeInputs() public { - // Create userOperation fields - address receiver = makeAddr("receiver"); - uint256 value = 10 gwei; - bytes memory callData = ""; - - // Create userOperation - instance.exec({ target: receiver, value: value, callData: callData }); - - // Validate userOperation - assertEq(receiver.balance, value, "Receiver should have 10 gwei"); - } - - function testexec__Given__FourInputs() public { - // Create userOperation fields - address receiver = makeAddr("receiver"); - uint256 value = 10 gwei; - bytes memory callData = ""; - bytes memory signature = ""; - - // Create userOperation - instance.getExecOps({ - target: receiver, - value: value, - callData: callData, - txValidator: address(instance.defaultValidator) - }).execUserOps(); - - // Validate userOperation - assertEq(receiver.balance, value, "Receiver should have 10 gwei"); - } - - function testexec__RevertWhen__UserOperationFails() public { - // Create userOperation fields - bytes memory callData = abi.encodeWithSelector(MockTarget.setAccessControl.selector, 2); - - // Create userOperation - instance.expect4337Revert(); - instance.exec({ target: address(mockTarget), callData: callData, value: 0 }); - } - - /*////////////////////////////////////////////////////////////////////////// - MODULES - //////////////////////////////////////////////////////////////////////////*/ - - function testAddValidator() public { - address newValidator = address(new MockValidator()); - address newValidator1 = address(new MockValidator()); - vm.label(newValidator, "2nd validator"); - - instance.installModule({ - moduleTypeId: MODULE_TYPE_VALIDATOR, - module: newValidator, - data: "" - }); - // instance.log4337Gas("testAddValidator()"); - // instance.enableGasLog(); - instance.installModule({ - moduleTypeId: MODULE_TYPE_VALIDATOR, - module: newValidator1, - data: "" - }); - - bool validatorEnabled = instance.isModuleInstalled(MODULE_TYPE_VALIDATOR, newValidator); - assertTrue(validatorEnabled); - bool validator1Enabled = instance.isModuleInstalled(MODULE_TYPE_VALIDATOR, newValidator1); - assertTrue(validator1Enabled); - } - - function testRemoveValidator() public { - address newValidator = address(new MockValidator()); - instance.installModule({ - moduleTypeId: MODULE_TYPE_VALIDATOR, - module: newValidator, - data: "" - }); - bool validatorEnabled = instance.isModuleInstalled(MODULE_TYPE_VALIDATOR, newValidator); - assertTrue(validatorEnabled); - - instance.uninstallModule({ - moduleTypeId: MODULE_TYPE_VALIDATOR, - module: newValidator, - data: "" - }); - validatorEnabled = instance.isModuleInstalled(MODULE_TYPE_VALIDATOR, newValidator); - assertFalse(validatorEnabled); - } - - function testAddSessionKey() public { - // NOT IMPLEMENTED - // uint256 validUntil = block.timestamp + 1 days; - // uint256 validAfter = block.timestamp; - // address sessionValidationModule = address(validator); - // bytes memory sessionKeyData = ""; - // - // instance.addSessionKey({ - // validUntil: validUntil, - // validAfter: validAfter, - // sessionValidationModule: sessionValidationModule, - // sessionKeyData: sessionKeyData - // }); - // - // // Validate proof - // Merkle m = new Merkle(); - // - // bytes32 leaf = instance.aux.sessionKeyManager._sessionMerkelLeaf({ - // validUntil: validUntil, - // validAfter: validAfter, - // sessionValidationModule: sessionValidationModule, - // sessionKeyData: sessionKeyData - // }); - // - // bytes32[] memory leaves = new bytes32[](2); - // leaves[0] = leaf; - // leaves[1] = leaf; - // - // bytes32 root = - // instance.aux.sessionKeyManager.getSessionKeys(instance.account).merkleRoot; - // bytes32[] memory proof = m.getProof(leaves, 1); - // - // bool isValidProof = m.verifyProof(root, proof, leaf); - // - // assertTrue(isValidProof); - } - - function testAddHook() public { - instance.installModule({ moduleTypeId: MODULE_TYPE_HOOK, module: address(hook), data: "" }); - - bool hookEnabled = instance.isModuleInstalled(MODULE_TYPE_HOOK, address(hook)); - assertTrue(hookEnabled); - } - - function testAddExecutor() public { - address newExecutor = address(new MockExecutor()); - - instance.installModule({ moduleTypeId: MODULE_TYPE_EXECUTOR, module: newExecutor, data: "" }); - bool executorEnabled = instance.isModuleInstalled(MODULE_TYPE_EXECUTOR, newExecutor); - assertTrue(executorEnabled); - } - - function testRemoveExecutor() public { - address newExecutor = address(new MockExecutor()); - - instance.installModule({ moduleTypeId: MODULE_TYPE_EXECUTOR, module: newExecutor, data: "" }); - bool executorEnabled = instance.isModuleInstalled(MODULE_TYPE_EXECUTOR, newExecutor); - assertTrue(executorEnabled); - - instance.uninstallModule({ - moduleTypeId: MODULE_TYPE_EXECUTOR, - module: newExecutor, - data: "" - }); - executorEnabled = instance.isModuleInstalled(MODULE_TYPE_EXECUTOR, newExecutor); - assertFalse(executorEnabled); - } - - // function testSetCondition() public { - // address newExecutor = address(new MockExecutor()); - // instance.addExecutor(newExecutor); - // - // address mockCondition = address(new MockCondition()); - // ConditionConfig[] memory conditions = new ConditionConfig[](1); - // conditions[0] = ConditionConfig({ condition: ICondition(mockCondition), - // conditionData: "" - // }); - // - // bytes32 digest = - // instance.aux.compConditionManager._conditionDigest(conditions); - // - // instance.setCondition(newExecutor, conditions); - // - // bytes32 digestOnManager = - // instance.aux.compConditionManager.getHash(instance.account, newExecutor); - // assertEq(digest, digestOnManager); - // } - - // function testAddFallback() public { - // TokenReceiver handler = new TokenReceiver(); - // bytes4 functionSig = IERC721TokenReceiver.onERC721Received.selector; - // - // bytes memory callData = abi.encodeWithSelector( - // functionSig, makeAddr("foo"), makeAddr("foo"), uint256(1), bytes("foo") - // ); - // - // instance.addFallback({ - // handleFunctionSig: functionSig, - // isStatic: true, - // handler: address(handler) - // }); - // - // (bool success,) = instance.account.call(callData); - // assertTrue(success); - // } - - /*////////////////////////////////////////////////////////////////////////// - UTILS - //////////////////////////////////////////////////////////////////////////*/ - - function testGetUserOpHash() public { - // // Create userOperation fields - // address receiver = makeAddr("receiver"); - // uint256 value = 10 gwei; - // bytes memory callData = abi.encode(true); - // - // // Create userOperation hash using lib - // bytes32 userOpHash = - // instance.getUserOpHash({ target: receiver, value: value, callData: callData }); - // - // UserOperation memory userOp = - // instance.getFormattedUserOp({ target: receiver, value: value, callData: callData }); - // bytes32 entryPointUserOpHash = instance.aux.entrypoint.getUserOpHash(userOp); - // - // // Validate userOperation - // assertEq(userOpHash, entryPointUserOpHash); - } - - function testDeployAccount() public { - AccountInstance memory newInstance = makeAccountInstance("new"); - assertTrue(newInstance.account.code.length == 0); - - newInstance.deployAccount(); - - assertTrue(newInstance.account.code.length > 0); - } - - function testWriteGas() public { - string memory gasIdentifier = "testWriteGas"; - string memory rootDir = "gas_calculations"; - string memory fileName = string.concat(rootDir, "/", gasIdentifier, ".json"); - assertTrue(vm.isDir("gas_calculations")); - if (vm.isFile(fileName)) { - vm.removeFile(fileName); - } - assertFalse(vm.isFile(fileName)); - - vm.setEnv("GAS", "true"); - - instance.log4337Gas("testWriteGas"); - testexec__Given__TwoInputs(); - assertTrue(vm.isFile(fileName)); - } - - function testSimulateUserOp() public { - writeSimulateUserOp(true); - testexec__Given__TwoInputs(); - } -} diff --git a/test/MakeAccount.t.sol b/test/MakeAccount.t.sol deleted file mode 100644 index 14b79a53..00000000 --- a/test/MakeAccount.t.sol +++ /dev/null @@ -1,36 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.23; - -/* solhint-disable no-global-import */ -import "forge-std/Test.sol"; -import "src/ModuleKit.sol"; -import "src/Accounts.sol"; -import "src/Mocks.sol"; -/* solhint-enable no-global-import */ - -contract BaseTest is RhinestoneModuleKit, Test { - using ModuleKitHelpers for AccountInstance; - - AccountInstance internal instance; - AccountInstance internal instanceSafe; - - address recipient; - - function setUp() public virtual { - instance = makeAccountInstance("1"); - - MockValidator defaultValidator = new MockValidator(); - MockExecutor defaultExecutor = new MockExecutor(); - vm.deal(instanceSafe.account, 1000 ether); - vm.deal(instance.account, 2 ether); - - recipient = makeAddr("recipient"); - } - - function test_transfer() public { - UserOpData memory data = instance.exec({ target: recipient, value: 1 ether, callData: "" }); - assertTrue(data.userOpHash != ""); - assertTrue(recipient.balance == 1 ether); - assertTrue(data.userOp.sender == instance.account); - } -} From fee71bc4e5557e50fa72acfe46011fdb3baf87f2 Mon Sep 17 00:00:00 2001 From: zeroknots Date: Tue, 20 Feb 2024 14:06:00 +0700 Subject: [PATCH 2/8] factory done --- package.json | 14 +- .../src/SessionKeyManagerBytecode.sol | 2 +- .../modulekit/foundry.toml | 0 packages/modulekit/package.json | 71 +++++ .../modulekit/remappings.txt | 0 {src => packages/modulekit/src}/Accounts.sol | 0 {src => packages/modulekit/src}/Core.sol | 0 {src => packages/modulekit/src}/Helpers.sol | 0 .../modulekit/src}/Integrations.sol | 0 {src => packages/modulekit/src}/Mocks.sol | 0 {src => packages/modulekit/src}/ModuleKit.sol | 0 {src => packages/modulekit/src}/Modules.sol | 0 .../src/accountFactory/MSAFactory.sol.bak | 0 .../accountFactory/MultiAccountFactory.sol | 41 +++ .../referenceImpl/RefImplFactory.sol | 49 ++++ .../src/accountFactory/safe7579/Bootstrap.sol | 69 +++++ .../safe7579/Safe7579Factory.sol | 57 ++++ .../modulekit/src}/core/ERC2771Handler.sol | 0 .../src}/core/ExtensibleFallbackHandler.sol | 0 .../modulekit/src}/core/GasTest/GasLog.sol | 0 .../core/Licensing/LicenseManager.sol.todo | 0 .../core/Licensing/LicensedModule.sol.bak | 0 .../src}/deployment/RegistryDeployer.sol | 0 .../modulekit/src}/external/ERC4337.sol | 0 .../modulekit/src}/external/ERC7579.sol | 0 .../modulekit/src}/integrations/ERC20.sol | 0 .../modulekit/src}/integrations/ERC4626.sol | 0 .../modulekit/src}/integrations/ERC721.sol | 0 .../integrations/interfaces/IBotRegistry.sol | 0 .../integrations/interfaces/IDFSRegistry.sol | 0 .../src}/integrations/interfaces/IDSProxy.sol | 0 .../src}/integrations/interfaces/IERC20.sol | 0 .../src}/integrations/interfaces/IERC4626.sol | 0 .../src}/integrations/interfaces/IERC721.sol | 0 .../interfaces/IERC721Enumerable.sol | 0 .../interfaces/IFLParamGetter.sol | 0 .../integrations/interfaces/IGasToken.sol | 0 .../integrations/interfaces/ILendingPool.sol | 0 .../interfaces/IMCDPriceVerifier.sol | 0 .../integrations/interfaces/IProxyERC20.sol | 0 .../interfaces/IProxyRegistry.sol | 0 .../interfaces/ISubscriptions.sol | 0 .../src}/integrations/interfaces/ITrigger.sol | 0 .../src}/integrations/interfaces/IWETH.sol | 0 .../integrations/interfaces/LSTs/ICBETH.sol | 0 .../integrations/interfaces/LSTs/IRETH.sol | 0 .../integrations/interfaces/LSTs/IWstETH.sol | 0 .../integrations/interfaces/aave/IAToken.sol | 0 .../interfaces/aave/ILendToAaveMigrator.sol | 0 .../interfaces/aave/ILendingPool.sol | 0 .../aave/ILendingPoolAddressesProvider.sol | 0 .../integrations/interfaces/aave/IStkAave.sol | 0 .../aaveV2/IAaveIncentivesController.sol | 0 .../aaveV2/IAaveProtocolDataProviderV2.sol | 0 .../ILendingPoolAddressesProviderV2.sol | 0 .../interfaces/aaveV2/ILendingPoolV2.sol | 0 .../aaveV2/IPriceOracleGetterAave.sol | 0 .../interfaces/aaveV2/IStakedToken.sol | 0 .../interfaces/aaveV3/DataTypes.sol | 0 .../aaveV3/IAaveProtocolDataProvider.sol | 0 .../interfaces/aaveV3/IAaveV3Oracle.sol | 0 .../interfaces/aaveV3/IL2PoolV3.sol | 0 .../aaveV3/IPoolAddressesProvider.sol | 0 .../interfaces/aaveV3/IPoolV3.sol | 0 .../interfaces/aaveV3/IPriceOracleGetter.sol | 0 .../aaveV3/IPriceOracleSentinel.sol | 0 .../interfaces/aaveV3/IRewardsController.sol | 0 .../interfaces/aaveV3/IRewardsDistributor.sol | 0 .../balancer/IFlashLoanRecipient.sol | 0 .../interfaces/balancer/IFlashLoans.sol | 0 .../interfaces/balancer/IMerkleRedeem.sol | 0 .../interfaces/balancer/IPool.sol | 0 .../interfaces/balancer/IVault.sol | 0 .../interfaces/bprotocol/IBAMM.sol | 0 .../interfaces/chainlink/IAggregatorV3.sol | 0 .../interfaces/chainlink/IFeedRegistry.sol | 0 .../interfaces/chainlink/IPhaseAggregator.sol | 0 .../interfaces/compound/ICToken.sol | 0 .../interfaces/compound/ICompoundOracle.sol | 0 .../interfaces/compound/IComptroller.sol | 0 .../interfaces/compoundV3/IComet.sol | 0 .../interfaces/compoundV3/ICometExt.sol | 0 .../interfaces/compoundV3/ICometRewards.sol | 0 .../interfaces/convex/IBaseRewardPool.sol | 0 .../interfaces/convex/IBooster.sol | 0 .../interfaces/convex/IConvexToken.sol | 0 .../interfaces/convex/IRewardPool.sol | 0 .../interfaces/curve/IAddressProvider.sol | 0 .../interfaces/curve/ICurve3PoolZap.sol | 0 .../interfaces/curve/ICurveFactory.sol | 0 .../interfaces/curve/IDepositZap.sol | 0 .../interfaces/curve/IFeeDistributor.sol | 0 .../interfaces/curve/ILiquidityGauge.sol | 0 .../integrations/interfaces/curve/IMinter.sol | 0 .../interfaces/curve/IRegistry.sol | 0 .../integrations/interfaces/curve/ISwaps.sol | 0 .../interfaces/curve/IVotingEscrow.sol | 0 .../curve/stethPool/ICurveStethPool.sol | 0 .../interfaces/curveusd/ICurveUsd.sol | 0 .../interfaces/dydx/ISoloMargin.sol | 0 .../integrations/interfaces/euler/IDToken.sol | 0 .../interfaces/euler/IEulerMarkets.sol | 0 .../interfaces/exchange/IExchangeV3.sol | 0 .../interfaces/exchange/IExchangeWrapper.sol | 0 .../exchange/IKyberNetworkProxy.sol | 0 .../interfaces/exchange/IOasis.sol | 0 .../exchange/IOffchainWrapper.sol.bak | 0 .../interfaces/exchange/IPair.sol | 0 .../interfaces/exchange/IQuoter.sol | 0 .../interfaces/exchange/ISwapRouter.sol | 0 .../interfaces/exchange/IUniswapRouter.sol | 0 .../flashloan/IERC3156FlashBorrower.sol | 0 .../flashloan/IERC3156FlashLender.sol | 0 .../interfaces/flashloan/IFlashLoanBase.sol | 0 .../interfaces/guni/IGUniPool.sol | 0 .../interfaces/guni/IGUniRouter02.sol | 0 .../interfaces/insta/IInstaAccountV2.sol | 0 .../interfaces/insta/IInstaIndex.sol | 0 .../insta/IInstaMakerDAOMerkleDistributor.sol | 0 .../interfaces/kyber/IAggregationExecutor.sol | 0 .../interfaces/kyber/IExecutorHelper.sol | 0 .../kyber/IMetaAggregationRouterV2.sol | 0 .../integrations/interfaces/lido/IWStEth.sol | 0 .../interfaces/liquity/IBondNFT.sol | 0 .../interfaces/liquity/IBondNFTArtwork.sol | 0 .../liquity/IBorrowerOperations.sol | 0 .../liquity/IChickenBondManager.sol | 0 .../interfaces/liquity/ICollSurplusPool.sol | 0 .../interfaces/liquity/IHintHelpers.sol | 0 .../interfaces/liquity/ILQTYStaking.sol | 0 .../interfaces/liquity/IPriceFeed.sol | 0 .../interfaces/liquity/ISortedTroves.sol | 0 .../interfaces/liquity/IStabilityPool.sol | 0 .../interfaces/liquity/ITroveManager.sol | 0 .../src}/integrations/interfaces/mcd/ICat.sol | 0 .../interfaces/mcd/ICdpRegistry.sol | 0 .../integrations/interfaces/mcd/ICropJoin.sol | 0 .../integrations/interfaces/mcd/ICropper.sol | 0 .../integrations/interfaces/mcd/IDSPause.sol | 0 .../integrations/interfaces/mcd/IDaiJoin.sol | 0 .../integrations/interfaces/mcd/IDssSpell.sol | 0 .../src}/integrations/interfaces/mcd/IGem.sol | 0 .../integrations/interfaces/mcd/IGetCdps.sol | 0 .../integrations/interfaces/mcd/IJoin.sol | 0 .../src}/integrations/interfaces/mcd/IJug.sol | 0 .../integrations/interfaces/mcd/IManager.sol | 0 .../src}/integrations/interfaces/mcd/IOsm.sol | 0 .../interfaces/mcd/IPipInterface.sol | 0 .../src}/integrations/interfaces/mcd/IPot.sol | 0 .../integrations/interfaces/mcd/ISpotter.sol | 0 .../src}/integrations/interfaces/mcd/IVat.sol | 0 .../interfaces/morpho/IMorpho.sol | 0 .../interfaces/morpho/IMorphoAaveV2Lens.sol | 0 .../interfaces/morpho/IMorphoAaveV3.sol | 0 .../interfaces/morpho/IRewardsDistributor.sol | 0 .../interfaces/morpho/MorphoTypes.sol | 0 .../interfaces/morpho/MorphoTypesAaveV3.sol | 0 .../mstable/IBoostedVaultWithLockup.sol | 0 .../interfaces/mstable/ISavingsContractV2.sol | 0 .../interfaces/mstable/ImAsset.sol | 0 .../interfaces/qidao/IQiDaoRegistry.sol | 0 .../interfaces/qidao/IStablecoin.sol | 0 .../interfaces/rari/IFundController.sol | 0 .../interfaces/rari/IFundManager.sol | 0 .../interfaces/rari/IFundProxy.sol | 0 .../interfaces/rari/IFuseAsset.sol | 0 .../reflexer/IBasicTokenAdapters.sol | 0 .../interfaces/reflexer/ICoinJoin.sol | 0 .../interfaces/reflexer/IFSMWrapper.sol | 0 .../interfaces/reflexer/IGetSafes.sol | 0 .../interfaces/reflexer/IMedianOracle.sol | 0 .../interfaces/reflexer/IOracleRelayer.sol | 0 .../interfaces/reflexer/ISAFEEngine.sol | 0 .../interfaces/reflexer/ISAFEManager.sol | 0 .../interfaces/reflexer/ISAFESaviour.sol | 0 .../interfaces/reflexer/ITaxCollector.sol | 0 .../integrations/interfaces/spark/IsDAI.sol | 0 .../interfaces/strategy/ISubStorage.sol | 0 .../interfaces/uniswap/IUniswapV2Factory.sol | 0 .../interfaces/uniswap/IUniswapV2Pair.sol | 0 .../interfaces/uniswap/v3/IQuoter.sol | 0 .../interfaces/uniswap/v3/ISwapRouter.sol | 0 .../uniswap/v3/IUniswapV3Factory.sol | 0 .../uniswap/v3/IUniswapV3FlashCallback.sol | 0 .../IUniswapV3NonfungiblePositionManager.sol | 0 .../interfaces/uniswap/v3/IUniswapV3Pool.sol | 0 .../uniswap/v3/IUniswapV3SwapCallback.sol | 0 .../integrations/interfaces/yearn/IYVault.sol | 0 .../interfaces/yearn/IYearnRegistry.sol | 0 .../src}/integrations/uniswap/MockUniswap.sol | 0 .../uniswap/helpers/MainnetAddresses.sol | 0 .../src}/integrations/uniswap/v3/Uniswap.sol | 0 .../modulekit/src}/interfaces/IERC1271.sol | 0 .../src}/interfaces/IERC7484Registry.sol | 0 .../modulekit/src}/mocks/MockExecutor.sol | 0 .../modulekit/src}/mocks/MockHook.sol | 0 .../modulekit/src}/mocks/MockRegistry.sol | 0 .../mocks/MockSessionKeyValidator.sol.bak | 0 .../modulekit/src}/mocks/MockTarget.sol | 0 .../modulekit/src}/mocks/MockValidator.sol | 0 .../src}/modules/ERC7579ExecutorBase.sol | 0 .../src}/modules/ERC7579FallbackBase.sol | 0 .../src}/modules/ERC7579HookBase.sol | 0 .../src}/modules/ERC7579HookDestruct.sol | 0 .../src}/modules/ERC7579ModuleBase.sol | 0 .../src}/modules/ERC7579ValidatorBase.sol | 0 .../src}/modules/ERC7579ValidatorMaster.sol | 0 .../modulekit/src}/modules/SessionKeyBase.sol | 0 .../modules/utils/ERC7579ValidatorLib.sol | 0 .../modulekit/src}/test/Auxiliary.sol | 0 .../src}/test/ModuleKitFallbackHandler.sol | 0 .../modulekit/src}/test/ModuleKitHelpers.sol | 0 .../modulekit/src}/test/ModuleKitSCM.sol | 0 .../modulekit/src}/test/ModuleKitUserOp.sol | 0 .../src/test/RhinestoneModuleKit.sol | 251 ++++++++++++++++++ .../src/test/RhinestoneModuleKit.sol.bak | 0 .../src}/test/predeploy/EntryPoint.sol | 0 .../src}/test/predeploy/MockFactory.sol | 0 .../src}/test/predeploy/SessionKeyManager.sol | 0 .../src}/test/utils/ERC4337Helpers.sol | 0 .../src}/test/utils/ERC7579Helpers.sol | 0 .../src}/test/utils/GasCalculations.sol | 0 .../modulekit/src}/test/utils/Log.sol | 0 .../src}/test/utils/ModuleKitCache.sol | 0 .../modulekit/src}/test/utils/Vm.sol | 0 .../modulekit/test}/LicenseManager.t.sol.bak | 0 .../test}/SessionValidator.t.sol.bak | 0 .../test}/SessionValidator.t.sol.bak2 | 0 .../modulekit/test}/ValidatorUtils.t.sol.bak | 0 pnpm-lock.yaml | 96 +++---- 230 files changed, 577 insertions(+), 73 deletions(-) rename foundry.toml => packages/modulekit/foundry.toml (100%) create mode 100644 packages/modulekit/package.json rename remappings.txt => packages/modulekit/remappings.txt (100%) rename {src => packages/modulekit/src}/Accounts.sol (100%) rename {src => packages/modulekit/src}/Core.sol (100%) rename {src => packages/modulekit/src}/Helpers.sol (100%) rename {src => packages/modulekit/src}/Integrations.sol (100%) rename {src => packages/modulekit/src}/Mocks.sol (100%) rename {src => packages/modulekit/src}/ModuleKit.sol (100%) rename {src => packages/modulekit/src}/Modules.sol (100%) create mode 100644 packages/modulekit/src/accountFactory/MSAFactory.sol.bak create mode 100644 packages/modulekit/src/accountFactory/MultiAccountFactory.sol create mode 100644 packages/modulekit/src/accountFactory/referenceImpl/RefImplFactory.sol create mode 100644 packages/modulekit/src/accountFactory/safe7579/Bootstrap.sol create mode 100644 packages/modulekit/src/accountFactory/safe7579/Safe7579Factory.sol rename {src => packages/modulekit/src}/core/ERC2771Handler.sol (100%) rename {src => packages/modulekit/src}/core/ExtensibleFallbackHandler.sol (100%) rename {src => packages/modulekit/src}/core/GasTest/GasLog.sol (100%) rename {src => packages/modulekit/src}/core/Licensing/LicenseManager.sol.todo (100%) rename {src => packages/modulekit/src}/core/Licensing/LicensedModule.sol.bak (100%) rename {src => packages/modulekit/src}/deployment/RegistryDeployer.sol (100%) rename {src => packages/modulekit/src}/external/ERC4337.sol (100%) rename {src => packages/modulekit/src}/external/ERC7579.sol (100%) rename {src => packages/modulekit/src}/integrations/ERC20.sol (100%) rename {src => packages/modulekit/src}/integrations/ERC4626.sol (100%) rename {src => packages/modulekit/src}/integrations/ERC721.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/IBotRegistry.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/IDFSRegistry.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/IDSProxy.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/IERC20.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/IERC4626.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/IERC721.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/IERC721Enumerable.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/IFLParamGetter.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/IGasToken.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/ILendingPool.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/IMCDPriceVerifier.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/IProxyERC20.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/IProxyRegistry.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/ISubscriptions.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/ITrigger.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/IWETH.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/LSTs/ICBETH.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/LSTs/IRETH.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/LSTs/IWstETH.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/aave/IAToken.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/aave/ILendToAaveMigrator.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/aave/ILendingPool.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/aave/ILendingPoolAddressesProvider.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/aave/IStkAave.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/aaveV2/IAaveIncentivesController.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/aaveV2/IAaveProtocolDataProviderV2.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/aaveV2/ILendingPoolAddressesProviderV2.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/aaveV2/ILendingPoolV2.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/aaveV2/IPriceOracleGetterAave.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/aaveV2/IStakedToken.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/aaveV3/DataTypes.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/aaveV3/IAaveProtocolDataProvider.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/aaveV3/IAaveV3Oracle.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/aaveV3/IL2PoolV3.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/aaveV3/IPoolAddressesProvider.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/aaveV3/IPoolV3.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/aaveV3/IPriceOracleGetter.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/aaveV3/IPriceOracleSentinel.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/aaveV3/IRewardsController.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/aaveV3/IRewardsDistributor.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/balancer/IFlashLoanRecipient.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/balancer/IFlashLoans.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/balancer/IMerkleRedeem.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/balancer/IPool.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/balancer/IVault.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/bprotocol/IBAMM.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/chainlink/IAggregatorV3.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/chainlink/IFeedRegistry.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/chainlink/IPhaseAggregator.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/compound/ICToken.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/compound/ICompoundOracle.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/compound/IComptroller.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/compoundV3/IComet.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/compoundV3/ICometExt.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/compoundV3/ICometRewards.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/convex/IBaseRewardPool.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/convex/IBooster.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/convex/IConvexToken.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/convex/IRewardPool.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/curve/IAddressProvider.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/curve/ICurve3PoolZap.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/curve/ICurveFactory.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/curve/IDepositZap.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/curve/IFeeDistributor.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/curve/ILiquidityGauge.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/curve/IMinter.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/curve/IRegistry.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/curve/ISwaps.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/curve/IVotingEscrow.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/curve/stethPool/ICurveStethPool.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/curveusd/ICurveUsd.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/dydx/ISoloMargin.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/euler/IDToken.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/euler/IEulerMarkets.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/exchange/IExchangeV3.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/exchange/IExchangeWrapper.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/exchange/IKyberNetworkProxy.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/exchange/IOasis.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/exchange/IOffchainWrapper.sol.bak (100%) rename {src => packages/modulekit/src}/integrations/interfaces/exchange/IPair.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/exchange/IQuoter.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/exchange/ISwapRouter.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/exchange/IUniswapRouter.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/flashloan/IERC3156FlashBorrower.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/flashloan/IERC3156FlashLender.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/flashloan/IFlashLoanBase.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/guni/IGUniPool.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/guni/IGUniRouter02.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/insta/IInstaAccountV2.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/insta/IInstaIndex.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/insta/IInstaMakerDAOMerkleDistributor.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/kyber/IAggregationExecutor.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/kyber/IExecutorHelper.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/kyber/IMetaAggregationRouterV2.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/lido/IWStEth.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/liquity/IBondNFT.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/liquity/IBondNFTArtwork.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/liquity/IBorrowerOperations.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/liquity/IChickenBondManager.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/liquity/ICollSurplusPool.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/liquity/IHintHelpers.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/liquity/ILQTYStaking.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/liquity/IPriceFeed.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/liquity/ISortedTroves.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/liquity/IStabilityPool.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/liquity/ITroveManager.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/mcd/ICat.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/mcd/ICdpRegistry.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/mcd/ICropJoin.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/mcd/ICropper.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/mcd/IDSPause.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/mcd/IDaiJoin.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/mcd/IDssSpell.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/mcd/IGem.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/mcd/IGetCdps.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/mcd/IJoin.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/mcd/IJug.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/mcd/IManager.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/mcd/IOsm.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/mcd/IPipInterface.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/mcd/IPot.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/mcd/ISpotter.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/mcd/IVat.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/morpho/IMorpho.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/morpho/IMorphoAaveV2Lens.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/morpho/IMorphoAaveV3.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/morpho/IRewardsDistributor.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/morpho/MorphoTypes.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/morpho/MorphoTypesAaveV3.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/mstable/IBoostedVaultWithLockup.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/mstable/ISavingsContractV2.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/mstable/ImAsset.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/qidao/IQiDaoRegistry.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/qidao/IStablecoin.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/rari/IFundController.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/rari/IFundManager.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/rari/IFundProxy.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/rari/IFuseAsset.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/reflexer/IBasicTokenAdapters.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/reflexer/ICoinJoin.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/reflexer/IFSMWrapper.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/reflexer/IGetSafes.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/reflexer/IMedianOracle.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/reflexer/IOracleRelayer.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/reflexer/ISAFEEngine.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/reflexer/ISAFEManager.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/reflexer/ISAFESaviour.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/reflexer/ITaxCollector.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/spark/IsDAI.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/strategy/ISubStorage.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/uniswap/IUniswapV2Factory.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/uniswap/IUniswapV2Pair.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/uniswap/v3/IQuoter.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/uniswap/v3/ISwapRouter.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/uniswap/v3/IUniswapV3Factory.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/uniswap/v3/IUniswapV3FlashCallback.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/uniswap/v3/IUniswapV3NonfungiblePositionManager.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/uniswap/v3/IUniswapV3Pool.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/uniswap/v3/IUniswapV3SwapCallback.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/yearn/IYVault.sol (100%) rename {src => packages/modulekit/src}/integrations/interfaces/yearn/IYearnRegistry.sol (100%) rename {src => packages/modulekit/src}/integrations/uniswap/MockUniswap.sol (100%) rename {src => packages/modulekit/src}/integrations/uniswap/helpers/MainnetAddresses.sol (100%) rename {src => packages/modulekit/src}/integrations/uniswap/v3/Uniswap.sol (100%) rename {src => packages/modulekit/src}/interfaces/IERC1271.sol (100%) rename {src => packages/modulekit/src}/interfaces/IERC7484Registry.sol (100%) rename {src => packages/modulekit/src}/mocks/MockExecutor.sol (100%) rename {src => packages/modulekit/src}/mocks/MockHook.sol (100%) rename {src => packages/modulekit/src}/mocks/MockRegistry.sol (100%) rename {src => packages/modulekit/src}/mocks/MockSessionKeyValidator.sol.bak (100%) rename {src => packages/modulekit/src}/mocks/MockTarget.sol (100%) rename {src => packages/modulekit/src}/mocks/MockValidator.sol (100%) rename {src => packages/modulekit/src}/modules/ERC7579ExecutorBase.sol (100%) rename {src => packages/modulekit/src}/modules/ERC7579FallbackBase.sol (100%) rename {src => packages/modulekit/src}/modules/ERC7579HookBase.sol (100%) rename {src => packages/modulekit/src}/modules/ERC7579HookDestruct.sol (100%) rename {src => packages/modulekit/src}/modules/ERC7579ModuleBase.sol (100%) rename {src => packages/modulekit/src}/modules/ERC7579ValidatorBase.sol (100%) rename {src => packages/modulekit/src}/modules/ERC7579ValidatorMaster.sol (100%) rename {src => packages/modulekit/src}/modules/SessionKeyBase.sol (100%) rename {src => packages/modulekit/src}/modules/utils/ERC7579ValidatorLib.sol (100%) rename {src => packages/modulekit/src}/test/Auxiliary.sol (100%) rename {src => packages/modulekit/src}/test/ModuleKitFallbackHandler.sol (100%) rename {src => packages/modulekit/src}/test/ModuleKitHelpers.sol (100%) rename {src => packages/modulekit/src}/test/ModuleKitSCM.sol (100%) rename {src => packages/modulekit/src}/test/ModuleKitUserOp.sol (100%) create mode 100644 packages/modulekit/src/test/RhinestoneModuleKit.sol rename src/test/RhinestoneModuleKit.sol => packages/modulekit/src/test/RhinestoneModuleKit.sol.bak (100%) rename {src => packages/modulekit/src}/test/predeploy/EntryPoint.sol (100%) rename {src => packages/modulekit/src}/test/predeploy/MockFactory.sol (100%) rename {src => packages/modulekit/src}/test/predeploy/SessionKeyManager.sol (100%) rename {src => packages/modulekit/src}/test/utils/ERC4337Helpers.sol (100%) rename {src => packages/modulekit/src}/test/utils/ERC7579Helpers.sol (100%) rename {src => packages/modulekit/src}/test/utils/GasCalculations.sol (100%) rename {src => packages/modulekit/src}/test/utils/Log.sol (100%) rename {src => packages/modulekit/src}/test/utils/ModuleKitCache.sol (100%) rename {src => packages/modulekit/src}/test/utils/Vm.sol (100%) rename {test => packages/modulekit/test}/LicenseManager.t.sol.bak (100%) rename {test => packages/modulekit/test}/SessionValidator.t.sol.bak (100%) rename {test => packages/modulekit/test}/SessionValidator.t.sol.bak2 (100%) rename {test => packages/modulekit/test}/ValidatorUtils.t.sol.bak (100%) diff --git a/package.json b/package.json index 34b5b8c0..3aeac978 100644 --- a/package.json +++ b/package.json @@ -19,19 +19,9 @@ "devDependencies": { "@rhinestone/sessionkeymanager": "workspace:*", "@rhinestone/safe7579": "workspace:*", - "ds-test": "github:dapphub/ds-test", - "forge-std": "github:foundry-rs/forge-std", - "@openzeppelin/contracts": "5.0.1", - "@prb/math": "^4.0.2", - "erc4337-validation": "github:rhinestonewtf/erc4337-validation", - "@ERC4337/account-abstraction": "github:kopy-kat/account-abstraction#develop", - "@ERC4337/account-abstraction-v0.6": "github:eth-infinitism/account-abstraction#v0.6.0", - "@safe-global/safe-contracts": "^1.4.1", - "erc7579": "github:erc7579/erc7579-implementation", + "@rhinestone/modulekit": "workspace:*", + "@rhinestone/modulekit": "workspace:*", "prettier": "^2.8.8", - "sentinellist": "github:zeroknots/sentinellist", - "solady": "github:vectorized/solady", - "solarray": "github:sablier-labs/solarray", "solhint": "^4.1.1" }, "files": [ diff --git a/packages/SessionKeyManager/src/SessionKeyManagerBytecode.sol b/packages/SessionKeyManager/src/SessionKeyManagerBytecode.sol index 1d078379..8447f255 100644 --- a/packages/SessionKeyManager/src/SessionKeyManagerBytecode.sol +++ b/packages/SessionKeyManager/src/SessionKeyManagerBytecode.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; +/* solhint-disable-nextline max-line-length */ -/* solhint-disable max-line-length */ bytes constant SESSIONKEYMANAGER_BYTECODE = hex"6080806040523461001657610cfe908161001c8239f35b600080fdfe60806040908082526004918236101561001757600080fd5b600091823560e01c90816306fdde03146106025750806354fd4d50146105be5780636d61fe70146105b95780638a91b0e3146105b95780639700320314610563578063cb9b272c14610308578063d4511ee9146102e7578063d60b347f146102c2578063d6cc1aa4146102a8578063df73e60e146101cb578063ecd05961146101a6578063f42c859d146100ff5763f551e2ee146100b457600080fd5b346100fb5760603660031901126100fb576100cd610727565b5060443567ffffffffffffffff81116100f7576020936100ef9136910161068f565b505051908152f35b8280fd5b5080fd5b508183346100fb5760203660031901126100fb576001903592838352826020528083203384526020528220828155016101388154610807565b80610169575b505050337f10103b778a5e09e8bcc680439d97711489525190a1fe679251002e893f9ea5638380a380f35b82601f8211600114610181575050555b81838061013e565b909180825261019f601f60208420940160051c840160018501610841565b5555610179565b509190346101c85760203660031901126101c857506001602092519135148152f35b80fd5b50346100fb57806003193601126100fb576102a460016101e9610727565b838051956101f68761073d565b808752606080602098838a820152838582015201526024358152808752818120848060a01b038094168252875220948451946102318661073d565b86549165ffffffffffff9788918285168952610271818a0192848760301c168452858b019660601c875261026a8651809a81930161088c565b038861078b565b606089019687528351998a99828b52511690890152511690860152511660608401525160808084015260a083019061064f565b0390f35b50346100fb57816003193601126100fb5751908152602090f35b50346100fb5760203660031901126100fb57906020916102e0610727565b5051908152f35b50346100fb576020906103016102fc366106f5565b610c34565b9051908152f35b5082346100f757610318366106f5565b9061032282610c34565b92838552602092858452818620338752845281862065ffffffffffff9283610349846107e0565b1690868401946bffffffffffff000000000000610365876107e0565b60301b16828601936bffffffffffffffffffffffff19610384866107f3565b60601b169117178455600180940160608601946103a186886107ad565b919067ffffffffffffffff9a8b841161055057509082918e8d6103c48754610807565b90601f8211610517575b90508193601f86116001146104ad575050926104a2575b50508160011b916000199060031b1c19161790555b6104178251968988528261040d88610858565b168a890152610858565b1690850152356001600160a01b0381169081900361049e57606084015235601e198236030181121561049a57018035930191831161049657823603821361049657806104907f57aa9b35aca9ac2ac77db1278fe563afa57004616360740e680d89bc674ebd1e93608080840152339560a084019161086b565b0390a380f35b8480fd5b8680fd5b8780fd5b013590508d806103e5565b8783528183209550929392601f19871692915b8383106104ff575050509084600195949392106104e5575b505050811b0190556103fa565b0135600019600384901b60f8161c191690558d80806104d8565b8185978293949688013581550196019301908f6104c0565b87835280832061053f92601f880160051c8201928810610546575b601f0160051c0190610841565b388e6103ce565b9091508190610532565b634e487b7160e01b8f526041905260248efd5b5090346101c8576003199282843601126100fb57803567ffffffffffffffff81116100f7576101208183019582360301126100f75760646105a59101856107ad565b919050116101c85750610301602092610922565b6106c2565b50346100fb57816003193601126100fb5780516102a4916105de8261076f565b6005825264302e302e3160d81b60208301525191829160208352602083019061064f565b919050346100f757826003193601126100f7576102a492506106238261076f565b601182527029b2b9b9b4b7b725b2bca6b0b730b3b2b960791b6020830152519182916020835260208301905b919082519283825260005b84811061067b575050826000602080949584010152601f8019910116010190565b60208183018101518483018201520161065a565b9181601f840112156106bd5782359167ffffffffffffffff83116106bd57602083818601950101116106bd57565b600080fd5b346106bd5760203660031901126106bd5760043567ffffffffffffffff81116106bd576106f390369060040161068f565b005b600319906020818301126106bd576004359167ffffffffffffffff83116106bd57826080920301126106bd5760040190565b600435906001600160a01b03821682036106bd57565b6080810190811067ffffffffffffffff82111761075957604052565b634e487b7160e01b600052604160045260246000fd5b6040810190811067ffffffffffffffff82111761075957604052565b90601f8019910116810190811067ffffffffffffffff82111761075957604052565b903590601e19813603018212156106bd570180359067ffffffffffffffff82116106bd576020019181360383136106bd57565b3565ffffffffffff811681036106bd5790565b356001600160a01b03811681036106bd5790565b90600182811c92168015610837575b602083101461082157565b634e487b7160e01b600052602260045260246000fd5b91607f1691610816565b81811061084c575050565b60008155600101610841565b359065ffffffffffff821682036106bd57565b908060209392818452848401376000828201840152601f01601f1916010190565b80546000939261089b82610807565b9182825260209360019160018116908160001461090357506001146108c2575b5050505050565b90939495506000929192528360002092846000945b8386106108ef575050505001019038808080806108bb565b8054858701830152940193859082016108d7565b60ff19168685015250505090151560051b0101915038808080806108bb565b6109306101008201826107ad565b5060018101356000526000602052604060002060018060a01b0383351660005260205261096660406000209260608101906107ad565b9290836004116106bd576003198401806020116106bd57806040116106bd57601f198501858111610c1e57806080116106bd57116106bd576109f7602091610a0c956000855460601c92610a2c604051998a968795869463c20bccb960e01b8652601081013560601c60048701526024810135602487015260a06044870152608460a4870192609f1901910161086b565b83810360031901606485015260018a0161088c565b82810360031901608484015260218a8101358b016001810135910161086b565b03925af1928315610c1257600093610bce575b5054916000916001600160a01b038216610a80575b505015610a7a5760a01b65ffffffffffff60d01b81169065ffffffffffff60a01b161790565b50600190565b9091506040519160018201356000526040600160218401358401013514610b6f575b6041600160218401358401013514610b25575b60006060526040838152630b135d3f60e11b8085526001848101356004870152602486019283526021808601358601808301356044890181905294979396602096899690959460649490930184860137602181013501013501916001600160a01b03165afa915114163880610a54565b6021828101358301606181013560001a6020526040910181376020600160806000825afa516001600160a01b038216183d1517610ab5575050600060605260405260013880610a54565b6021828101358301604181013560ff81901c601b01602090815291909201356040526001600160ff1b03909116606052600160806000825afa516001600160a01b038216183d1517610aa2575050600060605260405260013880610a54565b9092506020813d602011610c0a575b81610bea6020938361078b565b810103126106bd57516001600160a01b03811681036106bd579138610a3f565b3d9150610bdd565b6040513d6000823e3d90fd5b634e487b7160e01b600052601160045260246000fd5b610c3d816107e0565b90610cc26040610c4f602084016107e0565b93610c69610c5e8386016107f3565b9460608101906107ad565b80918451968794602086019965ffffffffffff60d01b809260d01b168b5260d01b1660268601526bffffffffffffffffffffffff199060601b16602c85015284840137810160008382015203602081018452018261078b565b5190209056fea264697066735822122026a81cd670005fcd561638caf42a14771310b8b3023b89447085b3f5739e2d3364736f6c63430008180033"; diff --git a/foundry.toml b/packages/modulekit/foundry.toml similarity index 100% rename from foundry.toml rename to packages/modulekit/foundry.toml diff --git a/packages/modulekit/package.json b/packages/modulekit/package.json new file mode 100644 index 00000000..d0da21e4 --- /dev/null +++ b/packages/modulekit/package.json @@ -0,0 +1,71 @@ +{ + "name": "@rhinestone/modulekit", + "description": "ModuleKit is a development toolkit to build Smart Account Modules", + "license": "MIT", + "version": "0.3.1", + "author": { + "name": "zeroknots.eth", + "url": "https://rhinestone.wtf" + }, + "bugs": { + "url": "https://github.com/rhinestonewtf/modulekit/issues" + }, + "dependencies": {}, + "devDependencies": { + "@rhinestone/sessionkeymanager": "workspace:*", + "@rhinestone/safe7579": "workspace:*", + "ds-test": "github:dapphub/ds-test", + "forge-std": "github:foundry-rs/forge-std", + "@openzeppelin/contracts": "5.0.1", + "@prb/math": "^4.0.2", + "erc4337-validation": "github:rhinestonewtf/erc4337-validation", + "@ERC4337/account-abstraction": "github:kopy-kat/account-abstraction#develop", + "@ERC4337/account-abstraction-v0.6": "github:eth-infinitism/account-abstraction#v0.6.0", + "@safe-global/safe-contracts": "^1.4.1", + "erc7579": "github:erc7579/erc7579-implementation", + "prettier": "^2.8.8", + "sentinellist": "github:zeroknots/sentinellist", + "solady": "github:vectorized/solady", + "solarray": "github:sablier-labs/solarray", + "solhint": "^4.1.1" + }, + "files": [ + "artifacts", + "src", + "test/utils", + "CHANGELOG.md", + "LICENSE-GPL.md" + ], + "homepage": "https://github.com/rhinestonewtf/modulekit/#readme", + "keywords": [ + "blockchain", + "ethereum", + "foundry", + "smart-contracts", + "solidity", + "web3" + ], + "publishConfig": { + "access": "public" + }, + "repository": "github.com/rhinestonewtf/modulekit", + "scripts": { + "build": "forge build", + "fmt": "forge fmt", + "fmt:check": "forge fmt --check", + "build:optimized": "FOUNDRY_PROFILE=optimized forge build", + "build:smt": "FOUNDRY_PROFILE=smt forge build", + "clean": "rm -rf artifacts broadcast cache docs out out-optimized out-svg", + "gas:report": "forge test --gas-report --mp \"./test/integration/**/*.sol\" --nmt \"test(Fuzz)?_RevertWhen_\\w{1,}?\"", + "gas:snapshot": "forge snapshot --mp \"./test/integration/**/*.sol\" --nmt \"test(Fuzz)?_RevertWhen_\\w{1,}?\"", + "gas:snapshot:optimized": "pnpm run build:optimized && FOUNDRY_PROFILE=test-optimized forge snapshot --mp \"./test/integration/**/*.sol\" --nmt \"test(Fork)?(Fuzz)?_RevertWhen_\\w{1,}?\"", + "lint": "pnpm run lint:sol && bun run prettier:check", + "lint:sol": "forge fmt --check && pnpm solhint \"{script,src,test}/**/*.sol\"", + "prepack": "pnpm install", + "prettier:check": "prettier --check \"**/*.{json,md,svg,yml}\"", + "prettier:write": "prettier --write \"**/*.{json,md,svg,yml}\"", + "test": "forge test", + "test:lite": "FOUNDRY_PROFILE=lite forge test", + "test:optimized": "pnpm run build:optimized && FOUNDRY_PROFILE=test-optimized forge test" + } +} diff --git a/remappings.txt b/packages/modulekit/remappings.txt similarity index 100% rename from remappings.txt rename to packages/modulekit/remappings.txt diff --git a/src/Accounts.sol b/packages/modulekit/src/Accounts.sol similarity index 100% rename from src/Accounts.sol rename to packages/modulekit/src/Accounts.sol diff --git a/src/Core.sol b/packages/modulekit/src/Core.sol similarity index 100% rename from src/Core.sol rename to packages/modulekit/src/Core.sol diff --git a/src/Helpers.sol b/packages/modulekit/src/Helpers.sol similarity index 100% rename from src/Helpers.sol rename to packages/modulekit/src/Helpers.sol diff --git a/src/Integrations.sol b/packages/modulekit/src/Integrations.sol similarity index 100% rename from src/Integrations.sol rename to packages/modulekit/src/Integrations.sol diff --git a/src/Mocks.sol b/packages/modulekit/src/Mocks.sol similarity index 100% rename from src/Mocks.sol rename to packages/modulekit/src/Mocks.sol diff --git a/src/ModuleKit.sol b/packages/modulekit/src/ModuleKit.sol similarity index 100% rename from src/ModuleKit.sol rename to packages/modulekit/src/ModuleKit.sol diff --git a/src/Modules.sol b/packages/modulekit/src/Modules.sol similarity index 100% rename from src/Modules.sol rename to packages/modulekit/src/Modules.sol diff --git a/packages/modulekit/src/accountFactory/MSAFactory.sol.bak b/packages/modulekit/src/accountFactory/MSAFactory.sol.bak new file mode 100644 index 00000000..e69de29b diff --git a/packages/modulekit/src/accountFactory/MultiAccountFactory.sol b/packages/modulekit/src/accountFactory/MultiAccountFactory.sol new file mode 100644 index 00000000..2f9a5c71 --- /dev/null +++ b/packages/modulekit/src/accountFactory/MultiAccountFactory.sol @@ -0,0 +1,41 @@ +import "forge-std/Base.sol"; +import "./safe7579/Safe7579Factory.sol"; +import "./referenceImpl/RefImplFactory.sol"; + +enum AccountType { + DEFAULT, + SAFE7579 +} + +string constant DEFAULT = "DEFAULT"; +string constant SAFE7579 = "SAFE7579"; + +contract MultiAccountFactory is TestBase, Safe7579Factory, RefImplFactory { + AccountType public env; + + constructor() { + string memory _env = vm.envOr("ACCOUNT_TYPE", DEFAULT); + + if (keccak256(abi.encodePacked(_env)) == keccak256(abi.encodePacked(SAFE7579))) { + env = AccountType.SAFE7579; + } else { + env = AccountType.DEFAULT; + } + } + + function makeAccount(bytes32 salt, bytes calldata initCode) public returns (address account) { + if (env == AccountType.SAFE7579) { + return _makeSafe(salt, initCode); + } else { + return _makeDefault(salt, initCode); + } + } + + function _makeDefault(bytes32 salt, bytes calldata initCode) public returns (address) { + return _createUMSA(salt, initCode); + } + + function _makeSafe(bytes32 salt, bytes calldata initCode) public returns (address) { + return _createSafe(address(erc7579Mod), initCode); + } +} diff --git a/packages/modulekit/src/accountFactory/referenceImpl/RefImplFactory.sol b/packages/modulekit/src/accountFactory/referenceImpl/RefImplFactory.sol new file mode 100644 index 00000000..0927b913 --- /dev/null +++ b/packages/modulekit/src/accountFactory/referenceImpl/RefImplFactory.sol @@ -0,0 +1,49 @@ +import "../../external/ERC7579.sol"; +import { LibClone } from "solady/src/utils/LibClone.sol"; + +interface IMSA { + function initializeAccount(bytes calldata initCode) external; +} + +contract RefImplFactory { + ERC7579Account internal implementation; + + constructor() { + implementation = new ERC7579Account(); + } + + function _createUMSA(bytes32 salt, bytes memory initCode) public returns (address account) { + bytes32 _salt = _getSalt(salt, initCode); + address account = LibClone.cloneDeterministic(0, address(implementation), initCode, _salt); + + IMSA(account).initializeAccount(initCode); + return account; + } + + function getAddress( + bytes32 salt, + bytes memory initCode + ) + public + view + virtual + returns (address) + { + bytes32 _salt = _getSalt(salt, initCode); + return LibClone.predictDeterministicAddress( + address(implementation), initCode, _salt, address(this) + ); + } + + function _getSalt( + bytes32 _salt, + bytes memory initCode + ) + public + pure + virtual + returns (bytes32 salt) + { + salt = keccak256(abi.encodePacked(_salt, initCode)); + } +} diff --git a/packages/modulekit/src/accountFactory/safe7579/Bootstrap.sol b/packages/modulekit/src/accountFactory/safe7579/Bootstrap.sol new file mode 100644 index 00000000..07b30f49 --- /dev/null +++ b/packages/modulekit/src/accountFactory/safe7579/Bootstrap.sol @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.21; + +import "@rhinestone/safe7579/src/core/ModuleManager.sol"; +import "@rhinestone/safe7579/src/core/HookManager.sol"; + +import "../../external/ERC7579.sol"; + +struct BootstrapConfig { + address module; + bytes data; +} + +contract Bootstrap is ModuleManager, HookManager { + function singleInitMSA(IERC7579Validator validator, bytes calldata data) external { + // init validator + _installValidator(address(validator), data); + } + + /** + * This function is intended to be called by the MSA with a delegatecall. + * Make sure that the MSA already initilazed the linked lists in the ModuleManager prior to + * calling this function + */ + function initMSA( + BootstrapConfig[] calldata _validators, + BootstrapConfig[] calldata _executors, + BootstrapConfig calldata _hook, + BootstrapConfig calldata _fallback + ) + external + { + // init validators + for (uint256 i; i < _validators.length; i++) { + _installValidator(_validators[i].module, _validators[i].data); + } + + // init executors + for (uint256 i; i < _executors.length; i++) { + if (_executors[i].module == address(0)) continue; + _installExecutor(_executors[i].module, _executors[i].data); + } + + // init hook + if (_hook.module != address(0)) { + _installHook(_hook.module, _hook.data); + } + + // init fallback + if (_fallback.module != address(0)) { + _installFallbackHandler(_fallback.module, _fallback.data); + } + } + + function _getInitMSACalldata( + BootstrapConfig[] calldata _validators, + BootstrapConfig[] calldata _executors, + BootstrapConfig calldata _hook, + BootstrapConfig calldata _fallback + ) + external + view + returns (bytes memory init) + { + init = abi.encode( + address(this), abi.encodeCall(this.initMSA, (_validators, _executors, _hook, _fallback)) + ); + } +} diff --git a/packages/modulekit/src/accountFactory/safe7579/Safe7579Factory.sol b/packages/modulekit/src/accountFactory/safe7579/Safe7579Factory.sol new file mode 100644 index 00000000..05965093 --- /dev/null +++ b/packages/modulekit/src/accountFactory/safe7579/Safe7579Factory.sol @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.23; + +import "forge-std/Base.sol"; +import { SafeERC7579 } from "@rhinestone/safe7579/src/SafeERC7579.sol"; +import "@safe-global/safe-contracts/contracts/Safe.sol"; +import { LibClone } from "solady/src/utils/LibClone.sol"; + +import { Bootstrap } from "./Bootstrap.sol"; + +contract Safe7579Factory is TestBase { + // singletons + + SafeERC7579 internal erc7579Mod; + Safe internal safeImpl; + + Bootstrap internal bootstrap; + + constructor() { + // Set up MSA and Factory + erc7579Mod = new SafeERC7579(); + safeImpl = new Safe(); + bootstrap = new Bootstrap(); + } + + function _createSafe( + address defaultValidator, + bytes calldata initCode + ) + internal + returns (address safe) + { + Safe clone = Safe(payable(LibClone.clone(address(safeImpl)))); + + address[] memory signers = new address[](2); + signers[0] = address(0x12345); + signers[1] = address(0x54321); + + clone.setup({ + _owners: signers, + _threshold: 2, + to: address(0), // optional delegatecall + data: "", + fallbackHandler: address(erc7579Mod), + paymentToken: address(0), // optional payment token + payment: 0, + paymentReceiver: payable(address(0)) // optional payment receiver + }); + + vm.startPrank(address(clone)); + clone.enableModule(address(erc7579Mod)); + erc7579Mod.initializeAccount(initCode); + vm.stopPrank(); + + return address(clone); + } +} diff --git a/src/core/ERC2771Handler.sol b/packages/modulekit/src/core/ERC2771Handler.sol similarity index 100% rename from src/core/ERC2771Handler.sol rename to packages/modulekit/src/core/ERC2771Handler.sol diff --git a/src/core/ExtensibleFallbackHandler.sol b/packages/modulekit/src/core/ExtensibleFallbackHandler.sol similarity index 100% rename from src/core/ExtensibleFallbackHandler.sol rename to packages/modulekit/src/core/ExtensibleFallbackHandler.sol diff --git a/src/core/GasTest/GasLog.sol b/packages/modulekit/src/core/GasTest/GasLog.sol similarity index 100% rename from src/core/GasTest/GasLog.sol rename to packages/modulekit/src/core/GasTest/GasLog.sol diff --git a/src/core/Licensing/LicenseManager.sol.todo b/packages/modulekit/src/core/Licensing/LicenseManager.sol.todo similarity index 100% rename from src/core/Licensing/LicenseManager.sol.todo rename to packages/modulekit/src/core/Licensing/LicenseManager.sol.todo diff --git a/src/core/Licensing/LicensedModule.sol.bak b/packages/modulekit/src/core/Licensing/LicensedModule.sol.bak similarity index 100% rename from src/core/Licensing/LicensedModule.sol.bak rename to packages/modulekit/src/core/Licensing/LicensedModule.sol.bak diff --git a/src/deployment/RegistryDeployer.sol b/packages/modulekit/src/deployment/RegistryDeployer.sol similarity index 100% rename from src/deployment/RegistryDeployer.sol rename to packages/modulekit/src/deployment/RegistryDeployer.sol diff --git a/src/external/ERC4337.sol b/packages/modulekit/src/external/ERC4337.sol similarity index 100% rename from src/external/ERC4337.sol rename to packages/modulekit/src/external/ERC4337.sol diff --git a/src/external/ERC7579.sol b/packages/modulekit/src/external/ERC7579.sol similarity index 100% rename from src/external/ERC7579.sol rename to packages/modulekit/src/external/ERC7579.sol diff --git a/src/integrations/ERC20.sol b/packages/modulekit/src/integrations/ERC20.sol similarity index 100% rename from src/integrations/ERC20.sol rename to packages/modulekit/src/integrations/ERC20.sol diff --git a/src/integrations/ERC4626.sol b/packages/modulekit/src/integrations/ERC4626.sol similarity index 100% rename from src/integrations/ERC4626.sol rename to packages/modulekit/src/integrations/ERC4626.sol diff --git a/src/integrations/ERC721.sol b/packages/modulekit/src/integrations/ERC721.sol similarity index 100% rename from src/integrations/ERC721.sol rename to packages/modulekit/src/integrations/ERC721.sol diff --git a/src/integrations/interfaces/IBotRegistry.sol b/packages/modulekit/src/integrations/interfaces/IBotRegistry.sol similarity index 100% rename from src/integrations/interfaces/IBotRegistry.sol rename to packages/modulekit/src/integrations/interfaces/IBotRegistry.sol diff --git a/src/integrations/interfaces/IDFSRegistry.sol b/packages/modulekit/src/integrations/interfaces/IDFSRegistry.sol similarity index 100% rename from src/integrations/interfaces/IDFSRegistry.sol rename to packages/modulekit/src/integrations/interfaces/IDFSRegistry.sol diff --git a/src/integrations/interfaces/IDSProxy.sol b/packages/modulekit/src/integrations/interfaces/IDSProxy.sol similarity index 100% rename from src/integrations/interfaces/IDSProxy.sol rename to packages/modulekit/src/integrations/interfaces/IDSProxy.sol diff --git a/src/integrations/interfaces/IERC20.sol b/packages/modulekit/src/integrations/interfaces/IERC20.sol similarity index 100% rename from src/integrations/interfaces/IERC20.sol rename to packages/modulekit/src/integrations/interfaces/IERC20.sol diff --git a/src/integrations/interfaces/IERC4626.sol b/packages/modulekit/src/integrations/interfaces/IERC4626.sol similarity index 100% rename from src/integrations/interfaces/IERC4626.sol rename to packages/modulekit/src/integrations/interfaces/IERC4626.sol diff --git a/src/integrations/interfaces/IERC721.sol b/packages/modulekit/src/integrations/interfaces/IERC721.sol similarity index 100% rename from src/integrations/interfaces/IERC721.sol rename to packages/modulekit/src/integrations/interfaces/IERC721.sol diff --git a/src/integrations/interfaces/IERC721Enumerable.sol b/packages/modulekit/src/integrations/interfaces/IERC721Enumerable.sol similarity index 100% rename from src/integrations/interfaces/IERC721Enumerable.sol rename to packages/modulekit/src/integrations/interfaces/IERC721Enumerable.sol diff --git a/src/integrations/interfaces/IFLParamGetter.sol b/packages/modulekit/src/integrations/interfaces/IFLParamGetter.sol similarity index 100% rename from src/integrations/interfaces/IFLParamGetter.sol rename to packages/modulekit/src/integrations/interfaces/IFLParamGetter.sol diff --git a/src/integrations/interfaces/IGasToken.sol b/packages/modulekit/src/integrations/interfaces/IGasToken.sol similarity index 100% rename from src/integrations/interfaces/IGasToken.sol rename to packages/modulekit/src/integrations/interfaces/IGasToken.sol diff --git a/src/integrations/interfaces/ILendingPool.sol b/packages/modulekit/src/integrations/interfaces/ILendingPool.sol similarity index 100% rename from src/integrations/interfaces/ILendingPool.sol rename to packages/modulekit/src/integrations/interfaces/ILendingPool.sol diff --git a/src/integrations/interfaces/IMCDPriceVerifier.sol b/packages/modulekit/src/integrations/interfaces/IMCDPriceVerifier.sol similarity index 100% rename from src/integrations/interfaces/IMCDPriceVerifier.sol rename to packages/modulekit/src/integrations/interfaces/IMCDPriceVerifier.sol diff --git a/src/integrations/interfaces/IProxyERC20.sol b/packages/modulekit/src/integrations/interfaces/IProxyERC20.sol similarity index 100% rename from src/integrations/interfaces/IProxyERC20.sol rename to packages/modulekit/src/integrations/interfaces/IProxyERC20.sol diff --git a/src/integrations/interfaces/IProxyRegistry.sol b/packages/modulekit/src/integrations/interfaces/IProxyRegistry.sol similarity index 100% rename from src/integrations/interfaces/IProxyRegistry.sol rename to packages/modulekit/src/integrations/interfaces/IProxyRegistry.sol diff --git a/src/integrations/interfaces/ISubscriptions.sol b/packages/modulekit/src/integrations/interfaces/ISubscriptions.sol similarity index 100% rename from src/integrations/interfaces/ISubscriptions.sol rename to packages/modulekit/src/integrations/interfaces/ISubscriptions.sol diff --git a/src/integrations/interfaces/ITrigger.sol b/packages/modulekit/src/integrations/interfaces/ITrigger.sol similarity index 100% rename from src/integrations/interfaces/ITrigger.sol rename to packages/modulekit/src/integrations/interfaces/ITrigger.sol diff --git a/src/integrations/interfaces/IWETH.sol b/packages/modulekit/src/integrations/interfaces/IWETH.sol similarity index 100% rename from src/integrations/interfaces/IWETH.sol rename to packages/modulekit/src/integrations/interfaces/IWETH.sol diff --git a/src/integrations/interfaces/LSTs/ICBETH.sol b/packages/modulekit/src/integrations/interfaces/LSTs/ICBETH.sol similarity index 100% rename from src/integrations/interfaces/LSTs/ICBETH.sol rename to packages/modulekit/src/integrations/interfaces/LSTs/ICBETH.sol diff --git a/src/integrations/interfaces/LSTs/IRETH.sol b/packages/modulekit/src/integrations/interfaces/LSTs/IRETH.sol similarity index 100% rename from src/integrations/interfaces/LSTs/IRETH.sol rename to packages/modulekit/src/integrations/interfaces/LSTs/IRETH.sol diff --git a/src/integrations/interfaces/LSTs/IWstETH.sol b/packages/modulekit/src/integrations/interfaces/LSTs/IWstETH.sol similarity index 100% rename from src/integrations/interfaces/LSTs/IWstETH.sol rename to packages/modulekit/src/integrations/interfaces/LSTs/IWstETH.sol diff --git a/src/integrations/interfaces/aave/IAToken.sol b/packages/modulekit/src/integrations/interfaces/aave/IAToken.sol similarity index 100% rename from src/integrations/interfaces/aave/IAToken.sol rename to packages/modulekit/src/integrations/interfaces/aave/IAToken.sol diff --git a/src/integrations/interfaces/aave/ILendToAaveMigrator.sol b/packages/modulekit/src/integrations/interfaces/aave/ILendToAaveMigrator.sol similarity index 100% rename from src/integrations/interfaces/aave/ILendToAaveMigrator.sol rename to packages/modulekit/src/integrations/interfaces/aave/ILendToAaveMigrator.sol diff --git a/src/integrations/interfaces/aave/ILendingPool.sol b/packages/modulekit/src/integrations/interfaces/aave/ILendingPool.sol similarity index 100% rename from src/integrations/interfaces/aave/ILendingPool.sol rename to packages/modulekit/src/integrations/interfaces/aave/ILendingPool.sol diff --git a/src/integrations/interfaces/aave/ILendingPoolAddressesProvider.sol b/packages/modulekit/src/integrations/interfaces/aave/ILendingPoolAddressesProvider.sol similarity index 100% rename from src/integrations/interfaces/aave/ILendingPoolAddressesProvider.sol rename to packages/modulekit/src/integrations/interfaces/aave/ILendingPoolAddressesProvider.sol diff --git a/src/integrations/interfaces/aave/IStkAave.sol b/packages/modulekit/src/integrations/interfaces/aave/IStkAave.sol similarity index 100% rename from src/integrations/interfaces/aave/IStkAave.sol rename to packages/modulekit/src/integrations/interfaces/aave/IStkAave.sol diff --git a/src/integrations/interfaces/aaveV2/IAaveIncentivesController.sol b/packages/modulekit/src/integrations/interfaces/aaveV2/IAaveIncentivesController.sol similarity index 100% rename from src/integrations/interfaces/aaveV2/IAaveIncentivesController.sol rename to packages/modulekit/src/integrations/interfaces/aaveV2/IAaveIncentivesController.sol diff --git a/src/integrations/interfaces/aaveV2/IAaveProtocolDataProviderV2.sol b/packages/modulekit/src/integrations/interfaces/aaveV2/IAaveProtocolDataProviderV2.sol similarity index 100% rename from src/integrations/interfaces/aaveV2/IAaveProtocolDataProviderV2.sol rename to packages/modulekit/src/integrations/interfaces/aaveV2/IAaveProtocolDataProviderV2.sol diff --git a/src/integrations/interfaces/aaveV2/ILendingPoolAddressesProviderV2.sol b/packages/modulekit/src/integrations/interfaces/aaveV2/ILendingPoolAddressesProviderV2.sol similarity index 100% rename from src/integrations/interfaces/aaveV2/ILendingPoolAddressesProviderV2.sol rename to packages/modulekit/src/integrations/interfaces/aaveV2/ILendingPoolAddressesProviderV2.sol diff --git a/src/integrations/interfaces/aaveV2/ILendingPoolV2.sol b/packages/modulekit/src/integrations/interfaces/aaveV2/ILendingPoolV2.sol similarity index 100% rename from src/integrations/interfaces/aaveV2/ILendingPoolV2.sol rename to packages/modulekit/src/integrations/interfaces/aaveV2/ILendingPoolV2.sol diff --git a/src/integrations/interfaces/aaveV2/IPriceOracleGetterAave.sol b/packages/modulekit/src/integrations/interfaces/aaveV2/IPriceOracleGetterAave.sol similarity index 100% rename from src/integrations/interfaces/aaveV2/IPriceOracleGetterAave.sol rename to packages/modulekit/src/integrations/interfaces/aaveV2/IPriceOracleGetterAave.sol diff --git a/src/integrations/interfaces/aaveV2/IStakedToken.sol b/packages/modulekit/src/integrations/interfaces/aaveV2/IStakedToken.sol similarity index 100% rename from src/integrations/interfaces/aaveV2/IStakedToken.sol rename to packages/modulekit/src/integrations/interfaces/aaveV2/IStakedToken.sol diff --git a/src/integrations/interfaces/aaveV3/DataTypes.sol b/packages/modulekit/src/integrations/interfaces/aaveV3/DataTypes.sol similarity index 100% rename from src/integrations/interfaces/aaveV3/DataTypes.sol rename to packages/modulekit/src/integrations/interfaces/aaveV3/DataTypes.sol diff --git a/src/integrations/interfaces/aaveV3/IAaveProtocolDataProvider.sol b/packages/modulekit/src/integrations/interfaces/aaveV3/IAaveProtocolDataProvider.sol similarity index 100% rename from src/integrations/interfaces/aaveV3/IAaveProtocolDataProvider.sol rename to packages/modulekit/src/integrations/interfaces/aaveV3/IAaveProtocolDataProvider.sol diff --git a/src/integrations/interfaces/aaveV3/IAaveV3Oracle.sol b/packages/modulekit/src/integrations/interfaces/aaveV3/IAaveV3Oracle.sol similarity index 100% rename from src/integrations/interfaces/aaveV3/IAaveV3Oracle.sol rename to packages/modulekit/src/integrations/interfaces/aaveV3/IAaveV3Oracle.sol diff --git a/src/integrations/interfaces/aaveV3/IL2PoolV3.sol b/packages/modulekit/src/integrations/interfaces/aaveV3/IL2PoolV3.sol similarity index 100% rename from src/integrations/interfaces/aaveV3/IL2PoolV3.sol rename to packages/modulekit/src/integrations/interfaces/aaveV3/IL2PoolV3.sol diff --git a/src/integrations/interfaces/aaveV3/IPoolAddressesProvider.sol b/packages/modulekit/src/integrations/interfaces/aaveV3/IPoolAddressesProvider.sol similarity index 100% rename from src/integrations/interfaces/aaveV3/IPoolAddressesProvider.sol rename to packages/modulekit/src/integrations/interfaces/aaveV3/IPoolAddressesProvider.sol diff --git a/src/integrations/interfaces/aaveV3/IPoolV3.sol b/packages/modulekit/src/integrations/interfaces/aaveV3/IPoolV3.sol similarity index 100% rename from src/integrations/interfaces/aaveV3/IPoolV3.sol rename to packages/modulekit/src/integrations/interfaces/aaveV3/IPoolV3.sol diff --git a/src/integrations/interfaces/aaveV3/IPriceOracleGetter.sol b/packages/modulekit/src/integrations/interfaces/aaveV3/IPriceOracleGetter.sol similarity index 100% rename from src/integrations/interfaces/aaveV3/IPriceOracleGetter.sol rename to packages/modulekit/src/integrations/interfaces/aaveV3/IPriceOracleGetter.sol diff --git a/src/integrations/interfaces/aaveV3/IPriceOracleSentinel.sol b/packages/modulekit/src/integrations/interfaces/aaveV3/IPriceOracleSentinel.sol similarity index 100% rename from src/integrations/interfaces/aaveV3/IPriceOracleSentinel.sol rename to packages/modulekit/src/integrations/interfaces/aaveV3/IPriceOracleSentinel.sol diff --git a/src/integrations/interfaces/aaveV3/IRewardsController.sol b/packages/modulekit/src/integrations/interfaces/aaveV3/IRewardsController.sol similarity index 100% rename from src/integrations/interfaces/aaveV3/IRewardsController.sol rename to packages/modulekit/src/integrations/interfaces/aaveV3/IRewardsController.sol diff --git a/src/integrations/interfaces/aaveV3/IRewardsDistributor.sol b/packages/modulekit/src/integrations/interfaces/aaveV3/IRewardsDistributor.sol similarity index 100% rename from src/integrations/interfaces/aaveV3/IRewardsDistributor.sol rename to packages/modulekit/src/integrations/interfaces/aaveV3/IRewardsDistributor.sol diff --git a/src/integrations/interfaces/balancer/IFlashLoanRecipient.sol b/packages/modulekit/src/integrations/interfaces/balancer/IFlashLoanRecipient.sol similarity index 100% rename from src/integrations/interfaces/balancer/IFlashLoanRecipient.sol rename to packages/modulekit/src/integrations/interfaces/balancer/IFlashLoanRecipient.sol diff --git a/src/integrations/interfaces/balancer/IFlashLoans.sol b/packages/modulekit/src/integrations/interfaces/balancer/IFlashLoans.sol similarity index 100% rename from src/integrations/interfaces/balancer/IFlashLoans.sol rename to packages/modulekit/src/integrations/interfaces/balancer/IFlashLoans.sol diff --git a/src/integrations/interfaces/balancer/IMerkleRedeem.sol b/packages/modulekit/src/integrations/interfaces/balancer/IMerkleRedeem.sol similarity index 100% rename from src/integrations/interfaces/balancer/IMerkleRedeem.sol rename to packages/modulekit/src/integrations/interfaces/balancer/IMerkleRedeem.sol diff --git a/src/integrations/interfaces/balancer/IPool.sol b/packages/modulekit/src/integrations/interfaces/balancer/IPool.sol similarity index 100% rename from src/integrations/interfaces/balancer/IPool.sol rename to packages/modulekit/src/integrations/interfaces/balancer/IPool.sol diff --git a/src/integrations/interfaces/balancer/IVault.sol b/packages/modulekit/src/integrations/interfaces/balancer/IVault.sol similarity index 100% rename from src/integrations/interfaces/balancer/IVault.sol rename to packages/modulekit/src/integrations/interfaces/balancer/IVault.sol diff --git a/src/integrations/interfaces/bprotocol/IBAMM.sol b/packages/modulekit/src/integrations/interfaces/bprotocol/IBAMM.sol similarity index 100% rename from src/integrations/interfaces/bprotocol/IBAMM.sol rename to packages/modulekit/src/integrations/interfaces/bprotocol/IBAMM.sol diff --git a/src/integrations/interfaces/chainlink/IAggregatorV3.sol b/packages/modulekit/src/integrations/interfaces/chainlink/IAggregatorV3.sol similarity index 100% rename from src/integrations/interfaces/chainlink/IAggregatorV3.sol rename to packages/modulekit/src/integrations/interfaces/chainlink/IAggregatorV3.sol diff --git a/src/integrations/interfaces/chainlink/IFeedRegistry.sol b/packages/modulekit/src/integrations/interfaces/chainlink/IFeedRegistry.sol similarity index 100% rename from src/integrations/interfaces/chainlink/IFeedRegistry.sol rename to packages/modulekit/src/integrations/interfaces/chainlink/IFeedRegistry.sol diff --git a/src/integrations/interfaces/chainlink/IPhaseAggregator.sol b/packages/modulekit/src/integrations/interfaces/chainlink/IPhaseAggregator.sol similarity index 100% rename from src/integrations/interfaces/chainlink/IPhaseAggregator.sol rename to packages/modulekit/src/integrations/interfaces/chainlink/IPhaseAggregator.sol diff --git a/src/integrations/interfaces/compound/ICToken.sol b/packages/modulekit/src/integrations/interfaces/compound/ICToken.sol similarity index 100% rename from src/integrations/interfaces/compound/ICToken.sol rename to packages/modulekit/src/integrations/interfaces/compound/ICToken.sol diff --git a/src/integrations/interfaces/compound/ICompoundOracle.sol b/packages/modulekit/src/integrations/interfaces/compound/ICompoundOracle.sol similarity index 100% rename from src/integrations/interfaces/compound/ICompoundOracle.sol rename to packages/modulekit/src/integrations/interfaces/compound/ICompoundOracle.sol diff --git a/src/integrations/interfaces/compound/IComptroller.sol b/packages/modulekit/src/integrations/interfaces/compound/IComptroller.sol similarity index 100% rename from src/integrations/interfaces/compound/IComptroller.sol rename to packages/modulekit/src/integrations/interfaces/compound/IComptroller.sol diff --git a/src/integrations/interfaces/compoundV3/IComet.sol b/packages/modulekit/src/integrations/interfaces/compoundV3/IComet.sol similarity index 100% rename from src/integrations/interfaces/compoundV3/IComet.sol rename to packages/modulekit/src/integrations/interfaces/compoundV3/IComet.sol diff --git a/src/integrations/interfaces/compoundV3/ICometExt.sol b/packages/modulekit/src/integrations/interfaces/compoundV3/ICometExt.sol similarity index 100% rename from src/integrations/interfaces/compoundV3/ICometExt.sol rename to packages/modulekit/src/integrations/interfaces/compoundV3/ICometExt.sol diff --git a/src/integrations/interfaces/compoundV3/ICometRewards.sol b/packages/modulekit/src/integrations/interfaces/compoundV3/ICometRewards.sol similarity index 100% rename from src/integrations/interfaces/compoundV3/ICometRewards.sol rename to packages/modulekit/src/integrations/interfaces/compoundV3/ICometRewards.sol diff --git a/src/integrations/interfaces/convex/IBaseRewardPool.sol b/packages/modulekit/src/integrations/interfaces/convex/IBaseRewardPool.sol similarity index 100% rename from src/integrations/interfaces/convex/IBaseRewardPool.sol rename to packages/modulekit/src/integrations/interfaces/convex/IBaseRewardPool.sol diff --git a/src/integrations/interfaces/convex/IBooster.sol b/packages/modulekit/src/integrations/interfaces/convex/IBooster.sol similarity index 100% rename from src/integrations/interfaces/convex/IBooster.sol rename to packages/modulekit/src/integrations/interfaces/convex/IBooster.sol diff --git a/src/integrations/interfaces/convex/IConvexToken.sol b/packages/modulekit/src/integrations/interfaces/convex/IConvexToken.sol similarity index 100% rename from src/integrations/interfaces/convex/IConvexToken.sol rename to packages/modulekit/src/integrations/interfaces/convex/IConvexToken.sol diff --git a/src/integrations/interfaces/convex/IRewardPool.sol b/packages/modulekit/src/integrations/interfaces/convex/IRewardPool.sol similarity index 100% rename from src/integrations/interfaces/convex/IRewardPool.sol rename to packages/modulekit/src/integrations/interfaces/convex/IRewardPool.sol diff --git a/src/integrations/interfaces/curve/IAddressProvider.sol b/packages/modulekit/src/integrations/interfaces/curve/IAddressProvider.sol similarity index 100% rename from src/integrations/interfaces/curve/IAddressProvider.sol rename to packages/modulekit/src/integrations/interfaces/curve/IAddressProvider.sol diff --git a/src/integrations/interfaces/curve/ICurve3PoolZap.sol b/packages/modulekit/src/integrations/interfaces/curve/ICurve3PoolZap.sol similarity index 100% rename from src/integrations/interfaces/curve/ICurve3PoolZap.sol rename to packages/modulekit/src/integrations/interfaces/curve/ICurve3PoolZap.sol diff --git a/src/integrations/interfaces/curve/ICurveFactory.sol b/packages/modulekit/src/integrations/interfaces/curve/ICurveFactory.sol similarity index 100% rename from src/integrations/interfaces/curve/ICurveFactory.sol rename to packages/modulekit/src/integrations/interfaces/curve/ICurveFactory.sol diff --git a/src/integrations/interfaces/curve/IDepositZap.sol b/packages/modulekit/src/integrations/interfaces/curve/IDepositZap.sol similarity index 100% rename from src/integrations/interfaces/curve/IDepositZap.sol rename to packages/modulekit/src/integrations/interfaces/curve/IDepositZap.sol diff --git a/src/integrations/interfaces/curve/IFeeDistributor.sol b/packages/modulekit/src/integrations/interfaces/curve/IFeeDistributor.sol similarity index 100% rename from src/integrations/interfaces/curve/IFeeDistributor.sol rename to packages/modulekit/src/integrations/interfaces/curve/IFeeDistributor.sol diff --git a/src/integrations/interfaces/curve/ILiquidityGauge.sol b/packages/modulekit/src/integrations/interfaces/curve/ILiquidityGauge.sol similarity index 100% rename from src/integrations/interfaces/curve/ILiquidityGauge.sol rename to packages/modulekit/src/integrations/interfaces/curve/ILiquidityGauge.sol diff --git a/src/integrations/interfaces/curve/IMinter.sol b/packages/modulekit/src/integrations/interfaces/curve/IMinter.sol similarity index 100% rename from src/integrations/interfaces/curve/IMinter.sol rename to packages/modulekit/src/integrations/interfaces/curve/IMinter.sol diff --git a/src/integrations/interfaces/curve/IRegistry.sol b/packages/modulekit/src/integrations/interfaces/curve/IRegistry.sol similarity index 100% rename from src/integrations/interfaces/curve/IRegistry.sol rename to packages/modulekit/src/integrations/interfaces/curve/IRegistry.sol diff --git a/src/integrations/interfaces/curve/ISwaps.sol b/packages/modulekit/src/integrations/interfaces/curve/ISwaps.sol similarity index 100% rename from src/integrations/interfaces/curve/ISwaps.sol rename to packages/modulekit/src/integrations/interfaces/curve/ISwaps.sol diff --git a/src/integrations/interfaces/curve/IVotingEscrow.sol b/packages/modulekit/src/integrations/interfaces/curve/IVotingEscrow.sol similarity index 100% rename from src/integrations/interfaces/curve/IVotingEscrow.sol rename to packages/modulekit/src/integrations/interfaces/curve/IVotingEscrow.sol diff --git a/src/integrations/interfaces/curve/stethPool/ICurveStethPool.sol b/packages/modulekit/src/integrations/interfaces/curve/stethPool/ICurveStethPool.sol similarity index 100% rename from src/integrations/interfaces/curve/stethPool/ICurveStethPool.sol rename to packages/modulekit/src/integrations/interfaces/curve/stethPool/ICurveStethPool.sol diff --git a/src/integrations/interfaces/curveusd/ICurveUsd.sol b/packages/modulekit/src/integrations/interfaces/curveusd/ICurveUsd.sol similarity index 100% rename from src/integrations/interfaces/curveusd/ICurveUsd.sol rename to packages/modulekit/src/integrations/interfaces/curveusd/ICurveUsd.sol diff --git a/src/integrations/interfaces/dydx/ISoloMargin.sol b/packages/modulekit/src/integrations/interfaces/dydx/ISoloMargin.sol similarity index 100% rename from src/integrations/interfaces/dydx/ISoloMargin.sol rename to packages/modulekit/src/integrations/interfaces/dydx/ISoloMargin.sol diff --git a/src/integrations/interfaces/euler/IDToken.sol b/packages/modulekit/src/integrations/interfaces/euler/IDToken.sol similarity index 100% rename from src/integrations/interfaces/euler/IDToken.sol rename to packages/modulekit/src/integrations/interfaces/euler/IDToken.sol diff --git a/src/integrations/interfaces/euler/IEulerMarkets.sol b/packages/modulekit/src/integrations/interfaces/euler/IEulerMarkets.sol similarity index 100% rename from src/integrations/interfaces/euler/IEulerMarkets.sol rename to packages/modulekit/src/integrations/interfaces/euler/IEulerMarkets.sol diff --git a/src/integrations/interfaces/exchange/IExchangeV3.sol b/packages/modulekit/src/integrations/interfaces/exchange/IExchangeV3.sol similarity index 100% rename from src/integrations/interfaces/exchange/IExchangeV3.sol rename to packages/modulekit/src/integrations/interfaces/exchange/IExchangeV3.sol diff --git a/src/integrations/interfaces/exchange/IExchangeWrapper.sol b/packages/modulekit/src/integrations/interfaces/exchange/IExchangeWrapper.sol similarity index 100% rename from src/integrations/interfaces/exchange/IExchangeWrapper.sol rename to packages/modulekit/src/integrations/interfaces/exchange/IExchangeWrapper.sol diff --git a/src/integrations/interfaces/exchange/IKyberNetworkProxy.sol b/packages/modulekit/src/integrations/interfaces/exchange/IKyberNetworkProxy.sol similarity index 100% rename from src/integrations/interfaces/exchange/IKyberNetworkProxy.sol rename to packages/modulekit/src/integrations/interfaces/exchange/IKyberNetworkProxy.sol diff --git a/src/integrations/interfaces/exchange/IOasis.sol b/packages/modulekit/src/integrations/interfaces/exchange/IOasis.sol similarity index 100% rename from src/integrations/interfaces/exchange/IOasis.sol rename to packages/modulekit/src/integrations/interfaces/exchange/IOasis.sol diff --git a/src/integrations/interfaces/exchange/IOffchainWrapper.sol.bak b/packages/modulekit/src/integrations/interfaces/exchange/IOffchainWrapper.sol.bak similarity index 100% rename from src/integrations/interfaces/exchange/IOffchainWrapper.sol.bak rename to packages/modulekit/src/integrations/interfaces/exchange/IOffchainWrapper.sol.bak diff --git a/src/integrations/interfaces/exchange/IPair.sol b/packages/modulekit/src/integrations/interfaces/exchange/IPair.sol similarity index 100% rename from src/integrations/interfaces/exchange/IPair.sol rename to packages/modulekit/src/integrations/interfaces/exchange/IPair.sol diff --git a/src/integrations/interfaces/exchange/IQuoter.sol b/packages/modulekit/src/integrations/interfaces/exchange/IQuoter.sol similarity index 100% rename from src/integrations/interfaces/exchange/IQuoter.sol rename to packages/modulekit/src/integrations/interfaces/exchange/IQuoter.sol diff --git a/src/integrations/interfaces/exchange/ISwapRouter.sol b/packages/modulekit/src/integrations/interfaces/exchange/ISwapRouter.sol similarity index 100% rename from src/integrations/interfaces/exchange/ISwapRouter.sol rename to packages/modulekit/src/integrations/interfaces/exchange/ISwapRouter.sol diff --git a/src/integrations/interfaces/exchange/IUniswapRouter.sol b/packages/modulekit/src/integrations/interfaces/exchange/IUniswapRouter.sol similarity index 100% rename from src/integrations/interfaces/exchange/IUniswapRouter.sol rename to packages/modulekit/src/integrations/interfaces/exchange/IUniswapRouter.sol diff --git a/src/integrations/interfaces/flashloan/IERC3156FlashBorrower.sol b/packages/modulekit/src/integrations/interfaces/flashloan/IERC3156FlashBorrower.sol similarity index 100% rename from src/integrations/interfaces/flashloan/IERC3156FlashBorrower.sol rename to packages/modulekit/src/integrations/interfaces/flashloan/IERC3156FlashBorrower.sol diff --git a/src/integrations/interfaces/flashloan/IERC3156FlashLender.sol b/packages/modulekit/src/integrations/interfaces/flashloan/IERC3156FlashLender.sol similarity index 100% rename from src/integrations/interfaces/flashloan/IERC3156FlashLender.sol rename to packages/modulekit/src/integrations/interfaces/flashloan/IERC3156FlashLender.sol diff --git a/src/integrations/interfaces/flashloan/IFlashLoanBase.sol b/packages/modulekit/src/integrations/interfaces/flashloan/IFlashLoanBase.sol similarity index 100% rename from src/integrations/interfaces/flashloan/IFlashLoanBase.sol rename to packages/modulekit/src/integrations/interfaces/flashloan/IFlashLoanBase.sol diff --git a/src/integrations/interfaces/guni/IGUniPool.sol b/packages/modulekit/src/integrations/interfaces/guni/IGUniPool.sol similarity index 100% rename from src/integrations/interfaces/guni/IGUniPool.sol rename to packages/modulekit/src/integrations/interfaces/guni/IGUniPool.sol diff --git a/src/integrations/interfaces/guni/IGUniRouter02.sol b/packages/modulekit/src/integrations/interfaces/guni/IGUniRouter02.sol similarity index 100% rename from src/integrations/interfaces/guni/IGUniRouter02.sol rename to packages/modulekit/src/integrations/interfaces/guni/IGUniRouter02.sol diff --git a/src/integrations/interfaces/insta/IInstaAccountV2.sol b/packages/modulekit/src/integrations/interfaces/insta/IInstaAccountV2.sol similarity index 100% rename from src/integrations/interfaces/insta/IInstaAccountV2.sol rename to packages/modulekit/src/integrations/interfaces/insta/IInstaAccountV2.sol diff --git a/src/integrations/interfaces/insta/IInstaIndex.sol b/packages/modulekit/src/integrations/interfaces/insta/IInstaIndex.sol similarity index 100% rename from src/integrations/interfaces/insta/IInstaIndex.sol rename to packages/modulekit/src/integrations/interfaces/insta/IInstaIndex.sol diff --git a/src/integrations/interfaces/insta/IInstaMakerDAOMerkleDistributor.sol b/packages/modulekit/src/integrations/interfaces/insta/IInstaMakerDAOMerkleDistributor.sol similarity index 100% rename from src/integrations/interfaces/insta/IInstaMakerDAOMerkleDistributor.sol rename to packages/modulekit/src/integrations/interfaces/insta/IInstaMakerDAOMerkleDistributor.sol diff --git a/src/integrations/interfaces/kyber/IAggregationExecutor.sol b/packages/modulekit/src/integrations/interfaces/kyber/IAggregationExecutor.sol similarity index 100% rename from src/integrations/interfaces/kyber/IAggregationExecutor.sol rename to packages/modulekit/src/integrations/interfaces/kyber/IAggregationExecutor.sol diff --git a/src/integrations/interfaces/kyber/IExecutorHelper.sol b/packages/modulekit/src/integrations/interfaces/kyber/IExecutorHelper.sol similarity index 100% rename from src/integrations/interfaces/kyber/IExecutorHelper.sol rename to packages/modulekit/src/integrations/interfaces/kyber/IExecutorHelper.sol diff --git a/src/integrations/interfaces/kyber/IMetaAggregationRouterV2.sol b/packages/modulekit/src/integrations/interfaces/kyber/IMetaAggregationRouterV2.sol similarity index 100% rename from src/integrations/interfaces/kyber/IMetaAggregationRouterV2.sol rename to packages/modulekit/src/integrations/interfaces/kyber/IMetaAggregationRouterV2.sol diff --git a/src/integrations/interfaces/lido/IWStEth.sol b/packages/modulekit/src/integrations/interfaces/lido/IWStEth.sol similarity index 100% rename from src/integrations/interfaces/lido/IWStEth.sol rename to packages/modulekit/src/integrations/interfaces/lido/IWStEth.sol diff --git a/src/integrations/interfaces/liquity/IBondNFT.sol b/packages/modulekit/src/integrations/interfaces/liquity/IBondNFT.sol similarity index 100% rename from src/integrations/interfaces/liquity/IBondNFT.sol rename to packages/modulekit/src/integrations/interfaces/liquity/IBondNFT.sol diff --git a/src/integrations/interfaces/liquity/IBondNFTArtwork.sol b/packages/modulekit/src/integrations/interfaces/liquity/IBondNFTArtwork.sol similarity index 100% rename from src/integrations/interfaces/liquity/IBondNFTArtwork.sol rename to packages/modulekit/src/integrations/interfaces/liquity/IBondNFTArtwork.sol diff --git a/src/integrations/interfaces/liquity/IBorrowerOperations.sol b/packages/modulekit/src/integrations/interfaces/liquity/IBorrowerOperations.sol similarity index 100% rename from src/integrations/interfaces/liquity/IBorrowerOperations.sol rename to packages/modulekit/src/integrations/interfaces/liquity/IBorrowerOperations.sol diff --git a/src/integrations/interfaces/liquity/IChickenBondManager.sol b/packages/modulekit/src/integrations/interfaces/liquity/IChickenBondManager.sol similarity index 100% rename from src/integrations/interfaces/liquity/IChickenBondManager.sol rename to packages/modulekit/src/integrations/interfaces/liquity/IChickenBondManager.sol diff --git a/src/integrations/interfaces/liquity/ICollSurplusPool.sol b/packages/modulekit/src/integrations/interfaces/liquity/ICollSurplusPool.sol similarity index 100% rename from src/integrations/interfaces/liquity/ICollSurplusPool.sol rename to packages/modulekit/src/integrations/interfaces/liquity/ICollSurplusPool.sol diff --git a/src/integrations/interfaces/liquity/IHintHelpers.sol b/packages/modulekit/src/integrations/interfaces/liquity/IHintHelpers.sol similarity index 100% rename from src/integrations/interfaces/liquity/IHintHelpers.sol rename to packages/modulekit/src/integrations/interfaces/liquity/IHintHelpers.sol diff --git a/src/integrations/interfaces/liquity/ILQTYStaking.sol b/packages/modulekit/src/integrations/interfaces/liquity/ILQTYStaking.sol similarity index 100% rename from src/integrations/interfaces/liquity/ILQTYStaking.sol rename to packages/modulekit/src/integrations/interfaces/liquity/ILQTYStaking.sol diff --git a/src/integrations/interfaces/liquity/IPriceFeed.sol b/packages/modulekit/src/integrations/interfaces/liquity/IPriceFeed.sol similarity index 100% rename from src/integrations/interfaces/liquity/IPriceFeed.sol rename to packages/modulekit/src/integrations/interfaces/liquity/IPriceFeed.sol diff --git a/src/integrations/interfaces/liquity/ISortedTroves.sol b/packages/modulekit/src/integrations/interfaces/liquity/ISortedTroves.sol similarity index 100% rename from src/integrations/interfaces/liquity/ISortedTroves.sol rename to packages/modulekit/src/integrations/interfaces/liquity/ISortedTroves.sol diff --git a/src/integrations/interfaces/liquity/IStabilityPool.sol b/packages/modulekit/src/integrations/interfaces/liquity/IStabilityPool.sol similarity index 100% rename from src/integrations/interfaces/liquity/IStabilityPool.sol rename to packages/modulekit/src/integrations/interfaces/liquity/IStabilityPool.sol diff --git a/src/integrations/interfaces/liquity/ITroveManager.sol b/packages/modulekit/src/integrations/interfaces/liquity/ITroveManager.sol similarity index 100% rename from src/integrations/interfaces/liquity/ITroveManager.sol rename to packages/modulekit/src/integrations/interfaces/liquity/ITroveManager.sol diff --git a/src/integrations/interfaces/mcd/ICat.sol b/packages/modulekit/src/integrations/interfaces/mcd/ICat.sol similarity index 100% rename from src/integrations/interfaces/mcd/ICat.sol rename to packages/modulekit/src/integrations/interfaces/mcd/ICat.sol diff --git a/src/integrations/interfaces/mcd/ICdpRegistry.sol b/packages/modulekit/src/integrations/interfaces/mcd/ICdpRegistry.sol similarity index 100% rename from src/integrations/interfaces/mcd/ICdpRegistry.sol rename to packages/modulekit/src/integrations/interfaces/mcd/ICdpRegistry.sol diff --git a/src/integrations/interfaces/mcd/ICropJoin.sol b/packages/modulekit/src/integrations/interfaces/mcd/ICropJoin.sol similarity index 100% rename from src/integrations/interfaces/mcd/ICropJoin.sol rename to packages/modulekit/src/integrations/interfaces/mcd/ICropJoin.sol diff --git a/src/integrations/interfaces/mcd/ICropper.sol b/packages/modulekit/src/integrations/interfaces/mcd/ICropper.sol similarity index 100% rename from src/integrations/interfaces/mcd/ICropper.sol rename to packages/modulekit/src/integrations/interfaces/mcd/ICropper.sol diff --git a/src/integrations/interfaces/mcd/IDSPause.sol b/packages/modulekit/src/integrations/interfaces/mcd/IDSPause.sol similarity index 100% rename from src/integrations/interfaces/mcd/IDSPause.sol rename to packages/modulekit/src/integrations/interfaces/mcd/IDSPause.sol diff --git a/src/integrations/interfaces/mcd/IDaiJoin.sol b/packages/modulekit/src/integrations/interfaces/mcd/IDaiJoin.sol similarity index 100% rename from src/integrations/interfaces/mcd/IDaiJoin.sol rename to packages/modulekit/src/integrations/interfaces/mcd/IDaiJoin.sol diff --git a/src/integrations/interfaces/mcd/IDssSpell.sol b/packages/modulekit/src/integrations/interfaces/mcd/IDssSpell.sol similarity index 100% rename from src/integrations/interfaces/mcd/IDssSpell.sol rename to packages/modulekit/src/integrations/interfaces/mcd/IDssSpell.sol diff --git a/src/integrations/interfaces/mcd/IGem.sol b/packages/modulekit/src/integrations/interfaces/mcd/IGem.sol similarity index 100% rename from src/integrations/interfaces/mcd/IGem.sol rename to packages/modulekit/src/integrations/interfaces/mcd/IGem.sol diff --git a/src/integrations/interfaces/mcd/IGetCdps.sol b/packages/modulekit/src/integrations/interfaces/mcd/IGetCdps.sol similarity index 100% rename from src/integrations/interfaces/mcd/IGetCdps.sol rename to packages/modulekit/src/integrations/interfaces/mcd/IGetCdps.sol diff --git a/src/integrations/interfaces/mcd/IJoin.sol b/packages/modulekit/src/integrations/interfaces/mcd/IJoin.sol similarity index 100% rename from src/integrations/interfaces/mcd/IJoin.sol rename to packages/modulekit/src/integrations/interfaces/mcd/IJoin.sol diff --git a/src/integrations/interfaces/mcd/IJug.sol b/packages/modulekit/src/integrations/interfaces/mcd/IJug.sol similarity index 100% rename from src/integrations/interfaces/mcd/IJug.sol rename to packages/modulekit/src/integrations/interfaces/mcd/IJug.sol diff --git a/src/integrations/interfaces/mcd/IManager.sol b/packages/modulekit/src/integrations/interfaces/mcd/IManager.sol similarity index 100% rename from src/integrations/interfaces/mcd/IManager.sol rename to packages/modulekit/src/integrations/interfaces/mcd/IManager.sol diff --git a/src/integrations/interfaces/mcd/IOsm.sol b/packages/modulekit/src/integrations/interfaces/mcd/IOsm.sol similarity index 100% rename from src/integrations/interfaces/mcd/IOsm.sol rename to packages/modulekit/src/integrations/interfaces/mcd/IOsm.sol diff --git a/src/integrations/interfaces/mcd/IPipInterface.sol b/packages/modulekit/src/integrations/interfaces/mcd/IPipInterface.sol similarity index 100% rename from src/integrations/interfaces/mcd/IPipInterface.sol rename to packages/modulekit/src/integrations/interfaces/mcd/IPipInterface.sol diff --git a/src/integrations/interfaces/mcd/IPot.sol b/packages/modulekit/src/integrations/interfaces/mcd/IPot.sol similarity index 100% rename from src/integrations/interfaces/mcd/IPot.sol rename to packages/modulekit/src/integrations/interfaces/mcd/IPot.sol diff --git a/src/integrations/interfaces/mcd/ISpotter.sol b/packages/modulekit/src/integrations/interfaces/mcd/ISpotter.sol similarity index 100% rename from src/integrations/interfaces/mcd/ISpotter.sol rename to packages/modulekit/src/integrations/interfaces/mcd/ISpotter.sol diff --git a/src/integrations/interfaces/mcd/IVat.sol b/packages/modulekit/src/integrations/interfaces/mcd/IVat.sol similarity index 100% rename from src/integrations/interfaces/mcd/IVat.sol rename to packages/modulekit/src/integrations/interfaces/mcd/IVat.sol diff --git a/src/integrations/interfaces/morpho/IMorpho.sol b/packages/modulekit/src/integrations/interfaces/morpho/IMorpho.sol similarity index 100% rename from src/integrations/interfaces/morpho/IMorpho.sol rename to packages/modulekit/src/integrations/interfaces/morpho/IMorpho.sol diff --git a/src/integrations/interfaces/morpho/IMorphoAaveV2Lens.sol b/packages/modulekit/src/integrations/interfaces/morpho/IMorphoAaveV2Lens.sol similarity index 100% rename from src/integrations/interfaces/morpho/IMorphoAaveV2Lens.sol rename to packages/modulekit/src/integrations/interfaces/morpho/IMorphoAaveV2Lens.sol diff --git a/src/integrations/interfaces/morpho/IMorphoAaveV3.sol b/packages/modulekit/src/integrations/interfaces/morpho/IMorphoAaveV3.sol similarity index 100% rename from src/integrations/interfaces/morpho/IMorphoAaveV3.sol rename to packages/modulekit/src/integrations/interfaces/morpho/IMorphoAaveV3.sol diff --git a/src/integrations/interfaces/morpho/IRewardsDistributor.sol b/packages/modulekit/src/integrations/interfaces/morpho/IRewardsDistributor.sol similarity index 100% rename from src/integrations/interfaces/morpho/IRewardsDistributor.sol rename to packages/modulekit/src/integrations/interfaces/morpho/IRewardsDistributor.sol diff --git a/src/integrations/interfaces/morpho/MorphoTypes.sol b/packages/modulekit/src/integrations/interfaces/morpho/MorphoTypes.sol similarity index 100% rename from src/integrations/interfaces/morpho/MorphoTypes.sol rename to packages/modulekit/src/integrations/interfaces/morpho/MorphoTypes.sol diff --git a/src/integrations/interfaces/morpho/MorphoTypesAaveV3.sol b/packages/modulekit/src/integrations/interfaces/morpho/MorphoTypesAaveV3.sol similarity index 100% rename from src/integrations/interfaces/morpho/MorphoTypesAaveV3.sol rename to packages/modulekit/src/integrations/interfaces/morpho/MorphoTypesAaveV3.sol diff --git a/src/integrations/interfaces/mstable/IBoostedVaultWithLockup.sol b/packages/modulekit/src/integrations/interfaces/mstable/IBoostedVaultWithLockup.sol similarity index 100% rename from src/integrations/interfaces/mstable/IBoostedVaultWithLockup.sol rename to packages/modulekit/src/integrations/interfaces/mstable/IBoostedVaultWithLockup.sol diff --git a/src/integrations/interfaces/mstable/ISavingsContractV2.sol b/packages/modulekit/src/integrations/interfaces/mstable/ISavingsContractV2.sol similarity index 100% rename from src/integrations/interfaces/mstable/ISavingsContractV2.sol rename to packages/modulekit/src/integrations/interfaces/mstable/ISavingsContractV2.sol diff --git a/src/integrations/interfaces/mstable/ImAsset.sol b/packages/modulekit/src/integrations/interfaces/mstable/ImAsset.sol similarity index 100% rename from src/integrations/interfaces/mstable/ImAsset.sol rename to packages/modulekit/src/integrations/interfaces/mstable/ImAsset.sol diff --git a/src/integrations/interfaces/qidao/IQiDaoRegistry.sol b/packages/modulekit/src/integrations/interfaces/qidao/IQiDaoRegistry.sol similarity index 100% rename from src/integrations/interfaces/qidao/IQiDaoRegistry.sol rename to packages/modulekit/src/integrations/interfaces/qidao/IQiDaoRegistry.sol diff --git a/src/integrations/interfaces/qidao/IStablecoin.sol b/packages/modulekit/src/integrations/interfaces/qidao/IStablecoin.sol similarity index 100% rename from src/integrations/interfaces/qidao/IStablecoin.sol rename to packages/modulekit/src/integrations/interfaces/qidao/IStablecoin.sol diff --git a/src/integrations/interfaces/rari/IFundController.sol b/packages/modulekit/src/integrations/interfaces/rari/IFundController.sol similarity index 100% rename from src/integrations/interfaces/rari/IFundController.sol rename to packages/modulekit/src/integrations/interfaces/rari/IFundController.sol diff --git a/src/integrations/interfaces/rari/IFundManager.sol b/packages/modulekit/src/integrations/interfaces/rari/IFundManager.sol similarity index 100% rename from src/integrations/interfaces/rari/IFundManager.sol rename to packages/modulekit/src/integrations/interfaces/rari/IFundManager.sol diff --git a/src/integrations/interfaces/rari/IFundProxy.sol b/packages/modulekit/src/integrations/interfaces/rari/IFundProxy.sol similarity index 100% rename from src/integrations/interfaces/rari/IFundProxy.sol rename to packages/modulekit/src/integrations/interfaces/rari/IFundProxy.sol diff --git a/src/integrations/interfaces/rari/IFuseAsset.sol b/packages/modulekit/src/integrations/interfaces/rari/IFuseAsset.sol similarity index 100% rename from src/integrations/interfaces/rari/IFuseAsset.sol rename to packages/modulekit/src/integrations/interfaces/rari/IFuseAsset.sol diff --git a/src/integrations/interfaces/reflexer/IBasicTokenAdapters.sol b/packages/modulekit/src/integrations/interfaces/reflexer/IBasicTokenAdapters.sol similarity index 100% rename from src/integrations/interfaces/reflexer/IBasicTokenAdapters.sol rename to packages/modulekit/src/integrations/interfaces/reflexer/IBasicTokenAdapters.sol diff --git a/src/integrations/interfaces/reflexer/ICoinJoin.sol b/packages/modulekit/src/integrations/interfaces/reflexer/ICoinJoin.sol similarity index 100% rename from src/integrations/interfaces/reflexer/ICoinJoin.sol rename to packages/modulekit/src/integrations/interfaces/reflexer/ICoinJoin.sol diff --git a/src/integrations/interfaces/reflexer/IFSMWrapper.sol b/packages/modulekit/src/integrations/interfaces/reflexer/IFSMWrapper.sol similarity index 100% rename from src/integrations/interfaces/reflexer/IFSMWrapper.sol rename to packages/modulekit/src/integrations/interfaces/reflexer/IFSMWrapper.sol diff --git a/src/integrations/interfaces/reflexer/IGetSafes.sol b/packages/modulekit/src/integrations/interfaces/reflexer/IGetSafes.sol similarity index 100% rename from src/integrations/interfaces/reflexer/IGetSafes.sol rename to packages/modulekit/src/integrations/interfaces/reflexer/IGetSafes.sol diff --git a/src/integrations/interfaces/reflexer/IMedianOracle.sol b/packages/modulekit/src/integrations/interfaces/reflexer/IMedianOracle.sol similarity index 100% rename from src/integrations/interfaces/reflexer/IMedianOracle.sol rename to packages/modulekit/src/integrations/interfaces/reflexer/IMedianOracle.sol diff --git a/src/integrations/interfaces/reflexer/IOracleRelayer.sol b/packages/modulekit/src/integrations/interfaces/reflexer/IOracleRelayer.sol similarity index 100% rename from src/integrations/interfaces/reflexer/IOracleRelayer.sol rename to packages/modulekit/src/integrations/interfaces/reflexer/IOracleRelayer.sol diff --git a/src/integrations/interfaces/reflexer/ISAFEEngine.sol b/packages/modulekit/src/integrations/interfaces/reflexer/ISAFEEngine.sol similarity index 100% rename from src/integrations/interfaces/reflexer/ISAFEEngine.sol rename to packages/modulekit/src/integrations/interfaces/reflexer/ISAFEEngine.sol diff --git a/src/integrations/interfaces/reflexer/ISAFEManager.sol b/packages/modulekit/src/integrations/interfaces/reflexer/ISAFEManager.sol similarity index 100% rename from src/integrations/interfaces/reflexer/ISAFEManager.sol rename to packages/modulekit/src/integrations/interfaces/reflexer/ISAFEManager.sol diff --git a/src/integrations/interfaces/reflexer/ISAFESaviour.sol b/packages/modulekit/src/integrations/interfaces/reflexer/ISAFESaviour.sol similarity index 100% rename from src/integrations/interfaces/reflexer/ISAFESaviour.sol rename to packages/modulekit/src/integrations/interfaces/reflexer/ISAFESaviour.sol diff --git a/src/integrations/interfaces/reflexer/ITaxCollector.sol b/packages/modulekit/src/integrations/interfaces/reflexer/ITaxCollector.sol similarity index 100% rename from src/integrations/interfaces/reflexer/ITaxCollector.sol rename to packages/modulekit/src/integrations/interfaces/reflexer/ITaxCollector.sol diff --git a/src/integrations/interfaces/spark/IsDAI.sol b/packages/modulekit/src/integrations/interfaces/spark/IsDAI.sol similarity index 100% rename from src/integrations/interfaces/spark/IsDAI.sol rename to packages/modulekit/src/integrations/interfaces/spark/IsDAI.sol diff --git a/src/integrations/interfaces/strategy/ISubStorage.sol b/packages/modulekit/src/integrations/interfaces/strategy/ISubStorage.sol similarity index 100% rename from src/integrations/interfaces/strategy/ISubStorage.sol rename to packages/modulekit/src/integrations/interfaces/strategy/ISubStorage.sol diff --git a/src/integrations/interfaces/uniswap/IUniswapV2Factory.sol b/packages/modulekit/src/integrations/interfaces/uniswap/IUniswapV2Factory.sol similarity index 100% rename from src/integrations/interfaces/uniswap/IUniswapV2Factory.sol rename to packages/modulekit/src/integrations/interfaces/uniswap/IUniswapV2Factory.sol diff --git a/src/integrations/interfaces/uniswap/IUniswapV2Pair.sol b/packages/modulekit/src/integrations/interfaces/uniswap/IUniswapV2Pair.sol similarity index 100% rename from src/integrations/interfaces/uniswap/IUniswapV2Pair.sol rename to packages/modulekit/src/integrations/interfaces/uniswap/IUniswapV2Pair.sol diff --git a/src/integrations/interfaces/uniswap/v3/IQuoter.sol b/packages/modulekit/src/integrations/interfaces/uniswap/v3/IQuoter.sol similarity index 100% rename from src/integrations/interfaces/uniswap/v3/IQuoter.sol rename to packages/modulekit/src/integrations/interfaces/uniswap/v3/IQuoter.sol diff --git a/src/integrations/interfaces/uniswap/v3/ISwapRouter.sol b/packages/modulekit/src/integrations/interfaces/uniswap/v3/ISwapRouter.sol similarity index 100% rename from src/integrations/interfaces/uniswap/v3/ISwapRouter.sol rename to packages/modulekit/src/integrations/interfaces/uniswap/v3/ISwapRouter.sol diff --git a/src/integrations/interfaces/uniswap/v3/IUniswapV3Factory.sol b/packages/modulekit/src/integrations/interfaces/uniswap/v3/IUniswapV3Factory.sol similarity index 100% rename from src/integrations/interfaces/uniswap/v3/IUniswapV3Factory.sol rename to packages/modulekit/src/integrations/interfaces/uniswap/v3/IUniswapV3Factory.sol diff --git a/src/integrations/interfaces/uniswap/v3/IUniswapV3FlashCallback.sol b/packages/modulekit/src/integrations/interfaces/uniswap/v3/IUniswapV3FlashCallback.sol similarity index 100% rename from src/integrations/interfaces/uniswap/v3/IUniswapV3FlashCallback.sol rename to packages/modulekit/src/integrations/interfaces/uniswap/v3/IUniswapV3FlashCallback.sol diff --git a/src/integrations/interfaces/uniswap/v3/IUniswapV3NonfungiblePositionManager.sol b/packages/modulekit/src/integrations/interfaces/uniswap/v3/IUniswapV3NonfungiblePositionManager.sol similarity index 100% rename from src/integrations/interfaces/uniswap/v3/IUniswapV3NonfungiblePositionManager.sol rename to packages/modulekit/src/integrations/interfaces/uniswap/v3/IUniswapV3NonfungiblePositionManager.sol diff --git a/src/integrations/interfaces/uniswap/v3/IUniswapV3Pool.sol b/packages/modulekit/src/integrations/interfaces/uniswap/v3/IUniswapV3Pool.sol similarity index 100% rename from src/integrations/interfaces/uniswap/v3/IUniswapV3Pool.sol rename to packages/modulekit/src/integrations/interfaces/uniswap/v3/IUniswapV3Pool.sol diff --git a/src/integrations/interfaces/uniswap/v3/IUniswapV3SwapCallback.sol b/packages/modulekit/src/integrations/interfaces/uniswap/v3/IUniswapV3SwapCallback.sol similarity index 100% rename from src/integrations/interfaces/uniswap/v3/IUniswapV3SwapCallback.sol rename to packages/modulekit/src/integrations/interfaces/uniswap/v3/IUniswapV3SwapCallback.sol diff --git a/src/integrations/interfaces/yearn/IYVault.sol b/packages/modulekit/src/integrations/interfaces/yearn/IYVault.sol similarity index 100% rename from src/integrations/interfaces/yearn/IYVault.sol rename to packages/modulekit/src/integrations/interfaces/yearn/IYVault.sol diff --git a/src/integrations/interfaces/yearn/IYearnRegistry.sol b/packages/modulekit/src/integrations/interfaces/yearn/IYearnRegistry.sol similarity index 100% rename from src/integrations/interfaces/yearn/IYearnRegistry.sol rename to packages/modulekit/src/integrations/interfaces/yearn/IYearnRegistry.sol diff --git a/src/integrations/uniswap/MockUniswap.sol b/packages/modulekit/src/integrations/uniswap/MockUniswap.sol similarity index 100% rename from src/integrations/uniswap/MockUniswap.sol rename to packages/modulekit/src/integrations/uniswap/MockUniswap.sol diff --git a/src/integrations/uniswap/helpers/MainnetAddresses.sol b/packages/modulekit/src/integrations/uniswap/helpers/MainnetAddresses.sol similarity index 100% rename from src/integrations/uniswap/helpers/MainnetAddresses.sol rename to packages/modulekit/src/integrations/uniswap/helpers/MainnetAddresses.sol diff --git a/src/integrations/uniswap/v3/Uniswap.sol b/packages/modulekit/src/integrations/uniswap/v3/Uniswap.sol similarity index 100% rename from src/integrations/uniswap/v3/Uniswap.sol rename to packages/modulekit/src/integrations/uniswap/v3/Uniswap.sol diff --git a/src/interfaces/IERC1271.sol b/packages/modulekit/src/interfaces/IERC1271.sol similarity index 100% rename from src/interfaces/IERC1271.sol rename to packages/modulekit/src/interfaces/IERC1271.sol diff --git a/src/interfaces/IERC7484Registry.sol b/packages/modulekit/src/interfaces/IERC7484Registry.sol similarity index 100% rename from src/interfaces/IERC7484Registry.sol rename to packages/modulekit/src/interfaces/IERC7484Registry.sol diff --git a/src/mocks/MockExecutor.sol b/packages/modulekit/src/mocks/MockExecutor.sol similarity index 100% rename from src/mocks/MockExecutor.sol rename to packages/modulekit/src/mocks/MockExecutor.sol diff --git a/src/mocks/MockHook.sol b/packages/modulekit/src/mocks/MockHook.sol similarity index 100% rename from src/mocks/MockHook.sol rename to packages/modulekit/src/mocks/MockHook.sol diff --git a/src/mocks/MockRegistry.sol b/packages/modulekit/src/mocks/MockRegistry.sol similarity index 100% rename from src/mocks/MockRegistry.sol rename to packages/modulekit/src/mocks/MockRegistry.sol diff --git a/src/mocks/MockSessionKeyValidator.sol.bak b/packages/modulekit/src/mocks/MockSessionKeyValidator.sol.bak similarity index 100% rename from src/mocks/MockSessionKeyValidator.sol.bak rename to packages/modulekit/src/mocks/MockSessionKeyValidator.sol.bak diff --git a/src/mocks/MockTarget.sol b/packages/modulekit/src/mocks/MockTarget.sol similarity index 100% rename from src/mocks/MockTarget.sol rename to packages/modulekit/src/mocks/MockTarget.sol diff --git a/src/mocks/MockValidator.sol b/packages/modulekit/src/mocks/MockValidator.sol similarity index 100% rename from src/mocks/MockValidator.sol rename to packages/modulekit/src/mocks/MockValidator.sol diff --git a/src/modules/ERC7579ExecutorBase.sol b/packages/modulekit/src/modules/ERC7579ExecutorBase.sol similarity index 100% rename from src/modules/ERC7579ExecutorBase.sol rename to packages/modulekit/src/modules/ERC7579ExecutorBase.sol diff --git a/src/modules/ERC7579FallbackBase.sol b/packages/modulekit/src/modules/ERC7579FallbackBase.sol similarity index 100% rename from src/modules/ERC7579FallbackBase.sol rename to packages/modulekit/src/modules/ERC7579FallbackBase.sol diff --git a/src/modules/ERC7579HookBase.sol b/packages/modulekit/src/modules/ERC7579HookBase.sol similarity index 100% rename from src/modules/ERC7579HookBase.sol rename to packages/modulekit/src/modules/ERC7579HookBase.sol diff --git a/src/modules/ERC7579HookDestruct.sol b/packages/modulekit/src/modules/ERC7579HookDestruct.sol similarity index 100% rename from src/modules/ERC7579HookDestruct.sol rename to packages/modulekit/src/modules/ERC7579HookDestruct.sol diff --git a/src/modules/ERC7579ModuleBase.sol b/packages/modulekit/src/modules/ERC7579ModuleBase.sol similarity index 100% rename from src/modules/ERC7579ModuleBase.sol rename to packages/modulekit/src/modules/ERC7579ModuleBase.sol diff --git a/src/modules/ERC7579ValidatorBase.sol b/packages/modulekit/src/modules/ERC7579ValidatorBase.sol similarity index 100% rename from src/modules/ERC7579ValidatorBase.sol rename to packages/modulekit/src/modules/ERC7579ValidatorBase.sol diff --git a/src/modules/ERC7579ValidatorMaster.sol b/packages/modulekit/src/modules/ERC7579ValidatorMaster.sol similarity index 100% rename from src/modules/ERC7579ValidatorMaster.sol rename to packages/modulekit/src/modules/ERC7579ValidatorMaster.sol diff --git a/src/modules/SessionKeyBase.sol b/packages/modulekit/src/modules/SessionKeyBase.sol similarity index 100% rename from src/modules/SessionKeyBase.sol rename to packages/modulekit/src/modules/SessionKeyBase.sol diff --git a/src/modules/utils/ERC7579ValidatorLib.sol b/packages/modulekit/src/modules/utils/ERC7579ValidatorLib.sol similarity index 100% rename from src/modules/utils/ERC7579ValidatorLib.sol rename to packages/modulekit/src/modules/utils/ERC7579ValidatorLib.sol diff --git a/src/test/Auxiliary.sol b/packages/modulekit/src/test/Auxiliary.sol similarity index 100% rename from src/test/Auxiliary.sol rename to packages/modulekit/src/test/Auxiliary.sol diff --git a/src/test/ModuleKitFallbackHandler.sol b/packages/modulekit/src/test/ModuleKitFallbackHandler.sol similarity index 100% rename from src/test/ModuleKitFallbackHandler.sol rename to packages/modulekit/src/test/ModuleKitFallbackHandler.sol diff --git a/src/test/ModuleKitHelpers.sol b/packages/modulekit/src/test/ModuleKitHelpers.sol similarity index 100% rename from src/test/ModuleKitHelpers.sol rename to packages/modulekit/src/test/ModuleKitHelpers.sol diff --git a/src/test/ModuleKitSCM.sol b/packages/modulekit/src/test/ModuleKitSCM.sol similarity index 100% rename from src/test/ModuleKitSCM.sol rename to packages/modulekit/src/test/ModuleKitSCM.sol diff --git a/src/test/ModuleKitUserOp.sol b/packages/modulekit/src/test/ModuleKitUserOp.sol similarity index 100% rename from src/test/ModuleKitUserOp.sol rename to packages/modulekit/src/test/ModuleKitUserOp.sol diff --git a/packages/modulekit/src/test/RhinestoneModuleKit.sol b/packages/modulekit/src/test/RhinestoneModuleKit.sol new file mode 100644 index 00000000..355f911d --- /dev/null +++ b/packages/modulekit/src/test/RhinestoneModuleKit.sol @@ -0,0 +1,251 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.23; + +import { Auxiliary, AuxiliaryFactory } from "./Auxiliary.sol"; +import { PackedUserOperation, IEntryPoint, IStakeManager } from "../external/ERC4337.sol"; +import { ERC7579Helpers, BootstrapUtil } from "./utils/ERC7579Helpers.sol"; +import { ENTRYPOINT_ADDR } from "./predeploy/EntryPoint.sol"; + +import { + ERC7579BootstrapConfig, + IERC7579Account, + ERC7579Account, + ERC7579AccountFactory, + IERC7579Validator +} from "../external/ERC7579.sol"; + +import { ModuleKitUserOp } from "./ModuleKitUserOp.sol"; +import { ModuleKitHelpers } from "./ModuleKitHelpers.sol"; +import { MockValidator } from "../Mocks.sol"; + +import "./utils/Vm.sol"; +import "./utils/ModuleKitCache.sol"; +import "./utils/Log.sol"; + +struct AccountInstance { + address account; + Auxiliary aux; + IERC7579Validator defaultValidator; + bytes32 salt; + bytes initCode; + bool gasLog; +} + +struct UserOpData { + PackedUserOperation userOp; + bytes32 userOpHash; +} + +contract RhinestoneModuleKit is AuxiliaryFactory { + ERC7579AccountFactory public accountFactory; + IERC7579Account public accountImplementationSingleton; + + bool internal isInit; + + MockValidator public defaultValidator; + + constructor() { + init(); + } + + /** + * Initializes Auxiliary and /src/core + * This function will run before any accounts can be created + */ + function init() internal virtual override { + if (!isInit) { + super.init(); + isInit = true; + } + + isInit = true; + + // Deploy default contracts + accountImplementationSingleton = new ERC7579Account(); + label(address(accountImplementationSingleton), "ERC7579AccountImpl"); + accountFactory = new ERC7579AccountFactory(address(accountImplementationSingleton)); + label(address(accountFactory), "ERC7579AccountFactory"); + defaultValidator = new MockValidator(); + label(address(defaultValidator), "DefaultValidator"); + + // Stake factory on EntryPoint + deal(address(accountFactory), 10 ether); + prank(address(accountFactory)); + IStakeManager(ENTRYPOINT_ADDR).addStake{ value: 10 ether }(100_000); + } + + /** + * create new AccountInstance with initCode + * @param salt account salt / name + * @param counterFactualAddress of the account + * @param initCode4337 to be added to userOp:initCode + */ + function makeAccountInstance( + bytes32 salt, + address counterFactualAddress, + bytes memory initCode4337 + ) + internal + returns (AccountInstance memory instance) + { + // Create AccountInstance struct with counterFactualAddress and initCode + // The initcode will be set to 0, once the account was created by EntryPoint.sol + instance = AccountInstance({ + account: counterFactualAddress, + aux: auxiliary, + salt: salt, + defaultValidator: IERC7579Validator(address(defaultValidator)), + initCode: initCode4337, + gasLog: false + }); + + ModuleKitCache.logEntrypoint(instance.account, auxiliary.entrypoint); + } + + /** + * create new AccountInstance with ERC7579BootstrapConfig + * + * @param salt account salt / name + * @param validators ERC7549 validators to be installed on the account + * @param executors ERC7549 executors to be installed on the account + * @param hook ERC7549 hook to be installed on the account + * @param fallBack ERC7549 fallbackHandler to be installed on the account + */ + function makeAccountInstance( + bytes32 salt, + ERC7579BootstrapConfig[] memory validators, + ERC7579BootstrapConfig[] memory executors, + ERC7579BootstrapConfig memory hook, + ERC7579BootstrapConfig memory fallBack + ) + internal + returns (AccountInstance memory instance) + { + init(); + + if (validators.length == 0) validators = new ERC7579BootstrapConfig[](1); + + // inject the defaultValidator if it is not already in the list + // defaultValidator is used a lot in ModuleKit, to make it easier to use + // if defaultValidator isnt available on the account, a lot of ModuleKit Abstractions would + // break + if (validators[0].module != address(0) && validators[0].module != address(defaultValidator)) + { + ERC7579BootstrapConfig[] memory _validators = + new ERC7579BootstrapConfig[](validators.length + 1); + _validators[0] = ERC7579BootstrapConfig({ module: address(defaultValidator), data: "" }); + for (uint256 i = 0; i < validators.length; i++) { + _validators[i + 1] = validators[i]; + } + validators = _validators; + } + + bytes memory bootstrapCalldata = + auxiliary.bootstrap._getInitMSACalldata(validators, executors, hook, fallBack); + address account = accountFactory.getAddress(salt, bootstrapCalldata); + + // using MSAFactory from ERC7579 repo. + bytes memory createAccountOnFactory = + abi.encodeCall(accountFactory.createAccount, (salt, bootstrapCalldata)); + + address factory = address(accountFactory); + // encode pack factory and account initCode to comply with SenderCreater (EntryPoint.sol) + bytes memory initCode4337 = abi.encodePacked(factory, createAccountOnFactory); + label(address(account), bytes32ToString(salt)); + deal(account, 1 ether); + + instance = makeAccountInstance(salt, account, initCode4337); + } + + /** + * create new AccountInstance with modulekit defaults + * + * @param salt account salt / name + */ + function makeAccountInstance(bytes32 salt) internal returns (AccountInstance memory instance) { + init(); + ERC7579BootstrapConfig[] memory validators = + makeBootstrapConfig(address(defaultValidator), ""); + + ERC7579BootstrapConfig[] memory executors = _emptyConfigs(); + + ERC7579BootstrapConfig memory hook = _emptyConfig(); + + ERC7579BootstrapConfig memory fallBack = _emptyConfig(); + instance = makeAccountInstance(salt, validators, executors, hook, fallBack); + } + + function makeAccountInstance( + bytes32 salt, + address account, + address defaultValidator, + bytes memory initCode + ) + internal + returns (AccountInstance memory instance) + { + init(); + + instance = AccountInstance({ + account: account, + aux: auxiliary, + salt: salt, + defaultValidator: IERC7579Validator(address(defaultValidator)), + initCode: initCode, + gasLog: false + }); + + ModuleKitCache.logEntrypoint(instance.account, auxiliary.entrypoint); + } + + function bytes32ToString(bytes32 _bytes32) public pure returns (string memory) { + bytes memory _bytes = new bytes(32); + for (uint256 i = 0; i < 32; i++) { + _bytes[i] = _bytes32[i]; + } + return string(_bytes); + } + + function _emptyConfig() internal pure returns (ERC7579BootstrapConfig memory config) { } + function _emptyConfigs() internal pure returns (ERC7579BootstrapConfig[] memory config) { } + + function _makeBootstrapConfig( + address module, + bytes memory data + ) + public + pure + returns (ERC7579BootstrapConfig memory config) + { + config.module = module; + config.data = data; + } + + function makeBootstrapConfig( + address module, + bytes memory data + ) + public + pure + returns (ERC7579BootstrapConfig[] memory config) + { + config = new ERC7579BootstrapConfig[](1); + config[0].module = module; + config[0].data = data; + } + + function makeBootstrapConfig( + address[] memory modules, + bytes[] memory datas + ) + public + pure + returns (ERC7579BootstrapConfig[] memory configs) + { + configs = new ERC7579BootstrapConfig[](modules.length); + + for (uint256 i; i < modules.length; i++) { + configs[i] = _makeBootstrapConfig(modules[i], datas[i]); + } + } +} diff --git a/src/test/RhinestoneModuleKit.sol b/packages/modulekit/src/test/RhinestoneModuleKit.sol.bak similarity index 100% rename from src/test/RhinestoneModuleKit.sol rename to packages/modulekit/src/test/RhinestoneModuleKit.sol.bak diff --git a/src/test/predeploy/EntryPoint.sol b/packages/modulekit/src/test/predeploy/EntryPoint.sol similarity index 100% rename from src/test/predeploy/EntryPoint.sol rename to packages/modulekit/src/test/predeploy/EntryPoint.sol diff --git a/src/test/predeploy/MockFactory.sol b/packages/modulekit/src/test/predeploy/MockFactory.sol similarity index 100% rename from src/test/predeploy/MockFactory.sol rename to packages/modulekit/src/test/predeploy/MockFactory.sol diff --git a/src/test/predeploy/SessionKeyManager.sol b/packages/modulekit/src/test/predeploy/SessionKeyManager.sol similarity index 100% rename from src/test/predeploy/SessionKeyManager.sol rename to packages/modulekit/src/test/predeploy/SessionKeyManager.sol diff --git a/src/test/utils/ERC4337Helpers.sol b/packages/modulekit/src/test/utils/ERC4337Helpers.sol similarity index 100% rename from src/test/utils/ERC4337Helpers.sol rename to packages/modulekit/src/test/utils/ERC4337Helpers.sol diff --git a/src/test/utils/ERC7579Helpers.sol b/packages/modulekit/src/test/utils/ERC7579Helpers.sol similarity index 100% rename from src/test/utils/ERC7579Helpers.sol rename to packages/modulekit/src/test/utils/ERC7579Helpers.sol diff --git a/src/test/utils/GasCalculations.sol b/packages/modulekit/src/test/utils/GasCalculations.sol similarity index 100% rename from src/test/utils/GasCalculations.sol rename to packages/modulekit/src/test/utils/GasCalculations.sol diff --git a/src/test/utils/Log.sol b/packages/modulekit/src/test/utils/Log.sol similarity index 100% rename from src/test/utils/Log.sol rename to packages/modulekit/src/test/utils/Log.sol diff --git a/src/test/utils/ModuleKitCache.sol b/packages/modulekit/src/test/utils/ModuleKitCache.sol similarity index 100% rename from src/test/utils/ModuleKitCache.sol rename to packages/modulekit/src/test/utils/ModuleKitCache.sol diff --git a/src/test/utils/Vm.sol b/packages/modulekit/src/test/utils/Vm.sol similarity index 100% rename from src/test/utils/Vm.sol rename to packages/modulekit/src/test/utils/Vm.sol diff --git a/test/LicenseManager.t.sol.bak b/packages/modulekit/test/LicenseManager.t.sol.bak similarity index 100% rename from test/LicenseManager.t.sol.bak rename to packages/modulekit/test/LicenseManager.t.sol.bak diff --git a/test/SessionValidator.t.sol.bak b/packages/modulekit/test/SessionValidator.t.sol.bak similarity index 100% rename from test/SessionValidator.t.sol.bak rename to packages/modulekit/test/SessionValidator.t.sol.bak diff --git a/test/SessionValidator.t.sol.bak2 b/packages/modulekit/test/SessionValidator.t.sol.bak2 similarity index 100% rename from test/SessionValidator.t.sol.bak2 rename to packages/modulekit/test/SessionValidator.t.sol.bak2 diff --git a/test/ValidatorUtils.t.sol.bak b/packages/modulekit/test/ValidatorUtils.t.sol.bak similarity index 100% rename from test/ValidatorUtils.t.sol.bak rename to packages/modulekit/test/ValidatorUtils.t.sol.bak diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6f41b3f6..2e337280 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,51 +8,18 @@ importers: .: devDependencies: - '@ERC4337/account-abstraction': - specifier: github:kopy-kat/account-abstraction#develop - version: github.com/kopy-kat/account-abstraction/aafae2a1f974e4c05f7025b3303d0d4aba85fa76(ethers@5.4.0)(hardhat@2.20.1)(lodash@4.17.21)(typechain@5.2.0) - '@ERC4337/account-abstraction-v0.6': - specifier: github:eth-infinitism/account-abstraction#v0.6.0 - version: github.com/eth-infinitism/account-abstraction/7174d6d845618dbd11cee68eefa715f5263690b6(ethers@5.4.0)(hardhat@2.20.1)(lodash@4.17.21)(typechain@5.2.0) - '@openzeppelin/contracts': - specifier: 5.0.1 - version: 5.0.1 - '@prb/math': - specifier: ^4.0.2 - version: 4.0.2 + '@rhinestone/modulekit': + specifier: workspace:* + version: link:packages/modulekit '@rhinestone/safe7579': specifier: workspace:* version: link:accounts/safe7579 '@rhinestone/sessionkeymanager': specifier: workspace:* version: link:packages/SessionKeyManager - '@safe-global/safe-contracts': - specifier: ^1.4.1 - version: 1.4.1(ethers@5.4.0) - ds-test: - specifier: github:dapphub/ds-test - version: github.com/dapphub/ds-test/e282159d5170298eb2455a6c05280ab5a73a4ef0 - erc4337-validation: - specifier: github:rhinestonewtf/erc4337-validation - version: github.com/rhinestonewtf/erc4337-validation/19a97d86f8f29709664334078925b2a843be19e0 - erc7579: - specifier: github:erc7579/erc7579-implementation - version: github.com/erc7579/erc7579-implementation/be581c908df73f1554f466cb6b47c8ce8777e50f - forge-std: - specifier: github:foundry-rs/forge-std - version: github.com/foundry-rs/forge-std/1d0766bc5d814f117c7b1e643828f7d85024fb51 prettier: specifier: ^2.8.8 version: 2.8.8 - sentinellist: - specifier: github:zeroknots/sentinellist - version: github.com/zeroknots/sentinellist/1f9ec0250f1b3f14ba5d200629e3d9f3264fde61 - solady: - specifier: github:vectorized/solady - version: github.com/vectorized/solady/9deb9ed36a27261a8745db5b7cd7f4cdc3b1cd4e - solarray: - specifier: github:sablier-labs/solarray - version: github.com/sablier-labs/solarray/6bf10cb34cdace52a3ba5fe437e78cc82df92684 solhint: specifier: ^4.1.1 version: 4.1.1(typescript@5.3.3) @@ -73,7 +40,7 @@ importers: version: 4.0.2 '@rhinestone/modulekit': specifier: workspace:* - version: link:../.. + version: link:../../packages/modulekit '@rhinestone/sessionkeymanager': specifier: workspace:* version: link:../../packages/SessionKeyManager @@ -127,7 +94,7 @@ importers: version: 4.0.2 '@rhinestone/modulekit': specifier: workspace:* - version: link:.. + version: link:../packages/modulekit '@rhinestone/sessionkeymanager': specifier: workspace:* version: link:../packages/SessionKeyManager @@ -162,32 +129,23 @@ importers: specifier: github:transmissions11/solmate version: github.com/transmissions11/solmate/c892309933b25c03d32b1b0d674df7ae292ba925 - packages/AccountFactory: + packages/SessionKeyManager: devDependencies: '@ERC4337/account-abstraction': specifier: github:kopy-kat/account-abstraction#develop - version: github.com/kopy-kat/account-abstraction/aafae2a1f974e4c05f7025b3303d0d4aba85fa76(ethers@5.4.0)(hardhat@2.20.1)(lodash@4.17.21)(typechain@5.2.0) + version: github.com/kopy-kat/account-abstraction/aafae2a1f974e4c05f7025b3303d0d4aba85fa76(ethers@5.7.2)(hardhat@2.20.1)(lodash@4.17.21)(typechain@5.2.0) '@ERC4337/account-abstraction-v0.6': specifier: github:eth-infinitism/account-abstraction#v0.6.0 - version: github.com/eth-infinitism/account-abstraction/7174d6d845618dbd11cee68eefa715f5263690b6(ethers@5.4.0)(hardhat@2.20.1)(lodash@4.17.21)(typechain@5.2.0) - '@openzeppelin/contracts': - specifier: 5.0.1 - version: 5.0.1 + version: github.com/eth-infinitism/account-abstraction/7174d6d845618dbd11cee68eefa715f5263690b6(ethers@5.7.2)(hardhat@2.20.1)(lodash@4.17.21)(typechain@5.2.0) '@rhinestone/modulekit': specifier: workspace:* - version: link:../.. - '@rhinestone/safe7579': - specifier: workspace:* - version: link:../../accounts/safe7579 - '@safe-global/safe-contracts': - specifier: ^1.4.1 - version: 1.4.1(ethers@5.4.0) + version: link:../modulekit ds-test: specifier: github:dapphub/ds-test version: github.com/dapphub/ds-test/e282159d5170298eb2455a6c05280ab5a73a4ef0 erc7579: specifier: github:erc7579/erc7579-implementation - version: github.com/erc7579/erc7579-implementation/957cd05deeab6a9a85343bb8d1c9701705ed4ecf + version: github.com/erc7579/erc7579-implementation/be581c908df73f1554f466cb6b47c8ce8777e50f forge-std: specifier: github:foundry-rs/forge-std version: github.com/foundry-rs/forge-std/1d0766bc5d814f117c7b1e643828f7d85024fb51 @@ -199,28 +157,43 @@ importers: version: github.com/zeroknots/sentinellist/1f9ec0250f1b3f14ba5d200629e3d9f3264fde61 solady: specifier: github:vectorized/solady - version: github.com/vectorized/solady/1372606383445c0a247e6c58eb255a529734258a + version: github.com/vectorized/solady/9deb9ed36a27261a8745db5b7cd7f4cdc3b1cd4e solhint: specifier: ^4.1.1 version: 4.1.1(typescript@5.3.3) - packages/SessionKeyManager: + packages/modulekit: devDependencies: '@ERC4337/account-abstraction': specifier: github:kopy-kat/account-abstraction#develop - version: github.com/kopy-kat/account-abstraction/aafae2a1f974e4c05f7025b3303d0d4aba85fa76(ethers@5.7.2)(hardhat@2.20.1)(lodash@4.17.21)(typechain@5.2.0) + version: github.com/kopy-kat/account-abstraction/aafae2a1f974e4c05f7025b3303d0d4aba85fa76(ethers@5.4.0)(hardhat@2.20.1)(lodash@4.17.21)(typechain@5.2.0) '@ERC4337/account-abstraction-v0.6': specifier: github:eth-infinitism/account-abstraction#v0.6.0 - version: github.com/eth-infinitism/account-abstraction/7174d6d845618dbd11cee68eefa715f5263690b6(ethers@5.7.2)(hardhat@2.20.1)(lodash@4.17.21)(typechain@5.2.0) - '@rhinestone/modulekit': + version: github.com/eth-infinitism/account-abstraction/7174d6d845618dbd11cee68eefa715f5263690b6(ethers@5.4.0)(hardhat@2.20.1)(lodash@4.17.21)(typechain@5.2.0) + '@openzeppelin/contracts': + specifier: 5.0.1 + version: 5.0.1 + '@prb/math': + specifier: ^4.0.2 + version: 4.0.2 + '@rhinestone/safe7579': specifier: workspace:* - version: link:../.. + version: link:../../accounts/safe7579 + '@rhinestone/sessionkeymanager': + specifier: workspace:* + version: link:../SessionKeyManager + '@safe-global/safe-contracts': + specifier: ^1.4.1 + version: 1.4.1(ethers@5.4.0) ds-test: specifier: github:dapphub/ds-test version: github.com/dapphub/ds-test/e282159d5170298eb2455a6c05280ab5a73a4ef0 + erc4337-validation: + specifier: github:rhinestonewtf/erc4337-validation + version: github.com/rhinestonewtf/erc4337-validation/19a97d86f8f29709664334078925b2a843be19e0 erc7579: specifier: github:erc7579/erc7579-implementation - version: github.com/erc7579/erc7579-implementation/be581c908df73f1554f466cb6b47c8ce8777e50f + version: github.com/erc7579/erc7579-implementation/957cd05deeab6a9a85343bb8d1c9701705ed4ecf forge-std: specifier: github:foundry-rs/forge-std version: github.com/foundry-rs/forge-std/1d0766bc5d814f117c7b1e643828f7d85024fb51 @@ -232,7 +205,10 @@ importers: version: github.com/zeroknots/sentinellist/1f9ec0250f1b3f14ba5d200629e3d9f3264fde61 solady: specifier: github:vectorized/solady - version: github.com/vectorized/solady/9deb9ed36a27261a8745db5b7cd7f4cdc3b1cd4e + version: github.com/vectorized/solady/1372606383445c0a247e6c58eb255a529734258a + solarray: + specifier: github:sablier-labs/solarray + version: github.com/sablier-labs/solarray/6bf10cb34cdace52a3ba5fe437e78cc82df92684 solhint: specifier: ^4.1.1 version: 4.1.1(typescript@5.3.3) From 3c650b4ac6a90fad3c4c41619e083a6fa15d43b4 Mon Sep 17 00:00:00 2001 From: zeroknots Date: Tue, 20 Feb 2024 14:42:36 +0700 Subject: [PATCH 3/8] works --- accounts/safe7579/src/SafeERC7579.sol | 4 + .../accountFactory/MultiAccountFactory.sol | 65 +++- .../referenceImpl/RefImplFactory.sol | 11 +- .../{Bootstrap.sol => BootstrapSafe.sol} | 22 +- .../safe7579/Safe7579Factory.sol | 43 ++- .../src/test/RhinestoneModuleKit.sol | 26 +- packages/modulekit/test/Diff.t.sol | 324 ++++++++++++++++++ packages/modulekit/test/MakeAccount.t.sol | 36 ++ 8 files changed, 490 insertions(+), 41 deletions(-) rename packages/modulekit/src/accountFactory/safe7579/{Bootstrap.sol => BootstrapSafe.sol} (77%) create mode 100644 packages/modulekit/test/Diff.t.sol create mode 100644 packages/modulekit/test/MakeAccount.t.sol diff --git a/accounts/safe7579/src/SafeERC7579.sol b/accounts/safe7579/src/SafeERC7579.sol index 51913f6e..6cb3f374 100644 --- a/accounts/safe7579/src/SafeERC7579.sol +++ b/accounts/safe7579/src/SafeERC7579.sol @@ -25,6 +25,8 @@ import { } from "@ERC4337/account-abstraction/contracts/core/UserOperationLib.sol"; import { _packValidationData } from "@ERC4337/account-abstraction/contracts/core/Helpers.sol"; +import "forge-std/console2.sol"; + /** * @title ERC7579 Adapter for Safe accounts. * By using Safe's Fallback and Execution modules, @@ -358,6 +360,8 @@ contract SafeERC7579 is _initModuleManager(); (address bootstrap, bytes memory bootstrapCall) = abi.decode(data, (address, bytes)); + console2.log("bootstrap: ", bootstrap); + (bool success,) = bootstrap.delegatecall(bootstrapCall); if (!success) revert AccountInitializationFailed(); } diff --git a/packages/modulekit/src/accountFactory/MultiAccountFactory.sol b/packages/modulekit/src/accountFactory/MultiAccountFactory.sol index 2f9a5c71..69f82a6b 100644 --- a/packages/modulekit/src/accountFactory/MultiAccountFactory.sol +++ b/packages/modulekit/src/accountFactory/MultiAccountFactory.sol @@ -1,6 +1,7 @@ import "forge-std/Base.sol"; import "./safe7579/Safe7579Factory.sol"; import "./referenceImpl/RefImplFactory.sol"; +import { ERC7579BootstrapConfig } from "../external/ERC7579.sol"; enum AccountType { DEFAULT, @@ -23,7 +24,13 @@ contract MultiAccountFactory is TestBase, Safe7579Factory, RefImplFactory { } } - function makeAccount(bytes32 salt, bytes calldata initCode) public returns (address account) { + function createAccount( + bytes32 salt, + bytes calldata initCode + ) + public + returns (address account) + { if (env == AccountType.SAFE7579) { return _makeSafe(salt, initCode); } else { @@ -36,6 +43,60 @@ contract MultiAccountFactory is TestBase, Safe7579Factory, RefImplFactory { } function _makeSafe(bytes32 salt, bytes calldata initCode) public returns (address) { - return _createSafe(address(erc7579Mod), initCode); + return _createSafe(salt, initCode); + } + + function getAddress( + bytes32 salt, + bytes memory initCode + ) + public + view + virtual + returns (address) + { + if (env == AccountType.SAFE7579) { + return getAddressSafe(salt, initCode); + } else { + return getAddressUMSA(salt, initCode); + } + } + + function _getSalt( + bytes32 _salt, + bytes memory initCode + ) + public + pure + virtual + override(RefImplFactory, Safe7579Factory) + returns (bytes32 salt) + { + salt = keccak256(abi.encodePacked(_salt, initCode)); + } + + function getBootstrapCallData( + ERC7579BootstrapConfig[] calldata _validators, + ERC7579BootstrapConfig[] calldata _executors, + ERC7579BootstrapConfig calldata _hook, + ERC7579BootstrapConfig calldata _fallback + ) + external + view + returns (bytes memory init) + { + if (env == AccountType.SAFE7579) { + init = abi.encode( + address(bootstrapSafe), + abi.encodeCall( + ERC7579Bootstrap.initMSA, (_validators, _executors, _hook, _fallback) + ) + ); + } else { + init = abi.encode( + address(bootstrapDefault), + abi.encodeCall(BootstrapSafe.initMSA, (_validators, _executors, _hook, _fallback)) + ); + } } } diff --git a/packages/modulekit/src/accountFactory/referenceImpl/RefImplFactory.sol b/packages/modulekit/src/accountFactory/referenceImpl/RefImplFactory.sol index 0927b913..a0be61cd 100644 --- a/packages/modulekit/src/accountFactory/referenceImpl/RefImplFactory.sol +++ b/packages/modulekit/src/accountFactory/referenceImpl/RefImplFactory.sol @@ -5,11 +5,13 @@ interface IMSA { function initializeAccount(bytes calldata initCode) external; } -contract RefImplFactory { +abstract contract RefImplFactory { ERC7579Account internal implementation; + ERC7579Bootstrap internal bootstrapDefault; constructor() { implementation = new ERC7579Account(); + bootstrapDefault = new ERC7579Bootstrap(); } function _createUMSA(bytes32 salt, bytes memory initCode) public returns (address account) { @@ -20,7 +22,7 @@ contract RefImplFactory { return account; } - function getAddress( + function getAddressUMSA( bytes32 salt, bytes memory initCode ) @@ -42,8 +44,5 @@ contract RefImplFactory { public pure virtual - returns (bytes32 salt) - { - salt = keccak256(abi.encodePacked(_salt, initCode)); - } + returns (bytes32 salt); } diff --git a/packages/modulekit/src/accountFactory/safe7579/Bootstrap.sol b/packages/modulekit/src/accountFactory/safe7579/BootstrapSafe.sol similarity index 77% rename from packages/modulekit/src/accountFactory/safe7579/Bootstrap.sol rename to packages/modulekit/src/accountFactory/safe7579/BootstrapSafe.sol index 07b30f49..5794398c 100644 --- a/packages/modulekit/src/accountFactory/safe7579/Bootstrap.sol +++ b/packages/modulekit/src/accountFactory/safe7579/BootstrapSafe.sol @@ -6,12 +6,8 @@ import "@rhinestone/safe7579/src/core/HookManager.sol"; import "../../external/ERC7579.sol"; -struct BootstrapConfig { - address module; - bytes data; -} -contract Bootstrap is ModuleManager, HookManager { +contract BootstrapSafe is ModuleManager, HookManager { function singleInitMSA(IERC7579Validator validator, bytes calldata data) external { // init validator _installValidator(address(validator), data); @@ -23,10 +19,10 @@ contract Bootstrap is ModuleManager, HookManager { * calling this function */ function initMSA( - BootstrapConfig[] calldata _validators, - BootstrapConfig[] calldata _executors, - BootstrapConfig calldata _hook, - BootstrapConfig calldata _fallback + ERC7579BootstrapConfig[] calldata _validators, + ERC7579BootstrapConfig[] calldata _executors, + ERC7579BootstrapConfig calldata _hook, + ERC7579BootstrapConfig calldata _fallback ) external { @@ -53,10 +49,10 @@ contract Bootstrap is ModuleManager, HookManager { } function _getInitMSACalldata( - BootstrapConfig[] calldata _validators, - BootstrapConfig[] calldata _executors, - BootstrapConfig calldata _hook, - BootstrapConfig calldata _fallback + ERC7579BootstrapConfig[] calldata _validators, + ERC7579BootstrapConfig[] calldata _executors, + ERC7579BootstrapConfig calldata _hook, + ERC7579BootstrapConfig calldata _fallback ) external view diff --git a/packages/modulekit/src/accountFactory/safe7579/Safe7579Factory.sol b/packages/modulekit/src/accountFactory/safe7579/Safe7579Factory.sol index 05965093..1d2a157d 100644 --- a/packages/modulekit/src/accountFactory/safe7579/Safe7579Factory.sol +++ b/packages/modulekit/src/accountFactory/safe7579/Safe7579Factory.sol @@ -6,31 +6,27 @@ import { SafeERC7579 } from "@rhinestone/safe7579/src/SafeERC7579.sol"; import "@safe-global/safe-contracts/contracts/Safe.sol"; import { LibClone } from "solady/src/utils/LibClone.sol"; -import { Bootstrap } from "./Bootstrap.sol"; +import { BootstrapSafe } from "./BootstrapSafe.sol"; -contract Safe7579Factory is TestBase { +abstract contract Safe7579Factory is TestBase { // singletons SafeERC7579 internal erc7579Mod; Safe internal safeImpl; - Bootstrap internal bootstrap; + BootstrapSafe internal bootstrapSafe; constructor() { // Set up MSA and Factory erc7579Mod = new SafeERC7579(); safeImpl = new Safe(); - bootstrap = new Bootstrap(); + bootstrapSafe = new BootstrapSafe(); } - function _createSafe( - address defaultValidator, - bytes calldata initCode - ) - internal - returns (address safe) - { - Safe clone = Safe(payable(LibClone.clone(address(safeImpl)))); + function _createSafe(bytes32 salt, bytes calldata initCode) internal returns (address safe) { + bytes32 _salt = _getSalt(salt, initCode); + Safe clone = + Safe(payable(LibClone.cloneDeterministic(0, address(safeImpl), initCode, _salt))); address[] memory signers = new address[](2); signers[0] = address(0x12345); @@ -54,4 +50,27 @@ contract Safe7579Factory is TestBase { return address(clone); } + + function getAddressSafe( + bytes32 salt, + bytes memory initCode + ) + public + view + virtual + returns (address) + { + bytes32 _salt = _getSalt(salt, initCode); + return + LibClone.predictDeterministicAddress(address(safeImpl), initCode, _salt, address(this)); + } + + function _getSalt( + bytes32 _salt, + bytes memory initCode + ) + public + pure + virtual + returns (bytes32 salt); } diff --git a/packages/modulekit/src/test/RhinestoneModuleKit.sol b/packages/modulekit/src/test/RhinestoneModuleKit.sol index 355f911d..2aeff995 100644 --- a/packages/modulekit/src/test/RhinestoneModuleKit.sol +++ b/packages/modulekit/src/test/RhinestoneModuleKit.sol @@ -2,6 +2,7 @@ pragma solidity ^0.8.23; import { Auxiliary, AuxiliaryFactory } from "./Auxiliary.sol"; +import { MultiAccountFactory } from "../accountFactory/MultiAccountFactory.sol"; import { PackedUserOperation, IEntryPoint, IStakeManager } from "../external/ERC4337.sol"; import { ERC7579Helpers, BootstrapUtil } from "./utils/ERC7579Helpers.sol"; import { ENTRYPOINT_ADDR } from "./predeploy/EntryPoint.sol"; @@ -22,6 +23,8 @@ import "./utils/Vm.sol"; import "./utils/ModuleKitCache.sol"; import "./utils/Log.sol"; +import "forge-std/console2.sol"; + struct AccountInstance { address account; Auxiliary aux; @@ -37,8 +40,10 @@ struct UserOpData { } contract RhinestoneModuleKit is AuxiliaryFactory { - ERC7579AccountFactory public accountFactory; - IERC7579Account public accountImplementationSingleton; + // ERC7579AccountFactory public accountFactory; + // IERC7579Account public accountImplementationSingleton; + + MultiAccountFactory public accountFactory; bool internal isInit; @@ -60,11 +65,13 @@ contract RhinestoneModuleKit is AuxiliaryFactory { isInit = true; - // Deploy default contracts - accountImplementationSingleton = new ERC7579Account(); - label(address(accountImplementationSingleton), "ERC7579AccountImpl"); - accountFactory = new ERC7579AccountFactory(address(accountImplementationSingleton)); - label(address(accountFactory), "ERC7579AccountFactory"); + // // Deploy default contracts + // accountImplementationSingleton = new ERC7579Account(); + // label(address(accountImplementationSingleton), "ERC7579AccountImpl"); + // accountFactory = new ERC7579AccountFactory(address(accountImplementationSingleton)); + // label(address(accountFactory), "ERC7579AccountFactory"); + + accountFactory = new MultiAccountFactory(); defaultValidator = new MockValidator(); label(address(defaultValidator), "DefaultValidator"); @@ -140,9 +147,12 @@ contract RhinestoneModuleKit is AuxiliaryFactory { validators = _validators; } + // bytes memory bootstrapCalldata = + // auxiliary.bootstrap._getInitMSACalldata(validators, executors, hook, fallBack); bytes memory bootstrapCalldata = - auxiliary.bootstrap._getInitMSACalldata(validators, executors, hook, fallBack); + accountFactory.getBootstrapCallData(validators, executors, hook, fallBack); address account = accountFactory.getAddress(salt, bootstrapCalldata); + console2.log("Account address: ", account); // using MSAFactory from ERC7579 repo. bytes memory createAccountOnFactory = diff --git a/packages/modulekit/test/Diff.t.sol b/packages/modulekit/test/Diff.t.sol new file mode 100644 index 00000000..56b9e9f8 --- /dev/null +++ b/packages/modulekit/test/Diff.t.sol @@ -0,0 +1,324 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.23; + +/* solhint-disable no-global-import */ +import "src/ModuleKit.sol"; +import "./MakeAccount.t.sol"; +import "src/Mocks.sol"; +import { writeSimulateUserOp } from "src/test/utils/Log.sol"; +import { + MODULE_TYPE_VALIDATOR, MODULE_TYPE_EXECUTOR, MODULE_TYPE_HOOK +} from "src/external/ERC7579.sol"; +/* solhint-enable no-global-import */ + +contract ERC7579DifferentialModuleKitLibTest is BaseTest { + using ModuleKitHelpers for *; + using ModuleKitUserOp for *; + + MockValidator internal validator; + MockHook internal hook; + MockExecutor internal executor; + MockTarget internal mockTarget; + + MockERC20 internal token; + + function setUp() public override { + super.setUp(); + // Setup account + instance = makeAccountInstance("1"); + + // Setup modules + validator = new MockValidator(); + hook = new MockHook(); + executor = new MockExecutor(); + mockTarget = new MockTarget(); + + // Setup aux + token = new MockERC20(); + token.initialize("Mock Token", "MTK", 18); + deal(address(token), instance.account, 100 ether); + vm.deal(instance.account, 1000 ether); + } + + // function fund() internal { + // for (uint256 i; i < diffAccounts.length; i++) { + // instance = diffAccounts[i]; + // deal(address(token), instance.account, 100 ether); + // vm.deal(instance.account, 1000 ether); + // } + // } + // + // modifier () { + // uint256 snapshot = vm.snapshot(); // saves the state + // for (uint256 i; i < diffAccounts.length; i++) { + // instance = diffAccounts[i]; + // _; + // vm.revertTo(snapshot); + // } + // } + + /*////////////////////////////////////////////////////////////////////////// + exec + //////////////////////////////////////////////////////////////////////////*/ + + function testexec__Given__TwoInputs() public { + // Create userOperation fields + address receiver = makeAddr("receiver"); + uint256 value = 10 gwei; + bytes memory callData = + abi.encodeWithSignature("transfer(address,uint256)", receiver, value); + + // Create userOperation + instance.exec({ target: address(token), callData: callData }); + + // Validate userOperation + assertEq(token.balanceOf(receiver), value, "Receiver should have 10 gwei in tokens"); + } + + function testexec__Given__ThreeInputs() public { + // Create userOperation fields + address receiver = makeAddr("receiver"); + uint256 value = 10 gwei; + bytes memory callData = ""; + + // Create userOperation + instance.exec({ target: receiver, value: value, callData: callData }); + + // Validate userOperation + assertEq(receiver.balance, value, "Receiver should have 10 gwei"); + } + + function testexec__Given__FourInputs() public { + // Create userOperation fields + address receiver = makeAddr("receiver"); + uint256 value = 10 gwei; + bytes memory callData = ""; + bytes memory signature = ""; + + // Create userOperation + instance.getExecOps({ + target: receiver, + value: value, + callData: callData, + txValidator: address(instance.defaultValidator) + }).execUserOps(); + + // Validate userOperation + assertEq(receiver.balance, value, "Receiver should have 10 gwei"); + } + + function testexec__RevertWhen__UserOperationFails() public { + // Create userOperation fields + bytes memory callData = abi.encodeWithSelector(MockTarget.setAccessControl.selector, 2); + + // Create userOperation + instance.expect4337Revert(); + instance.exec({ target: address(mockTarget), callData: callData, value: 0 }); + } + + /*////////////////////////////////////////////////////////////////////////// + MODULES + //////////////////////////////////////////////////////////////////////////*/ + + function testAddValidator() public { + address newValidator = address(new MockValidator()); + address newValidator1 = address(new MockValidator()); + vm.label(newValidator, "2nd validator"); + + instance.installModule({ + moduleTypeId: MODULE_TYPE_VALIDATOR, + module: newValidator, + data: "" + }); + // instance.log4337Gas("testAddValidator()"); + // instance.enableGasLog(); + instance.installModule({ + moduleTypeId: MODULE_TYPE_VALIDATOR, + module: newValidator1, + data: "" + }); + + bool validatorEnabled = instance.isModuleInstalled(MODULE_TYPE_VALIDATOR, newValidator); + assertTrue(validatorEnabled); + bool validator1Enabled = instance.isModuleInstalled(MODULE_TYPE_VALIDATOR, newValidator1); + assertTrue(validator1Enabled); + } + + function testRemoveValidator() public { + address newValidator = address(new MockValidator()); + instance.installModule({ + moduleTypeId: MODULE_TYPE_VALIDATOR, + module: newValidator, + data: "" + }); + bool validatorEnabled = instance.isModuleInstalled(MODULE_TYPE_VALIDATOR, newValidator); + assertTrue(validatorEnabled); + + instance.uninstallModule({ + moduleTypeId: MODULE_TYPE_VALIDATOR, + module: newValidator, + data: "" + }); + validatorEnabled = instance.isModuleInstalled(MODULE_TYPE_VALIDATOR, newValidator); + assertFalse(validatorEnabled); + } + + function testAddSessionKey() public { + // NOT IMPLEMENTED + // uint256 validUntil = block.timestamp + 1 days; + // uint256 validAfter = block.timestamp; + // address sessionValidationModule = address(validator); + // bytes memory sessionKeyData = ""; + // + // instance.addSessionKey({ + // validUntil: validUntil, + // validAfter: validAfter, + // sessionValidationModule: sessionValidationModule, + // sessionKeyData: sessionKeyData + // }); + // + // // Validate proof + // Merkle m = new Merkle(); + // + // bytes32 leaf = instance.aux.sessionKeyManager._sessionMerkelLeaf({ + // validUntil: validUntil, + // validAfter: validAfter, + // sessionValidationModule: sessionValidationModule, + // sessionKeyData: sessionKeyData + // }); + // + // bytes32[] memory leaves = new bytes32[](2); + // leaves[0] = leaf; + // leaves[1] = leaf; + // + // bytes32 root = + // instance.aux.sessionKeyManager.getSessionKeys(instance.account).merkleRoot; + // bytes32[] memory proof = m.getProof(leaves, 1); + // + // bool isValidProof = m.verifyProof(root, proof, leaf); + // + // assertTrue(isValidProof); + } + + function testAddHook() public { + instance.installModule({ moduleTypeId: MODULE_TYPE_HOOK, module: address(hook), data: "" }); + + bool hookEnabled = instance.isModuleInstalled(MODULE_TYPE_HOOK, address(hook)); + assertTrue(hookEnabled); + } + + function testAddExecutor() public { + address newExecutor = address(new MockExecutor()); + + instance.installModule({ moduleTypeId: MODULE_TYPE_EXECUTOR, module: newExecutor, data: "" }); + bool executorEnabled = instance.isModuleInstalled(MODULE_TYPE_EXECUTOR, newExecutor); + assertTrue(executorEnabled); + } + + function testRemoveExecutor() public { + address newExecutor = address(new MockExecutor()); + + instance.installModule({ moduleTypeId: MODULE_TYPE_EXECUTOR, module: newExecutor, data: "" }); + bool executorEnabled = instance.isModuleInstalled(MODULE_TYPE_EXECUTOR, newExecutor); + assertTrue(executorEnabled); + + instance.uninstallModule({ + moduleTypeId: MODULE_TYPE_EXECUTOR, + module: newExecutor, + data: "" + }); + executorEnabled = instance.isModuleInstalled(MODULE_TYPE_EXECUTOR, newExecutor); + assertFalse(executorEnabled); + } + + // function testSetCondition() public { + // address newExecutor = address(new MockExecutor()); + // instance.addExecutor(newExecutor); + // + // address mockCondition = address(new MockCondition()); + // ConditionConfig[] memory conditions = new ConditionConfig[](1); + // conditions[0] = ConditionConfig({ condition: ICondition(mockCondition), + // conditionData: "" + // }); + // + // bytes32 digest = + // instance.aux.compConditionManager._conditionDigest(conditions); + // + // instance.setCondition(newExecutor, conditions); + // + // bytes32 digestOnManager = + // instance.aux.compConditionManager.getHash(instance.account, newExecutor); + // assertEq(digest, digestOnManager); + // } + + // function testAddFallback() public { + // TokenReceiver handler = new TokenReceiver(); + // bytes4 functionSig = IERC721TokenReceiver.onERC721Received.selector; + // + // bytes memory callData = abi.encodeWithSelector( + // functionSig, makeAddr("foo"), makeAddr("foo"), uint256(1), bytes("foo") + // ); + // + // instance.addFallback({ + // handleFunctionSig: functionSig, + // isStatic: true, + // handler: address(handler) + // }); + // + // (bool success,) = instance.account.call(callData); + // assertTrue(success); + // } + + /*////////////////////////////////////////////////////////////////////////// + UTILS + //////////////////////////////////////////////////////////////////////////*/ + + function testGetUserOpHash() public { + // // Create userOperation fields + // address receiver = makeAddr("receiver"); + // uint256 value = 10 gwei; + // bytes memory callData = abi.encode(true); + // + // // Create userOperation hash using lib + // bytes32 userOpHash = + // instance.getUserOpHash({ target: receiver, value: value, callData: callData }); + // + // UserOperation memory userOp = + // instance.getFormattedUserOp({ target: receiver, value: value, callData: callData }); + // bytes32 entryPointUserOpHash = instance.aux.entrypoint.getUserOpHash(userOp); + // + // // Validate userOperation + // assertEq(userOpHash, entryPointUserOpHash); + } + + function testDeployAccount() public { + AccountInstance memory newInstance = makeAccountInstance("new"); + assertTrue(newInstance.account.code.length == 0); + + newInstance.deployAccount(); + + assertTrue(newInstance.account.code.length > 0); + } + + function testWriteGas() public { + string memory gasIdentifier = "testWriteGas"; + string memory rootDir = "gas_calculations"; + string memory fileName = string.concat(rootDir, "/", gasIdentifier, ".json"); + assertTrue(vm.isDir("gas_calculations")); + if (vm.isFile(fileName)) { + vm.removeFile(fileName); + } + assertFalse(vm.isFile(fileName)); + + vm.setEnv("GAS", "true"); + + instance.log4337Gas("testWriteGas"); + testexec__Given__TwoInputs(); + assertTrue(vm.isFile(fileName)); + } + + function testSimulateUserOp() public { + writeSimulateUserOp(true); + testexec__Given__TwoInputs(); + } +} diff --git a/packages/modulekit/test/MakeAccount.t.sol b/packages/modulekit/test/MakeAccount.t.sol new file mode 100644 index 00000000..14b79a53 --- /dev/null +++ b/packages/modulekit/test/MakeAccount.t.sol @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.23; + +/* solhint-disable no-global-import */ +import "forge-std/Test.sol"; +import "src/ModuleKit.sol"; +import "src/Accounts.sol"; +import "src/Mocks.sol"; +/* solhint-enable no-global-import */ + +contract BaseTest is RhinestoneModuleKit, Test { + using ModuleKitHelpers for AccountInstance; + + AccountInstance internal instance; + AccountInstance internal instanceSafe; + + address recipient; + + function setUp() public virtual { + instance = makeAccountInstance("1"); + + MockValidator defaultValidator = new MockValidator(); + MockExecutor defaultExecutor = new MockExecutor(); + vm.deal(instanceSafe.account, 1000 ether); + vm.deal(instance.account, 2 ether); + + recipient = makeAddr("recipient"); + } + + function test_transfer() public { + UserOpData memory data = instance.exec({ target: recipient, value: 1 ether, callData: "" }); + assertTrue(data.userOpHash != ""); + assertTrue(recipient.balance == 1 ether); + assertTrue(data.userOp.sender == instance.account); + } +} From 54a9a79110dae3ee048dc2d27dd6358ef1d40c57 Mon Sep 17 00:00:00 2001 From: zeroknots Date: Tue, 20 Feb 2024 14:49:55 +0700 Subject: [PATCH 4/8] fix gas calculations --- accounts/safe7579/test/Base.t.sol | 5 ----- examples/package.json | 2 ++ .../modulekit/gas_calculations/testWriteGas.json | 12 ++++++++++++ .../modulekit/src/accountFactory/MSAFactory.sol.bak | 0 pnpm-lock.yaml | 10 ++++++++-- 5 files changed, 22 insertions(+), 7 deletions(-) create mode 100644 packages/modulekit/gas_calculations/testWriteGas.json delete mode 100644 packages/modulekit/src/accountFactory/MSAFactory.sol.bak diff --git a/accounts/safe7579/test/Base.t.sol b/accounts/safe7579/test/Base.t.sol index 5bc41054..d0d4b458 100644 --- a/accounts/safe7579/test/Base.t.sol +++ b/accounts/safe7579/test/Base.t.sol @@ -70,11 +70,6 @@ contract TestBaseUtil is Test { vm.startPrank(address(clone)); clone.enableModule(address(erc7579Mod)); - address[] memory validators = new address[](1); - validators[0] = address(defaultValidator); - - address[] memory executors = new address[](1); - executors[0] = address(defaultExecutor); erc7579Mod.initializeAccount(abi.encode(validators, executors)); vm.stopPrank(); } diff --git a/examples/package.json b/examples/package.json index b797558d..d9c5dbf1 100644 --- a/examples/package.json +++ b/examples/package.json @@ -13,10 +13,12 @@ "devDependencies": { "@openzeppelin/contracts": "5.0.1", "@rhinestone/modulekit": "workspace:*", + "@rhinestone/safe7579": "workspace:*", "@rhinestone/sessionkeymanager": "workspace:*", "@prb/math": "^4.0.2", "erc4337-validation": "github:rhinestonewtf/erc4337-validation", "@ERC4337/account-abstraction": "github:kopy-kat/account-abstraction#develop", + "@safe-global/safe-contracts": "^1.4.1", "@ERC4337/account-abstraction-v0.6": "github:eth-infinitism/account-abstraction#v0.6.0", "forge-std": "github:foundry-rs/forge-std", "ds-test": "github:dapphub/ds-test", diff --git a/packages/modulekit/gas_calculations/testWriteGas.json b/packages/modulekit/gas_calculations/testWriteGas.json new file mode 100644 index 00000000..a0c00af0 --- /dev/null +++ b/packages/modulekit/gas_calculations/testWriteGas.json @@ -0,0 +1,12 @@ +{ + "Calldata": { + "Arbitrum": "6376 gas", + "OP-Stack": "8802 gas" + }, + "Phases": { + "Creation": "549886 gas", + "Execution": "41448 gas", + "Validation": "42835 gas" + }, + "Total": "2924474 gas" +} \ No newline at end of file diff --git a/packages/modulekit/src/accountFactory/MSAFactory.sol.bak b/packages/modulekit/src/accountFactory/MSAFactory.sol.bak deleted file mode 100644 index e69de29b..00000000 diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2e337280..85bafa51 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -82,10 +82,10 @@ importers: devDependencies: '@ERC4337/account-abstraction': specifier: github:kopy-kat/account-abstraction#develop - version: github.com/kopy-kat/account-abstraction/aafae2a1f974e4c05f7025b3303d0d4aba85fa76(ethers@5.7.2)(hardhat@2.20.1)(lodash@4.17.21)(typechain@5.2.0) + version: github.com/kopy-kat/account-abstraction/aafae2a1f974e4c05f7025b3303d0d4aba85fa76(ethers@5.4.0)(hardhat@2.20.1)(lodash@4.17.21)(typechain@5.2.0) '@ERC4337/account-abstraction-v0.6': specifier: github:eth-infinitism/account-abstraction#v0.6.0 - version: github.com/eth-infinitism/account-abstraction/7174d6d845618dbd11cee68eefa715f5263690b6(ethers@5.7.2)(hardhat@2.20.1)(lodash@4.17.21)(typechain@5.2.0) + version: github.com/eth-infinitism/account-abstraction/7174d6d845618dbd11cee68eefa715f5263690b6(ethers@5.4.0)(hardhat@2.20.1)(lodash@4.17.21)(typechain@5.2.0) '@openzeppelin/contracts': specifier: 5.0.1 version: 5.0.1 @@ -95,9 +95,15 @@ importers: '@rhinestone/modulekit': specifier: workspace:* version: link:../packages/modulekit + '@rhinestone/safe7579': + specifier: workspace:* + version: link:../accounts/safe7579 '@rhinestone/sessionkeymanager': specifier: workspace:* version: link:../packages/SessionKeyManager + '@safe-global/safe-contracts': + specifier: ^1.4.1 + version: 1.4.1(ethers@5.4.0) ds-test: specifier: github:dapphub/ds-test version: github.com/dapphub/ds-test/e282159d5170298eb2455a6c05280ab5a73a4ef0 From 3ae5239395492ee6428947d276aff8804d5ff3b4 Mon Sep 17 00:00:00 2001 From: zeroknots Date: Tue, 20 Feb 2024 15:10:07 +0700 Subject: [PATCH 5/8] fixed tests --- .../src/core/ValidatorStorageHelper.sol | 1 + accounts/safe7579/test/Base.t.sol | 29 +++++++++++++++++-- gas_calculations/.gitkeep | 0 .../accountFactory/safe7579/BootstrapSafe.sol | 1 - 4 files changed, 28 insertions(+), 3 deletions(-) delete mode 100644 gas_calculations/.gitkeep diff --git a/accounts/safe7579/src/core/ValidatorStorageHelper.sol b/accounts/safe7579/src/core/ValidatorStorageHelper.sol index 2db5bfe4..5be8995a 100644 --- a/accounts/safe7579/src/core/ValidatorStorageHelper.sol +++ b/accounts/safe7579/src/core/ValidatorStorageHelper.sol @@ -39,6 +39,7 @@ contract ValidatorStorageHelper { // Ensures that the functions are only interacted with via delegatecall modifier onlyDelegateCall() { + // TODO: // if (msg.sender != address(this)) revert Unauthorized(); _; } diff --git a/accounts/safe7579/test/Base.t.sol b/accounts/safe7579/test/Base.t.sol index d0d4b458..ad97493f 100644 --- a/accounts/safe7579/test/Base.t.sol +++ b/accounts/safe7579/test/Base.t.sol @@ -3,15 +3,31 @@ pragma solidity ^0.8.23; import "forge-std/Test.sol"; import { SafeERC7579 } from "src/SafeERC7579.sol"; +import { ModuleManager } from "src/core/ModuleManager.sol"; import { MockValidator } from "./mocks/MockValidator.sol"; import { MockExecutor } from "./mocks/MockExecutor.sol"; import { MockTarget } from "./mocks/MockTarget.sol"; -import "@safe-global/safe-contracts/contracts/Safe.sol"; +import { Safe } from "@safe-global/safe-contracts/contracts/Safe.sol"; import { LibClone } from "solady/src/utils/LibClone.sol"; import "./dependencies/EntryPoint.sol"; +contract Bootstrap is ModuleManager { + function singleInitMSA( + address validator, + bytes calldata validatorData, + address executor, + bytes calldata executorData + ) + external + { + // init validator + _installValidator(address(validator), validatorData); + _installExecutor(executor, executorData); + } +} + contract TestBaseUtil is Test { // singletons SafeERC7579 internal erc7579Mod; @@ -21,6 +37,7 @@ contract TestBaseUtil is Test { MockValidator internal defaultValidator; MockExecutor internal defaultExecutor; + Bootstrap internal bootstrap; MockTarget internal target; @@ -32,6 +49,7 @@ contract TestBaseUtil is Test { etchEntrypoint(); // Set up MSA and Factory + bootstrap = new Bootstrap(); erc7579Mod = new SafeERC7579(); safeImpl = new Safe(); @@ -70,7 +88,14 @@ contract TestBaseUtil is Test { vm.startPrank(address(clone)); clone.enableModule(address(erc7579Mod)); - erc7579Mod.initializeAccount(abi.encode(validators, executors)); + erc7579Mod.initializeAccount( + abi.encode( + address(bootstrap), + abi.encodeCall( + Bootstrap.singleInitMSA, (_defaultValidator, "", address(defaultExecutor), "") + ) + ) + ); vm.stopPrank(); } diff --git a/gas_calculations/.gitkeep b/gas_calculations/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/packages/modulekit/src/accountFactory/safe7579/BootstrapSafe.sol b/packages/modulekit/src/accountFactory/safe7579/BootstrapSafe.sol index 5794398c..73d00c2b 100644 --- a/packages/modulekit/src/accountFactory/safe7579/BootstrapSafe.sol +++ b/packages/modulekit/src/accountFactory/safe7579/BootstrapSafe.sol @@ -6,7 +6,6 @@ import "@rhinestone/safe7579/src/core/HookManager.sol"; import "../../external/ERC7579.sol"; - contract BootstrapSafe is ModuleManager, HookManager { function singleInitMSA(IERC7579Validator validator, bytes calldata data) external { // init validator From dfb252de3f552d3e600a6a646733b21110aace57 Mon Sep 17 00:00:00 2001 From: zeroknots Date: Tue, 20 Feb 2024 15:22:52 +0700 Subject: [PATCH 6/8] feat: implemented safe hook --- .gitignore | 2 +- accounts/safe7579/src/SafeERC7579.sol | 10 +--------- .../safe7579/src/core/ExecutionHelper.sol | 2 +- accounts/safe7579/src/core/HookManager.sol | 19 +++++++++++++++++-- accounts/safe7579/src/core/ModuleManager.sol | 3 ++- 5 files changed, 22 insertions(+), 14 deletions(-) diff --git a/.gitignore b/.gitignore index 63d07405..f0620b6b 100644 --- a/.gitignore +++ b/.gitignore @@ -7,7 +7,7 @@ out/ /broadcast/*/31337/ /broadcast/**/dry-run/ -gas_calculations/*.json +packages/modulekit/gas_calculations/*.json # Docs docs/ diff --git a/accounts/safe7579/src/SafeERC7579.sol b/accounts/safe7579/src/SafeERC7579.sol index 6cb3f374..d1f563e4 100644 --- a/accounts/safe7579/src/SafeERC7579.sol +++ b/accounts/safe7579/src/SafeERC7579.sol @@ -16,7 +16,6 @@ import { } from "erc7579/interfaces/IERC7579Module.sol"; import { AccessControl } from "./core/AccessControl.sol"; import { HookManager } from "./core/HookManager.sol"; -import { ExecutionHelper } from "./core/ExecutionHelper.sol"; import { ISafeOp, SAFE_OP_TYPEHASH } from "./interfaces/ISafeOp.sol"; import { ISafe } from "./interfaces/ISafe.sol"; import { @@ -33,14 +32,7 @@ import "forge-std/console2.sol"; * this contract creates full ERC7579 compliance to Safe accounts * @author zeroknots.eth | rhinestone.wtf */ -contract SafeERC7579 is - ISafeOp, - IERC7579Account, - AccessControl, - ExecutionHelper, - IMSA, - HookManager -{ +contract SafeERC7579 is ISafeOp, IERC7579Account, AccessControl, IMSA, HookManager { using UserOperationLib for PackedUserOperation; using ModeLib for ModeCode; using ExecutionLib for bytes; diff --git a/accounts/safe7579/src/core/ExecutionHelper.sol b/accounts/safe7579/src/core/ExecutionHelper.sol index 727f6a05..501b5873 100644 --- a/accounts/safe7579/src/core/ExecutionHelper.sol +++ b/accounts/safe7579/src/core/ExecutionHelper.sol @@ -21,7 +21,7 @@ contract ExecutionHelper { address safe, address target, uint256 value, - bytes calldata callData + bytes memory callData ) internal returns (bytes memory returnData) diff --git a/accounts/safe7579/src/core/HookManager.sol b/accounts/safe7579/src/core/HookManager.sol index 253001ac..c5c5eff2 100644 --- a/accounts/safe7579/src/core/HookManager.sol +++ b/accounts/safe7579/src/core/HookManager.sol @@ -29,9 +29,24 @@ abstract contract HookManager is ModuleManager { if (hook == address(0)) { _; } else { - bytes memory hookData = IHook(hook).preCheck(_msgSender(), msg.data); + bytes memory retData = _executeReturnData({ + safe: msg.sender, + target: hook, + value: 0, + callData: abi.encodeCall(IHook.preCheck, (_msgSender(), msg.data)) + }); + bytes memory hookPreContext = abi.decode(retData, (bytes)); + _; - if (!IHook(hook).postCheck(hookData)) revert HookPostCheckFailed(); + retData = _executeReturnData({ + safe: msg.sender, + target: hook, + value: 0, + callData: abi.encodeCall(IHook.postCheck, (hookPreContext)) + }); + bool success = abi.decode(retData, (bool)); + + if (!success) revert HookPostCheckFailed(); } } diff --git a/accounts/safe7579/src/core/ModuleManager.sol b/accounts/safe7579/src/core/ModuleManager.sol index 05084f77..b25047de 100644 --- a/accounts/safe7579/src/core/ModuleManager.sol +++ b/accounts/safe7579/src/core/ModuleManager.sol @@ -3,6 +3,7 @@ pragma solidity ^0.8.23; import { SentinelListLib, SENTINEL } from "sentinellist/SentinelList.sol"; import { IExecutor, IValidator, IFallback } from "erc7579/interfaces/IERC7579Module.sol"; +import { ExecutionHelper } from "./ExecutionHelper.sol"; import { Receiver } from "erc7579/core/Receiver.sol"; import { AccessControl } from "./AccessControl.sol"; import { ISafe } from "../interfaces/ISafe.sol"; @@ -27,7 +28,7 @@ bytes32 constant MODULEMANAGER_STORAGE_LOCATION = * Contract that implements ERC7579 Module compatibility for Safe accounts * @author zeroknots.eth | rhinestone.wtf */ -abstract contract ModuleManager is AccessControl, Receiver { +abstract contract ModuleManager is AccessControl, Receiver, ExecutionHelper { using SentinelListLib for SentinelListLib.SentinelList; using ValidatorStorageLib for SentinelListLib.SentinelList; From f9dc75678166fe0c7ad852c36fd1e76af27bcba0 Mon Sep 17 00:00:00 2001 From: zeroknots Date: Tue, 20 Feb 2024 15:58:39 +0700 Subject: [PATCH 7/8] wip --- .../ISSUE_TEMPLATE/Safe7579_issue_template.md | 6 ++++++ accounts/safe7579/src/SafeERC7579.sol | 9 ++++++--- accounts/safe7579/src/core/ExecutionHelper.sol | 16 ++++++++++++---- accounts/safe7579/src/core/ModuleManager.sol | 17 ++++++++++++++--- packages/modulekit/.gas-snapshot | 16 ++++++++++++++++ 5 files changed, 54 insertions(+), 10 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/Safe7579_issue_template.md create mode 100644 packages/modulekit/.gas-snapshot diff --git a/.github/ISSUE_TEMPLATE/Safe7579_issue_template.md b/.github/ISSUE_TEMPLATE/Safe7579_issue_template.md new file mode 100644 index 00000000..965109b2 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/Safe7579_issue_template.md @@ -0,0 +1,6 @@ +--- +name: Safe7579 Issue Template +about: Use this template to report a bug in the Safe7579 module +title: "[Safe7579]: [TITLE OF THE ISSUE]" +labels: safe7579, modulekit +--- diff --git a/accounts/safe7579/src/SafeERC7579.sol b/accounts/safe7579/src/SafeERC7579.sol index d1f563e4..7ea976cf 100644 --- a/accounts/safe7579/src/SafeERC7579.sol +++ b/accounts/safe7579/src/SafeERC7579.sol @@ -137,9 +137,12 @@ contract SafeERC7579 is ISafeOp, IERC7579Account, AccessControl, IMSA, HookManag // pay prefund if (missingAccountFunds != 0) { - ISafe(userOp.getSender()).execTransactionFromModule( - entryPoint(), missingAccountFunds, "", 0 - ); + _execute({ + safe: userOp.getSender(), + target: entryPoint(), + value: missingAccountFunds, + callData: "" + }); } } diff --git a/accounts/safe7579/src/core/ExecutionHelper.sol b/accounts/safe7579/src/core/ExecutionHelper.sol index 501b5873..0a2a0c8b 100644 --- a/accounts/safe7579/src/core/ExecutionHelper.sol +++ b/accounts/safe7579/src/core/ExecutionHelper.sol @@ -4,17 +4,25 @@ pragma solidity >=0.8.0 <0.9.0; import { Execution } from "erc7579/interfaces/IERC7579Account.sol"; import "../interfaces/ISafe.sol"; -contract ExecutionHelper { +/** + * @title Helper contract to execute transactions from a safe + * All functions implemented in this contract check, + * that the transaction was successful + * @author zeroknots.eth + */ +abstract contract ExecutionHelper { + error ExecutionFailed(); + function _execute( address safe, address target, uint256 value, - bytes calldata callData + bytes memory callData ) internal { bool success = ISafe(safe).execTransactionFromModule(target, value, callData, 0); - require(success, "Execution failed"); + if (!success) revert ExecutionFailed(); } function _executeReturnData( @@ -29,7 +37,7 @@ contract ExecutionHelper { bool success; (success, returnData) = ISafe(safe).execTransactionFromModuleReturnData(target, value, callData, 0); - require(success, "Execution failed"); + if (!success) revert ExecutionFailed(); } function _execute(address safe, Execution[] calldata executions) internal { diff --git a/accounts/safe7579/src/core/ModuleManager.sol b/accounts/safe7579/src/core/ModuleManager.sol index b25047de..ab6f3f22 100644 --- a/accounts/safe7579/src/core/ModuleManager.sol +++ b/accounts/safe7579/src/core/ModuleManager.sol @@ -85,7 +85,10 @@ abstract contract ModuleManager is AccessControl, Receiver, ExecutionHelper { // Manage Validators //////////////////////////////////////////////////// /** - * Write into validator linked list via ValidatorStorageHelper DELEGATECALL + * install and initialize validator module + * @dev this function Write into the Safe account storage (validator linked) list via + * ValidatorStorageHelper DELEGATECALL + * the onInstall call to the module(ERC7579), will be executed from the Safe */ function _installValidator(address validator, bytes memory data) internal virtual { bool success = ISafe(msg.sender).execTransactionFromModule({ @@ -97,13 +100,19 @@ abstract contract ModuleManager is AccessControl, Receiver, ExecutionHelper { if (!success) revert ValidatorStorageHelperError(); } + /** + * Uninstall and de-initialize validator module + * @dev this function Write into the Safe account storage (validator linked) list via + * ValidatorStorageHelper DELEGATECALL + * the onUninstall call to the module (ERC7579), will be executed from the Safe + */ function _uninstallValidator(address validator, bytes memory data) internal { bool success = ISafe(msg.sender).execTransactionFromModule({ to: address(VALIDATOR_STORAGE), value: 0, data: abi.encodeCall(ValidatorStorageHelper.uninstallValidator, (validator, data)), - operation: 1 - }); + operation: 1 // <-- DELEGATECALL + }); if (!success) revert ValidatorStorageHelperError(); } @@ -172,6 +181,7 @@ abstract contract ModuleManager is AccessControl, Receiver, ExecutionHelper { SentinelListLib.SentinelList storage _executors = _getModuleManagerStorage(msg.sender)._executors; _executors.push(executor); + // TODO: IExecutor(executor).onInstall(data); } @@ -180,6 +190,7 @@ abstract contract ModuleManager is AccessControl, Receiver, ExecutionHelper { _getModuleManagerStorage(msg.sender)._executors; (address prev, bytes memory disableModuleData) = abi.decode(data, (address, bytes)); _executors.pop(prev, executor); + // TODO: IExecutor(executor).onUninstall(disableModuleData); } diff --git a/packages/modulekit/.gas-snapshot b/packages/modulekit/.gas-snapshot new file mode 100644 index 00000000..e42aa0d8 --- /dev/null +++ b/packages/modulekit/.gas-snapshot @@ -0,0 +1,16 @@ +BaseTest:test_transfer() (gas: 712286) +ERC7579DifferentialModuleKitLibTest:testAddExecutor() (gas: 1083971) +ERC7579DifferentialModuleKitLibTest:testAddHook() (gas: 717077) +ERC7579DifferentialModuleKitLibTest:testAddSessionKey() (gas: 166) +ERC7579DifferentialModuleKitLibTest:testAddValidator() (gas: 1245668) +ERC7579DifferentialModuleKitLibTest:testDeployAccount() (gas: 21930821) +ERC7579DifferentialModuleKitLibTest:testGetUserOpHash() (gas: 188) +ERC7579DifferentialModuleKitLibTest:testRemoveExecutor() (gas: 1160614) +ERC7579DifferentialModuleKitLibTest:testRemoveValidator() (gas: 1002540) +ERC7579DifferentialModuleKitLibTest:testSimulateUserOp() (gas: 1303147) +ERC7579DifferentialModuleKitLibTest:testWriteGas() (gas: 1567493) +ERC7579DifferentialModuleKitLibTest:test_transfer() (gas: 712433) +ERC7579DifferentialModuleKitLibTest:testexec__Given__FourInputs() (gas: 710834) +ERC7579DifferentialModuleKitLibTest:testexec__Given__ThreeInputs() (gas: 711677) +ERC7579DifferentialModuleKitLibTest:testexec__Given__TwoInputs() (gas: 716290) +ERC7579DifferentialModuleKitLibTest:testexec__RevertWhen__UserOperationFails() (gas: 694530) \ No newline at end of file From c21951dafbdfb4bef8e274d4bd1b90b76218e720 Mon Sep 17 00:00:00 2001 From: zeroknots Date: Wed, 21 Feb 2024 08:58:56 +0700 Subject: [PATCH 8/8] using new sentinellist 4337 --- accounts/safe7579/src/core/ModuleManager.sol | 172 +++++----- .../safe7579/src/core/ModuleManager.sol.bak | 287 ++++++++++++++++ .../gas_calculations/testWriteGas.json | 8 +- pnpm-lock.yaml | 318 +++++++++--------- 4 files changed, 533 insertions(+), 252 deletions(-) create mode 100644 accounts/safe7579/src/core/ModuleManager.sol.bak diff --git a/accounts/safe7579/src/core/ModuleManager.sol b/accounts/safe7579/src/core/ModuleManager.sol index ab6f3f22..9d6f8b5a 100644 --- a/accounts/safe7579/src/core/ModuleManager.sol +++ b/accounts/safe7579/src/core/ModuleManager.sol @@ -2,7 +2,8 @@ pragma solidity ^0.8.23; import { SentinelListLib, SENTINEL } from "sentinellist/SentinelList.sol"; -import { IExecutor, IValidator, IFallback } from "erc7579/interfaces/IERC7579Module.sol"; +import { SentinelList4337Lib } from "sentinellist/SentinelList4337.sol"; +import { IModule, IExecutor, IValidator, IFallback } from "erc7579/interfaces/IERC7579Module.sol"; import { ExecutionHelper } from "./ExecutionHelper.sol"; import { Receiver } from "erc7579/core/Receiver.sol"; import { AccessControl } from "./AccessControl.sol"; @@ -19,10 +20,13 @@ struct ModuleManagerStorage { address fallbackHandler; } -// keccak256("modulemanager.storage.msa"); -bytes32 constant MODULEMANAGER_STORAGE_LOCATION = - 0xf88ce1fdb7fb1cbd3282e49729100fa3f2d6ee9f797961fe4fb1871cea89ea02; - +// // keccak256("modulemanager.storage.msa"); +// bytes32 constant MODULEMANAGER_STORAGE_LOCATION = +// 0xf88ce1fdb7fb1cbd3282e49729100fa3f2d6ee9f797961fe4fb1871cea89ea02; +// +// // keccak256("modulemanager.validator.storage.msa") +// bytes32 constant VALIDATOR_STORAGE_LOCATION = +// 0x7ab08468dcbe2bcd9b34ba12d148d0310762840a62884f0cdee905ee43538c87; /** * @title ModuleManager * Contract that implements ERC7579 Module compatibility for Safe accounts @@ -30,7 +34,7 @@ bytes32 constant MODULEMANAGER_STORAGE_LOCATION = */ abstract contract ModuleManager is AccessControl, Receiver, ExecutionHelper { using SentinelListLib for SentinelListLib.SentinelList; - using ValidatorStorageLib for SentinelListLib.SentinelList; + using SentinelList4337Lib for SentinelList4337Lib.SentinelList; error InvalidModule(address module); error LinkedListError(); @@ -42,17 +46,7 @@ abstract contract ModuleManager is AccessControl, Receiver, ExecutionHelper { mapping(address smartAccount => ModuleManagerStorage) private $moduleManager; - constructor() { - VALIDATOR_STORAGE = new ValidatorStorageHelper(); - } - - function _getModuleManagerStorage(address account) - internal - view - returns (ModuleManagerStorage storage ims) - { - return $moduleManager[account]; - } + SentinelList4337Lib.SentinelList $validators; modifier onlyExecutorModule() { if (!_isExecutorInstalled(_msgSender())) revert InvalidModule(_msgSender()); @@ -67,18 +61,11 @@ abstract contract ModuleManager is AccessControl, Receiver, ExecutionHelper { * Validators are stored within the Safe's account storage. */ function _initModuleManager() internal { - bool success = ISafe(msg.sender).execTransactionFromModule({ - to: address(VALIDATOR_STORAGE), - value: 0, - data: abi.encodeCall(ValidatorStorageHelper.initModuleManager, ()), - operation: 1 // <--- DELEGATECALL - }); - // this will be false if the list is already initialized - if (!success) revert InitializerError(); + ModuleManagerStorage storage $mms = $moduleManager[msg.sender]; - ModuleManagerStorage storage ims = _getModuleManagerStorage(msg.sender); // this will revert if list is already initialized - ims._executors.init(); + $validators.init({ account: msg.sender }); + $mms._executors.init(); } ///////////////////////////////////////////////////// @@ -91,13 +78,15 @@ abstract contract ModuleManager is AccessControl, Receiver, ExecutionHelper { * the onInstall call to the module(ERC7579), will be executed from the Safe */ function _installValidator(address validator, bytes memory data) internal virtual { - bool success = ISafe(msg.sender).execTransactionFromModule({ - to: address(VALIDATOR_STORAGE), + $validators.push({ account: msg.sender, newEntry: validator }); + + // Initialize Validator Module via Account + _execute({ + safe: msg.sender, + target: validator, value: 0, - data: abi.encodeCall(ValidatorStorageHelper.installValidator, (validator, data)), - operation: 1 // <-- DELEGATECALL - }); - if (!success) revert ValidatorStorageHelperError(); + callData: abi.encodeCall(IModule.onInstall, (data)) + }); } /** @@ -107,13 +96,16 @@ abstract contract ModuleManager is AccessControl, Receiver, ExecutionHelper { * the onUninstall call to the module (ERC7579), will be executed from the Safe */ function _uninstallValidator(address validator, bytes memory data) internal { - bool success = ISafe(msg.sender).execTransactionFromModule({ - to: address(VALIDATOR_STORAGE), + (address prev, bytes memory disableModuleData) = abi.decode(data, (address, bytes)); + $validators.pop({ account: msg.sender, prevEntry: prev, popEntry: validator }); + + // De-Initialize Validator Module via Account + _execute({ + safe: msg.sender, + target: validator, value: 0, - data: abi.encodeCall(ValidatorStorageHelper.uninstallValidator, (validator, data)), - operation: 1 // <-- DELEGATECALL - }); - if (!success) revert ValidatorStorageHelperError(); + callData: abi.encodeCall(IModule.onUninstall, (disableModuleData)) + }); } /** @@ -127,12 +119,7 @@ abstract contract ModuleManager is AccessControl, Receiver, ExecutionHelper { virtual returns (bool isInstalled) { - // calculate slot for linked list - SentinelListLib.SentinelList storage $validators = $validator()._validators; - // predict slot for validator in ValidatorStorageHelper linked list - address link = $validators.getNextEntry(validator); - // See https://github.com/zeroknots/sentinellist/blob/main/src/SentinelList.sol#L52 - isInstalled = SENTINEL != validator && link != address(0); + isInstalled = $validators.contains({ account: msg.sender, entry: validator }); } /** @@ -148,29 +135,11 @@ abstract contract ModuleManager is AccessControl, Receiver, ExecutionHelper { virtual returns (address[] memory array, address next) { - if (start != SENTINEL && _isExecutorInstalled(start)) revert LinkedListError(); - if (pageSize == 0) revert LinkedListError(); - - array = new address[](pageSize); - - // Populate return array - uint256 entryCount; - SentinelListLib.SentinelList storage $validators = $validator()._validators; - next = $validators.getNextEntry(start); - while (next != address(0) && next != SENTINEL && entryCount < pageSize) { - array[entryCount] = next; - next = $validators.getNextEntry(next); - entryCount++; - } - - if (next != SENTINEL) { - next = array[entryCount - 1]; - } - // Set correct size of returned array - // solhint-disable-next-line no-inline-assembly - assembly ("memory-safe") { - mstore(array, entryCount) - } + return $validators.getEntriesPaginated({ + account: msg.sender, + start: start, + pageSize: pageSize + }); } ///////////////////////////////////////////////////// @@ -178,26 +147,34 @@ abstract contract ModuleManager is AccessControl, Receiver, ExecutionHelper { //////////////////////////////////////////////////// function _installExecutor(address executor, bytes memory data) internal { - SentinelListLib.SentinelList storage _executors = - _getModuleManagerStorage(msg.sender)._executors; - _executors.push(executor); - // TODO: - IExecutor(executor).onInstall(data); + SentinelListLib.SentinelList storage $executors = $moduleManager[msg.sender]._executors; + $executors.push(executor); + // Initialize Executor Module via Account + _execute({ + safe: msg.sender, + target: executor, + value: 0, + callData: abi.encodeCall(IModule.onInstall, (data)) + }); } function _uninstallExecutor(address executor, bytes calldata data) internal { - SentinelListLib.SentinelList storage _executors = - _getModuleManagerStorage(msg.sender)._executors; + SentinelListLib.SentinelList storage $executors = $moduleManager[msg.sender]._executors; (address prev, bytes memory disableModuleData) = abi.decode(data, (address, bytes)); - _executors.pop(prev, executor); - // TODO: - IExecutor(executor).onUninstall(disableModuleData); + $executors.pop(prev, executor); + + // De-Initialize Executor Module via Account + _execute({ + safe: msg.sender, + target: executor, + value: 0, + callData: abi.encodeCall(IModule.onUninstall, (disableModuleData)) + }); } function _isExecutorInstalled(address executor) internal view virtual returns (bool) { - SentinelListLib.SentinelList storage _executors = - _getModuleManagerStorage(msg.sender)._executors; - return _executors.contains(executor); + SentinelListLib.SentinelList storage $executors = $moduleManager[msg.sender]._executors; + return $executors.contains(executor); } /** * THIS IS NOT PART OF THE STANDARD @@ -213,9 +190,8 @@ abstract contract ModuleManager is AccessControl, Receiver, ExecutionHelper { virtual returns (address[] memory array, address next) { - SentinelListLib.SentinelList storage _executors = - _getModuleManagerStorage(msg.sender)._executors; - return _executors.getEntriesPaginated(cursor, size); + SentinelListLib.SentinelList storage $executors = $moduleManager[msg.sender]._executors; + return $executors.getEntriesPaginated(cursor, size); } ///////////////////////////////////////////////////// @@ -223,20 +199,32 @@ abstract contract ModuleManager is AccessControl, Receiver, ExecutionHelper { //////////////////////////////////////////////////// function _installFallbackHandler(address handler, bytes calldata initData) internal virtual { - ModuleManagerStorage storage ims = _getModuleManagerStorage(msg.sender); - ims.fallbackHandler = handler; - IFallback(handler).onInstall(initData); + ModuleManagerStorage storage $mms = $moduleManager[msg.sender]; + $mms.fallbackHandler = handler; + // Initialize Fallback Module via Account + _execute({ + safe: msg.sender, + target: handler, + value: 0, + callData: abi.encodeCall(IModule.onInstall, (initData)) + }); } function _uninstallFallbackHandler(address handler, bytes calldata initData) internal virtual { - ModuleManagerStorage storage ims = _getModuleManagerStorage(msg.sender); - ims.fallbackHandler = address(0); - IFallback(handler).onUninstall(initData); + ModuleManagerStorage storage $mms = $moduleManager[msg.sender]; + $mms.fallbackHandler = address(0); + // De-Initialize Fallback Module via Account + _execute({ + safe: msg.sender, + target: handler, + value: 0, + callData: abi.encodeCall(IModule.onUninstall, (initData)) + }); } function _getFallbackHandler() internal view virtual returns (address fallbackHandler) { - ModuleManagerStorage storage ims = _getModuleManagerStorage(msg.sender); - return ims.fallbackHandler; + ModuleManagerStorage storage $mms = $moduleManager[msg.sender]; + return $mms.fallbackHandler; } function _isFallbackHandlerInstalled(address _handler) internal view virtual returns (bool) { diff --git a/accounts/safe7579/src/core/ModuleManager.sol.bak b/accounts/safe7579/src/core/ModuleManager.sol.bak new file mode 100644 index 00000000..ab6f3f22 --- /dev/null +++ b/accounts/safe7579/src/core/ModuleManager.sol.bak @@ -0,0 +1,287 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.23; + +import { SentinelListLib, SENTINEL } from "sentinellist/SentinelList.sol"; +import { IExecutor, IValidator, IFallback } from "erc7579/interfaces/IERC7579Module.sol"; +import { ExecutionHelper } from "./ExecutionHelper.sol"; +import { Receiver } from "erc7579/core/Receiver.sol"; +import { AccessControl } from "./AccessControl.sol"; +import { ISafe } from "../interfaces/ISafe.sol"; +import { + ValidatorStorageHelper, ValidatorStorageLib, $validator +} from "./ValidatorStorageHelper.sol"; + +struct ModuleManagerStorage { + // linked list of executors. List is initialized by initializeAccount() + SentinelListLib.SentinelList _executors; + // single fallback handler for all fallbacks + // account vendors may implement this differently. This is just a reference implementation + address fallbackHandler; +} + +// keccak256("modulemanager.storage.msa"); +bytes32 constant MODULEMANAGER_STORAGE_LOCATION = + 0xf88ce1fdb7fb1cbd3282e49729100fa3f2d6ee9f797961fe4fb1871cea89ea02; + +/** + * @title ModuleManager + * Contract that implements ERC7579 Module compatibility for Safe accounts + * @author zeroknots.eth | rhinestone.wtf + */ +abstract contract ModuleManager is AccessControl, Receiver, ExecutionHelper { + using SentinelListLib for SentinelListLib.SentinelList; + using ValidatorStorageLib for SentinelListLib.SentinelList; + + error InvalidModule(address module); + error LinkedListError(); + error CannotRemoveLastValidator(); + error InitializerError(); + error ValidatorStorageHelperError(); + + ValidatorStorageHelper internal immutable VALIDATOR_STORAGE; + + mapping(address smartAccount => ModuleManagerStorage) private $moduleManager; + + constructor() { + VALIDATOR_STORAGE = new ValidatorStorageHelper(); + } + + function _getModuleManagerStorage(address account) + internal + view + returns (ModuleManagerStorage storage ims) + { + return $moduleManager[account]; + } + + modifier onlyExecutorModule() { + if (!_isExecutorInstalled(_msgSender())) revert InvalidModule(_msgSender()); + _; + } + + /** + * Initializes linked list that handles installed Validator and Executor + * For Validators: + * The Safe Account will call VALIDATOR_STORAGE via DELEGTATECALL. + * Due to the storage restrictions of ERC-4337 of the validation phase, + * Validators are stored within the Safe's account storage. + */ + function _initModuleManager() internal { + bool success = ISafe(msg.sender).execTransactionFromModule({ + to: address(VALIDATOR_STORAGE), + value: 0, + data: abi.encodeCall(ValidatorStorageHelper.initModuleManager, ()), + operation: 1 // <--- DELEGATECALL + }); + // this will be false if the list is already initialized + if (!success) revert InitializerError(); + + ModuleManagerStorage storage ims = _getModuleManagerStorage(msg.sender); + // this will revert if list is already initialized + ims._executors.init(); + } + + ///////////////////////////////////////////////////// + // Manage Validators + //////////////////////////////////////////////////// + /** + * install and initialize validator module + * @dev this function Write into the Safe account storage (validator linked) list via + * ValidatorStorageHelper DELEGATECALL + * the onInstall call to the module(ERC7579), will be executed from the Safe + */ + function _installValidator(address validator, bytes memory data) internal virtual { + bool success = ISafe(msg.sender).execTransactionFromModule({ + to: address(VALIDATOR_STORAGE), + value: 0, + data: abi.encodeCall(ValidatorStorageHelper.installValidator, (validator, data)), + operation: 1 // <-- DELEGATECALL + }); + if (!success) revert ValidatorStorageHelperError(); + } + + /** + * Uninstall and de-initialize validator module + * @dev this function Write into the Safe account storage (validator linked) list via + * ValidatorStorageHelper DELEGATECALL + * the onUninstall call to the module (ERC7579), will be executed from the Safe + */ + function _uninstallValidator(address validator, bytes memory data) internal { + bool success = ISafe(msg.sender).execTransactionFromModule({ + to: address(VALIDATOR_STORAGE), + value: 0, + data: abi.encodeCall(ValidatorStorageHelper.uninstallValidator, (validator, data)), + operation: 1 // <-- DELEGATECALL + }); + if (!success) revert ValidatorStorageHelperError(); + } + + /** + * Helper function that will calculate storage slot for + * validator address within the linked list in ValidatorStorageHelper + * and use Safe's getStorageAt() to read 32bytes from Safe's storage + */ + function _isValidatorInstalled(address validator) + internal + view + virtual + returns (bool isInstalled) + { + // calculate slot for linked list + SentinelListLib.SentinelList storage $validators = $validator()._validators; + // predict slot for validator in ValidatorStorageHelper linked list + address link = $validators.getNextEntry(validator); + // See https://github.com/zeroknots/sentinellist/blob/main/src/SentinelList.sol#L52 + isInstalled = SENTINEL != validator && link != address(0); + } + + /** + * THIS IS NOT PART OF THE STANDARD + * Helper Function to access linked list + */ + function getValidatorPaginated( + address start, + uint256 pageSize + ) + external + view + virtual + returns (address[] memory array, address next) + { + if (start != SENTINEL && _isExecutorInstalled(start)) revert LinkedListError(); + if (pageSize == 0) revert LinkedListError(); + + array = new address[](pageSize); + + // Populate return array + uint256 entryCount; + SentinelListLib.SentinelList storage $validators = $validator()._validators; + next = $validators.getNextEntry(start); + while (next != address(0) && next != SENTINEL && entryCount < pageSize) { + array[entryCount] = next; + next = $validators.getNextEntry(next); + entryCount++; + } + + if (next != SENTINEL) { + next = array[entryCount - 1]; + } + // Set correct size of returned array + // solhint-disable-next-line no-inline-assembly + assembly ("memory-safe") { + mstore(array, entryCount) + } + } + + ///////////////////////////////////////////////////// + // Manage Executors + //////////////////////////////////////////////////// + + function _installExecutor(address executor, bytes memory data) internal { + SentinelListLib.SentinelList storage _executors = + _getModuleManagerStorage(msg.sender)._executors; + _executors.push(executor); + // TODO: + IExecutor(executor).onInstall(data); + } + + function _uninstallExecutor(address executor, bytes calldata data) internal { + SentinelListLib.SentinelList storage _executors = + _getModuleManagerStorage(msg.sender)._executors; + (address prev, bytes memory disableModuleData) = abi.decode(data, (address, bytes)); + _executors.pop(prev, executor); + // TODO: + IExecutor(executor).onUninstall(disableModuleData); + } + + function _isExecutorInstalled(address executor) internal view virtual returns (bool) { + SentinelListLib.SentinelList storage _executors = + _getModuleManagerStorage(msg.sender)._executors; + return _executors.contains(executor); + } + /** + * THIS IS NOT PART OF THE STANDARD + * Helper Function to access linked list + */ + + function getExecutorsPaginated( + address cursor, + uint256 size + ) + external + view + virtual + returns (address[] memory array, address next) + { + SentinelListLib.SentinelList storage _executors = + _getModuleManagerStorage(msg.sender)._executors; + return _executors.getEntriesPaginated(cursor, size); + } + + ///////////////////////////////////////////////////// + // Manage Fallback + //////////////////////////////////////////////////// + + function _installFallbackHandler(address handler, bytes calldata initData) internal virtual { + ModuleManagerStorage storage ims = _getModuleManagerStorage(msg.sender); + ims.fallbackHandler = handler; + IFallback(handler).onInstall(initData); + } + + function _uninstallFallbackHandler(address handler, bytes calldata initData) internal virtual { + ModuleManagerStorage storage ims = _getModuleManagerStorage(msg.sender); + ims.fallbackHandler = address(0); + IFallback(handler).onUninstall(initData); + } + + function _getFallbackHandler() internal view virtual returns (address fallbackHandler) { + ModuleManagerStorage storage ims = _getModuleManagerStorage(msg.sender); + return ims.fallbackHandler; + } + + function _isFallbackHandlerInstalled(address _handler) internal view virtual returns (bool) { + return _getFallbackHandler() == _handler; + } + + function getActiveFallbackHandler() external view virtual returns (address) { + return _getFallbackHandler(); + } + + // FALLBACK + fallback() external payable override(Receiver) receiverFallback { + address handler = _getFallbackHandler(); + if (handler == address(0)) revert(); + /* solhint-disable no-inline-assembly */ + /// @solidity memory-safe-assembly + // solhint-disable-next-line no-inline-assembly + assembly { + // When compiled with the optimizer, the compiler relies on a certain assumptions on how + // the + // memory is used, therefore we need to guarantee memory safety (keeping the free memory + // point 0x40 slot intact, + // not going beyond the scratch space, etc) + // Solidity docs: https://docs.soliditylang.org/en/latest/assembly.html#memory-safety + function allocate(length) -> pos { + pos := mload(0x40) + mstore(0x40, add(pos, length)) + } + + let calldataPtr := allocate(calldatasize()) + calldatacopy(calldataPtr, 0, calldatasize()) + + // The msg.sender address is shifted to the left by 12 bytes to remove the padding + // Then the address without padding is stored right after the calldata + let senderPtr := allocate(20) + mstore(senderPtr, shl(96, caller())) + + // Add 20 bytes for the address appended add the end + let success := call(gas(), handler, 0, calldataPtr, add(calldatasize(), 20), 0, 0) + + let returnDataPtr := allocate(returndatasize()) + returndatacopy(returnDataPtr, 0, returndatasize()) + if iszero(success) { revert(returnDataPtr, returndatasize()) } + return(returnDataPtr, returndatasize()) + } + /* solhint-enable no-inline-assembly */ + } +} diff --git a/packages/modulekit/gas_calculations/testWriteGas.json b/packages/modulekit/gas_calculations/testWriteGas.json index a0c00af0..f1ba663a 100644 --- a/packages/modulekit/gas_calculations/testWriteGas.json +++ b/packages/modulekit/gas_calculations/testWriteGas.json @@ -4,9 +4,9 @@ "OP-Stack": "8802 gas" }, "Phases": { - "Creation": "549886 gas", - "Execution": "41448 gas", - "Validation": "42835 gas" + "Creation": "539076 gas", + "Execution": "41815 gas", + "Validation": "40829 gas" }, - "Total": "2924474 gas" + "Total": "2911988 gas" } \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 85bafa51..c03add87 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -55,7 +55,7 @@ importers: version: github.com/rhinestonewtf/erc4337-validation/19a97d86f8f29709664334078925b2a843be19e0 erc7579: specifier: github:erc7579/erc7579-implementation - version: github.com/erc7579/erc7579-implementation/be581c908df73f1554f466cb6b47c8ce8777e50f + version: github.com/erc7579/erc7579-implementation/957cd05deeab6a9a85343bb8d1c9701705ed4ecf forge-std: specifier: github:foundry-rs/forge-std version: github.com/foundry-rs/forge-std/1d0766bc5d814f117c7b1e643828f7d85024fb51 @@ -64,10 +64,10 @@ importers: version: 2.8.8 sentinellist: specifier: github:zeroknots/sentinellist - version: github.com/zeroknots/sentinellist/1f9ec0250f1b3f14ba5d200629e3d9f3264fde61 + version: github.com/zeroknots/sentinellist/2783f466b6d9c457da0a240e392db183ca1607bb solady: specifier: github:vectorized/solady - version: github.com/vectorized/solady/9deb9ed36a27261a8745db5b7cd7f4cdc3b1cd4e + version: github.com/vectorized/solady/1372606383445c0a247e6c58eb255a529734258a solarray: specifier: github:sablier-labs/solarray version: github.com/sablier-labs/solarray/6bf10cb34cdace52a3ba5fe437e78cc82df92684 @@ -208,7 +208,7 @@ importers: version: 2.8.8 sentinellist: specifier: github:zeroknots/sentinellist - version: github.com/zeroknots/sentinellist/1f9ec0250f1b3f14ba5d200629e3d9f3264fde61 + version: github.com/zeroknots/sentinellist/2783f466b6d9c457da0a240e392db183ca1607bb solady: specifier: github:vectorized/solady version: github.com/vectorized/solady/1372606383445c0a247e6c58eb255a529734258a @@ -261,15 +261,15 @@ packages: /@ethersproject/abi@5.4.0: resolution: {integrity: sha512-9gU2H+/yK1j2eVMdzm6xvHSnMxk8waIHQGYCZg5uvAyH0rsAzxkModzBSpbAkAuhKFEovC2S9hM4nPuLym8IZw==} dependencies: - '@ethersproject/address': 5.7.0 - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/constants': 5.7.0 - '@ethersproject/hash': 5.7.0 - '@ethersproject/keccak256': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/properties': 5.7.0 - '@ethersproject/strings': 5.7.0 + '@ethersproject/address': 5.4.0 + '@ethersproject/bignumber': 5.4.0 + '@ethersproject/bytes': 5.4.0 + '@ethersproject/constants': 5.4.0 + '@ethersproject/hash': 5.4.0 + '@ethersproject/keccak256': 5.4.0 + '@ethersproject/logger': 5.4.0 + '@ethersproject/properties': 5.4.0 + '@ethersproject/strings': 5.4.0 dev: true /@ethersproject/abi@5.7.0: @@ -289,13 +289,13 @@ packages: /@ethersproject/abstract-provider@5.4.0: resolution: {integrity: sha512-vPBR7HKUBY0lpdllIn7tLIzNN7DrVnhCLKSzY0l8WAwxz686m/aL7ASDzrVxV93GJtIub6N2t4dfZ29CkPOxgA==} dependencies: - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/networks': 5.7.1 - '@ethersproject/properties': 5.7.0 - '@ethersproject/transactions': 5.7.0 - '@ethersproject/web': 5.7.1 + '@ethersproject/bignumber': 5.4.0 + '@ethersproject/bytes': 5.4.0 + '@ethersproject/logger': 5.4.0 + '@ethersproject/networks': 5.4.0 + '@ethersproject/properties': 5.4.0 + '@ethersproject/transactions': 5.4.0 + '@ethersproject/web': 5.4.0 dev: true /@ethersproject/abstract-provider@5.7.0: @@ -313,11 +313,11 @@ packages: /@ethersproject/abstract-signer@5.4.0: resolution: {integrity: sha512-AieQAzt05HJZS2bMofpuxMEp81AHufA5D6M4ScKwtolj041nrfIbIi8ciNW7+F59VYxXq+V4c3d568Q6l2m8ew==} dependencies: - '@ethersproject/abstract-provider': 5.7.0 - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/properties': 5.7.0 + '@ethersproject/abstract-provider': 5.4.0 + '@ethersproject/bignumber': 5.4.0 + '@ethersproject/bytes': 5.4.0 + '@ethersproject/logger': 5.4.0 + '@ethersproject/properties': 5.4.0 dev: true /@ethersproject/abstract-signer@5.7.0: @@ -333,11 +333,11 @@ packages: /@ethersproject/address@5.4.0: resolution: {integrity: sha512-SD0VgOEkcACEG/C6xavlU1Hy3m5DGSXW3CUHkaaEHbAPPsgi0coP5oNPsxau8eTlZOk/bpa/hKeCNoK5IzVI2Q==} dependencies: - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/keccak256': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/rlp': 5.7.0 + '@ethersproject/bignumber': 5.4.0 + '@ethersproject/bytes': 5.4.0 + '@ethersproject/keccak256': 5.4.0 + '@ethersproject/logger': 5.4.0 + '@ethersproject/rlp': 5.4.0 dev: true /@ethersproject/address@5.7.0: @@ -353,7 +353,7 @@ packages: /@ethersproject/base64@5.4.0: resolution: {integrity: sha512-CjQw6E17QDSSC5jiM9YpF7N1aSCHmYGMt9bWD8PWv6YPMxjsys2/Q8xLrROKI3IWJ7sFfZ8B3flKDTM5wlWuZQ==} dependencies: - '@ethersproject/bytes': 5.7.0 + '@ethersproject/bytes': 5.4.0 dev: true /@ethersproject/base64@5.7.0: @@ -365,8 +365,8 @@ packages: /@ethersproject/basex@5.4.0: resolution: {integrity: sha512-J07+QCVJ7np2bcpxydFVf/CuYo9mZ7T73Pe7KQY4c1lRlrixMeblauMxHXD0MPwFmUHZIILDNViVkykFBZylbg==} dependencies: - '@ethersproject/bytes': 5.7.0 - '@ethersproject/properties': 5.7.0 + '@ethersproject/bytes': 5.4.0 + '@ethersproject/properties': 5.4.0 dev: true /@ethersproject/basex@5.7.0: @@ -379,8 +379,8 @@ packages: /@ethersproject/bignumber@5.4.0: resolution: {integrity: sha512-OXUu9f9hO3vGRIPxU40cignXZVaYyfx6j9NNMjebKdnaCL3anCLSSy8/b8d03vY6dh7duCC0kW72GEC4tZer2w==} dependencies: - '@ethersproject/bytes': 5.7.0 - '@ethersproject/logger': 5.7.0 + '@ethersproject/bytes': 5.4.0 + '@ethersproject/logger': 5.4.0 bn.js: 4.12.0 dev: true @@ -395,7 +395,7 @@ packages: /@ethersproject/bytes@5.4.0: resolution: {integrity: sha512-H60ceqgTHbhzOj4uRc/83SCN9d+BSUnOkrr2intevqdtEMO1JFVZ1XL84OEZV+QjV36OaZYxtnt4lGmxcGsPfA==} dependencies: - '@ethersproject/logger': 5.7.0 + '@ethersproject/logger': 5.4.0 dev: true /@ethersproject/bytes@5.7.0: @@ -407,7 +407,7 @@ packages: /@ethersproject/constants@5.4.0: resolution: {integrity: sha512-tzjn6S7sj9+DIIeKTJLjK9WGN2Tj0P++Z8ONEIlZjyoTkBuODN+0VfhAyYksKi43l1Sx9tX2VlFfzjfmr5Wl3Q==} dependencies: - '@ethersproject/bignumber': 5.7.0 + '@ethersproject/bignumber': 5.4.0 dev: true /@ethersproject/constants@5.7.0: @@ -419,16 +419,16 @@ packages: /@ethersproject/contracts@5.4.0: resolution: {integrity: sha512-hkO3L3IhS1Z3ZtHtaAG/T87nQ7KiPV+/qnvutag35I0IkiQ8G3ZpCQ9NNOpSCzn4pWSW4CfzmtE02FcqnLI+hw==} dependencies: - '@ethersproject/abi': 5.7.0 - '@ethersproject/abstract-provider': 5.7.0 - '@ethersproject/abstract-signer': 5.7.0 - '@ethersproject/address': 5.7.0 - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/constants': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/properties': 5.7.0 - '@ethersproject/transactions': 5.7.0 + '@ethersproject/abi': 5.4.0 + '@ethersproject/abstract-provider': 5.4.0 + '@ethersproject/abstract-signer': 5.4.0 + '@ethersproject/address': 5.4.0 + '@ethersproject/bignumber': 5.4.0 + '@ethersproject/bytes': 5.4.0 + '@ethersproject/constants': 5.4.0 + '@ethersproject/logger': 5.4.0 + '@ethersproject/properties': 5.4.0 + '@ethersproject/transactions': 5.4.0 dev: true /@ethersproject/contracts@5.7.0: @@ -449,14 +449,14 @@ packages: /@ethersproject/hash@5.4.0: resolution: {integrity: sha512-xymAM9tmikKgbktOCjW60Z5sdouiIIurkZUr9oW5NOex5uwxrbsYG09kb5bMcNjlVeJD3yPivTNzViIs1GCbqA==} dependencies: - '@ethersproject/abstract-signer': 5.7.0 - '@ethersproject/address': 5.7.0 - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/keccak256': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/properties': 5.7.0 - '@ethersproject/strings': 5.7.0 + '@ethersproject/abstract-signer': 5.4.0 + '@ethersproject/address': 5.4.0 + '@ethersproject/bignumber': 5.4.0 + '@ethersproject/bytes': 5.4.0 + '@ethersproject/keccak256': 5.4.0 + '@ethersproject/logger': 5.4.0 + '@ethersproject/properties': 5.4.0 + '@ethersproject/strings': 5.4.0 dev: true /@ethersproject/hash@5.7.0: @@ -476,18 +476,18 @@ packages: /@ethersproject/hdnode@5.4.0: resolution: {integrity: sha512-pKxdS0KAaeVGfZPp1KOiDLB0jba11tG6OP1u11QnYfb7pXn6IZx0xceqWRr6ygke8+Kw74IpOoSi7/DwANhy8Q==} dependencies: - '@ethersproject/abstract-signer': 5.7.0 - '@ethersproject/basex': 5.7.0 - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/pbkdf2': 5.7.0 - '@ethersproject/properties': 5.7.0 - '@ethersproject/sha2': 5.7.0 - '@ethersproject/signing-key': 5.7.0 - '@ethersproject/strings': 5.7.0 - '@ethersproject/transactions': 5.7.0 - '@ethersproject/wordlists': 5.7.0 + '@ethersproject/abstract-signer': 5.4.0 + '@ethersproject/basex': 5.4.0 + '@ethersproject/bignumber': 5.4.0 + '@ethersproject/bytes': 5.4.0 + '@ethersproject/logger': 5.4.0 + '@ethersproject/pbkdf2': 5.4.0 + '@ethersproject/properties': 5.4.0 + '@ethersproject/sha2': 5.4.0 + '@ethersproject/signing-key': 5.4.0 + '@ethersproject/strings': 5.4.0 + '@ethersproject/transactions': 5.4.0 + '@ethersproject/wordlists': 5.4.0 dev: true /@ethersproject/hdnode@5.7.0: @@ -510,17 +510,17 @@ packages: /@ethersproject/json-wallets@5.4.0: resolution: {integrity: sha512-igWcu3fx4aiczrzEHwG1xJZo9l1cFfQOWzTqwRw/xcvxTk58q4f9M7cjh51EKphMHvrJtcezJ1gf1q1AUOfEQQ==} dependencies: - '@ethersproject/abstract-signer': 5.7.0 - '@ethersproject/address': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/hdnode': 5.7.0 - '@ethersproject/keccak256': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/pbkdf2': 5.7.0 - '@ethersproject/properties': 5.7.0 - '@ethersproject/random': 5.7.0 - '@ethersproject/strings': 5.7.0 - '@ethersproject/transactions': 5.7.0 + '@ethersproject/abstract-signer': 5.4.0 + '@ethersproject/address': 5.4.0 + '@ethersproject/bytes': 5.4.0 + '@ethersproject/hdnode': 5.4.0 + '@ethersproject/keccak256': 5.4.0 + '@ethersproject/logger': 5.4.0 + '@ethersproject/pbkdf2': 5.4.0 + '@ethersproject/properties': 5.4.0 + '@ethersproject/random': 5.4.0 + '@ethersproject/strings': 5.4.0 + '@ethersproject/transactions': 5.4.0 aes-js: 3.0.0 scrypt-js: 3.0.1 dev: true @@ -546,7 +546,7 @@ packages: /@ethersproject/keccak256@5.4.0: resolution: {integrity: sha512-FBI1plWet+dPUvAzPAeHzRKiPpETQzqSUWR1wXJGHVWi4i8bOSrpC3NwpkPjgeXG7MnugVc1B42VbfnQikyC/A==} dependencies: - '@ethersproject/bytes': 5.7.0 + '@ethersproject/bytes': 5.4.0 js-sha3: 0.5.7 dev: true @@ -568,7 +568,7 @@ packages: /@ethersproject/networks@5.4.0: resolution: {integrity: sha512-5fywtKRDcnaVeA5SjxXH3DOQqe/IbeD/plwydi94SdPps1fbDUrnO6SzDExaruBZXxpxJcO9upG9UComsei4bg==} dependencies: - '@ethersproject/logger': 5.7.0 + '@ethersproject/logger': 5.4.0 dev: true /@ethersproject/networks@5.7.1: @@ -580,8 +580,8 @@ packages: /@ethersproject/pbkdf2@5.4.0: resolution: {integrity: sha512-x94aIv6tiA04g6BnazZSLoRXqyusawRyZWlUhKip2jvoLpzJuLb//KtMM6PEovE47pMbW+Qe1uw+68ameJjB7g==} dependencies: - '@ethersproject/bytes': 5.7.0 - '@ethersproject/sha2': 5.7.0 + '@ethersproject/bytes': 5.4.0 + '@ethersproject/sha2': 5.4.0 dev: true /@ethersproject/pbkdf2@5.7.0: @@ -594,7 +594,7 @@ packages: /@ethersproject/properties@5.4.0: resolution: {integrity: sha512-7jczalGVRAJ+XSRvNA6D5sAwT4gavLq3OXPuV/74o3Rd2wuzSL035IMpIMgei4CYyBdialJMrTqkOnzccLHn4A==} dependencies: - '@ethersproject/logger': 5.7.0 + '@ethersproject/logger': 5.4.0 dev: true /@ethersproject/properties@5.7.0: @@ -606,23 +606,23 @@ packages: /@ethersproject/providers@5.4.0: resolution: {integrity: sha512-XRmI9syLnkNdLA8ikEeg0duxmwSWTTt9S+xabnTOyI51JPJyhQ0QUNT+wvmod218ebb7rLupHDPQ7UVe2/+Tjg==} dependencies: - '@ethersproject/abstract-provider': 5.7.0 - '@ethersproject/abstract-signer': 5.7.0 - '@ethersproject/address': 5.7.0 - '@ethersproject/basex': 5.7.0 - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/constants': 5.7.0 - '@ethersproject/hash': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/networks': 5.7.1 - '@ethersproject/properties': 5.7.0 - '@ethersproject/random': 5.7.0 - '@ethersproject/rlp': 5.7.0 - '@ethersproject/sha2': 5.7.0 - '@ethersproject/strings': 5.7.0 - '@ethersproject/transactions': 5.7.0 - '@ethersproject/web': 5.7.1 + '@ethersproject/abstract-provider': 5.4.0 + '@ethersproject/abstract-signer': 5.4.0 + '@ethersproject/address': 5.4.0 + '@ethersproject/basex': 5.4.0 + '@ethersproject/bignumber': 5.4.0 + '@ethersproject/bytes': 5.4.0 + '@ethersproject/constants': 5.4.0 + '@ethersproject/hash': 5.4.0 + '@ethersproject/logger': 5.4.0 + '@ethersproject/networks': 5.4.0 + '@ethersproject/properties': 5.4.0 + '@ethersproject/random': 5.4.0 + '@ethersproject/rlp': 5.4.0 + '@ethersproject/sha2': 5.4.0 + '@ethersproject/strings': 5.4.0 + '@ethersproject/transactions': 5.4.0 + '@ethersproject/web': 5.4.0 bech32: 1.1.4 ws: 7.4.6 transitivePeerDependencies: @@ -661,8 +661,8 @@ packages: /@ethersproject/random@5.4.0: resolution: {integrity: sha512-pnpWNQlf0VAZDEOVp1rsYQosmv2o0ITS/PecNw+mS2/btF8eYdspkN0vIXrCMtkX09EAh9bdk8GoXmFXM1eAKw==} dependencies: - '@ethersproject/bytes': 5.7.0 - '@ethersproject/logger': 5.7.0 + '@ethersproject/bytes': 5.4.0 + '@ethersproject/logger': 5.4.0 dev: true /@ethersproject/random@5.7.0: @@ -675,8 +675,8 @@ packages: /@ethersproject/rlp@5.4.0: resolution: {integrity: sha512-0I7MZKfi+T5+G8atId9QaQKHRvvasM/kqLyAH4XxBCBchAooH2EX5rL9kYZWwcm3awYV+XC7VF6nLhfeQFKVPg==} dependencies: - '@ethersproject/bytes': 5.7.0 - '@ethersproject/logger': 5.7.0 + '@ethersproject/bytes': 5.4.0 + '@ethersproject/logger': 5.4.0 dev: true /@ethersproject/rlp@5.7.0: @@ -689,8 +689,8 @@ packages: /@ethersproject/sha2@5.4.0: resolution: {integrity: sha512-siheo36r1WD7Cy+bDdE1BJ8y0bDtqXCOxRMzPa4bV1TGt/eTUUt03BHoJNB6reWJD8A30E/pdJ8WFkq+/uz4Gg==} dependencies: - '@ethersproject/bytes': 5.7.0 - '@ethersproject/logger': 5.7.0 + '@ethersproject/bytes': 5.4.0 + '@ethersproject/logger': 5.4.0 hash.js: 1.1.7 dev: true @@ -705,9 +705,9 @@ packages: /@ethersproject/signing-key@5.4.0: resolution: {integrity: sha512-q8POUeywx6AKg2/jX9qBYZIAmKSB4ubGXdQ88l40hmATj29JnG5pp331nAWwwxPn2Qao4JpWHNZsQN+bPiSW9A==} dependencies: - '@ethersproject/bytes': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/properties': 5.7.0 + '@ethersproject/bytes': 5.4.0 + '@ethersproject/logger': 5.4.0 + '@ethersproject/properties': 5.4.0 bn.js: 4.12.0 elliptic: 6.5.4 hash.js: 1.1.7 @@ -727,11 +727,11 @@ packages: /@ethersproject/solidity@5.4.0: resolution: {integrity: sha512-XFQTZ7wFSHOhHcV1DpcWj7VXECEiSrBuv7JErJvB9Uo+KfCdc3QtUZV+Vjh/AAaYgezUEKbCtE6Khjm44seevQ==} dependencies: - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/keccak256': 5.7.0 - '@ethersproject/sha2': 5.7.0 - '@ethersproject/strings': 5.7.0 + '@ethersproject/bignumber': 5.4.0 + '@ethersproject/bytes': 5.4.0 + '@ethersproject/keccak256': 5.4.0 + '@ethersproject/sha2': 5.4.0 + '@ethersproject/strings': 5.4.0 dev: true /@ethersproject/solidity@5.7.0: @@ -748,9 +748,9 @@ packages: /@ethersproject/strings@5.4.0: resolution: {integrity: sha512-k/9DkH5UGDhv7aReXLluFG5ExurwtIpUfnDNhQA29w896Dw3i4uDTz01Quaptbks1Uj9kI8wo9tmW73wcIEaWA==} dependencies: - '@ethersproject/bytes': 5.7.0 - '@ethersproject/constants': 5.7.0 - '@ethersproject/logger': 5.7.0 + '@ethersproject/bytes': 5.4.0 + '@ethersproject/constants': 5.4.0 + '@ethersproject/logger': 5.4.0 dev: true /@ethersproject/strings@5.7.0: @@ -764,15 +764,15 @@ packages: /@ethersproject/transactions@5.4.0: resolution: {integrity: sha512-s3EjZZt7xa4BkLknJZ98QGoIza94rVjaEed0rzZ/jB9WrIuu/1+tjvYCWzVrystXtDswy7TPBeIepyXwSYa4WQ==} dependencies: - '@ethersproject/address': 5.7.0 - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/constants': 5.7.0 - '@ethersproject/keccak256': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/properties': 5.7.0 - '@ethersproject/rlp': 5.7.0 - '@ethersproject/signing-key': 5.7.0 + '@ethersproject/address': 5.4.0 + '@ethersproject/bignumber': 5.4.0 + '@ethersproject/bytes': 5.4.0 + '@ethersproject/constants': 5.4.0 + '@ethersproject/keccak256': 5.4.0 + '@ethersproject/logger': 5.4.0 + '@ethersproject/properties': 5.4.0 + '@ethersproject/rlp': 5.4.0 + '@ethersproject/signing-key': 5.4.0 dev: true /@ethersproject/transactions@5.7.0: @@ -792,9 +792,9 @@ packages: /@ethersproject/units@5.4.0: resolution: {integrity: sha512-Z88krX40KCp+JqPCP5oPv5p750g+uU6gopDYRTBGcDvOASh6qhiEYCRatuM/suC4S2XW9Zz90QI35MfSrTIaFg==} dependencies: - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/constants': 5.7.0 - '@ethersproject/logger': 5.7.0 + '@ethersproject/bignumber': 5.4.0 + '@ethersproject/constants': 5.4.0 + '@ethersproject/logger': 5.4.0 dev: true /@ethersproject/units@5.7.0: @@ -808,21 +808,21 @@ packages: /@ethersproject/wallet@5.4.0: resolution: {integrity: sha512-wU29majLjM6AjCjpat21mPPviG+EpK7wY1+jzKD0fg3ui5fgedf2zEu1RDgpfIMsfn8fJHJuzM4zXZ2+hSHaSQ==} dependencies: - '@ethersproject/abstract-provider': 5.7.0 - '@ethersproject/abstract-signer': 5.7.0 - '@ethersproject/address': 5.7.0 - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/hash': 5.7.0 - '@ethersproject/hdnode': 5.7.0 - '@ethersproject/json-wallets': 5.7.0 - '@ethersproject/keccak256': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/properties': 5.7.0 - '@ethersproject/random': 5.7.0 - '@ethersproject/signing-key': 5.7.0 - '@ethersproject/transactions': 5.7.0 - '@ethersproject/wordlists': 5.7.0 + '@ethersproject/abstract-provider': 5.4.0 + '@ethersproject/abstract-signer': 5.4.0 + '@ethersproject/address': 5.4.0 + '@ethersproject/bignumber': 5.4.0 + '@ethersproject/bytes': 5.4.0 + '@ethersproject/hash': 5.4.0 + '@ethersproject/hdnode': 5.4.0 + '@ethersproject/json-wallets': 5.4.0 + '@ethersproject/keccak256': 5.4.0 + '@ethersproject/logger': 5.4.0 + '@ethersproject/properties': 5.4.0 + '@ethersproject/random': 5.4.0 + '@ethersproject/signing-key': 5.4.0 + '@ethersproject/transactions': 5.4.0 + '@ethersproject/wordlists': 5.4.0 dev: true /@ethersproject/wallet@5.7.0: @@ -848,11 +848,11 @@ packages: /@ethersproject/web@5.4.0: resolution: {integrity: sha512-1bUusGmcoRLYgMn6c1BLk1tOKUIFuTg8j+6N8lYlbMpDesnle+i3pGSagGNvwjaiLo4Y5gBibwctpPRmjrh4Og==} dependencies: - '@ethersproject/base64': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/properties': 5.7.0 - '@ethersproject/strings': 5.7.0 + '@ethersproject/base64': 5.4.0 + '@ethersproject/bytes': 5.4.0 + '@ethersproject/logger': 5.4.0 + '@ethersproject/properties': 5.4.0 + '@ethersproject/strings': 5.4.0 dev: true /@ethersproject/web@5.7.1: @@ -868,11 +868,11 @@ packages: /@ethersproject/wordlists@5.4.0: resolution: {integrity: sha512-FemEkf6a+EBKEPxlzeVgUaVSodU7G0Na89jqKjmWMlDB0tomoU8RlEMgUvXyqtrg8N4cwpLh8nyRnm1Nay1isA==} dependencies: - '@ethersproject/bytes': 5.7.0 - '@ethersproject/hash': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/properties': 5.7.0 - '@ethersproject/strings': 5.7.0 + '@ethersproject/bytes': 5.4.0 + '@ethersproject/hash': 5.4.0 + '@ethersproject/logger': 5.4.0 + '@ethersproject/properties': 5.4.0 + '@ethersproject/strings': 5.4.0 dev: true /@ethersproject/wordlists@5.7.0: @@ -3784,7 +3784,7 @@ packages: resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} hasBin: true dependencies: - glob: 7.2.3 + glob: 7.2.0 dev: true /ripemd160@2.0.2: @@ -4612,7 +4612,7 @@ packages: version: 0.0.1 dependencies: '@openzeppelin/contracts': 5.0.1 - solady: github.com/vectorized/solady/9deb9ed36a27261a8745db5b7cd7f4cdc3b1cd4e + solady: github.com/vectorized/solady/1372606383445c0a247e6c58eb255a529734258a dev: true github.com/sablier-labs/solarray/6bf10cb34cdace52a3ba5fe437e78cc82df92684: @@ -4644,3 +4644,9 @@ packages: name: sentinellist version: 0.0.0 dev: true + + github.com/zeroknots/sentinellist/2783f466b6d9c457da0a240e392db183ca1607bb: + resolution: {tarball: https://codeload.github.com/zeroknots/sentinellist/tar.gz/2783f466b6d9c457da0a240e392db183ca1607bb} + name: sentinellist + version: 0.0.0 + dev: true