Skip to content
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

chore: update to 4337 v0.7 (1/n) #48

Merged
merged 6 commits into from
May 1, 2024
Merged
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
2 changes: 1 addition & 1 deletion lib/account-abstraction
2 changes: 1 addition & 1 deletion lib/openzeppelin-contracts
1 change: 0 additions & 1 deletion src/account/AccountLoupe.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ abstract contract AccountLoupe is IAccountLoupe {

if (
selector == IStandardExecutor.execute.selector || selector == IStandardExecutor.executeBatch.selector
|| selector == UUPSUpgradeable.upgradeTo.selector
|| selector == UUPSUpgradeable.upgradeToAndCall.selector
|| selector == IPluginManager.installPlugin.selector
|| selector == IPluginManager.uninstallPlugin.selector
Expand Down
72 changes: 47 additions & 25 deletions src/account/AccountStorageInitializable.sol
Original file line number Diff line number Diff line change
@@ -1,45 +1,67 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.25;

import {Address} from "@openzeppelin/contracts/utils/Address.sol";

import {AccountStorage, getAccountStorage} from "./AccountStorage.sol";

/// @title AccountStorageInitializable
/// @dev Bulk of the impl is lifted from OZ 5.0 Initializible
abstract contract AccountStorageInitializable {
error AlreadyInitialized();
error AlreadyInitializing();
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint64 version);

/**
* @dev The contract is already initialized.
*/
error InvalidInitialization();

/**
* @dev The contract is not initializing.
*/
error NotInitializing();

/// @notice Modifier to put on function intended to be called only once per implementation
/// @dev Reverts if the contract has already been initialized
modifier initializer() {
AccountStorage storage _storage = getAccountStorage();
bool isTopLevelCall = !_storage.initializing;
if (
isTopLevelCall && _storage.initialized < 1
|| !Address.isContract(address(this)) && _storage.initialized == 1
) {
_storage.initialized = 1;
if (isTopLevelCall) {
_storage.initializing = true;
}
_;
if (isTopLevelCall) {
_storage.initializing = false;
}
} else {
revert AlreadyInitialized();
AccountStorage storage $ = getAccountStorage();

// Cache values to avoid duplicated sloads
bool isTopLevelCall = !$.initializing;
uint64 initialized = $.initialized;

// Allowed calls:
// - initialSetup: the contract is not in the initializing state and no previous version was
// initialized
// - construction: the contract is initialized at version 1 (no reininitialization) and the
// current contract is just being deployed
bool initialSetup = initialized == 0 && isTopLevelCall;
bool construction = initialized == 1 && address(this).code.length == 0;

if (!initialSetup && !construction) {
revert InvalidInitialization();
}
$.initialized = 1;
if (isTopLevelCall) {
$.initializing = true;
}
_;
if (isTopLevelCall) {
$.initializing = false;
emit Initialized(1);
}
}

/// @notice Internal function to disable calls to initialization functions
/// @dev Reverts if the contract has already been initialized
function _disableInitializers() internal virtual {
AccountStorage storage _storage = getAccountStorage();
if (_storage.initializing) {
revert AlreadyInitializing();
AccountStorage storage $ = getAccountStorage();
if ($.initializing) {
revert InvalidInitialization();
}
if (_storage.initialized != type(uint8).max) {
_storage.initialized = type(uint8).max;
if ($.initialized != type(uint8).max) {
$.initialized = type(uint8).max;
emit Initialized(type(uint8).max);
}
}
}
13 changes: 4 additions & 9 deletions src/account/UpgradeableModularAccount.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ pragma solidity ^0.8.25;

import {BaseAccount} from "@eth-infinitism/account-abstraction/core/BaseAccount.sol";
import {IEntryPoint} from "@eth-infinitism/account-abstraction/interfaces/IEntryPoint.sol";
import {UserOperation} from "@eth-infinitism/account-abstraction/interfaces/UserOperation.sol";
import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interfaces/PackedUserOperation.sol";
import {UUPSUpgradeable} from "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol";
import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
import {EnumerableMap} from "@openzeppelin/contracts/utils/structs/EnumerableMap.sol";
Expand Down Expand Up @@ -292,11 +292,6 @@ contract UpgradeableModularAccount is
return getAccountStorage().supportedIfaces[interfaceId] > 0;
}

/// @inheritdoc UUPSUpgradeable
function upgradeTo(address newImplementation) public override onlyProxy wrapNativeFunction {
_upgradeToAndCallUUPS(newImplementation, new bytes(0), false);
}

/// @inheritdoc UUPSUpgradeable
function upgradeToAndCall(address newImplementation, bytes memory data)
public
Expand All @@ -305,7 +300,7 @@ contract UpgradeableModularAccount is
onlyProxy
wrapNativeFunction
{
_upgradeToAndCallUUPS(newImplementation, data, true);
super.upgradeToAndCall(newImplementation, data);
}

/// @notice Gets the entry point for this account
Expand All @@ -317,7 +312,7 @@ contract UpgradeableModularAccount is
// INTERNAL FUNCTIONS

// Parent function validateUserOp enforces that this call can only be made by the EntryPoint
function _validateSignature(UserOperation calldata userOp, bytes32 userOpHash)
function _validateSignature(PackedUserOperation calldata userOp, bytes32 userOpHash)
internal
virtual
override
Expand All @@ -337,7 +332,7 @@ contract UpgradeableModularAccount is
function _doUserOpValidation(
bytes4 selector,
FunctionReference userOpValidationFunction,
UserOperation calldata userOp,
PackedUserOperation calldata userOp,
bytes32 userOpHash
) internal returns (uint256 validationData) {
if (userOpValidationFunction.isEmpty()) {
Expand Down
6 changes: 3 additions & 3 deletions src/interfaces/IPlugin.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: CC0-1.0
pragma solidity ^0.8.25;

import {UserOperation} from "@eth-infinitism/account-abstraction/interfaces/UserOperation.sol";
import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interfaces/PackedUserOperation.sol";

// Forge formatter will displace the first comment for the enum field out of the enum itself,
// so annotating here to prevent that.
Expand Down Expand Up @@ -116,7 +116,7 @@ interface IPlugin {
/// @param userOp The user operation.
/// @param userOpHash The user operation hash.
/// @return Packed validation data for validAfter (6 bytes), validUntil (6 bytes), and authorizer (20 bytes).
function preUserOpValidationHook(uint8 functionId, UserOperation calldata userOp, bytes32 userOpHash)
function preUserOpValidationHook(uint8 functionId, PackedUserOperation calldata userOp, bytes32 userOpHash)
external
returns (uint256);

Expand All @@ -126,7 +126,7 @@ interface IPlugin {
/// @param userOp The user operation.
/// @param userOpHash The user operation hash.
/// @return Packed validation data for validAfter (6 bytes), validUntil (6 bytes), and authorizer (20 bytes).
function userOpValidationFunction(uint8 functionId, UserOperation calldata userOp, bytes32 userOpHash)
function userOpValidationFunction(uint8 functionId, PackedUserOperation calldata userOp, bytes32 userOpHash)
external
returns (uint256);

Expand Down
6 changes: 3 additions & 3 deletions src/plugins/BasePlugin.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.25;

import {UserOperation} from "@eth-infinitism/account-abstraction/interfaces/UserOperation.sol";
import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interfaces/PackedUserOperation.sol";
import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol";

import {IPlugin, PluginManifest, PluginMetadata} from "../interfaces/IPlugin.sol";
Expand Down Expand Up @@ -38,7 +38,7 @@ abstract contract BasePlugin is ERC165, IPlugin {
/// @param userOp The user operation.
/// @param userOpHash The user operation hash.
/// @return Packed validation data for validAfter (6 bytes), validUntil (6 bytes), and authorizer (20 bytes).
function preUserOpValidationHook(uint8 functionId, UserOperation calldata userOp, bytes32 userOpHash)
function preUserOpValidationHook(uint8 functionId, PackedUserOperation calldata userOp, bytes32 userOpHash)
external
virtual
returns (uint256)
Expand All @@ -53,7 +53,7 @@ abstract contract BasePlugin is ERC165, IPlugin {
/// @param userOp The user operation.
/// @param userOpHash The user operation hash.
/// @return Packed validation data for validAfter (6 bytes), validUntil (6 bytes), and authorizer (20 bytes).
function userOpValidationFunction(uint8 functionId, UserOperation calldata userOp, bytes32 userOpHash)
function userOpValidationFunction(uint8 functionId, PackedUserOperation calldata userOp, bytes32 userOpHash)
external
virtual
returns (uint256)
Expand Down
34 changes: 10 additions & 24 deletions src/plugins/TokenReceiverPlugin.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
pragma solidity ^0.8.25;

import {IERC721Receiver} from "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
import {IERC777Recipient} from "@openzeppelin/contracts/interfaces/IERC777Recipient.sol";
import {IERC1155Receiver} from "@openzeppelin/contracts/interfaces/IERC1155Receiver.sol";

import {
Expand All @@ -18,7 +17,7 @@ import {BasePlugin} from "./BasePlugin.sol";
/// @author ERC-6900 Authors
/// @notice This plugin allows modular accounts to receive various types of tokens by implementing
/// required token receiver interfaces.
contract TokenReceiverPlugin is BasePlugin, IERC721Receiver, IERC777Recipient, IERC1155Receiver {
contract TokenReceiverPlugin is BasePlugin, IERC721Receiver, IERC1155Receiver {
string public constant NAME = "Token Receiver Plugin";
string public constant VERSION = "1.0.0";
string public constant AUTHOR = "ERC-6900 Authors";
Expand All @@ -27,13 +26,6 @@ contract TokenReceiverPlugin is BasePlugin, IERC721Receiver, IERC777Recipient, I
// ┃ Execution functions ┃
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━┛

function tokensReceived(address, address, address, uint256, bytes calldata, bytes calldata)
external
pure
override
// solhint-disable-next-line no-empty-blocks
{}

function onERC721Received(address, address, uint256, bytes calldata) external pure override returns (bytes4) {
return IERC721Receiver.onERC721Received.selector;
}
Expand Down Expand Up @@ -72,40 +64,34 @@ contract TokenReceiverPlugin is BasePlugin, IERC721Receiver, IERC777Recipient, I
function pluginManifest() external pure override returns (PluginManifest memory) {
PluginManifest memory manifest;

manifest.executionFunctions = new bytes4[](4);
manifest.executionFunctions[0] = this.tokensReceived.selector;
manifest.executionFunctions[1] = this.onERC721Received.selector;
manifest.executionFunctions[2] = this.onERC1155Received.selector;
manifest.executionFunctions[3] = this.onERC1155BatchReceived.selector;
manifest.executionFunctions = new bytes4[](3);
manifest.executionFunctions[0] = this.onERC721Received.selector;
manifest.executionFunctions[1] = this.onERC1155Received.selector;
manifest.executionFunctions[2] = this.onERC1155BatchReceived.selector;

// Only runtime validationFunction is needed since callbacks come from token contracts only
ManifestFunction memory alwaysAllowRuntime = ManifestFunction({
functionType: ManifestAssociatedFunctionType.RUNTIME_VALIDATION_ALWAYS_ALLOW,
functionId: 0, // Unused.
dependencyIndex: 0 // Unused.
});
manifest.validationFunctions = new ManifestAssociatedFunction[](4);
manifest.validationFunctions = new ManifestAssociatedFunction[](3);
manifest.validationFunctions[0] = ManifestAssociatedFunction({
executionSelector: this.tokensReceived.selector,
associatedFunction: alwaysAllowRuntime
});
manifest.validationFunctions[1] = ManifestAssociatedFunction({
executionSelector: this.onERC721Received.selector,
associatedFunction: alwaysAllowRuntime
});
manifest.validationFunctions[2] = ManifestAssociatedFunction({
manifest.validationFunctions[1] = ManifestAssociatedFunction({
executionSelector: this.onERC1155Received.selector,
associatedFunction: alwaysAllowRuntime
});
manifest.validationFunctions[3] = ManifestAssociatedFunction({
manifest.validationFunctions[2] = ManifestAssociatedFunction({
executionSelector: this.onERC1155BatchReceived.selector,
associatedFunction: alwaysAllowRuntime
});

manifest.interfaceIds = new bytes4[](3);
manifest.interfaceIds = new bytes4[](2);
manifest.interfaceIds[0] = type(IERC721Receiver).interfaceId;
manifest.interfaceIds[1] = type(IERC777Recipient).interfaceId;
manifest.interfaceIds[2] = type(IERC1155Receiver).interfaceId;
manifest.interfaceIds[1] = type(IERC1155Receiver).interfaceId;

return manifest;
}
Expand Down
16 changes: 7 additions & 9 deletions src/plugins/owner/SingleOwnerPlugin.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ pragma solidity ^0.8.25;
import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import {IERC1271} from "@openzeppelin/contracts/interfaces/IERC1271.sol";
import {SignatureChecker} from "@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol";
import {UserOperation} from "@eth-infinitism/account-abstraction/interfaces/UserOperation.sol";
import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interfaces/PackedUserOperation.sol";
import {MessageHashUtils} from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol";

import {UUPSUpgradeable} from "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol";
import {IPluginManager} from "../../interfaces/IPluginManager.sol";
Expand Down Expand Up @@ -38,6 +39,7 @@ import {ISingleOwnerPlugin} from "./ISingleOwnerPlugin.sol";
/// send user operations through a bundler.
contract SingleOwnerPlugin is BasePlugin, ISingleOwnerPlugin, IERC1271 {
using ECDSA for bytes32;
using MessageHashUtils for bytes32;

string public constant NAME = "Single Owner Plugin";
string public constant VERSION = "1.0.0";
Expand Down Expand Up @@ -91,15 +93,15 @@ contract SingleOwnerPlugin is BasePlugin, ISingleOwnerPlugin, IERC1271 {
}

/// @inheritdoc BasePlugin
function userOpValidationFunction(uint8 functionId, UserOperation calldata userOp, bytes32 userOpHash)
function userOpValidationFunction(uint8 functionId, PackedUserOperation calldata userOp, bytes32 userOpHash)
external
view
override
returns (uint256)
{
if (functionId == uint8(FunctionId.VALIDATION_OWNER_OR_SELF)) {
// Validate the user op signature against the owner.
(address signer,) = (userOpHash.toEthSignedMessageHash()).tryRecover(userOp.signature);
(address signer,,) = (userOpHash.toEthSignedMessageHash()).tryRecover(userOp.signature);
if (signer == address(0) || signer != _owners[msg.sender]) {
return _SIG_VALIDATION_FAILED;
}
Expand Down Expand Up @@ -154,7 +156,7 @@ contract SingleOwnerPlugin is BasePlugin, ISingleOwnerPlugin, IERC1271 {
functionId: uint8(FunctionId.VALIDATION_OWNER_OR_SELF),
dependencyIndex: 0 // Unused.
});
manifest.validationFunctions = new ManifestAssociatedFunction[](8);
manifest.validationFunctions = new ManifestAssociatedFunction[](7);
manifest.validationFunctions[0] = ManifestAssociatedFunction({
executionSelector: this.transferOwnership.selector,
associatedFunction: ownerValidationFunction
Expand All @@ -176,10 +178,6 @@ contract SingleOwnerPlugin is BasePlugin, ISingleOwnerPlugin, IERC1271 {
associatedFunction: ownerValidationFunction
});
manifest.validationFunctions[5] = ManifestAssociatedFunction({
executionSelector: UUPSUpgradeable.upgradeTo.selector,
associatedFunction: ownerValidationFunction
});
manifest.validationFunctions[6] = ManifestAssociatedFunction({
executionSelector: UUPSUpgradeable.upgradeToAndCall.selector,
associatedFunction: ownerValidationFunction
});
Expand All @@ -189,7 +187,7 @@ contract SingleOwnerPlugin is BasePlugin, ISingleOwnerPlugin, IERC1271 {
functionId: 0, // Unused.
dependencyIndex: 0 // Unused.
});
manifest.validationFunctions[7] = ManifestAssociatedFunction({
manifest.validationFunctions[6] = ManifestAssociatedFunction({
executionSelector: this.isValidSignature.selector,
associatedFunction: alwaysAllowRuntime
});
Expand Down
4 changes: 2 additions & 2 deletions src/samples/plugins/ModularSessionKeyPlugin.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ pragma solidity ^0.8.25;

// import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
// import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
// import {UserOperation} from "@eth-infinitism/account-abstraction/interfaces/UserOperation.sol";
// import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interfaces/PackedUserOperation.sol";
// import {UpgradeableModularAccount} from "../../account/UpgradeableModularAccount.sol";
// import {
// ManifestFunction,
Expand Down Expand Up @@ -188,7 +188,7 @@ pragma solidity ^0.8.25;
// }

// /// @inheritdoc BasePlugin
// function userOpValidationFunction(uint8 functionId, UserOperation calldata userOp, bytes32 userOpHash)
// function userOpValidationFunction(uint8 functionId, PackedUserOperation calldata userOp, bytes32 userOpHash)
// external
// view
// override
Expand Down
2 changes: 1 addition & 1 deletion src/samples/plugins/interfaces/ISessionKeyPlugin.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.25;

// import {UserOperation} from "@eth-infinitism/account-abstraction/interfaces/UserOperation.sol";
// import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interfaces/PackedUserOperation.sol";

// interface IModularSessionKeyPlugin {
// enum FunctionId {
Expand Down
2 changes: 1 addition & 1 deletion src/samples/plugins/interfaces/ITokenSessionKeyPlugin.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.25;

// import {UserOperation} from "@eth-infinitism/account-abstraction/interfaces/UserOperation.sol";
// import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interfaces/PackedUserOperation.sol";

// interface ITokenSessionKeyPlugin {
// error NotAuthorized();
Expand Down
Loading
Loading