Skip to content

Typo #32

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open

Typo #32

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
192 changes: 120 additions & 72 deletions src/core/ModuleManager.sol
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;

import { SentinelListLib, SENTINEL } from "sentinellist/SentinelList.sol";
import {
CallType, CALLTYPE_SINGLE, CALLTYPE_DELEGATECALL, CALLTYPE_STATIC
} from "../lib/ModeLib.sol";
import { AccountBase } from "./AccountBase.sol";
import {SentinelListLib, SENTINEL} from "sentinellist/SentinelList.sol";
import {CallType, CALLTYPE_SINGLE, CALLTYPE_DELEGATECALL, CALLTYPE_STATIC} from "../lib/ModeLib.sol";
import {AccountBase} from "./AccountBase.sol";
import "../interfaces/IERC7579Module.sol";
import "forge-std/interfaces/IERC165.sol";
import "./Receiver.sol";
Expand Down Expand Up @@ -36,64 +34,85 @@ abstract contract ModuleManager is AccountBase, Receiver {
/// @custom:storage-location erc7201:modulemanager.storage.msa
struct ModuleManagerStorage {
// linked list of validators. List is initialized by initializeAccount()
SentinelListLib.SentinelList $valdiators;
SentinelListLib.SentinelList $validators;
// 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
mapping(bytes4 selector => FallbackHandler fallbackHandler) $fallbacks;
}

function $moduleManager() internal pure virtual returns (ModuleManagerStorage storage $ims) {
function $moduleManager()
internal
pure
virtual
returns (ModuleManagerStorage storage $ims)
{
bytes32 position = MODULEMANAGER_STORAGE_LOCATION;
assembly {
$ims.slot := position
}
}

modifier onlyExecutorModule() {
SentinelListLib.SentinelList storage $executors = $moduleManager().$executors;
SentinelListLib.SentinelList storage $executors = $moduleManager()
.$executors;
if (!$executors.contains(msg.sender)) revert InvalidModule(msg.sender);
_;
}

modifier onlyValidatorModule(address validator) {
SentinelListLib.SentinelList storage $valdiators = $moduleManager().$valdiators;
if (!$valdiators.contains(validator)) revert InvalidModule(validator);
SentinelListLib.SentinelList storage $validators = $moduleManager()
.$validators;
if (!$validators.contains(validator)) revert InvalidModule(validator);
_;
}

function _initModuleManager() internal virtual {
ModuleManagerStorage storage $ims = $moduleManager();
$ims.$executors.init();
$ims.$valdiators.init();
$ims.$validators.init();
}

function isAlreadyInitialized() internal view virtual returns (bool) {
ModuleManagerStorage storage $ims = $moduleManager();
return $ims.$valdiators.alreadyInitialized();
return $ims.$validators.alreadyInitialized();
}

/////////////////////////////////////////////////////
// Manage Validators
////////////////////////////////////////////////////
function _installValidator(address validator, bytes calldata data) internal virtual {
SentinelListLib.SentinelList storage $valdiators = $moduleManager().$valdiators;
$valdiators.push(validator);
function _installValidator(
address validator,
bytes calldata data
) internal virtual {
SentinelListLib.SentinelList storage $validators = $moduleManager()
.$validators;
$validators.push(validator);
IValidator(validator).onInstall(data);
}

function _uninstallValidator(address validator, bytes calldata data) internal {
function _uninstallValidator(
address validator,
bytes calldata data
) internal {
// TODO: check if its the last validator. this might brick the account
SentinelListLib.SentinelList storage $valdiators = $moduleManager().$valdiators;
(address prev, bytes memory disableModuleData) = abi.decode(data, (address, bytes));
$valdiators.pop(prev, validator);
SentinelListLib.SentinelList storage $validators = $moduleManager()
.$validators;
(address prev, bytes memory disableModuleData) = abi.decode(
data,
(address, bytes)
);
$validators.pop(prev, validator);
IValidator(validator).onUninstall(disableModuleData);
}

function _isValidatorInstalled(address validator) internal view virtual returns (bool) {
SentinelListLib.SentinelList storage $valdiators = $moduleManager().$valdiators;
return $valdiators.contains(validator);
function _isValidatorInstalled(
address validator
) internal view virtual returns (bool) {
SentinelListLib.SentinelList storage $validators = $moduleManager()
.$validators;
return $validators.contains(validator);
}

/**
Expand All @@ -103,35 +122,42 @@ abstract contract ModuleManager is AccountBase, Receiver {
function getValidatorsPaginated(
address cursor,
uint256 size
)
external
view
virtual
returns (address[] memory array, address next)
{
SentinelListLib.SentinelList storage $valdiators = $moduleManager().$valdiators;
return $valdiators.getEntriesPaginated(cursor, size);
) external view virtual returns (address[] memory array, address next) {
SentinelListLib.SentinelList storage $validators = $moduleManager()
.$validators;
return $validators.getEntriesPaginated(cursor, size);
}

/////////////////////////////////////////////////////
// Manage Executors
////////////////////////////////////////////////////

function _installExecutor(address executor, bytes calldata data) internal {
SentinelListLib.SentinelList storage $executors = $moduleManager().$executors;
SentinelListLib.SentinelList storage $executors = $moduleManager()
.$executors;
$executors.push(executor);
IExecutor(executor).onInstall(data);
}

function _uninstallExecutor(address executor, bytes calldata data) internal {
SentinelListLib.SentinelList storage $executors = $moduleManager().$executors;
(address prev, bytes memory disableModuleData) = abi.decode(data, (address, bytes));
function _uninstallExecutor(
address executor,
bytes calldata data
) internal {
SentinelListLib.SentinelList storage $executors = $moduleManager()
.$executors;
(address prev, bytes memory disableModuleData) = abi.decode(
data,
(address, bytes)
);
$executors.pop(prev, executor);
IExecutor(executor).onUninstall(disableModuleData);
}

function _isExecutorInstalled(address executor) internal view virtual returns (bool) {
SentinelListLib.SentinelList storage $executors = $moduleManager().$executors;
function _isExecutorInstalled(
address executor
) internal view virtual returns (bool) {
SentinelListLib.SentinelList storage $executors = $moduleManager()
.$executors;
return $executors.contains(executor);
}

Expand All @@ -142,89 +168,93 @@ abstract contract ModuleManager is AccountBase, Receiver {
function getExecutorsPaginated(
address cursor,
uint256 size
)
external
view
virtual
returns (address[] memory array, address next)
{
SentinelListLib.SentinelList storage $executors = $moduleManager().$executors;
) external view virtual returns (address[] memory array, address next) {
SentinelListLib.SentinelList storage $executors = $moduleManager()
.$executors;
return $executors.getEntriesPaginated(cursor, size);
}

/////////////////////////////////////////////////////
// Manage Fallback
////////////////////////////////////////////////////

function _installFallbackHandler(address handler, bytes calldata params) internal virtual {
function _installFallbackHandler(
address handler,
bytes calldata params
) internal virtual {
bytes4 selector = bytes4(params[0:4]);
CallType calltype = CallType.wrap(bytes1(params[4]));
bytes memory initData = params[5:];

if (_isFallbackHandlerInstalled(selector)) {
revert("Function selector already used");
}
$moduleManager().$fallbacks[selector] = FallbackHandler(handler, calltype);
$moduleManager().$fallbacks[selector] = FallbackHandler(
handler,
calltype
);
IFallback(handler).onInstall(initData);
}

function _uninstallFallbackHandler(
address handler,
bytes calldata deInitData
)
internal
virtual
{
) internal virtual {
bytes4 selector = bytes4(deInitData[0:4]);
bytes memory _deInitData = deInitData[4:];

if (!_isFallbackHandlerInstalled(selector)) {
revert("Function selector not used");
}

FallbackHandler memory activeFallback = $moduleManager().$fallbacks[selector];
FallbackHandler memory activeFallback = $moduleManager().$fallbacks[
selector
];

if (activeFallback.handler != handler) {
revert("Function selector not used by this handler");
}

CallType callType = activeFallback.calltype;

$moduleManager().$fallbacks[selector] = FallbackHandler(address(0), CallType.wrap(0x00));
$moduleManager().$fallbacks[selector] = FallbackHandler(
address(0),
CallType.wrap(0x00)
);

IFallback(handler).onUninstall(_deInitData);
}

function _isFallbackHandlerInstalled(bytes4 functionSig) internal view virtual returns (bool) {
FallbackHandler storage $fallback = $moduleManager().$fallbacks[functionSig];
function _isFallbackHandlerInstalled(
bytes4 functionSig
) internal view virtual returns (bool) {
FallbackHandler storage $fallback = $moduleManager().$fallbacks[
functionSig
];
return $fallback.handler != address(0);
}

function _isFallbackHandlerInstalled(
bytes4 functionSig,
address _handler
)
internal
view
virtual
returns (bool)
{
FallbackHandler storage $fallback = $moduleManager().$fallbacks[functionSig];
) internal view virtual returns (bool) {
FallbackHandler storage $fallback = $moduleManager().$fallbacks[
functionSig
];
return $fallback.handler == _handler;
}

function getActiveFallbackHandler(bytes4 functionSig)
external
view
virtual
returns (FallbackHandler memory)
{
function getActiveFallbackHandler(
bytes4 functionSig
) external view virtual returns (FallbackHandler memory) {
return $moduleManager().$fallbacks[functionSig];
}

// FALLBACK
fallback() external payable override(Receiver) receiverFallback {
FallbackHandler storage $fallbackHandler = $moduleManager().$fallbacks[msg.sig];
FallbackHandler storage $fallbackHandler = $moduleManager().$fallbacks[
msg.sig
];
address handler = $fallbackHandler.handler;
CallType calltype = $fallbackHandler.calltype;
if (handler == address(0)) revert NoFallbackHandler(msg.sig);
Expand All @@ -245,12 +275,20 @@ abstract contract ModuleManager is AccountBase, Receiver {
mstore(senderPtr, shl(96, caller()))

// Add 20 bytes for the address appended add the end
let success :=
staticcall(gas(), handler, calldataPtr, add(calldatasize(), 20), 0, 0)
let success := staticcall(
gas(),
handler,
calldataPtr,
add(calldatasize(), 20),
0,
0
)

let returnDataPtr := allocate(returndatasize())
returndatacopy(returnDataPtr, 0, returndatasize())
if iszero(success) { revert(returnDataPtr, returndatasize()) }
if iszero(success) {
revert(returnDataPtr, returndatasize())
}
return(returnDataPtr, returndatasize())
}
}
Expand All @@ -270,11 +308,21 @@ abstract contract ModuleManager is AccountBase, Receiver {
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 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()) }
if iszero(success) {
revert(returnDataPtr, returndatasize())
}
return(returnDataPtr, returndatasize())
}
}
Expand Down
23 changes: 10 additions & 13 deletions src/utils/Bootstrap.sol
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,14 @@ contract Bootstrap is ModuleManager, HookManager {
* calling this function
*/
function initMSA(
BootstrapConfig[] calldata $valdiators,
BootstrapConfig[] calldata $validators,
BootstrapConfig[] calldata $executors,
BootstrapConfig calldata _hook,
BootstrapConfig[] calldata _fallbacks
)
external
{
) external {
// init validators
for (uint256 i; i < $valdiators.length; i++) {
_installValidator($valdiators[i].module, $valdiators[i].data);
for (uint256 i; i < $validators.length; i++) {
_installValidator($validators[i].module, $validators[i].data);
}

// init executors
Expand All @@ -54,18 +52,17 @@ contract Bootstrap is ModuleManager, HookManager {
}

function _getInitMSACalldata(
BootstrapConfig[] calldata $valdiators,
BootstrapConfig[] calldata $validators,
BootstrapConfig[] calldata $executors,
BootstrapConfig calldata _hook,
BootstrapConfig[] calldata _fallbacks
)
external
view
returns (bytes memory init)
{
) external view returns (bytes memory init) {
init = abi.encode(
address(this),
abi.encodeCall(this.initMSA, ($valdiators, $executors, _hook, _fallbacks))
abi.encodeCall(
this.initMSA,
($validators, $executors, _hook, _fallbacks)
)
);
}
}