diff --git a/src/factory/TempKernel.sol b/src/factory/TempKernel.sol index e2fe92d1..5c106717 100644 --- a/src/factory/TempKernel.sol +++ b/src/factory/TempKernel.sol @@ -176,9 +176,29 @@ contract TempKernel is EIP712, IAccount { if (address(validator) != address(0)) { validator.enable(getStorage().validatorData); } - - (bool success, bytes memory ret) = _newImplementation.delegatecall(msg.data); - require(success, string(ret)); + + assembly { + // Copy msg.data. We take full control of memory in this inline assembly + // block because it will not return to Solidity code. We overwrite the + // Solidity scratch pad at memory position 0. + calldatacopy(0, 0, calldatasize()) + + // Call the implementation. + // out and outsize are 0 because we don't know the size yet. + let result := delegatecall(gas(), _newImplementation, 0, calldatasize(), 0, 0) + + // Copy the returned data. + returndatacopy(0, 0, returndatasize()) + + switch result + // delegatecall returns 0 on error. + case 0 { + revert(0, returndatasize()) + } + default { + return(0, returndatasize()) + } + } } // WARTNING: this function is NOT VIEW @@ -223,6 +243,8 @@ contract TempKernel is EIP712, IAccount { ret := ptr success := result } - require(success, string(ret)); + if(!success) { + revert(string(ret)); + } } } diff --git a/src/test/TestERC721.sol b/src/test/TestERC721.sol index 2cc1aa8a..9733f5c3 100644 --- a/src/test/TestERC721.sol +++ b/src/test/TestERC721.sol @@ -9,4 +9,8 @@ contract TestERC721 is ERC721 { function mint(address _to, uint256 _id) external { _mint(_to, _id); } + + function safeMint(address _to, uint256 _id) external { + _safeMint(_to, _id); + } } diff --git a/test/foundry/Kernel.test.sol b/test/foundry/Kernel.test.sol index e0a931bd..c0fc84c7 100644 --- a/test/foundry/Kernel.test.sol +++ b/test/foundry/Kernel.test.sol @@ -2,13 +2,13 @@ pragma solidity ^0.8.0; import "src/factory/KernelFactory.sol"; -import "src/factory/TempKernel.sol"; import "src/factory/ECDSAKernelFactory.sol"; import "src/Kernel.sol"; import "src/validator/ECDSAValidator.sol"; import "src/factory/EIP1967Proxy.sol"; // test artifacts import "src/test/TestValidator.sol"; +import "src/test/TestERC721.sol"; // test utils import "forge-std/Test.sol"; import {ERC4337Utils} from "./ERC4337Utils.sol"; @@ -63,6 +63,13 @@ contract KernelTest is Test { assertEq(storage_.owner, owner); } + function test_erc721_receive() external { + Kernel kernel2 = Kernel(payable(address(ecdsaFactory.createAccount(owner, 1)))); + TestERC721 nft = new TestERC721(); + nft.safeMint(address(kernel2), 1); + assertEq(nft.ownerOf(1), address(kernel2)); + } + function test_validate_signature() external { Kernel kernel2 = Kernel(payable(address(ecdsaFactory.createAccount(owner, 1)))); bytes32 hash = keccak256(abi.encodePacked("hello world"));