Skip to content

Commit

Permalink
feat: encoding issue
Browse files Browse the repository at this point in the history
  • Loading branch information
zeroknots committed Feb 29, 2024
1 parent d16bab3 commit 9567e9f
Show file tree
Hide file tree
Showing 8 changed files with 334 additions and 98 deletions.
198 changes: 143 additions & 55 deletions examples/src/HookMultiplex/HookMultiplexer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,38 +3,73 @@ pragma solidity ^0.8.23;

import { Execution } from "@rhinestone/modulekit/src/Accounts.sol";
import { SENTINEL, SentinelListLib } from "sentinellist/SentinelList.sol";
import { SENTINEL as SENTINELBytes32, LinkedBytes32Lib } from "sentinellist/SentinelListBytes32.sol";
import { ERC7579HookDestruct } from "@rhinestone/modulekit/src/modules/ERC7579HookDestruct.sol";
import "forge-std/console2.sol";
import { ISubHook } from "./ISubHook.sol";
import { IHookMultiPlexer, hookFlag } from "./IHookMultiplexer.sol";
import { HookEncodingLib } from "./lib/HookEncodingLib.sol";

contract HookMultiPlexer is ERC7579HookDestruct {
bytes32 constant STORAGE_SLOT = bytes32(uint256(1_244_444_444));

contract HookMultiPlexer is ERC7579HookDestruct, IHookMultiPlexer {
using SentinelListLib for SentinelListLib.SentinelList;
using LinkedBytes32Lib for LinkedBytes32Lib.LinkedBytes32;
using HookEncodingLib for ConfigParam;
using HookEncodingLib for bytes32;

uint256 internal constant MAX_HOOK_NR = 16;
mapping(address smartAccount => SentinelListLib.SentinelList globalSubHooks) internal
$globalSubHooks;
mapping(address smartAccount => mapping(address module => SentinelListLib.SentinelList))
internal $moduleSubHooks;

function installGlobalHooks(address[] memory hooks) public {
uint256 length = hooks.length;
error SubHookFailed(bytes32 hook);

struct MultiPlexerStorage {
mapping(address smartAccount => LinkedBytes32Lib.LinkedBytes32 globalSubHooks)
$globalSubHooks;
mapping(address smartAccount => mapping(address module => LinkedBytes32Lib.LinkedBytes32))
$moduleSubHooks;
}

function $multiplexer() internal returns (MultiPlexerStorage storage strg) {
bytes32 position = STORAGE_SLOT;
assembly {
strg.slot := position
}
}

function installGlobalHooks(ConfigParam[] calldata params) public {
uint256 length = params.length;
for (uint256 i; i < length; i++) {
$globalSubHooks[msg.sender].push(hooks[i]);
// TODO check if the hook is already enabled for module
ConfigParam calldata conf = params[i];
bytes32 _packed = conf.pack();
console2.logBytes32(_packed);
console2.log(
conf.hook,
hookFlag.unwrap(conf.isValidatorHook),
hookFlag.unwrap(conf.isExecutorHook)
);
$multiplexer().$globalSubHooks[msg.sender].push(_packed);
}
}

function installModuleHooks(address module, address[] memory hooks) public {
uint256 length = hooks.length;
function installModuleHooks(address module, ConfigParam[] calldata params) public {
uint256 length = params.length;
$multiplexer().$moduleSubHooks[msg.sender][module].init();
for (uint256 i; i < length; i++) {
ConfigParam calldata conf = params[i];
bytes32 _packed = conf.pack();
// check if the hook is already enabled for global
if ($globalSubHooks[msg.sender].contains(hooks[i])) continue;
$moduleSubHooks[msg.sender][module].push(hooks[i]);
if ($multiplexer().$globalSubHooks[msg.sender].contains(_packed)) continue;
$multiplexer().$moduleSubHooks[msg.sender][module].push(_packed);
}
}

function configSubHook(address module, bytes32 hook, bytes calldata configCallData) external {
if (!$multiplexer().$moduleSubHooks[msg.sender][module].contains(hook)) revert();
(bool success,) = hook.decodeAddress().call(configCallData);
}

function onInstall(bytes calldata data) external override {
$globalSubHooks[msg.sender].init();
$multiplexer().$globalSubHooks[msg.sender].init();
}

function onUninstall(bytes calldata data) external override {
Expand All @@ -46,7 +81,7 @@ contract HookMultiPlexer is ERC7579HookDestruct {
}

function name() external pure virtual returns (string memory) {
return "PermissionHook";
return "MultiPlexerHook";
}

function isModuleType(uint256 isType) external pure virtual override returns (bool) {
Expand All @@ -57,19 +92,46 @@ contract HookMultiPlexer is ERC7579HookDestruct {
// todo
}

function _delegatecallSubHook(
bytes4 functionSig,
address subHook,
address msgSender,
address target,
uint256 value,
bytes calldata callData
function _execSubHooks(
address module,
bytes memory callData,
function (bytes32) returns(bool) checkFlagFn
)
internal
{ }
{
(bytes32[] memory globalHooks,) = $multiplexer().$globalSubHooks[msg.sender]
.getEntriesPaginated(SENTINELBytes32, MAX_HOOK_NR);

uint256 length = globalHooks.length;

for (uint256 i; i < length; i++) {
bytes32 _globalHook = globalHooks[i];
console2.logBytes32(_globalHook);
console2.log("flag", checkFlagFn(_globalHook));
if (!checkFlagFn(_globalHook)) continue;
(bool success,) = _globalHook.decodeAddress().call(callData);
if (!success) revert SubHookFailed(_globalHook);
}

LinkedBytes32Lib.LinkedBytes32 storage $moduleHooks =
$multiplexer().$moduleSubHooks[msg.sender][module];
// TODO: make this nicer
if (!$moduleHooks.alreadyInitialized()) return;

(bytes32[] memory moduleHooks,) = $multiplexer().$moduleSubHooks[msg.sender][module]
.getEntriesPaginated(SENTINELBytes32, MAX_HOOK_NR);
length = moduleHooks.length;
for (uint256 i; i < length; i++) {
bytes32 _moduleHook = moduleHooks[i];

if (!checkFlagFn(_moduleHook)) continue;
(bool success,) = _moduleHook.decodeAddress().call(callData);
if (!success) revert SubHookFailed(_moduleHook);
}
}

function onExecute(
address msgSender,
address module,
address target,
uint256 value,
bytes calldata callData
Expand All @@ -79,37 +141,31 @@ contract HookMultiPlexer is ERC7579HookDestruct {
override
returns (bytes memory hookData)
{
console2.log("onExecute: msgSender", msg.sender);
(address[] memory globalHooks,) =
$globalSubHooks[msg.sender].getEntriesPaginated(SENTINEL, MAX_HOOK_NR);

uint256 length = globalHooks.length;
console2.log("globalHooks.length", length);

for (uint256 i; i < length; i++) {
address hook = globalHooks[i];
(bool success,) = hook.delegatecall(
abi.encodeCall(ISubHook.onExecute, (msgSender, target, value, callData))
);
require(success, "HookMultiPlexer: onExecute: subhook failed");
}

// TODO:
// implement for loop for module specific hooks
_execSubHooks({
module: module,
callData: abi.encodeCall(ISubHook.onExecute, (msg.sender, module, target, value, callData)),
checkFlagFn: HookEncodingLib.is4337Hook
});
}

function onExecuteBatch(
address msgSender,
Execution[] calldata
address module,
Execution[] calldata executions
)
internal
virtual
override
returns (bytes memory hookData)
{ }
{
_execSubHooks({
module: module,
callData: abi.encodeCall(ISubHook.onExecuteBatch, (msg.sender, module, executions)),
checkFlagFn: HookEncodingLib.is4337Hook
});
}

function onExecuteFromExecutor(
address msgSender,
address module,
address target,
uint256 value,
bytes calldata callData
Expand All @@ -118,41 +174,73 @@ contract HookMultiPlexer is ERC7579HookDestruct {
virtual
override
returns (bytes memory hookData)
{ }
{
_execSubHooks({
module: module,
callData: abi.encodeCall(
ISubHook.onExecuteFromExecutor, (msg.sender, module, target, value, callData)
),
checkFlagFn: HookEncodingLib.isExecutorHook
});
}

function onExecuteBatchFromExecutor(
address msgSender,
Execution[] calldata
address module,
Execution[] calldata executions
)
internal
virtual
override
returns (bytes memory hookData)
{ }
{
_execSubHooks({
module: module,
callData: abi.encodeCall(
ISubHook.onExecuteBatchFromExecutor, (msg.sender, module, executions)
),
checkFlagFn: HookEncodingLib.isExecutorHook
});
}

function onInstallModule(
address msgSender,
uint256 moduleType,
address module,
uint256 moduleType,
address installModule,
bytes calldata initData
)
internal
virtual
override
returns (bytes memory hookData)
{ }
{
_execSubHooks({
module: module,
callData: abi.encodeCall(
ISubHook.onInstallModule, (msg.sender, module, moduleType, installModule, initData)
),
checkFlagFn: HookEncodingLib.isConfigHook
});
}

function onUninstallModule(
address msgSender,
uint256 moduleType,
address module,
uint256 moduleType,
address uninstallModule,
bytes calldata deInitData
)
internal
virtual
override
returns (bytes memory hookData)
{ }
{
_execSubHooks({
module: module,
callData: abi.encodeCall(
ISubHook.onInstallModule, (msg.sender, module, moduleType, uninstallModule, deInitData)
),
checkFlagFn: HookEncodingLib.isConfigHook
});
}

function onPostCheck(bytes calldata hookData)
internal
Expand Down
10 changes: 10 additions & 0 deletions examples/src/HookMultiplex/IHookMultiplexer.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
type hookFlag is bool;

interface IHookMultiPlexer {
struct ConfigParam {
address hook;
hookFlag isExecutorHook;
hookFlag isValidatorHook;
hookFlag isConfigHook;
}
}
26 changes: 16 additions & 10 deletions examples/src/HookMultiplex/ISubHook.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import { Execution } from "@rhinestone/modulekit/src/Accounts.sol";

interface ISubHook {
function onExecute(
address msgSender,
address smartAccount,
address module,
address target,
uint256 value,
bytes calldata callData
Expand All @@ -14,14 +15,16 @@ interface ISubHook {
returns (bytes memory hookData);

function onExecuteBatch(
address msgSender,
Execution[] calldata
address smartAccount,
address module,
Execution[] calldata executions
)
external
returns (bytes memory hookData);

function onExecuteFromExecutor(
address msgSender,
address smartAccount,
address module,
address target,
uint256 value,
bytes calldata callData
Expand All @@ -30,8 +33,9 @@ interface ISubHook {
returns (bytes memory hookData);

function onExecuteBatchFromExecutor(
address msgSender,
Execution[] calldata
address smartAccount,
address module,
Execution[] calldata executions
)
external
returns (bytes memory hookData);
Expand All @@ -41,18 +45,20 @@ interface ISubHook {
//////////////////////////////////////////////////////////////////////////*/

function onInstallModule(
address msgSender,
uint256 moduleType,
address smartAccount,
address module,
uint256 moduleType,
address moduleToInstall,
bytes calldata initData
)
external
returns (bytes memory hookData);

function onUninstallModule(
address msgSender,
uint256 moduleType,
address smartAccount,
address module,
uint256 moduleType,
address moduleToUninstall,
bytes calldata deInitData
)
external
Expand Down
Loading

0 comments on commit 9567e9f

Please sign in to comment.