diff --git a/accounts/safe7579/src/core/ModuleManager.sol b/accounts/safe7579/src/core/ModuleManager.sol index ab6f3f22..9d6f8b5a 100644 --- a/accounts/safe7579/src/core/ModuleManager.sol +++ b/accounts/safe7579/src/core/ModuleManager.sol @@ -2,7 +2,8 @@ pragma solidity ^0.8.23; import { SentinelListLib, SENTINEL } from "sentinellist/SentinelList.sol"; -import { IExecutor, IValidator, IFallback } from "erc7579/interfaces/IERC7579Module.sol"; +import { SentinelList4337Lib } from "sentinellist/SentinelList4337.sol"; +import { IModule, IExecutor, IValidator, IFallback } from "erc7579/interfaces/IERC7579Module.sol"; import { ExecutionHelper } from "./ExecutionHelper.sol"; import { Receiver } from "erc7579/core/Receiver.sol"; import { AccessControl } from "./AccessControl.sol"; @@ -19,10 +20,13 @@ struct ModuleManagerStorage { address fallbackHandler; } -// keccak256("modulemanager.storage.msa"); -bytes32 constant MODULEMANAGER_STORAGE_LOCATION = - 0xf88ce1fdb7fb1cbd3282e49729100fa3f2d6ee9f797961fe4fb1871cea89ea02; - +// // keccak256("modulemanager.storage.msa"); +// bytes32 constant MODULEMANAGER_STORAGE_LOCATION = +// 0xf88ce1fdb7fb1cbd3282e49729100fa3f2d6ee9f797961fe4fb1871cea89ea02; +// +// // keccak256("modulemanager.validator.storage.msa") +// bytes32 constant VALIDATOR_STORAGE_LOCATION = +// 0x7ab08468dcbe2bcd9b34ba12d148d0310762840a62884f0cdee905ee43538c87; /** * @title ModuleManager * Contract that implements ERC7579 Module compatibility for Safe accounts @@ -30,7 +34,7 @@ bytes32 constant MODULEMANAGER_STORAGE_LOCATION = */ abstract contract ModuleManager is AccessControl, Receiver, ExecutionHelper { using SentinelListLib for SentinelListLib.SentinelList; - using ValidatorStorageLib for SentinelListLib.SentinelList; + using SentinelList4337Lib for SentinelList4337Lib.SentinelList; error InvalidModule(address module); error LinkedListError(); @@ -42,17 +46,7 @@ abstract contract ModuleManager is AccessControl, Receiver, ExecutionHelper { mapping(address smartAccount => ModuleManagerStorage) private $moduleManager; - constructor() { - VALIDATOR_STORAGE = new ValidatorStorageHelper(); - } - - function _getModuleManagerStorage(address account) - internal - view - returns (ModuleManagerStorage storage ims) - { - return $moduleManager[account]; - } + SentinelList4337Lib.SentinelList $validators; modifier onlyExecutorModule() { if (!_isExecutorInstalled(_msgSender())) revert InvalidModule(_msgSender()); @@ -67,18 +61,11 @@ abstract contract ModuleManager is AccessControl, Receiver, ExecutionHelper { * Validators are stored within the Safe's account storage. */ function _initModuleManager() internal { - bool success = ISafe(msg.sender).execTransactionFromModule({ - to: address(VALIDATOR_STORAGE), - value: 0, - data: abi.encodeCall(ValidatorStorageHelper.initModuleManager, ()), - operation: 1 // <--- DELEGATECALL - }); - // this will be false if the list is already initialized - if (!success) revert InitializerError(); + ModuleManagerStorage storage $mms = $moduleManager[msg.sender]; - ModuleManagerStorage storage ims = _getModuleManagerStorage(msg.sender); // this will revert if list is already initialized - ims._executors.init(); + $validators.init({ account: msg.sender }); + $mms._executors.init(); } ///////////////////////////////////////////////////// @@ -91,13 +78,15 @@ abstract contract ModuleManager is AccessControl, Receiver, ExecutionHelper { * the onInstall call to the module(ERC7579), will be executed from the Safe */ function _installValidator(address validator, bytes memory data) internal virtual { - bool success = ISafe(msg.sender).execTransactionFromModule({ - to: address(VALIDATOR_STORAGE), + $validators.push({ account: msg.sender, newEntry: validator }); + + // Initialize Validator Module via Account + _execute({ + safe: msg.sender, + target: validator, value: 0, - data: abi.encodeCall(ValidatorStorageHelper.installValidator, (validator, data)), - operation: 1 // <-- DELEGATECALL - }); - if (!success) revert ValidatorStorageHelperError(); + callData: abi.encodeCall(IModule.onInstall, (data)) + }); } /** @@ -107,13 +96,16 @@ abstract contract ModuleManager is AccessControl, Receiver, ExecutionHelper { * the onUninstall call to the module (ERC7579), will be executed from the Safe */ function _uninstallValidator(address validator, bytes memory data) internal { - bool success = ISafe(msg.sender).execTransactionFromModule({ - to: address(VALIDATOR_STORAGE), + (address prev, bytes memory disableModuleData) = abi.decode(data, (address, bytes)); + $validators.pop({ account: msg.sender, prevEntry: prev, popEntry: validator }); + + // De-Initialize Validator Module via Account + _execute({ + safe: msg.sender, + target: validator, value: 0, - data: abi.encodeCall(ValidatorStorageHelper.uninstallValidator, (validator, data)), - operation: 1 // <-- DELEGATECALL - }); - if (!success) revert ValidatorStorageHelperError(); + callData: abi.encodeCall(IModule.onUninstall, (disableModuleData)) + }); } /** @@ -127,12 +119,7 @@ abstract contract ModuleManager is AccessControl, Receiver, ExecutionHelper { virtual returns (bool isInstalled) { - // calculate slot for linked list - SentinelListLib.SentinelList storage $validators = $validator()._validators; - // predict slot for validator in ValidatorStorageHelper linked list - address link = $validators.getNextEntry(validator); - // See https://github.com/zeroknots/sentinellist/blob/main/src/SentinelList.sol#L52 - isInstalled = SENTINEL != validator && link != address(0); + isInstalled = $validators.contains({ account: msg.sender, entry: validator }); } /** @@ -148,29 +135,11 @@ abstract contract ModuleManager is AccessControl, Receiver, ExecutionHelper { virtual returns (address[] memory array, address next) { - if (start != SENTINEL && _isExecutorInstalled(start)) revert LinkedListError(); - if (pageSize == 0) revert LinkedListError(); - - array = new address[](pageSize); - - // Populate return array - uint256 entryCount; - SentinelListLib.SentinelList storage $validators = $validator()._validators; - next = $validators.getNextEntry(start); - while (next != address(0) && next != SENTINEL && entryCount < pageSize) { - array[entryCount] = next; - next = $validators.getNextEntry(next); - entryCount++; - } - - if (next != SENTINEL) { - next = array[entryCount - 1]; - } - // Set correct size of returned array - // solhint-disable-next-line no-inline-assembly - assembly ("memory-safe") { - mstore(array, entryCount) - } + return $validators.getEntriesPaginated({ + account: msg.sender, + start: start, + pageSize: pageSize + }); } ///////////////////////////////////////////////////// @@ -178,26 +147,34 @@ abstract contract ModuleManager is AccessControl, Receiver, ExecutionHelper { //////////////////////////////////////////////////// function _installExecutor(address executor, bytes memory data) internal { - SentinelListLib.SentinelList storage _executors = - _getModuleManagerStorage(msg.sender)._executors; - _executors.push(executor); - // TODO: - IExecutor(executor).onInstall(data); + SentinelListLib.SentinelList storage $executors = $moduleManager[msg.sender]._executors; + $executors.push(executor); + // Initialize Executor Module via Account + _execute({ + safe: msg.sender, + target: executor, + value: 0, + callData: abi.encodeCall(IModule.onInstall, (data)) + }); } function _uninstallExecutor(address executor, bytes calldata data) internal { - SentinelListLib.SentinelList storage _executors = - _getModuleManagerStorage(msg.sender)._executors; + SentinelListLib.SentinelList storage $executors = $moduleManager[msg.sender]._executors; (address prev, bytes memory disableModuleData) = abi.decode(data, (address, bytes)); - _executors.pop(prev, executor); - // TODO: - IExecutor(executor).onUninstall(disableModuleData); + $executors.pop(prev, executor); + + // De-Initialize Executor Module via Account + _execute({ + safe: msg.sender, + target: executor, + value: 0, + callData: abi.encodeCall(IModule.onUninstall, (disableModuleData)) + }); } function _isExecutorInstalled(address executor) internal view virtual returns (bool) { - SentinelListLib.SentinelList storage _executors = - _getModuleManagerStorage(msg.sender)._executors; - return _executors.contains(executor); + SentinelListLib.SentinelList storage $executors = $moduleManager[msg.sender]._executors; + return $executors.contains(executor); } /** * THIS IS NOT PART OF THE STANDARD @@ -213,9 +190,8 @@ abstract contract ModuleManager is AccessControl, Receiver, ExecutionHelper { virtual returns (address[] memory array, address next) { - SentinelListLib.SentinelList storage _executors = - _getModuleManagerStorage(msg.sender)._executors; - return _executors.getEntriesPaginated(cursor, size); + SentinelListLib.SentinelList storage $executors = $moduleManager[msg.sender]._executors; + return $executors.getEntriesPaginated(cursor, size); } ///////////////////////////////////////////////////// @@ -223,20 +199,32 @@ abstract contract ModuleManager is AccessControl, Receiver, ExecutionHelper { //////////////////////////////////////////////////// function _installFallbackHandler(address handler, bytes calldata initData) internal virtual { - ModuleManagerStorage storage ims = _getModuleManagerStorage(msg.sender); - ims.fallbackHandler = handler; - IFallback(handler).onInstall(initData); + ModuleManagerStorage storage $mms = $moduleManager[msg.sender]; + $mms.fallbackHandler = handler; + // Initialize Fallback Module via Account + _execute({ + safe: msg.sender, + target: handler, + value: 0, + callData: abi.encodeCall(IModule.onInstall, (initData)) + }); } function _uninstallFallbackHandler(address handler, bytes calldata initData) internal virtual { - ModuleManagerStorage storage ims = _getModuleManagerStorage(msg.sender); - ims.fallbackHandler = address(0); - IFallback(handler).onUninstall(initData); + ModuleManagerStorage storage $mms = $moduleManager[msg.sender]; + $mms.fallbackHandler = address(0); + // De-Initialize Fallback Module via Account + _execute({ + safe: msg.sender, + target: handler, + value: 0, + callData: abi.encodeCall(IModule.onUninstall, (initData)) + }); } function _getFallbackHandler() internal view virtual returns (address fallbackHandler) { - ModuleManagerStorage storage ims = _getModuleManagerStorage(msg.sender); - return ims.fallbackHandler; + ModuleManagerStorage storage $mms = $moduleManager[msg.sender]; + return $mms.fallbackHandler; } function _isFallbackHandlerInstalled(address _handler) internal view virtual returns (bool) { diff --git a/accounts/safe7579/src/core/ModuleManager.sol.bak b/accounts/safe7579/src/core/ModuleManager.sol.bak new file mode 100644 index 00000000..ab6f3f22 --- /dev/null +++ b/accounts/safe7579/src/core/ModuleManager.sol.bak @@ -0,0 +1,287 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.23; + +import { SentinelListLib, SENTINEL } from "sentinellist/SentinelList.sol"; +import { IExecutor, IValidator, IFallback } from "erc7579/interfaces/IERC7579Module.sol"; +import { ExecutionHelper } from "./ExecutionHelper.sol"; +import { Receiver } from "erc7579/core/Receiver.sol"; +import { AccessControl } from "./AccessControl.sol"; +import { ISafe } from "../interfaces/ISafe.sol"; +import { + ValidatorStorageHelper, ValidatorStorageLib, $validator +} from "./ValidatorStorageHelper.sol"; + +struct ModuleManagerStorage { + // linked list of executors. List is initialized by initializeAccount() + SentinelListLib.SentinelList _executors; + // single fallback handler for all fallbacks + // account vendors may implement this differently. This is just a reference implementation + address fallbackHandler; +} + +// keccak256("modulemanager.storage.msa"); +bytes32 constant MODULEMANAGER_STORAGE_LOCATION = + 0xf88ce1fdb7fb1cbd3282e49729100fa3f2d6ee9f797961fe4fb1871cea89ea02; + +/** + * @title ModuleManager + * Contract that implements ERC7579 Module compatibility for Safe accounts + * @author zeroknots.eth | rhinestone.wtf + */ +abstract contract ModuleManager is AccessControl, Receiver, ExecutionHelper { + using SentinelListLib for SentinelListLib.SentinelList; + using ValidatorStorageLib for SentinelListLib.SentinelList; + + error InvalidModule(address module); + error LinkedListError(); + error CannotRemoveLastValidator(); + error InitializerError(); + error ValidatorStorageHelperError(); + + ValidatorStorageHelper internal immutable VALIDATOR_STORAGE; + + mapping(address smartAccount => ModuleManagerStorage) private $moduleManager; + + constructor() { + VALIDATOR_STORAGE = new ValidatorStorageHelper(); + } + + function _getModuleManagerStorage(address account) + internal + view + returns (ModuleManagerStorage storage ims) + { + return $moduleManager[account]; + } + + modifier onlyExecutorModule() { + if (!_isExecutorInstalled(_msgSender())) revert InvalidModule(_msgSender()); + _; + } + + /** + * Initializes linked list that handles installed Validator and Executor + * For Validators: + * The Safe Account will call VALIDATOR_STORAGE via DELEGTATECALL. + * Due to the storage restrictions of ERC-4337 of the validation phase, + * Validators are stored within the Safe's account storage. + */ + function _initModuleManager() internal { + bool success = ISafe(msg.sender).execTransactionFromModule({ + to: address(VALIDATOR_STORAGE), + value: 0, + data: abi.encodeCall(ValidatorStorageHelper.initModuleManager, ()), + operation: 1 // <--- DELEGATECALL + }); + // this will be false if the list is already initialized + if (!success) revert InitializerError(); + + ModuleManagerStorage storage ims = _getModuleManagerStorage(msg.sender); + // this will revert if list is already initialized + ims._executors.init(); + } + + ///////////////////////////////////////////////////// + // Manage Validators + //////////////////////////////////////////////////// + /** + * install and initialize validator module + * @dev this function Write into the Safe account storage (validator linked) list via + * ValidatorStorageHelper DELEGATECALL + * the onInstall call to the module(ERC7579), will be executed from the Safe + */ + function _installValidator(address validator, bytes memory data) internal virtual { + bool success = ISafe(msg.sender).execTransactionFromModule({ + to: address(VALIDATOR_STORAGE), + value: 0, + data: abi.encodeCall(ValidatorStorageHelper.installValidator, (validator, data)), + operation: 1 // <-- DELEGATECALL + }); + if (!success) revert ValidatorStorageHelperError(); + } + + /** + * Uninstall and de-initialize validator module + * @dev this function Write into the Safe account storage (validator linked) list via + * ValidatorStorageHelper DELEGATECALL + * the onUninstall call to the module (ERC7579), will be executed from the Safe + */ + function _uninstallValidator(address validator, bytes memory data) internal { + bool success = ISafe(msg.sender).execTransactionFromModule({ + to: address(VALIDATOR_STORAGE), + value: 0, + data: abi.encodeCall(ValidatorStorageHelper.uninstallValidator, (validator, data)), + operation: 1 // <-- DELEGATECALL + }); + if (!success) revert ValidatorStorageHelperError(); + } + + /** + * Helper function that will calculate storage slot for + * validator address within the linked list in ValidatorStorageHelper + * and use Safe's getStorageAt() to read 32bytes from Safe's storage + */ + function _isValidatorInstalled(address validator) + internal + view + virtual + returns (bool isInstalled) + { + // calculate slot for linked list + SentinelListLib.SentinelList storage $validators = $validator()._validators; + // predict slot for validator in ValidatorStorageHelper linked list + address link = $validators.getNextEntry(validator); + // See https://github.com/zeroknots/sentinellist/blob/main/src/SentinelList.sol#L52 + isInstalled = SENTINEL != validator && link != address(0); + } + + /** + * THIS IS NOT PART OF THE STANDARD + * Helper Function to access linked list + */ + function getValidatorPaginated( + address start, + uint256 pageSize + ) + external + view + virtual + returns (address[] memory array, address next) + { + if (start != SENTINEL && _isExecutorInstalled(start)) revert LinkedListError(); + if (pageSize == 0) revert LinkedListError(); + + array = new address[](pageSize); + + // Populate return array + uint256 entryCount; + SentinelListLib.SentinelList storage $validators = $validator()._validators; + next = $validators.getNextEntry(start); + while (next != address(0) && next != SENTINEL && entryCount < pageSize) { + array[entryCount] = next; + next = $validators.getNextEntry(next); + entryCount++; + } + + if (next != SENTINEL) { + next = array[entryCount - 1]; + } + // Set correct size of returned array + // solhint-disable-next-line no-inline-assembly + assembly ("memory-safe") { + mstore(array, entryCount) + } + } + + ///////////////////////////////////////////////////// + // Manage Executors + //////////////////////////////////////////////////// + + function _installExecutor(address executor, bytes memory data) internal { + SentinelListLib.SentinelList storage _executors = + _getModuleManagerStorage(msg.sender)._executors; + _executors.push(executor); + // TODO: + IExecutor(executor).onInstall(data); + } + + function _uninstallExecutor(address executor, bytes calldata data) internal { + SentinelListLib.SentinelList storage _executors = + _getModuleManagerStorage(msg.sender)._executors; + (address prev, bytes memory disableModuleData) = abi.decode(data, (address, bytes)); + _executors.pop(prev, executor); + // TODO: + IExecutor(executor).onUninstall(disableModuleData); + } + + function _isExecutorInstalled(address executor) internal view virtual returns (bool) { + SentinelListLib.SentinelList storage _executors = + _getModuleManagerStorage(msg.sender)._executors; + return _executors.contains(executor); + } + /** + * THIS IS NOT PART OF THE STANDARD + * Helper Function to access linked list + */ + + function getExecutorsPaginated( + address cursor, + uint256 size + ) + external + view + virtual + returns (address[] memory array, address next) + { + SentinelListLib.SentinelList storage _executors = + _getModuleManagerStorage(msg.sender)._executors; + return _executors.getEntriesPaginated(cursor, size); + } + + ///////////////////////////////////////////////////// + // Manage Fallback + //////////////////////////////////////////////////// + + function _installFallbackHandler(address handler, bytes calldata initData) internal virtual { + ModuleManagerStorage storage ims = _getModuleManagerStorage(msg.sender); + ims.fallbackHandler = handler; + IFallback(handler).onInstall(initData); + } + + function _uninstallFallbackHandler(address handler, bytes calldata initData) internal virtual { + ModuleManagerStorage storage ims = _getModuleManagerStorage(msg.sender); + ims.fallbackHandler = address(0); + IFallback(handler).onUninstall(initData); + } + + function _getFallbackHandler() internal view virtual returns (address fallbackHandler) { + ModuleManagerStorage storage ims = _getModuleManagerStorage(msg.sender); + return ims.fallbackHandler; + } + + function _isFallbackHandlerInstalled(address _handler) internal view virtual returns (bool) { + return _getFallbackHandler() == _handler; + } + + function getActiveFallbackHandler() external view virtual returns (address) { + return _getFallbackHandler(); + } + + // FALLBACK + fallback() external payable override(Receiver) receiverFallback { + address handler = _getFallbackHandler(); + if (handler == address(0)) revert(); + /* solhint-disable no-inline-assembly */ + /// @solidity memory-safe-assembly + // solhint-disable-next-line no-inline-assembly + assembly { + // When compiled with the optimizer, the compiler relies on a certain assumptions on how + // the + // memory is used, therefore we need to guarantee memory safety (keeping the free memory + // point 0x40 slot intact, + // not going beyond the scratch space, etc) + // Solidity docs: https://docs.soliditylang.org/en/latest/assembly.html#memory-safety + function allocate(length) -> pos { + pos := mload(0x40) + mstore(0x40, add(pos, length)) + } + + let calldataPtr := allocate(calldatasize()) + calldatacopy(calldataPtr, 0, calldatasize()) + + // The msg.sender address is shifted to the left by 12 bytes to remove the padding + // Then the address without padding is stored right after the calldata + let senderPtr := allocate(20) + mstore(senderPtr, shl(96, caller())) + + // Add 20 bytes for the address appended add the end + let success := call(gas(), handler, 0, calldataPtr, add(calldatasize(), 20), 0, 0) + + let returnDataPtr := allocate(returndatasize()) + returndatacopy(returnDataPtr, 0, returndatasize()) + if iszero(success) { revert(returnDataPtr, returndatasize()) } + return(returnDataPtr, returndatasize()) + } + /* solhint-enable no-inline-assembly */ + } +} diff --git a/packages/modulekit/gas_calculations/testWriteGas.json b/packages/modulekit/gas_calculations/testWriteGas.json index a0c00af0..f1ba663a 100644 --- a/packages/modulekit/gas_calculations/testWriteGas.json +++ b/packages/modulekit/gas_calculations/testWriteGas.json @@ -4,9 +4,9 @@ "OP-Stack": "8802 gas" }, "Phases": { - "Creation": "549886 gas", - "Execution": "41448 gas", - "Validation": "42835 gas" + "Creation": "539076 gas", + "Execution": "41815 gas", + "Validation": "40829 gas" }, - "Total": "2924474 gas" + "Total": "2911988 gas" } \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 85bafa51..c03add87 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -55,7 +55,7 @@ importers: version: github.com/rhinestonewtf/erc4337-validation/19a97d86f8f29709664334078925b2a843be19e0 erc7579: specifier: github:erc7579/erc7579-implementation - version: github.com/erc7579/erc7579-implementation/be581c908df73f1554f466cb6b47c8ce8777e50f + version: github.com/erc7579/erc7579-implementation/957cd05deeab6a9a85343bb8d1c9701705ed4ecf forge-std: specifier: github:foundry-rs/forge-std version: github.com/foundry-rs/forge-std/1d0766bc5d814f117c7b1e643828f7d85024fb51 @@ -64,10 +64,10 @@ importers: version: 2.8.8 sentinellist: specifier: github:zeroknots/sentinellist - version: github.com/zeroknots/sentinellist/1f9ec0250f1b3f14ba5d200629e3d9f3264fde61 + version: github.com/zeroknots/sentinellist/2783f466b6d9c457da0a240e392db183ca1607bb solady: specifier: github:vectorized/solady - version: github.com/vectorized/solady/9deb9ed36a27261a8745db5b7cd7f4cdc3b1cd4e + version: github.com/vectorized/solady/1372606383445c0a247e6c58eb255a529734258a solarray: specifier: github:sablier-labs/solarray version: github.com/sablier-labs/solarray/6bf10cb34cdace52a3ba5fe437e78cc82df92684 @@ -208,7 +208,7 @@ importers: version: 2.8.8 sentinellist: specifier: github:zeroknots/sentinellist - version: github.com/zeroknots/sentinellist/1f9ec0250f1b3f14ba5d200629e3d9f3264fde61 + version: github.com/zeroknots/sentinellist/2783f466b6d9c457da0a240e392db183ca1607bb solady: specifier: github:vectorized/solady version: github.com/vectorized/solady/1372606383445c0a247e6c58eb255a529734258a @@ -261,15 +261,15 @@ packages: /@ethersproject/abi@5.4.0: resolution: {integrity: sha512-9gU2H+/yK1j2eVMdzm6xvHSnMxk8waIHQGYCZg5uvAyH0rsAzxkModzBSpbAkAuhKFEovC2S9hM4nPuLym8IZw==} dependencies: - '@ethersproject/address': 5.7.0 - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/constants': 5.7.0 - '@ethersproject/hash': 5.7.0 - '@ethersproject/keccak256': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/properties': 5.7.0 - '@ethersproject/strings': 5.7.0 + '@ethersproject/address': 5.4.0 + '@ethersproject/bignumber': 5.4.0 + '@ethersproject/bytes': 5.4.0 + '@ethersproject/constants': 5.4.0 + '@ethersproject/hash': 5.4.0 + '@ethersproject/keccak256': 5.4.0 + '@ethersproject/logger': 5.4.0 + '@ethersproject/properties': 5.4.0 + '@ethersproject/strings': 5.4.0 dev: true /@ethersproject/abi@5.7.0: @@ -289,13 +289,13 @@ packages: /@ethersproject/abstract-provider@5.4.0: resolution: {integrity: sha512-vPBR7HKUBY0lpdllIn7tLIzNN7DrVnhCLKSzY0l8WAwxz686m/aL7ASDzrVxV93GJtIub6N2t4dfZ29CkPOxgA==} dependencies: - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/networks': 5.7.1 - '@ethersproject/properties': 5.7.0 - '@ethersproject/transactions': 5.7.0 - '@ethersproject/web': 5.7.1 + '@ethersproject/bignumber': 5.4.0 + '@ethersproject/bytes': 5.4.0 + '@ethersproject/logger': 5.4.0 + '@ethersproject/networks': 5.4.0 + '@ethersproject/properties': 5.4.0 + '@ethersproject/transactions': 5.4.0 + '@ethersproject/web': 5.4.0 dev: true /@ethersproject/abstract-provider@5.7.0: @@ -313,11 +313,11 @@ packages: /@ethersproject/abstract-signer@5.4.0: resolution: {integrity: sha512-AieQAzt05HJZS2bMofpuxMEp81AHufA5D6M4ScKwtolj041nrfIbIi8ciNW7+F59VYxXq+V4c3d568Q6l2m8ew==} dependencies: - '@ethersproject/abstract-provider': 5.7.0 - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/properties': 5.7.0 + '@ethersproject/abstract-provider': 5.4.0 + '@ethersproject/bignumber': 5.4.0 + '@ethersproject/bytes': 5.4.0 + '@ethersproject/logger': 5.4.0 + '@ethersproject/properties': 5.4.0 dev: true /@ethersproject/abstract-signer@5.7.0: @@ -333,11 +333,11 @@ packages: /@ethersproject/address@5.4.0: resolution: {integrity: sha512-SD0VgOEkcACEG/C6xavlU1Hy3m5DGSXW3CUHkaaEHbAPPsgi0coP5oNPsxau8eTlZOk/bpa/hKeCNoK5IzVI2Q==} dependencies: - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/keccak256': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/rlp': 5.7.0 + '@ethersproject/bignumber': 5.4.0 + '@ethersproject/bytes': 5.4.0 + '@ethersproject/keccak256': 5.4.0 + '@ethersproject/logger': 5.4.0 + '@ethersproject/rlp': 5.4.0 dev: true /@ethersproject/address@5.7.0: @@ -353,7 +353,7 @@ packages: /@ethersproject/base64@5.4.0: resolution: {integrity: sha512-CjQw6E17QDSSC5jiM9YpF7N1aSCHmYGMt9bWD8PWv6YPMxjsys2/Q8xLrROKI3IWJ7sFfZ8B3flKDTM5wlWuZQ==} dependencies: - '@ethersproject/bytes': 5.7.0 + '@ethersproject/bytes': 5.4.0 dev: true /@ethersproject/base64@5.7.0: @@ -365,8 +365,8 @@ packages: /@ethersproject/basex@5.4.0: resolution: {integrity: sha512-J07+QCVJ7np2bcpxydFVf/CuYo9mZ7T73Pe7KQY4c1lRlrixMeblauMxHXD0MPwFmUHZIILDNViVkykFBZylbg==} dependencies: - '@ethersproject/bytes': 5.7.0 - '@ethersproject/properties': 5.7.0 + '@ethersproject/bytes': 5.4.0 + '@ethersproject/properties': 5.4.0 dev: true /@ethersproject/basex@5.7.0: @@ -379,8 +379,8 @@ packages: /@ethersproject/bignumber@5.4.0: resolution: {integrity: sha512-OXUu9f9hO3vGRIPxU40cignXZVaYyfx6j9NNMjebKdnaCL3anCLSSy8/b8d03vY6dh7duCC0kW72GEC4tZer2w==} dependencies: - '@ethersproject/bytes': 5.7.0 - '@ethersproject/logger': 5.7.0 + '@ethersproject/bytes': 5.4.0 + '@ethersproject/logger': 5.4.0 bn.js: 4.12.0 dev: true @@ -395,7 +395,7 @@ packages: /@ethersproject/bytes@5.4.0: resolution: {integrity: sha512-H60ceqgTHbhzOj4uRc/83SCN9d+BSUnOkrr2intevqdtEMO1JFVZ1XL84OEZV+QjV36OaZYxtnt4lGmxcGsPfA==} dependencies: - '@ethersproject/logger': 5.7.0 + '@ethersproject/logger': 5.4.0 dev: true /@ethersproject/bytes@5.7.0: @@ -407,7 +407,7 @@ packages: /@ethersproject/constants@5.4.0: resolution: {integrity: sha512-tzjn6S7sj9+DIIeKTJLjK9WGN2Tj0P++Z8ONEIlZjyoTkBuODN+0VfhAyYksKi43l1Sx9tX2VlFfzjfmr5Wl3Q==} dependencies: - '@ethersproject/bignumber': 5.7.0 + '@ethersproject/bignumber': 5.4.0 dev: true /@ethersproject/constants@5.7.0: @@ -419,16 +419,16 @@ packages: /@ethersproject/contracts@5.4.0: resolution: {integrity: sha512-hkO3L3IhS1Z3ZtHtaAG/T87nQ7KiPV+/qnvutag35I0IkiQ8G3ZpCQ9NNOpSCzn4pWSW4CfzmtE02FcqnLI+hw==} dependencies: - '@ethersproject/abi': 5.7.0 - '@ethersproject/abstract-provider': 5.7.0 - '@ethersproject/abstract-signer': 5.7.0 - '@ethersproject/address': 5.7.0 - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/constants': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/properties': 5.7.0 - '@ethersproject/transactions': 5.7.0 + '@ethersproject/abi': 5.4.0 + '@ethersproject/abstract-provider': 5.4.0 + '@ethersproject/abstract-signer': 5.4.0 + '@ethersproject/address': 5.4.0 + '@ethersproject/bignumber': 5.4.0 + '@ethersproject/bytes': 5.4.0 + '@ethersproject/constants': 5.4.0 + '@ethersproject/logger': 5.4.0 + '@ethersproject/properties': 5.4.0 + '@ethersproject/transactions': 5.4.0 dev: true /@ethersproject/contracts@5.7.0: @@ -449,14 +449,14 @@ packages: /@ethersproject/hash@5.4.0: resolution: {integrity: sha512-xymAM9tmikKgbktOCjW60Z5sdouiIIurkZUr9oW5NOex5uwxrbsYG09kb5bMcNjlVeJD3yPivTNzViIs1GCbqA==} dependencies: - '@ethersproject/abstract-signer': 5.7.0 - '@ethersproject/address': 5.7.0 - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/keccak256': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/properties': 5.7.0 - '@ethersproject/strings': 5.7.0 + '@ethersproject/abstract-signer': 5.4.0 + '@ethersproject/address': 5.4.0 + '@ethersproject/bignumber': 5.4.0 + '@ethersproject/bytes': 5.4.0 + '@ethersproject/keccak256': 5.4.0 + '@ethersproject/logger': 5.4.0 + '@ethersproject/properties': 5.4.0 + '@ethersproject/strings': 5.4.0 dev: true /@ethersproject/hash@5.7.0: @@ -476,18 +476,18 @@ packages: /@ethersproject/hdnode@5.4.0: resolution: {integrity: sha512-pKxdS0KAaeVGfZPp1KOiDLB0jba11tG6OP1u11QnYfb7pXn6IZx0xceqWRr6ygke8+Kw74IpOoSi7/DwANhy8Q==} dependencies: - '@ethersproject/abstract-signer': 5.7.0 - '@ethersproject/basex': 5.7.0 - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/pbkdf2': 5.7.0 - '@ethersproject/properties': 5.7.0 - '@ethersproject/sha2': 5.7.0 - '@ethersproject/signing-key': 5.7.0 - '@ethersproject/strings': 5.7.0 - '@ethersproject/transactions': 5.7.0 - '@ethersproject/wordlists': 5.7.0 + '@ethersproject/abstract-signer': 5.4.0 + '@ethersproject/basex': 5.4.0 + '@ethersproject/bignumber': 5.4.0 + '@ethersproject/bytes': 5.4.0 + '@ethersproject/logger': 5.4.0 + '@ethersproject/pbkdf2': 5.4.0 + '@ethersproject/properties': 5.4.0 + '@ethersproject/sha2': 5.4.0 + '@ethersproject/signing-key': 5.4.0 + '@ethersproject/strings': 5.4.0 + '@ethersproject/transactions': 5.4.0 + '@ethersproject/wordlists': 5.4.0 dev: true /@ethersproject/hdnode@5.7.0: @@ -510,17 +510,17 @@ packages: /@ethersproject/json-wallets@5.4.0: resolution: {integrity: sha512-igWcu3fx4aiczrzEHwG1xJZo9l1cFfQOWzTqwRw/xcvxTk58q4f9M7cjh51EKphMHvrJtcezJ1gf1q1AUOfEQQ==} dependencies: - '@ethersproject/abstract-signer': 5.7.0 - '@ethersproject/address': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/hdnode': 5.7.0 - '@ethersproject/keccak256': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/pbkdf2': 5.7.0 - '@ethersproject/properties': 5.7.0 - '@ethersproject/random': 5.7.0 - '@ethersproject/strings': 5.7.0 - '@ethersproject/transactions': 5.7.0 + '@ethersproject/abstract-signer': 5.4.0 + '@ethersproject/address': 5.4.0 + '@ethersproject/bytes': 5.4.0 + '@ethersproject/hdnode': 5.4.0 + '@ethersproject/keccak256': 5.4.0 + '@ethersproject/logger': 5.4.0 + '@ethersproject/pbkdf2': 5.4.0 + '@ethersproject/properties': 5.4.0 + '@ethersproject/random': 5.4.0 + '@ethersproject/strings': 5.4.0 + '@ethersproject/transactions': 5.4.0 aes-js: 3.0.0 scrypt-js: 3.0.1 dev: true @@ -546,7 +546,7 @@ packages: /@ethersproject/keccak256@5.4.0: resolution: {integrity: sha512-FBI1plWet+dPUvAzPAeHzRKiPpETQzqSUWR1wXJGHVWi4i8bOSrpC3NwpkPjgeXG7MnugVc1B42VbfnQikyC/A==} dependencies: - '@ethersproject/bytes': 5.7.0 + '@ethersproject/bytes': 5.4.0 js-sha3: 0.5.7 dev: true @@ -568,7 +568,7 @@ packages: /@ethersproject/networks@5.4.0: resolution: {integrity: sha512-5fywtKRDcnaVeA5SjxXH3DOQqe/IbeD/plwydi94SdPps1fbDUrnO6SzDExaruBZXxpxJcO9upG9UComsei4bg==} dependencies: - '@ethersproject/logger': 5.7.0 + '@ethersproject/logger': 5.4.0 dev: true /@ethersproject/networks@5.7.1: @@ -580,8 +580,8 @@ packages: /@ethersproject/pbkdf2@5.4.0: resolution: {integrity: sha512-x94aIv6tiA04g6BnazZSLoRXqyusawRyZWlUhKip2jvoLpzJuLb//KtMM6PEovE47pMbW+Qe1uw+68ameJjB7g==} dependencies: - '@ethersproject/bytes': 5.7.0 - '@ethersproject/sha2': 5.7.0 + '@ethersproject/bytes': 5.4.0 + '@ethersproject/sha2': 5.4.0 dev: true /@ethersproject/pbkdf2@5.7.0: @@ -594,7 +594,7 @@ packages: /@ethersproject/properties@5.4.0: resolution: {integrity: sha512-7jczalGVRAJ+XSRvNA6D5sAwT4gavLq3OXPuV/74o3Rd2wuzSL035IMpIMgei4CYyBdialJMrTqkOnzccLHn4A==} dependencies: - '@ethersproject/logger': 5.7.0 + '@ethersproject/logger': 5.4.0 dev: true /@ethersproject/properties@5.7.0: @@ -606,23 +606,23 @@ packages: /@ethersproject/providers@5.4.0: resolution: {integrity: sha512-XRmI9syLnkNdLA8ikEeg0duxmwSWTTt9S+xabnTOyI51JPJyhQ0QUNT+wvmod218ebb7rLupHDPQ7UVe2/+Tjg==} dependencies: - '@ethersproject/abstract-provider': 5.7.0 - '@ethersproject/abstract-signer': 5.7.0 - '@ethersproject/address': 5.7.0 - '@ethersproject/basex': 5.7.0 - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/constants': 5.7.0 - '@ethersproject/hash': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/networks': 5.7.1 - '@ethersproject/properties': 5.7.0 - '@ethersproject/random': 5.7.0 - '@ethersproject/rlp': 5.7.0 - '@ethersproject/sha2': 5.7.0 - '@ethersproject/strings': 5.7.0 - '@ethersproject/transactions': 5.7.0 - '@ethersproject/web': 5.7.1 + '@ethersproject/abstract-provider': 5.4.0 + '@ethersproject/abstract-signer': 5.4.0 + '@ethersproject/address': 5.4.0 + '@ethersproject/basex': 5.4.0 + '@ethersproject/bignumber': 5.4.0 + '@ethersproject/bytes': 5.4.0 + '@ethersproject/constants': 5.4.0 + '@ethersproject/hash': 5.4.0 + '@ethersproject/logger': 5.4.0 + '@ethersproject/networks': 5.4.0 + '@ethersproject/properties': 5.4.0 + '@ethersproject/random': 5.4.0 + '@ethersproject/rlp': 5.4.0 + '@ethersproject/sha2': 5.4.0 + '@ethersproject/strings': 5.4.0 + '@ethersproject/transactions': 5.4.0 + '@ethersproject/web': 5.4.0 bech32: 1.1.4 ws: 7.4.6 transitivePeerDependencies: @@ -661,8 +661,8 @@ packages: /@ethersproject/random@5.4.0: resolution: {integrity: sha512-pnpWNQlf0VAZDEOVp1rsYQosmv2o0ITS/PecNw+mS2/btF8eYdspkN0vIXrCMtkX09EAh9bdk8GoXmFXM1eAKw==} dependencies: - '@ethersproject/bytes': 5.7.0 - '@ethersproject/logger': 5.7.0 + '@ethersproject/bytes': 5.4.0 + '@ethersproject/logger': 5.4.0 dev: true /@ethersproject/random@5.7.0: @@ -675,8 +675,8 @@ packages: /@ethersproject/rlp@5.4.0: resolution: {integrity: sha512-0I7MZKfi+T5+G8atId9QaQKHRvvasM/kqLyAH4XxBCBchAooH2EX5rL9kYZWwcm3awYV+XC7VF6nLhfeQFKVPg==} dependencies: - '@ethersproject/bytes': 5.7.0 - '@ethersproject/logger': 5.7.0 + '@ethersproject/bytes': 5.4.0 + '@ethersproject/logger': 5.4.0 dev: true /@ethersproject/rlp@5.7.0: @@ -689,8 +689,8 @@ packages: /@ethersproject/sha2@5.4.0: resolution: {integrity: sha512-siheo36r1WD7Cy+bDdE1BJ8y0bDtqXCOxRMzPa4bV1TGt/eTUUt03BHoJNB6reWJD8A30E/pdJ8WFkq+/uz4Gg==} dependencies: - '@ethersproject/bytes': 5.7.0 - '@ethersproject/logger': 5.7.0 + '@ethersproject/bytes': 5.4.0 + '@ethersproject/logger': 5.4.0 hash.js: 1.1.7 dev: true @@ -705,9 +705,9 @@ packages: /@ethersproject/signing-key@5.4.0: resolution: {integrity: sha512-q8POUeywx6AKg2/jX9qBYZIAmKSB4ubGXdQ88l40hmATj29JnG5pp331nAWwwxPn2Qao4JpWHNZsQN+bPiSW9A==} dependencies: - '@ethersproject/bytes': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/properties': 5.7.0 + '@ethersproject/bytes': 5.4.0 + '@ethersproject/logger': 5.4.0 + '@ethersproject/properties': 5.4.0 bn.js: 4.12.0 elliptic: 6.5.4 hash.js: 1.1.7 @@ -727,11 +727,11 @@ packages: /@ethersproject/solidity@5.4.0: resolution: {integrity: sha512-XFQTZ7wFSHOhHcV1DpcWj7VXECEiSrBuv7JErJvB9Uo+KfCdc3QtUZV+Vjh/AAaYgezUEKbCtE6Khjm44seevQ==} dependencies: - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/keccak256': 5.7.0 - '@ethersproject/sha2': 5.7.0 - '@ethersproject/strings': 5.7.0 + '@ethersproject/bignumber': 5.4.0 + '@ethersproject/bytes': 5.4.0 + '@ethersproject/keccak256': 5.4.0 + '@ethersproject/sha2': 5.4.0 + '@ethersproject/strings': 5.4.0 dev: true /@ethersproject/solidity@5.7.0: @@ -748,9 +748,9 @@ packages: /@ethersproject/strings@5.4.0: resolution: {integrity: sha512-k/9DkH5UGDhv7aReXLluFG5ExurwtIpUfnDNhQA29w896Dw3i4uDTz01Quaptbks1Uj9kI8wo9tmW73wcIEaWA==} dependencies: - '@ethersproject/bytes': 5.7.0 - '@ethersproject/constants': 5.7.0 - '@ethersproject/logger': 5.7.0 + '@ethersproject/bytes': 5.4.0 + '@ethersproject/constants': 5.4.0 + '@ethersproject/logger': 5.4.0 dev: true /@ethersproject/strings@5.7.0: @@ -764,15 +764,15 @@ packages: /@ethersproject/transactions@5.4.0: resolution: {integrity: sha512-s3EjZZt7xa4BkLknJZ98QGoIza94rVjaEed0rzZ/jB9WrIuu/1+tjvYCWzVrystXtDswy7TPBeIepyXwSYa4WQ==} dependencies: - '@ethersproject/address': 5.7.0 - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/constants': 5.7.0 - '@ethersproject/keccak256': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/properties': 5.7.0 - '@ethersproject/rlp': 5.7.0 - '@ethersproject/signing-key': 5.7.0 + '@ethersproject/address': 5.4.0 + '@ethersproject/bignumber': 5.4.0 + '@ethersproject/bytes': 5.4.0 + '@ethersproject/constants': 5.4.0 + '@ethersproject/keccak256': 5.4.0 + '@ethersproject/logger': 5.4.0 + '@ethersproject/properties': 5.4.0 + '@ethersproject/rlp': 5.4.0 + '@ethersproject/signing-key': 5.4.0 dev: true /@ethersproject/transactions@5.7.0: @@ -792,9 +792,9 @@ packages: /@ethersproject/units@5.4.0: resolution: {integrity: sha512-Z88krX40KCp+JqPCP5oPv5p750g+uU6gopDYRTBGcDvOASh6qhiEYCRatuM/suC4S2XW9Zz90QI35MfSrTIaFg==} dependencies: - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/constants': 5.7.0 - '@ethersproject/logger': 5.7.0 + '@ethersproject/bignumber': 5.4.0 + '@ethersproject/constants': 5.4.0 + '@ethersproject/logger': 5.4.0 dev: true /@ethersproject/units@5.7.0: @@ -808,21 +808,21 @@ packages: /@ethersproject/wallet@5.4.0: resolution: {integrity: sha512-wU29majLjM6AjCjpat21mPPviG+EpK7wY1+jzKD0fg3ui5fgedf2zEu1RDgpfIMsfn8fJHJuzM4zXZ2+hSHaSQ==} dependencies: - '@ethersproject/abstract-provider': 5.7.0 - '@ethersproject/abstract-signer': 5.7.0 - '@ethersproject/address': 5.7.0 - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/hash': 5.7.0 - '@ethersproject/hdnode': 5.7.0 - '@ethersproject/json-wallets': 5.7.0 - '@ethersproject/keccak256': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/properties': 5.7.0 - '@ethersproject/random': 5.7.0 - '@ethersproject/signing-key': 5.7.0 - '@ethersproject/transactions': 5.7.0 - '@ethersproject/wordlists': 5.7.0 + '@ethersproject/abstract-provider': 5.4.0 + '@ethersproject/abstract-signer': 5.4.0 + '@ethersproject/address': 5.4.0 + '@ethersproject/bignumber': 5.4.0 + '@ethersproject/bytes': 5.4.0 + '@ethersproject/hash': 5.4.0 + '@ethersproject/hdnode': 5.4.0 + '@ethersproject/json-wallets': 5.4.0 + '@ethersproject/keccak256': 5.4.0 + '@ethersproject/logger': 5.4.0 + '@ethersproject/properties': 5.4.0 + '@ethersproject/random': 5.4.0 + '@ethersproject/signing-key': 5.4.0 + '@ethersproject/transactions': 5.4.0 + '@ethersproject/wordlists': 5.4.0 dev: true /@ethersproject/wallet@5.7.0: @@ -848,11 +848,11 @@ packages: /@ethersproject/web@5.4.0: resolution: {integrity: sha512-1bUusGmcoRLYgMn6c1BLk1tOKUIFuTg8j+6N8lYlbMpDesnle+i3pGSagGNvwjaiLo4Y5gBibwctpPRmjrh4Og==} dependencies: - '@ethersproject/base64': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/properties': 5.7.0 - '@ethersproject/strings': 5.7.0 + '@ethersproject/base64': 5.4.0 + '@ethersproject/bytes': 5.4.0 + '@ethersproject/logger': 5.4.0 + '@ethersproject/properties': 5.4.0 + '@ethersproject/strings': 5.4.0 dev: true /@ethersproject/web@5.7.1: @@ -868,11 +868,11 @@ packages: /@ethersproject/wordlists@5.4.0: resolution: {integrity: sha512-FemEkf6a+EBKEPxlzeVgUaVSodU7G0Na89jqKjmWMlDB0tomoU8RlEMgUvXyqtrg8N4cwpLh8nyRnm1Nay1isA==} dependencies: - '@ethersproject/bytes': 5.7.0 - '@ethersproject/hash': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/properties': 5.7.0 - '@ethersproject/strings': 5.7.0 + '@ethersproject/bytes': 5.4.0 + '@ethersproject/hash': 5.4.0 + '@ethersproject/logger': 5.4.0 + '@ethersproject/properties': 5.4.0 + '@ethersproject/strings': 5.4.0 dev: true /@ethersproject/wordlists@5.7.0: @@ -3784,7 +3784,7 @@ packages: resolution: {integrity: sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==} hasBin: true dependencies: - glob: 7.2.3 + glob: 7.2.0 dev: true /ripemd160@2.0.2: @@ -4612,7 +4612,7 @@ packages: version: 0.0.1 dependencies: '@openzeppelin/contracts': 5.0.1 - solady: github.com/vectorized/solady/9deb9ed36a27261a8745db5b7cd7f4cdc3b1cd4e + solady: github.com/vectorized/solady/1372606383445c0a247e6c58eb255a529734258a dev: true github.com/sablier-labs/solarray/6bf10cb34cdace52a3ba5fe437e78cc82df92684: @@ -4644,3 +4644,9 @@ packages: name: sentinellist version: 0.0.0 dev: true + + github.com/zeroknots/sentinellist/2783f466b6d9c457da0a240e392db183ca1607bb: + resolution: {tarball: https://codeload.github.com/zeroknots/sentinellist/tar.gz/2783f466b6d9c457da0a240e392db183ca1607bb} + name: sentinellist + version: 0.0.0 + dev: true