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/.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/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..7ea976cf 100644 --- a/accounts/safe7579/src/SafeERC7579.sol +++ b/accounts/safe7579/src/SafeERC7579.sol @@ -1,34 +1,50 @@ // 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 { 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"; -contract SafeERC7579 is - ISafeOp, - IERC7579Account, - AccessControl, - ExecutionHelper, - IMSA, - HookManager -{ +import "forge-std/console2.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, AccessControl, IMSA, HookManager { using UserOperationLib for PackedUserOperation; 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 +69,9 @@ contract SafeERC7579 is } } + /** + * @inheritdoc IERC7579Account + */ function executeFromExecutor( ModeCode mode, bytes calldata executionCalldata @@ -79,13 +98,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, @@ -110,9 +137,12 @@ contract SafeERC7579 is // pay prefund if (missingAccountFunds != 0) { - ISafe(userOp.getSender()).execTransactionFromModule( - entryPoint(), missingAccountFunds, "", 0 - ); + _execute({ + safe: userOp.getSender(), + target: entryPoint(), + value: missingAccountFunds, + callData: "" + }); } } @@ -142,8 +172,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 +198,9 @@ contract SafeERC7579 is emit ModuleInstalled(moduleType, module); } + /** + * @inheritdoc IERC7579Account + */ function uninstallModule( uint256 moduleType, address module, @@ -180,6 +219,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 +229,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 +239,9 @@ contract SafeERC7579 is else return false; } + /** + * @inheritdoc IERC7579Account + */ function isModuleInstalled( uint256 moduleType, address module, @@ -211,8 +259,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 +344,20 @@ 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)); + console2.log("bootstrap: ", bootstrap); + + (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 76% rename from accounts/safe7579/src/ExecutionHelper.sol rename to accounts/safe7579/src/core/ExecutionHelper.sol index b2d12bd6..0a2a0c8b 100644 --- a/accounts/safe7579/src/ExecutionHelper.sol +++ b/accounts/safe7579/src/core/ExecutionHelper.sol @@ -2,27 +2,34 @@ 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"; + +/** + * @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(); -contract ExecutionHelper { 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( address safe, address target, uint256 value, - bytes calldata callData + bytes memory callData ) internal returns (bytes memory returnData) @@ -30,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/HookManager.sol b/accounts/safe7579/src/core/HookManager.sol similarity index 74% rename from accounts/safe7579/src/HookManager.sol rename to accounts/safe7579/src/core/HookManager.sol index 56088dc7..c5c5eff2 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 { @@ -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 new file mode 100644 index 00000000..9d6f8b5a --- /dev/null +++ b/accounts/safe7579/src/core/ModuleManager.sol @@ -0,0 +1,275 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.23; + +import { SentinelListLib, SENTINEL } from "sentinellist/SentinelList.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"; +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; +// +// // keccak256("modulemanager.validator.storage.msa") +// bytes32 constant VALIDATOR_STORAGE_LOCATION = +// 0x7ab08468dcbe2bcd9b34ba12d148d0310762840a62884f0cdee905ee43538c87; +/** + * @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 SentinelList4337Lib for SentinelList4337Lib.SentinelList; + + error InvalidModule(address module); + error LinkedListError(); + error CannotRemoveLastValidator(); + error InitializerError(); + error ValidatorStorageHelperError(); + + ValidatorStorageHelper internal immutable VALIDATOR_STORAGE; + + mapping(address smartAccount => ModuleManagerStorage) private $moduleManager; + + SentinelList4337Lib.SentinelList $validators; + + 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 { + ModuleManagerStorage storage $mms = $moduleManager[msg.sender]; + + // this will revert if list is already initialized + $validators.init({ account: msg.sender }); + $mms._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 { + $validators.push({ account: msg.sender, newEntry: validator }); + + // Initialize Validator Module via Account + _execute({ + safe: msg.sender, + target: validator, + value: 0, + callData: abi.encodeCall(IModule.onInstall, (data)) + }); + } + + /** + * 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 { + (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, + callData: abi.encodeCall(IModule.onUninstall, (disableModuleData)) + }); + } + + /** + * 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) + { + isInstalled = $validators.contains({ account: msg.sender, entry: validator }); + } + + /** + * 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) + { + return $validators.getEntriesPaginated({ + account: msg.sender, + start: start, + pageSize: pageSize + }); + } + + ///////////////////////////////////////////////////// + // Manage Executors + //////////////////////////////////////////////////// + + function _installExecutor(address executor, bytes memory data) internal { + 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 = $moduleManager[msg.sender]._executors; + (address prev, bytes memory disableModuleData) = abi.decode(data, (address, bytes)); + $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 = $moduleManager[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 = $moduleManager[msg.sender]._executors; + return $executors.getEntriesPaginated(cursor, size); + } + + ///////////////////////////////////////////////////// + // Manage Fallback + //////////////////////////////////////////////////// + + function _installFallbackHandler(address handler, bytes calldata initData) internal virtual { + 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 $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 $mms = $moduleManager[msg.sender]; + return $mms.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/accounts/safe7579/src/ModuleManager.sol b/accounts/safe7579/src/core/ModuleManager.sol.bak similarity index 57% rename from accounts/safe7579/src/ModuleManager.sol rename to accounts/safe7579/src/core/ModuleManager.sol.bak index bc1114e6..ab6f3f22 100644 --- a/accounts/safe7579/src/ModuleManager.sol +++ b/accounts/safe7579/src/core/ModuleManager.sol.bak @@ -2,18 +2,14 @@ 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 { ExecutionHelper } from "./ExecutionHelper.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 +17,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 { +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(); - 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 +51,7 @@ abstract contract ModuleManager is AccessControl, Receiver { view returns (ModuleManagerStorage storage ims) { - return _moduleManagerStorage[account]; + return $moduleManager[account]; } modifier onlyExecutorModule() { @@ -98,67 +59,80 @@ 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 { + /** + * 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(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 { + /** + * 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(STORAGE_MANAGER), + to: address(VALIDATOR_STORAGE), value: 0, - data: abi.encodeCall(ModuleStorage.uninstallValidator, (validator, data)), - operation: 1 - }); - require(success, "ModuleManager: failed to uninstall validator"); + data: abi.encodeCall(ValidatorStorageHelper.uninstallValidator, (validator, data)), + operation: 1 // <-- DELEGATECALL + }); + 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 +148,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,10 +177,11 @@ 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); + // TODO: IExecutor(executor).onInstall(data); } @@ -233,6 +190,7 @@ abstract contract ModuleManager is AccessControl, Receiver { _getModuleManagerStorage(msg.sender)._executors; (address prev, bytes memory disableModuleData) = abi.decode(data, (address, bytes)); _executors.pop(prev, executor); + // TODO: IExecutor(executor).onUninstall(disableModuleData); } @@ -295,6 +253,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..5be8995a --- /dev/null +++ b/accounts/safe7579/src/core/ValidatorStorageHelper.sol @@ -0,0 +1,124 @@ +// 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() { + // TODO: + // 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..ad97493f --- /dev/null +++ b/accounts/safe7579/test/Base.t.sol @@ -0,0 +1,120 @@ +// SPDX-License-Identifier: MIT +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 } 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; + Safe internal safeImpl; + Safe internal safe; + IEntryPoint internal entrypoint = IEntryPoint(ENTRYPOINT_ADDR); + + MockValidator internal defaultValidator; + MockExecutor internal defaultExecutor; + Bootstrap internal bootstrap; + + MockTarget internal target; + + Account internal signer1; + Account internal signer2; + + function setUp() public virtual { + // Set up EntryPoint + etchEntrypoint(); + + // Set up MSA and Factory + bootstrap = new Bootstrap(); + 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)); + erc7579Mod.initializeAccount( + abi.encode( + address(bootstrap), + abi.encodeCall( + Bootstrap.singleInitMSA, (_defaultValidator, "", address(defaultExecutor), "") + ) + ) + ); + 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/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/gas_calculations/.gitkeep b/gas_calculations/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/package.json b/package.json index 55a392ad..3aeac978 100644 --- a/package.json +++ b/package.json @@ -12,26 +12,16 @@ }, "workspaces": [ "packages/**", - "examples/", - "accounts/**" + "accounts/**", + "examples/" ], "dependencies": {}, "devDependencies": { - "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", - "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/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..8447f255 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-nextline max-line-length */ bytes constant SESSIONKEYMANAGER_BYTECODE = - hex"6080806040523461001657610cfe908161001c8239f35b600080fdfe60806040908082526004918236101561001757600080fd5b600091823560e01c90816306fdde03146106025750806354fd4d50146105be5780636d61fe70146105b95780638a91b0e3146105b95780639700320314610563578063cb9b272c14610308578063d4511ee9146102e7578063d60b347f146102c2578063d6cc1aa4146102a8578063df73e60e146101cb578063ecd05961146101a6578063f42c859d146100ff5763f551e2ee146100b457600080fd5b346100fb5760603660031901126100fb576100cd610727565b5060443567ffffffffffffffff81116100f7576020936100ef9136910161068f565b505051908152f35b8280fd5b5080fd5b508183346100fb5760203660031901126100fb576001903592838352826020528083203384526020528220828155016101388154610807565b80610169575b505050337f10103b778a5e09e8bcc680439d97711489525190a1fe679251002e893f9ea5638380a380f35b82601f8211600114610181575050555b81838061013e565b909180825261019f601f60208420940160051c840160018501610841565b5555610179565b509190346101c85760203660031901126101c857506001602092519135148152f35b80fd5b50346100fb57806003193601126100fb576102a460016101e9610727565b838051956101f68761073d565b808752606080602098838a820152838582015201526024358152808752818120848060a01b038094168252875220948451946102318661073d565b86549165ffffffffffff9788918285168952610271818a0192848760301c168452858b019660601c875261026a8651809a81930161088c565b038861078b565b606089019687528351998a99828b52511690890152511690860152511660608401525160808084015260a083019061064f565b0390f35b50346100fb57816003193601126100fb5751908152602090f35b50346100fb5760203660031901126100fb57906020916102e0610727565b5051908152f35b50346100fb576020906103016102fc366106f5565b610c34565b9051908152f35b5082346100f757610318366106f5565b9061032282610c34565b92838552602092858452818620338752845281862065ffffffffffff9283610349846107e0565b1690868401946bffffffffffff000000000000610365876107e0565b60301b16828601936bffffffffffffffffffffffff19610384866107f3565b60601b169117178455600180940160608601946103a186886107ad565b919067ffffffffffffffff9a8b841161055057509082918e8d6103c48754610807565b90601f8211610517575b90508193601f86116001146104ad575050926104a2575b50508160011b916000199060031b1c19161790555b6104178251968988528261040d88610858565b168a890152610858565b1690850152356001600160a01b0381169081900361049e57606084015235601e198236030181121561049a57018035930191831161049657823603821361049657806104907f57aa9b35aca9ac2ac77db1278fe563afa57004616360740e680d89bc674ebd1e93608080840152339560a084019161086b565b0390a380f35b8480fd5b8680fd5b8780fd5b013590508d806103e5565b8783528183209550929392601f19871692915b8383106104ff575050509084600195949392106104e5575b505050811b0190556103fa565b0135600019600384901b60f8161c191690558d80806104d8565b8185978293949688013581550196019301908f6104c0565b87835280832061053f92601f880160051c8201928810610546575b601f0160051c0190610841565b388e6103ce565b9091508190610532565b634e487b7160e01b8f526041905260248efd5b5090346101c8576003199282843601126100fb57803567ffffffffffffffff81116100f7576101208183019582360301126100f75760646105a59101856107ad565b919050116101c85750610301602092610922565b6106c2565b50346100fb57816003193601126100fb5780516102a4916105de8261076f565b6005825264302e302e3160d81b60208301525191829160208352602083019061064f565b919050346100f757826003193601126100f7576102a492506106238261076f565b601182527029b2b9b9b4b7b725b2bca6b0b730b3b2b960791b6020830152519182916020835260208301905b919082519283825260005b84811061067b575050826000602080949584010152601f8019910116010190565b60208183018101518483018201520161065a565b9181601f840112156106bd5782359167ffffffffffffffff83116106bd57602083818601950101116106bd57565b600080fd5b346106bd5760203660031901126106bd5760043567ffffffffffffffff81116106bd576106f390369060040161068f565b005b600319906020818301126106bd576004359167ffffffffffffffff83116106bd57826080920301126106bd5760040190565b600435906001600160a01b03821682036106bd57565b6080810190811067ffffffffffffffff82111761075957604052565b634e487b7160e01b600052604160045260246000fd5b6040810190811067ffffffffffffffff82111761075957604052565b90601f8019910116810190811067ffffffffffffffff82111761075957604052565b903590601e19813603018212156106bd570180359067ffffffffffffffff82116106bd576020019181360383136106bd57565b3565ffffffffffff811681036106bd5790565b356001600160a01b03811681036106bd5790565b90600182811c92168015610837575b602083101461082157565b634e487b7160e01b600052602260045260246000fd5b91607f1691610816565b81811061084c575050565b60008155600101610841565b359065ffffffffffff821682036106bd57565b908060209392818452848401376000828201840152601f01601f1916010190565b80546000939261089b82610807565b9182825260209360019160018116908160001461090357506001146108c2575b5050505050565b90939495506000929192528360002092846000945b8386106108ef575050505001019038808080806108bb565b8054858701830152940193859082016108d7565b60ff19168685015250505090151560051b0101915038808080806108bb565b6109306101008201826107ad565b5060018101356000526000602052604060002060018060a01b0383351660005260205261096660406000209260608101906107ad565b9290836004116106bd576003198401806020116106bd57806040116106bd57601f198501858111610c1e57806080116106bd57116106bd576109f7602091610a0c956000855460601c92610a2c604051998a968795869463c20bccb960e01b8652601081013560601c60048701526024810135602487015260a06044870152608460a4870192609f1901910161086b565b83810360031901606485015260018a0161088c565b82810360031901608484015260218a8101358b016001810135910161086b565b03925af1928315610c1257600093610bce575b5054916000916001600160a01b038216610a80575b505015610a7a5760a01b65ffffffffffff60d01b81169065ffffffffffff60a01b161790565b50600190565b9091506040519160018201356000526040600160218401358401013514610b6f575b6041600160218401358401013514610b25575b60006060526040838152630b135d3f60e11b8085526001848101356004870152602486019283526021808601358601808301356044890181905294979396602096899690959460649490930184860137602181013501013501916001600160a01b03165afa915114163880610a54565b6021828101358301606181013560001a6020526040910181376020600160806000825afa516001600160a01b038216183d1517610ab5575050600060605260405260013880610a54565b6021828101358301604181013560ff81901c601b01602090815291909201356040526001600160ff1b03909116606052600160806000825afa516001600160a01b038216183d1517610aa2575050600060605260405260013880610a54565b9092506020813d602011610c0a575b81610bea6020938361078b565b810103126106bd57516001600160a01b03811681036106bd579138610a3f565b3d9150610bdd565b6040513d6000823e3d90fd5b634e487b7160e01b600052601160045260246000fd5b610c3d816107e0565b90610cc26040610c4f602084016107e0565b93610c69610c5e8386016107f3565b9460608101906107ad565b80918451968794602086019965ffffffffffff60d01b809260d01b168b5260d01b1660268601526bffffffffffffffffffffffff199060601b16602c85015284840137810160008382015203602081018452018261078b565b5190209056fea2646970667358221220382b31db820b9e5359a6e195c39a621efa0137a06c8ea2d2183ef52d7060226264736f6c63430008180033"; + hex"6080806040523461001657610cfe908161001c8239f35b600080fdfe60806040908082526004918236101561001757600080fd5b600091823560e01c90816306fdde03146106025750806354fd4d50146105be5780636d61fe70146105b95780638a91b0e3146105b95780639700320314610563578063cb9b272c14610308578063d4511ee9146102e7578063d60b347f146102c2578063d6cc1aa4146102a8578063df73e60e146101cb578063ecd05961146101a6578063f42c859d146100ff5763f551e2ee146100b457600080fd5b346100fb5760603660031901126100fb576100cd610727565b5060443567ffffffffffffffff81116100f7576020936100ef9136910161068f565b505051908152f35b8280fd5b5080fd5b508183346100fb5760203660031901126100fb576001903592838352826020528083203384526020528220828155016101388154610807565b80610169575b505050337f10103b778a5e09e8bcc680439d97711489525190a1fe679251002e893f9ea5638380a380f35b82601f8211600114610181575050555b81838061013e565b909180825261019f601f60208420940160051c840160018501610841565b5555610179565b509190346101c85760203660031901126101c857506001602092519135148152f35b80fd5b50346100fb57806003193601126100fb576102a460016101e9610727565b838051956101f68761073d565b808752606080602098838a820152838582015201526024358152808752818120848060a01b038094168252875220948451946102318661073d565b86549165ffffffffffff9788918285168952610271818a0192848760301c168452858b019660601c875261026a8651809a81930161088c565b038861078b565b606089019687528351998a99828b52511690890152511690860152511660608401525160808084015260a083019061064f565b0390f35b50346100fb57816003193601126100fb5751908152602090f35b50346100fb5760203660031901126100fb57906020916102e0610727565b5051908152f35b50346100fb576020906103016102fc366106f5565b610c34565b9051908152f35b5082346100f757610318366106f5565b9061032282610c34565b92838552602092858452818620338752845281862065ffffffffffff9283610349846107e0565b1690868401946bffffffffffff000000000000610365876107e0565b60301b16828601936bffffffffffffffffffffffff19610384866107f3565b60601b169117178455600180940160608601946103a186886107ad565b919067ffffffffffffffff9a8b841161055057509082918e8d6103c48754610807565b90601f8211610517575b90508193601f86116001146104ad575050926104a2575b50508160011b916000199060031b1c19161790555b6104178251968988528261040d88610858565b168a890152610858565b1690850152356001600160a01b0381169081900361049e57606084015235601e198236030181121561049a57018035930191831161049657823603821361049657806104907f57aa9b35aca9ac2ac77db1278fe563afa57004616360740e680d89bc674ebd1e93608080840152339560a084019161086b565b0390a380f35b8480fd5b8680fd5b8780fd5b013590508d806103e5565b8783528183209550929392601f19871692915b8383106104ff575050509084600195949392106104e5575b505050811b0190556103fa565b0135600019600384901b60f8161c191690558d80806104d8565b8185978293949688013581550196019301908f6104c0565b87835280832061053f92601f880160051c8201928810610546575b601f0160051c0190610841565b388e6103ce565b9091508190610532565b634e487b7160e01b8f526041905260248efd5b5090346101c8576003199282843601126100fb57803567ffffffffffffffff81116100f7576101208183019582360301126100f75760646105a59101856107ad565b919050116101c85750610301602092610922565b6106c2565b50346100fb57816003193601126100fb5780516102a4916105de8261076f565b6005825264302e302e3160d81b60208301525191829160208352602083019061064f565b919050346100f757826003193601126100f7576102a492506106238261076f565b601182527029b2b9b9b4b7b725b2bca6b0b730b3b2b960791b6020830152519182916020835260208301905b919082519283825260005b84811061067b575050826000602080949584010152601f8019910116010190565b60208183018101518483018201520161065a565b9181601f840112156106bd5782359167ffffffffffffffff83116106bd57602083818601950101116106bd57565b600080fd5b346106bd5760203660031901126106bd5760043567ffffffffffffffff81116106bd576106f390369060040161068f565b005b600319906020818301126106bd576004359167ffffffffffffffff83116106bd57826080920301126106bd5760040190565b600435906001600160a01b03821682036106bd57565b6080810190811067ffffffffffffffff82111761075957604052565b634e487b7160e01b600052604160045260246000fd5b6040810190811067ffffffffffffffff82111761075957604052565b90601f8019910116810190811067ffffffffffffffff82111761075957604052565b903590601e19813603018212156106bd570180359067ffffffffffffffff82116106bd576020019181360383136106bd57565b3565ffffffffffff811681036106bd5790565b356001600160a01b03811681036106bd5790565b90600182811c92168015610837575b602083101461082157565b634e487b7160e01b600052602260045260246000fd5b91607f1691610816565b81811061084c575050565b60008155600101610841565b359065ffffffffffff821682036106bd57565b908060209392818452848401376000828201840152601f01601f1916010190565b80546000939261089b82610807565b9182825260209360019160018116908160001461090357506001146108c2575b5050505050565b90939495506000929192528360002092846000945b8386106108ef575050505001019038808080806108bb565b8054858701830152940193859082016108d7565b60ff19168685015250505090151560051b0101915038808080806108bb565b6109306101008201826107ad565b5060018101356000526000602052604060002060018060a01b0383351660005260205261096660406000209260608101906107ad565b9290836004116106bd576003198401806020116106bd57806040116106bd57601f198501858111610c1e57806080116106bd57116106bd576109f7602091610a0c956000855460601c92610a2c604051998a968795869463c20bccb960e01b8652601081013560601c60048701526024810135602487015260a06044870152608460a4870192609f1901910161086b565b83810360031901606485015260018a0161088c565b82810360031901608484015260218a8101358b016001810135910161086b565b03925af1928315610c1257600093610bce575b5054916000916001600160a01b038216610a80575b505015610a7a5760a01b65ffffffffffff60d01b81169065ffffffffffff60a01b161790565b50600190565b9091506040519160018201356000526040600160218401358401013514610b6f575b6041600160218401358401013514610b25575b60006060526040838152630b135d3f60e11b8085526001848101356004870152602486019283526021808601358601808301356044890181905294979396602096899690959460649490930184860137602181013501013501916001600160a01b03165afa915114163880610a54565b6021828101358301606181013560001a6020526040910181376020600160806000825afa516001600160a01b038216183d1517610ab5575050600060605260405260013880610a54565b6021828101358301604181013560ff81901c601b01602090815291909201356040526001600160ff1b03909116606052600160806000825afa516001600160a01b038216183d1517610aa2575050600060605260405260013880610a54565b9092506020813d602011610c0a575b81610bea6020938361078b565b810103126106bd57516001600160a01b03811681036106bd579138610a3f565b3d9150610bdd565b6040513d6000823e3d90fd5b634e487b7160e01b600052601160045260246000fd5b610c3d816107e0565b90610cc26040610c4f602084016107e0565b93610c69610c5e8386016107f3565b9460608101906107ad565b80918451968794602086019965ffffffffffff60d01b809260d01b168b5260d01b1660268601526bffffffffffffffffffffffff199060601b16602c85015284840137810160008382015203602081018452018261078b565b5190209056fea264697066735822122026a81cd670005fcd561638caf42a14771310b8b3023b89447085b3f5739e2d3364736f6c63430008180033"; 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 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/gas_calculations/testWriteGas.json b/packages/modulekit/gas_calculations/testWriteGas.json new file mode 100644 index 00000000..f1ba663a --- /dev/null +++ b/packages/modulekit/gas_calculations/testWriteGas.json @@ -0,0 +1,12 @@ +{ + "Calldata": { + "Arbitrum": "6376 gas", + "OP-Stack": "8802 gas" + }, + "Phases": { + "Creation": "539076 gas", + "Execution": "41815 gas", + "Validation": "40829 gas" + }, + "Total": "2911988 gas" +} \ No newline at end of file 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 99% rename from remappings.txt rename to packages/modulekit/remappings.txt index e80e0742..11d91084 100644 --- a/remappings.txt +++ b/packages/modulekit/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/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 82% rename from src/Modules.sol rename to packages/modulekit/src/Modules.sol index 1992c006..5222b7a3 100644 --- a/src/Modules.sol +++ b/packages/modulekit/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/packages/modulekit/src/accountFactory/MultiAccountFactory.sol b/packages/modulekit/src/accountFactory/MultiAccountFactory.sol new file mode 100644 index 00000000..69f82a6b --- /dev/null +++ b/packages/modulekit/src/accountFactory/MultiAccountFactory.sol @@ -0,0 +1,102 @@ +import "forge-std/Base.sol"; +import "./safe7579/Safe7579Factory.sol"; +import "./referenceImpl/RefImplFactory.sol"; +import { ERC7579BootstrapConfig } from "../external/ERC7579.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 createAccount( + 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(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 new file mode 100644 index 00000000..a0be61cd --- /dev/null +++ b/packages/modulekit/src/accountFactory/referenceImpl/RefImplFactory.sol @@ -0,0 +1,48 @@ +import "../../external/ERC7579.sol"; +import { LibClone } from "solady/src/utils/LibClone.sol"; + +interface IMSA { + function initializeAccount(bytes calldata initCode) external; +} + +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) { + bytes32 _salt = _getSalt(salt, initCode); + address account = LibClone.cloneDeterministic(0, address(implementation), initCode, _salt); + + IMSA(account).initializeAccount(initCode); + return account; + } + + function getAddressUMSA( + 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); +} diff --git a/packages/modulekit/src/accountFactory/safe7579/BootstrapSafe.sol b/packages/modulekit/src/accountFactory/safe7579/BootstrapSafe.sol new file mode 100644 index 00000000..73d00c2b --- /dev/null +++ b/packages/modulekit/src/accountFactory/safe7579/BootstrapSafe.sol @@ -0,0 +1,64 @@ +// 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"; + +contract BootstrapSafe 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( + ERC7579BootstrapConfig[] calldata _validators, + ERC7579BootstrapConfig[] calldata _executors, + ERC7579BootstrapConfig calldata _hook, + ERC7579BootstrapConfig 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( + ERC7579BootstrapConfig[] calldata _validators, + ERC7579BootstrapConfig[] calldata _executors, + ERC7579BootstrapConfig calldata _hook, + ERC7579BootstrapConfig 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..1d2a157d --- /dev/null +++ b/packages/modulekit/src/accountFactory/safe7579/Safe7579Factory.sol @@ -0,0 +1,76 @@ +// 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 { BootstrapSafe } from "./BootstrapSafe.sol"; + +abstract contract Safe7579Factory is TestBase { + // singletons + + SafeERC7579 internal erc7579Mod; + Safe internal safeImpl; + + BootstrapSafe internal bootstrapSafe; + + constructor() { + // Set up MSA and Factory + erc7579Mod = new SafeERC7579(); + safeImpl = new Safe(); + bootstrapSafe = new BootstrapSafe(); + } + + 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); + 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); + } + + 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/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 75% rename from src/modules/ERC7579HookDestruct.sol rename to packages/modulekit/src/modules/ERC7579HookDestruct.sol index 0adcbaea..330363e7 100644 --- a/src/modules/ERC7579HookDestruct.sol +++ b/packages/modulekit/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/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/src/test/RhinestoneModuleKit.sol b/packages/modulekit/src/test/RhinestoneModuleKit.sol similarity index 88% rename from src/test/RhinestoneModuleKit.sol rename to packages/modulekit/src/test/RhinestoneModuleKit.sol index 355f911d..2aeff995 100644 --- a/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/src/test/RhinestoneModuleKit.sol.bak b/packages/modulekit/src/test/RhinestoneModuleKit.sol.bak new file mode 100644 index 00000000..afedc21a --- /dev/null +++ b/packages/modulekit/src/test/RhinestoneModuleKit.sol.bak @@ -0,0 +1,101 @@ +// 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 { MultiAccountFactory } from "./MultiAccountFactory.sol"; +import { AccountDetection } from "./utils/AccountDetection.sol"; +import { IAccountFactory } from "../IAccountFactory.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 AccountDetection, AuxiliaryFactory, MultiAccountFactory { + IAccountFactory public accountFactory; + 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; + defaultValidator = new MockValidator(); + label(address(defaultValidator), "DefaultValidator"); + + // // 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); + } + + function makeAccountInstance(bytes32 salt) internal returns (AccountInstance memory instance) { + address account = makeAccount(accountFlavor, salt, address(defaultValidator), ""); + + instance = AccountInstance({ + account: account, + aux: auxiliary, + salt: salt, + defaultValidator: IERC7579Validator(address(defaultValidator)), + initCode: "", + gasLog: false + }); + } + + function makeAccountInstance( + bytes32 salt, + address account, + address defaultValidator, + bytes memory initCode + ) + internal + returns (AccountInstance memory instance) + { } +} 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/Diff.t.sol b/packages/modulekit/test/Diff.t.sol similarity index 100% rename from test/Diff.t.sol rename to packages/modulekit/test/Diff.t.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/MakeAccount.t.sol b/packages/modulekit/test/MakeAccount.t.sol similarity index 100% rename from test/MakeAccount.t.sol rename to packages/modulekit/test/MakeAccount.t.sol 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 737fb704..c03add87 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7,6 +7,24 @@ settings: importers: .: + devDependencies: + '@rhinestone/modulekit': + specifier: workspace:* + version: link:packages/modulekit + '@rhinestone/safe7579': + specifier: workspace:* + version: link:accounts/safe7579 + '@rhinestone/sessionkeymanager': + specifier: workspace:* + version: link:packages/SessionKeyManager + prettier: + specifier: ^2.8.8 + version: 2.8.8 + solhint: + specifier: ^4.1.1 + version: 4.1.1(typescript@5.3.3) + + accounts/safe7579: devDependencies: '@ERC4337/account-abstraction': specifier: github:kopy-kat/account-abstraction#develop @@ -20,12 +38,12 @@ importers: '@prb/math': specifier: ^4.0.2 version: 4.0.2 - '@rhinestone/safe7579': + '@rhinestone/modulekit': specifier: workspace:* - version: link:accounts/safe7579 + version: link:../../packages/modulekit '@rhinestone/sessionkeymanager': specifier: workspace:* - version: link:packages/SessionKeyManager + version: link:../../packages/SessionKeyManager '@safe-global/safe-contracts': specifier: ^1.4.1 version: 1.4.1(ethers@5.4.0) @@ -37,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 @@ -46,34 +64,52 @@ 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 solhint: specifier: ^4.1.1 version: 4.1.1(typescript@5.3.3) + solmate: + specifier: github:transmissions11/solmate + version: github.com/transmissions11/solmate/c892309933b25c03d32b1b0d674df7ae292ba925 - accounts/safe7579: + examples: 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:../.. + 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 @@ -99,7 +135,7 @@ importers: specifier: github:transmissions11/solmate version: github.com/transmissions11/solmate/c892309933b25c03d32b1b0d674df7ae292ba925 - examples: + packages/SessionKeyManager: devDependencies: '@ERC4337/account-abstraction': specifier: github:kopy-kat/account-abstraction#develop @@ -107,24 +143,12 @@ importers: '@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) - '@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 + version: link:../modulekit 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 @@ -140,33 +164,42 @@ importers: 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) - solmate: - specifier: github:transmissions11/solmate - version: github.com/transmissions11/solmate/c892309933b25c03d32b1b0d674df7ae292ba925 - 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:../../accounts/safe7579 + '@rhinestone/sessionkeymanager': specifier: workspace:* - version: link:../.. + 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 @@ -175,10 +208,13 @@ 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 solhint: specifier: ^4.1.1 version: 4.1.1(typescript@5.3.3) @@ -4426,6 +4462,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 @@ -4568,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: @@ -4583,6 +4627,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 @@ -4594,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