Skip to content

Commit

Permalink
Fix/return data for delegate call (#111)
Browse files Browse the repository at this point in the history
* sync to dev

* updated hook interface to updated 7579 hook postcheck interface, added return data for delegatecall
  • Loading branch information
leekt authored May 2, 2024
1 parent 55ad69d commit 8f7fd99
Show file tree
Hide file tree
Showing 9 changed files with 73 additions and 34 deletions.
8 changes: 4 additions & 4 deletions src/Kernel.sol
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ contract Kernel is IAccount, IAccountExecute, IERC7579Account, ValidationManager
if (validator.isModuleType(4)) {
bytes memory ret = IHook(address(validator)).preCheck(msg.sender, msg.value, msg.data);
_;
IHook(address(validator)).postCheck(ret, true, hex""); // TODO don't support try catch hook here
IHook(address(validator)).postCheck(ret); // TODO don't support try catch hook here
} else {
revert InvalidCaller();
}
Expand Down Expand Up @@ -171,7 +171,7 @@ contract Kernel is IAccount, IAccountExecute, IERC7579Account, ValidationManager
revert NotSupportedCallType();
}
if (address(config.hook) != address(1)) {
_doPostHook(config.hook, context, success, result);
_doPostHook(config.hook, context);
}
}
if (!success) {
Expand Down Expand Up @@ -255,7 +255,7 @@ contract Kernel is IAccount, IAccountExecute, IERC7579Account, ValidationManager
}
(bool success, bytes memory ret) = ExecLib.executeDelegatecall(address(this), userOp.callData[4:]);
if (address(hook) != address(1)) {
_doPostHook(hook, context, success, ret);
_doPostHook(hook, context);
} else if (!success) {
revert ExecutionReverted();
}
Expand All @@ -277,7 +277,7 @@ contract Kernel is IAccount, IAccountExecute, IERC7579Account, ValidationManager
}
returnData = ExecLib.execute(execMode, executionCalldata);
if (address(hook) != address(1)) {
_doPostHook(hook, context, true, abi.encode(returnData));
_doPostHook(hook, context);
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/core/HookManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ abstract contract HookManager {
context = hook.preCheck(msg.sender, value, callData);
}

function _doPostHook(IHook hook, bytes memory context, bool success, bytes memory result) internal {
function _doPostHook(IHook hook, bytes memory context) internal {
// bool success,
// bytes memory result
hook.postCheck(context, success, result);
hook.postCheck(context);
}

// @notice if hook is not initialized before, kernel will call hook.onInstall no matter what flag it shows, with hookData[1:]
Expand Down
22 changes: 2 additions & 20 deletions src/interfaces/IERC7579Modules.sol
Original file line number Diff line number Diff line change
Expand Up @@ -69,30 +69,12 @@ interface IValidator is IModule {
interface IExecutor is IModule {}

interface IHook is IModule {
/**
* @dev Called by the smart account before execution
* @param msgSender the address that called the smart account
* @param value the value that was sent to the smart account
* @param msgData the data that was sent to the smart account
*
* MAY return arbitrary data in the `hookData` return value
*/
function preCheck(address msgSender, uint256 value, bytes calldata msgData)
function preCheck(address msgSender, uint256 msgValue, bytes calldata msgData)
external
payable
returns (bytes memory hookData);

/**
* @dev Called by the smart account after execution
* @param hookData the data that was returned by the `preCheck` function
* @param executionSuccess whether the execution(s) was (were) successful
* @param executionReturn the return/revert data of the execution(s)
*
* MAY validate the `hookData` to validate transaction context of the `preCheck` function
*/
function postCheck(bytes calldata hookData, bool executionSuccess, bytes calldata executionReturn)
external
payable;
function postCheck(bytes calldata hookData) external payable;
}

interface IFallback is IModule {}
Expand Down
2 changes: 1 addition & 1 deletion src/mock/MockHook.sol
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ contract MockHook is IHook {
return data[msg.sender];
}

function postCheck(bytes calldata hookData, bool success, bytes memory res) external payable override {
function postCheck(bytes calldata hookData) external payable override {
postHookData[msg.sender] = hookData;
}
}
5 changes: 1 addition & 4 deletions src/mock/MockValidator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,7 @@ contract MockValidator is IValidator, IHook {
return hex"";
}

function postCheck(bytes calldata hookData, bool executionSuccess, bytes calldata executionReturn)
external
payable
{
function postCheck(bytes calldata hookData) external payable {
return;
}
}
51 changes: 51 additions & 0 deletions src/sdk/KernelTestBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,24 @@ import "../mock/MockERC721.sol";
import "../mock/MockERC1155.sol";
import "../core/ValidationManager.sol";
import "./TestBase/erc4337Util.sol";
import "../types/Types.sol";
import "../types/Structs.sol";

contract MockCallee {
uint256 public value;

event MockEvent(address indexed caller, address indexed here);

function setValue(uint256 _value) public {
value = _value;
}

function emitEvent(bool shouldFail) public {
if (shouldFail) {
revert("Hello");
}
emit MockEvent(msg.sender, address(this));
}
}

abstract contract KernelTestBase is Test {
Expand Down Expand Up @@ -853,6 +864,46 @@ abstract contract KernelTestBase is Test {
entrypoint.handleOps(ops, payable(address(0xdeadbeef)));
}

function testExecute(CallType callType, ExecType execType, bool shouldFail) external whenInitialized {
unchecked {
vm.assume(uint8(CallType.unwrap(callType)) + 1 < 3); //only call/batch/delegatecall
vm.assume(uint8(ExecType.unwrap(execType)) < 2);
}
vm.startPrank(address(entrypoint));
ExecMode code = ExecLib.encode(callType, execType, ExecModeSelector.wrap(0x00), ExecModePayload.wrap(0x00));
if (callType == CALLTYPE_BATCH) {
Execution[] memory execs = new Execution[](1);
execs[0] = Execution({
target: address(callee),
value: 0,
callData: abi.encodeWithSelector(MockCallee.emitEvent.selector, shouldFail)
});
bytes memory data = ExecLib.encodeBatch(execs);
if (execType == EXECTYPE_DEFAULT && shouldFail) {
vm.expectRevert();
}
kernel.execute(code, data);
} else if (callType == CALLTYPE_SINGLE) {
if (execType == EXECTYPE_DEFAULT && shouldFail) {
vm.expectRevert();
}
kernel.execute(
code,
abi.encodePacked(
address(callee), uint256(0), abi.encodeWithSelector(MockCallee.emitEvent.selector, shouldFail)
)
);
} else {
if (execType == EXECTYPE_DEFAULT && shouldFail) {
vm.expectRevert();
}
kernel.execute(
code,
abi.encodePacked(address(callee), abi.encodeWithSelector(MockCallee.emitEvent.selector, shouldFail))
);
}
}

function testExecutorInstall(bool withHook) external whenInitialized {
_installExecutor(withHook);
assertEq(mockExecutor.data(address(kernel)), abi.encodePacked("executorData"));
Expand Down
11 changes: 10 additions & 1 deletion src/utils/ExecLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,18 @@ library ExecLib {
revert("Unsupported");
}
} else if (callType == CALLTYPE_DELEGATECALL) {
returnData = new bytes[](1);
address delegate = address(bytes20(executionCalldata[0:20]));
bytes calldata callData = executionCalldata[20:];
executeDelegatecall(delegate, callData);
bool success;
(success, returnData[0]) = executeDelegatecall(delegate, callData);
if (execType == EXECTYPE_TRY) {
if (!success) emit TryExecuteUnsuccessful(0, returnData[0]);
} else if (execType == EXECTYPE_DEFAULT) {
if (!success) revert("Delegatecall failed");
} else {
revert("Unsupported");
}
} else {
revert("Unsupported");
}
Expand Down
2 changes: 1 addition & 1 deletion src/validator/ECDSAValidator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -94,5 +94,5 @@ contract ECDSAValidator is IValidator, IHook {
return hex"";
}

function postCheck(bytes calldata hookData, bool success, bytes calldata res) external payable override {}
function postCheck(bytes calldata hookData) external payable override {}
}
2 changes: 1 addition & 1 deletion src/validator/MultiSignatureECDSAValidator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -129,5 +129,5 @@ contract MultiSignatureECDSAValidator is IValidator, IHook {
return hex"";
}

function postCheck(bytes calldata hookData, bool success, bytes calldata res) external payable override {}
function postCheck(bytes calldata hookData) external payable override {}
}

0 comments on commit 8f7fd99

Please sign in to comment.