-
Notifications
You must be signed in to change notification settings - Fork 38
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
feat: move token receiver functions into account #124
Changes from all commits
0253655
8ea9b0d
3a4cfca
0b6ea86
f4ed920
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -53,6 +53,9 @@ abstract contract PluginManagerInternals is IPluginManager, AccountStorageV1 { | |
uint256 callbackGasLimit; | ||
} | ||
|
||
// As per the EIP-165 spec, no interface should ever match 0xffffffff | ||
bytes4 internal constant _INVALID_INTERFACE_ID = 0xffffffff; | ||
|
||
// These flags are used in LinkedListSet values to optimize lookups. | ||
// It's important that they don't overlap with bit 1 and bit 2, which are reserved bits used to indicate | ||
// the sentinel value and the existence of a next value, respectively. | ||
|
@@ -64,10 +67,10 @@ abstract contract PluginManagerInternals is IPluginManager, AccountStorageV1 { | |
error DuplicatePreUserOpValidationHookLimitExceeded(bytes4 selector, FunctionReference hook); | ||
error Erc4337FunctionNotAllowed(bytes4 selector); | ||
error ExecutionFunctionAlreadySet(bytes4 selector); | ||
error IPluginFunctionNotAllowed(bytes4 selector); | ||
error IPluginInterfaceNotAllowed(); | ||
error InterfaceNotAllowed(); | ||
error InvalidDependenciesProvided(); | ||
error InvalidPluginManifest(); | ||
error IPluginFunctionNotAllowed(bytes4 selector); | ||
error MissingPluginDependency(address dependency); | ||
error NativeFunctionNotAllowed(bytes4 selector); | ||
error NullFunctionReference(); | ||
|
@@ -452,8 +455,8 @@ abstract contract PluginManagerInternals is IPluginManager, AccountStorageV1 { | |
length = manifest.interfaceIds.length; | ||
for (uint256 i = 0; i < length; ++i) { | ||
bytes4 interfaceId = manifest.interfaceIds[i]; | ||
if (interfaceId == type(IPlugin).interfaceId) { | ||
revert IPluginInterfaceNotAllowed(); | ||
if (interfaceId == type(IPlugin).interfaceId || interfaceId == _INVALID_INTERFACE_ID) { | ||
revert InterfaceNotAllowed(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The following interface types are also not relevant, although it doesn't really hurt to add them
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. True. I'll probably leave this one as is since it doesn't hurt, and adding this in will increase contract size. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you want to reduce the contract size There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed! But I think this is ever so slightly different, which may justify this one.
|
||
} | ||
storage_.supportedInterfaces[interfaceId] += 1; | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,6 +17,9 @@ | |
|
||
pragma solidity ^0.8.22; | ||
|
||
import {IERC1155Receiver} from "@openzeppelin/contracts/interfaces/IERC1155Receiver.sol"; | ||
import {IERC777Recipient} from "@openzeppelin/contracts/interfaces/IERC777Recipient.sol"; | ||
import {IERC721Receiver} from "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol"; | ||
import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; | ||
|
||
import {UUPSUpgradeable} from "../../ext/UUPSUpgradeable.sol"; | ||
|
@@ -51,6 +54,9 @@ contract UpgradeableModularAccount is | |
IAccountInitializable, | ||
IAccountView, | ||
IERC165, | ||
IERC721Receiver, | ||
IERC777Recipient, | ||
IERC1155Receiver, | ||
IPluginExecutor, | ||
IStandardExecutor, | ||
UUPSUpgradeable | ||
|
@@ -80,8 +86,6 @@ contract UpgradeableModularAccount is | |
// ERC-4337 v0.6.0 entrypoint address only | ||
IEntryPoint private immutable _ENTRY_POINT; | ||
|
||
// As per the EIP-165 spec, no interface should ever match 0xffffffff | ||
bytes4 internal constant _INTERFACE_ID_INVALID = 0xffffffff; | ||
bytes4 internal constant _IERC165_INTERFACE_ID = 0x01ffc9a7; | ||
|
||
event ModularAccountInitialized(IEntryPoint indexed entryPoint); | ||
|
@@ -370,16 +374,58 @@ contract UpgradeableModularAccount is | |
_postNativeFunction(postExecHooks, postHookArgs); | ||
} | ||
|
||
/// @inheritdoc IERC165 | ||
function supportsInterface(bytes4 interfaceId) external view override returns (bool) { | ||
if (interfaceId == _INTERFACE_ID_INVALID) { | ||
return false; | ||
} | ||
if (interfaceId == _IERC165_INTERFACE_ID) { | ||
return true; | ||
} | ||
/// @inheritdoc IERC777Recipient | ||
/// @dev Runtime validation is bypassed for this function, but we still allow pre and post exec hooks to be | ||
/// assigned and run. | ||
function tokensReceived(address, address, address, uint256, bytes calldata, bytes calldata) | ||
jaypaik marked this conversation as resolved.
Show resolved
Hide resolved
|
||
external | ||
override | ||
{ | ||
(FunctionReference[][] memory postExecHooks, bytes[] memory postHookArgs) = | ||
_doPreExecHooks(_getAccountStorage().selectorData[msg.sig], ""); | ||
_postNativeFunction(postExecHooks, postHookArgs); | ||
} | ||
|
||
return _getAccountStorage().supportedInterfaces[interfaceId] > 0; | ||
/// @inheritdoc IERC721Receiver | ||
/// @dev Runtime validation is bypassed for this function, but we still allow pre and post exec hooks to be | ||
/// assigned and run. | ||
function onERC721Received(address, address, uint256, bytes calldata) | ||
external | ||
override | ||
returns (bytes4 selector) | ||
{ | ||
(FunctionReference[][] memory postExecHooks, bytes[] memory postHookArgs) = | ||
_doPreExecHooks(_getAccountStorage().selectorData[msg.sig], ""); | ||
selector = IERC721Receiver.onERC721Received.selector; | ||
_postNativeFunction(postExecHooks, postHookArgs); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In order to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good idea. Addressed in #127 ! |
||
|
||
/// @inheritdoc IERC1155Receiver | ||
/// @dev Runtime validation is bypassed for this function, but we still allow pre and post exec hooks to be | ||
/// assigned and run. | ||
function onERC1155Received(address, address, uint256, uint256, bytes calldata) | ||
external | ||
override | ||
returns (bytes4 selector) | ||
{ | ||
(FunctionReference[][] memory postExecHooks, bytes[] memory postHookArgs) = | ||
_doPreExecHooks(_getAccountStorage().selectorData[msg.sig], ""); | ||
selector = IERC1155Receiver.onERC1155Received.selector; | ||
_postNativeFunction(postExecHooks, postHookArgs); | ||
} | ||
|
||
/// @inheritdoc IERC1155Receiver | ||
/// @dev Runtime validation is bypassed for this function, but we still allow pre and post exec hooks to be | ||
/// assigned and run. | ||
function onERC1155BatchReceived(address, address, uint256[] calldata, uint256[] calldata, bytes calldata) | ||
external | ||
override | ||
returns (bytes4 selector) | ||
{ | ||
(FunctionReference[][] memory postExecHooks, bytes[] memory postHookArgs) = | ||
_doPreExecHooks(_getAccountStorage().selectorData[msg.sig], ""); | ||
selector = IERC1155Receiver.onERC1155BatchReceived.selector; | ||
_postNativeFunction(postExecHooks, postHookArgs); | ||
} | ||
|
||
/// @inheritdoc UUPSUpgradeable | ||
|
@@ -389,6 +435,16 @@ contract UpgradeableModularAccount is | |
_postNativeFunction(postExecHooks, postHookArgs); | ||
} | ||
|
||
/// @inheritdoc IERC165 | ||
function supportsInterface(bytes4 interfaceId) public view override returns (bool) { | ||
if (interfaceId == _INVALID_INTERFACE_ID) { | ||
return false; | ||
} | ||
return interfaceId == _IERC165_INTERFACE_ID || interfaceId == type(IERC721Receiver).interfaceId | ||
|| interfaceId == type(IERC777Recipient).interfaceId || interfaceId == type(IERC1155Receiver).interfaceId | ||
|| _getAccountStorage().supportedInterfaces[interfaceId] > 0; | ||
} | ||
|
||
/// @inheritdoc IAccountView | ||
function entryPoint() public view override returns (IEntryPoint) { | ||
return _ENTRY_POINT; | ||
|
@@ -417,7 +473,7 @@ contract UpgradeableModularAccount is | |
} | ||
|
||
/// @dev Wraps execution of a native function with runtime validation and hooks. Used for upgradeToAndCall, | ||
/// execute, executeBatch, installPlugin, uninstallPlugin. | ||
/// execute, executeBatch, installPlugin, uninstallPlugin, and the token receiver functions. | ||
function _postNativeFunction(FunctionReference[][] memory postExecHooks, bytes[] memory postHookArgs) | ||
internal | ||
{ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
probably not the PR for it, but we do support contract owners too.