@erc6900/reference-implementation 0.8.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of @erc6900/reference-implementation might be problematic. Click here for more details.
- package/package.json +5 -26
- package/preinstall.js +110 -0
- package/LICENSE +0 -21
- package/README.md +0 -76
- package/src/account/AccountExecutor.sol +0 -20
- package/src/account/AccountFactory.sol +0 -126
- package/src/account/AccountStorage.sol +0 -99
- package/src/account/AccountStorageInitializable.sol +0 -67
- package/src/account/ModularAccountView.sol +0 -66
- package/src/account/ModuleManagerInternals.sol +0 -325
- package/src/account/ReferenceModularAccount.sol +0 -769
- package/src/account/SemiModularAccount.sol +0 -214
- package/src/account/SemiModularAccount7702.sol +0 -38
- package/src/helpers/CollectReturnData.sol +0 -14
- package/src/helpers/Constants.sol +0 -11
- package/src/helpers/EmptyCalldataSlice.sol +0 -12
- package/src/helpers/ValidationResHelpers.sol +0 -50
- package/src/interfaces/IERC6900Account.sol +0 -127
- package/src/interfaces/IERC6900AccountView.sol +0 -52
- package/src/interfaces/IERC6900ExecutionHookModule.sol +0 -26
- package/src/interfaces/IERC6900ExecutionModule.sol +0 -37
- package/src/interfaces/IERC6900Module.sol +0 -24
- package/src/interfaces/IERC6900ValidationHookModule.sol +0 -46
- package/src/interfaces/IERC6900ValidationModule.sol +0 -53
- package/src/libraries/HookConfigLib.sol +0 -135
- package/src/libraries/KnownSelectorsLib.sol +0 -65
- package/src/libraries/ModuleEntityLib.sol +0 -37
- package/src/libraries/ModuleStorageLib.sol +0 -62
- package/src/libraries/SparseCalldataSegmentLib.sol +0 -95
- package/src/libraries/ValidationConfigLib.sol +0 -119
- package/src/modules/BaseModule.sol +0 -54
- package/src/modules/ModuleEIP712.sol +0 -29
- package/src/modules/ReplaySafeWrapper.sol +0 -38
- package/src/modules/TokenReceiverModule.sol +0 -87
- package/src/modules/permissions/AllowlistModule.sol +0 -156
- package/src/modules/permissions/ERC20TokenLimitModule.sol +0 -145
- package/src/modules/permissions/NativeTokenLimitModule.sol +0 -154
- package/src/modules/validation/ISingleSignerValidationModule.sol +0 -22
- package/src/modules/validation/SingleSignerValidationModule.sol +0 -138
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: CC0-1.0
|
|
2
|
-
pragma solidity ^0.8.20;
|
|
3
|
-
|
|
4
|
-
import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interfaces/PackedUserOperation.sol";
|
|
5
|
-
|
|
6
|
-
import {IERC6900Module} from "./IERC6900Module.sol";
|
|
7
|
-
|
|
8
|
-
interface IERC6900ValidationModule is IERC6900Module {
|
|
9
|
-
/// @notice Run the user operation validation function specified by the `entityId`.
|
|
10
|
-
/// @param entityId An identifier that routes the call to different internal implementations, should there
|
|
11
|
-
/// be more than one.
|
|
12
|
-
/// @param userOp The user operation.
|
|
13
|
-
/// @param userOpHash The user operation hash.
|
|
14
|
-
/// @return Packed validation data for validAfter (6 bytes), validUntil (6 bytes), and authorizer (20 bytes).
|
|
15
|
-
function validateUserOp(uint32 entityId, PackedUserOperation calldata userOp, bytes32 userOpHash)
|
|
16
|
-
external
|
|
17
|
-
returns (uint256);
|
|
18
|
-
|
|
19
|
-
/// @notice Run the runtime validation function specified by the `entityId`.
|
|
20
|
-
/// @dev To indicate the entire call should revert, the function MUST revert.
|
|
21
|
-
/// @param account The account to validate for.
|
|
22
|
-
/// @param entityId An identifier that routes the call to different internal implementations, should there
|
|
23
|
-
/// be more than one.
|
|
24
|
-
/// @param sender The caller address.
|
|
25
|
-
/// @param value The call value.
|
|
26
|
-
/// @param data The calldata sent.
|
|
27
|
-
/// @param authorization Additional data for the validation function to use.
|
|
28
|
-
function validateRuntime(
|
|
29
|
-
address account,
|
|
30
|
-
uint32 entityId,
|
|
31
|
-
address sender,
|
|
32
|
-
uint256 value,
|
|
33
|
-
bytes calldata data,
|
|
34
|
-
bytes calldata authorization
|
|
35
|
-
) external;
|
|
36
|
-
|
|
37
|
-
/// @notice Validates a signature using ERC-1271.
|
|
38
|
-
/// @dev To indicate the entire call should revert, the function MUST revert.
|
|
39
|
-
/// @param account The account to validate for.
|
|
40
|
-
/// @param entityId An identifier that routes the call to different internal implementations, should there
|
|
41
|
-
/// be more than one.
|
|
42
|
-
/// @param sender The address that sent the ERC-1271 request to the smart account.
|
|
43
|
-
/// @param hash The hash of the ERC-1271 request.
|
|
44
|
-
/// @param signature The signature of the ERC-1271 request.
|
|
45
|
-
/// @return The ERC-1271 `MAGIC_VALUE` if the signature is valid, or 0xFFFFFFFF if invalid.
|
|
46
|
-
function validateSignature(
|
|
47
|
-
address account,
|
|
48
|
-
uint32 entityId,
|
|
49
|
-
address sender,
|
|
50
|
-
bytes32 hash,
|
|
51
|
-
bytes calldata signature
|
|
52
|
-
) external view returns (bytes4);
|
|
53
|
-
}
|
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: MIT
|
|
2
|
-
pragma solidity ^0.8.20;
|
|
3
|
-
|
|
4
|
-
import {HookConfig, ModuleEntity} from "../interfaces/IERC6900Account.sol";
|
|
5
|
-
|
|
6
|
-
// Hook types:
|
|
7
|
-
// Exec hook: bools for hasPre, hasPost
|
|
8
|
-
// Validation hook: no bools
|
|
9
|
-
|
|
10
|
-
// Hook fields:
|
|
11
|
-
// module address
|
|
12
|
-
// entity ID
|
|
13
|
-
// hook type
|
|
14
|
-
// if exec hook: hasPre, hasPost
|
|
15
|
-
|
|
16
|
-
// Hook config is a packed representation of a hook function and flags for its configuration.
|
|
17
|
-
// Layout:
|
|
18
|
-
// 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA________________________ // Address
|
|
19
|
-
// 0x________________________________________BBBBBBBB________________ // Entity ID
|
|
20
|
-
// 0x________________________________________________CC______________ // Hook Flags
|
|
21
|
-
|
|
22
|
-
// Hook flags layout:
|
|
23
|
-
// 0b00000___ // unused
|
|
24
|
-
// 0b_____A__ // hasPre (exec only)
|
|
25
|
-
// 0b______B_ // hasPost (exec only)
|
|
26
|
-
// 0b_______C // hook type (0 for exec, 1 for validation)
|
|
27
|
-
|
|
28
|
-
library HookConfigLib {
|
|
29
|
-
// Hook type constants
|
|
30
|
-
// Exec has no bits set
|
|
31
|
-
bytes32 internal constant _HOOK_TYPE_EXEC = bytes32(uint256(0));
|
|
32
|
-
// Validation has 1 in the 25th byte
|
|
33
|
-
bytes32 internal constant _HOOK_TYPE_VALIDATION = bytes32(uint256(1) << 56);
|
|
34
|
-
|
|
35
|
-
// Exec hook flags constants
|
|
36
|
-
// Pre hook has 1 in 4's bit in the 25th byte
|
|
37
|
-
bytes32 internal constant _EXEC_HOOK_HAS_PRE = bytes32(uint256(1) << 58);
|
|
38
|
-
// Post hook has 1 in 2's bit in the 25th byte
|
|
39
|
-
bytes32 internal constant _EXEC_HOOK_HAS_POST = bytes32(uint256(1) << 57);
|
|
40
|
-
|
|
41
|
-
function packValidationHook(ModuleEntity _hookFunction) internal pure returns (HookConfig) {
|
|
42
|
-
return
|
|
43
|
-
HookConfig.wrap(bytes25(bytes25(ModuleEntity.unwrap(_hookFunction)) | bytes25(_HOOK_TYPE_VALIDATION)));
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function packValidationHook(address _module, uint32 _entityId) internal pure returns (HookConfig) {
|
|
47
|
-
return HookConfig.wrap(
|
|
48
|
-
bytes25(
|
|
49
|
-
// module address stored in the first 20 bytes
|
|
50
|
-
bytes25(bytes20(_module))
|
|
51
|
-
// entityId stored in the 21st - 24th byte
|
|
52
|
-
| bytes25(bytes24(uint192(_entityId))) | bytes25(_HOOK_TYPE_VALIDATION)
|
|
53
|
-
)
|
|
54
|
-
);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
function packExecHook(ModuleEntity _hookFunction, bool _hasPre, bool _hasPost)
|
|
58
|
-
internal
|
|
59
|
-
pure
|
|
60
|
-
returns (HookConfig)
|
|
61
|
-
{
|
|
62
|
-
return HookConfig.wrap(
|
|
63
|
-
bytes25(
|
|
64
|
-
bytes25(ModuleEntity.unwrap(_hookFunction))
|
|
65
|
-
// | bytes25(_HOOK_TYPE_EXEC) // Can omit because exec type is 0
|
|
66
|
-
| bytes25(_hasPre ? _EXEC_HOOK_HAS_PRE : bytes32(0))
|
|
67
|
-
| bytes25(_hasPost ? _EXEC_HOOK_HAS_POST : bytes32(0))
|
|
68
|
-
)
|
|
69
|
-
);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
function packExecHook(address _module, uint32 _entityId, bool _hasPre, bool _hasPost)
|
|
73
|
-
internal
|
|
74
|
-
pure
|
|
75
|
-
returns (HookConfig)
|
|
76
|
-
{
|
|
77
|
-
return HookConfig.wrap(
|
|
78
|
-
bytes25(
|
|
79
|
-
// module address stored in the first 20 bytes
|
|
80
|
-
bytes25(bytes20(_module))
|
|
81
|
-
// entityId stored in the 21st - 24th byte
|
|
82
|
-
| bytes25(bytes24(uint192(_entityId)))
|
|
83
|
-
// | bytes25(_HOOK_TYPE_EXEC) // Can omit because exec type is 0
|
|
84
|
-
| bytes25(_hasPre ? _EXEC_HOOK_HAS_PRE : bytes32(0))
|
|
85
|
-
| bytes25(_hasPost ? _EXEC_HOOK_HAS_POST : bytes32(0))
|
|
86
|
-
)
|
|
87
|
-
);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
function unpackValidationHook(HookConfig _config) internal pure returns (ModuleEntity _hookFunction) {
|
|
91
|
-
bytes25 configBytes = HookConfig.unwrap(_config);
|
|
92
|
-
_hookFunction = ModuleEntity.wrap(bytes24(configBytes));
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
function unpackExecHook(HookConfig _config)
|
|
96
|
-
internal
|
|
97
|
-
pure
|
|
98
|
-
returns (ModuleEntity _hookFunction, bool _hasPre, bool _hasPost)
|
|
99
|
-
{
|
|
100
|
-
bytes25 configBytes = HookConfig.unwrap(_config);
|
|
101
|
-
_hookFunction = ModuleEntity.wrap(bytes24(configBytes));
|
|
102
|
-
_hasPre = configBytes & _EXEC_HOOK_HAS_PRE != 0;
|
|
103
|
-
_hasPost = configBytes & _EXEC_HOOK_HAS_POST != 0;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
function module(HookConfig _config) internal pure returns (address) {
|
|
107
|
-
return address(bytes20(HookConfig.unwrap(_config)));
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
function entityId(HookConfig _config) internal pure returns (uint32) {
|
|
111
|
-
return uint32(bytes4(HookConfig.unwrap(_config) << 160));
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
function moduleEntity(HookConfig _config) internal pure returns (ModuleEntity) {
|
|
115
|
-
return ModuleEntity.wrap(bytes24(HookConfig.unwrap(_config)));
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// Check if the hook is a validation hook
|
|
119
|
-
// If false, it is an exec hook
|
|
120
|
-
function isValidationHook(HookConfig _config) internal pure returns (bool) {
|
|
121
|
-
return HookConfig.unwrap(_config) & _HOOK_TYPE_VALIDATION != 0;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
// Check if the exec hook has a pre hook
|
|
125
|
-
// Undefined behavior if the hook is not an exec hook
|
|
126
|
-
function hasPreHook(HookConfig _config) internal pure returns (bool) {
|
|
127
|
-
return HookConfig.unwrap(_config) & _EXEC_HOOK_HAS_PRE != 0;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
// Check if the exec hook has a post hook
|
|
131
|
-
// Undefined behavior if the hook is not an exec hook
|
|
132
|
-
function hasPostHook(HookConfig _config) internal pure returns (bool) {
|
|
133
|
-
return HookConfig.unwrap(_config) & _EXEC_HOOK_HAS_POST != 0;
|
|
134
|
-
}
|
|
135
|
-
}
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: MIT
|
|
2
|
-
pragma solidity ^0.8.20;
|
|
3
|
-
|
|
4
|
-
import {IAccount} from "@eth-infinitism/account-abstraction/interfaces/IAccount.sol";
|
|
5
|
-
import {IAggregator} from "@eth-infinitism/account-abstraction/interfaces/IAggregator.sol";
|
|
6
|
-
import {IPaymaster} from "@eth-infinitism/account-abstraction/interfaces/IPaymaster.sol";
|
|
7
|
-
import {UUPSUpgradeable} from "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol";
|
|
8
|
-
import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
|
|
9
|
-
|
|
10
|
-
import {IERC6900Account} from "../interfaces/IERC6900Account.sol";
|
|
11
|
-
|
|
12
|
-
import {IERC6900AccountView} from "../interfaces/IERC6900AccountView.sol";
|
|
13
|
-
|
|
14
|
-
import {IERC6900ExecutionHookModule} from "../interfaces/IERC6900ExecutionHookModule.sol";
|
|
15
|
-
|
|
16
|
-
import {IERC6900ExecutionModule} from "../interfaces/IERC6900ExecutionModule.sol";
|
|
17
|
-
import {IERC6900Module} from "../interfaces/IERC6900Module.sol";
|
|
18
|
-
import {IERC6900ValidationHookModule} from "../interfaces/IERC6900ValidationHookModule.sol";
|
|
19
|
-
import {IERC6900ValidationModule} from "../interfaces/IERC6900ValidationModule.sol";
|
|
20
|
-
|
|
21
|
-
/// @dev Library to help to check if a selector is a know function selector of the modular account or ERC-4337
|
|
22
|
-
/// contract.
|
|
23
|
-
library KnownSelectorsLib {
|
|
24
|
-
function isNativeFunction(bytes4 selector) internal pure returns (bool) {
|
|
25
|
-
return
|
|
26
|
-
// check against IAccount methods
|
|
27
|
-
selector == IAccount.validateUserOp.selector
|
|
28
|
-
// check against IERC6900Account methods
|
|
29
|
-
|| selector == IERC6900Account.installExecution.selector
|
|
30
|
-
|| selector == IERC6900Account.uninstallExecution.selector
|
|
31
|
-
|| selector == IERC6900Account.installValidation.selector
|
|
32
|
-
|| selector == IERC6900Account.uninstallValidation.selector || selector == IERC6900Account.execute.selector
|
|
33
|
-
|| selector == IERC6900Account.executeBatch.selector
|
|
34
|
-
|| selector == IERC6900Account.executeWithRuntimeValidation.selector
|
|
35
|
-
|| selector == IERC6900Account.accountId.selector
|
|
36
|
-
// check against IERC165 methods
|
|
37
|
-
|| selector == IERC165.supportsInterface.selector
|
|
38
|
-
// check against UUPSUpgradeable methods
|
|
39
|
-
|| selector == UUPSUpgradeable.proxiableUUID.selector
|
|
40
|
-
|| selector == UUPSUpgradeable.upgradeToAndCall.selector
|
|
41
|
-
// check against IERC6900AccountView methods
|
|
42
|
-
|| selector == IERC6900AccountView.getExecutionData.selector
|
|
43
|
-
|| selector == IERC6900AccountView.getValidationData.selector;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function isErc4337Function(bytes4 selector) internal pure returns (bool) {
|
|
47
|
-
return selector == IAggregator.validateSignatures.selector
|
|
48
|
-
|| selector == IAggregator.validateUserOpSignature.selector
|
|
49
|
-
|| selector == IAggregator.aggregateSignatures.selector
|
|
50
|
-
|| selector == IPaymaster.validatePaymasterUserOp.selector || selector == IPaymaster.postOp.selector;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
function isIModuleFunction(bytes4 selector) internal pure returns (bool) {
|
|
54
|
-
return selector == IERC6900Module.onInstall.selector || selector == IERC6900Module.onUninstall.selector
|
|
55
|
-
|| selector == IERC6900Module.moduleId.selector
|
|
56
|
-
|| selector == IERC6900ExecutionModule.executionManifest.selector
|
|
57
|
-
|| selector == IERC6900ExecutionHookModule.preExecutionHook.selector
|
|
58
|
-
|| selector == IERC6900ExecutionHookModule.postExecutionHook.selector
|
|
59
|
-
|| selector == IERC6900ValidationModule.validateUserOp.selector
|
|
60
|
-
|| selector == IERC6900ValidationModule.validateRuntime.selector
|
|
61
|
-
|| selector == IERC6900ValidationModule.validateSignature.selector
|
|
62
|
-
|| selector == IERC6900ValidationHookModule.preUserOpValidationHook.selector
|
|
63
|
-
|| selector == IERC6900ValidationHookModule.preRuntimeValidationHook.selector;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: MIT
|
|
2
|
-
pragma solidity ^0.8.20;
|
|
3
|
-
|
|
4
|
-
import {ModuleEntity} from "../interfaces/IERC6900Account.sol";
|
|
5
|
-
// ModuleEntity is a packed representation of a module function
|
|
6
|
-
// Layout:
|
|
7
|
-
// 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA________________________ // Address
|
|
8
|
-
// 0x________________________________________BBBBBBBB________________ // Entity ID
|
|
9
|
-
// 0x________________________________________________0000000000000000 // unused
|
|
10
|
-
|
|
11
|
-
library ModuleEntityLib {
|
|
12
|
-
function pack(address addr, uint32 entityId) internal pure returns (ModuleEntity) {
|
|
13
|
-
return ModuleEntity.wrap(bytes24(bytes20(addr)) | bytes24(uint192(entityId)));
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function unpack(ModuleEntity moduleEntity) internal pure returns (address addr, uint32 entityId) {
|
|
17
|
-
bytes24 underlying = ModuleEntity.unwrap(moduleEntity);
|
|
18
|
-
addr = address(bytes20(underlying));
|
|
19
|
-
entityId = uint32(bytes4(underlying << 160));
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
function isEmpty(ModuleEntity moduleEntity) internal pure returns (bool) {
|
|
23
|
-
return ModuleEntity.unwrap(moduleEntity) == bytes24(0);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function notEmpty(ModuleEntity moduleEntity) internal pure returns (bool) {
|
|
27
|
-
return ModuleEntity.unwrap(moduleEntity) != bytes24(0);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function eq(ModuleEntity a, ModuleEntity b) internal pure returns (bool) {
|
|
31
|
-
return ModuleEntity.unwrap(a) == ModuleEntity.unwrap(b);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function notEq(ModuleEntity a, ModuleEntity b) internal pure returns (bool) {
|
|
35
|
-
return ModuleEntity.unwrap(a) != ModuleEntity.unwrap(b);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: MIT
|
|
2
|
-
pragma solidity ^0.8.20;
|
|
3
|
-
|
|
4
|
-
type StoragePointer is bytes32;
|
|
5
|
-
|
|
6
|
-
/// @title Module Storage Library
|
|
7
|
-
/// @notice Library for allocating and accessing ERC-4337 address-associated storage within modules.
|
|
8
|
-
library ModuleStorageLib {
|
|
9
|
-
/// @notice Allocates a memory buffer for an associated storage key, and sets the associated address and batch
|
|
10
|
-
/// index.
|
|
11
|
-
/// @param addr The address to associate with the storage key.
|
|
12
|
-
/// @param batchIndex The batch index to associate with the storage key.
|
|
13
|
-
/// @param keySize The size of the key in words, where each word is 32 bytes. Not inclusive of the address and
|
|
14
|
-
/// batch index.
|
|
15
|
-
/// @return key The allocated memory buffer.
|
|
16
|
-
function allocateAssociatedStorageKey(address addr, uint256 batchIndex, uint8 keySize)
|
|
17
|
-
internal
|
|
18
|
-
pure
|
|
19
|
-
returns (bytes memory key)
|
|
20
|
-
{
|
|
21
|
-
/// @solidity memory-safe-assembly
|
|
22
|
-
assembly {
|
|
23
|
-
// Clear any dirty upper bits of keySize to prevent overflow
|
|
24
|
-
keySize := and(keySize, 0xff)
|
|
25
|
-
|
|
26
|
-
// compute the total size of the buffer, include the address and batch index
|
|
27
|
-
let totalSize := add(64, mul(32, keySize))
|
|
28
|
-
|
|
29
|
-
// Allocate memory for the key
|
|
30
|
-
key := mload(0x40)
|
|
31
|
-
mstore(0x40, add(add(key, totalSize), 32))
|
|
32
|
-
mstore(key, totalSize)
|
|
33
|
-
|
|
34
|
-
// Clear any dirty upper bits of address
|
|
35
|
-
addr := and(addr, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
|
|
36
|
-
// Store the address and batch index in the key buffer
|
|
37
|
-
mstore(add(key, 32), addr)
|
|
38
|
-
mstore(add(key, 64), batchIndex)
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function associatedStorageLookup(bytes memory key, bytes32 input) internal pure returns (StoragePointer ptr) {
|
|
43
|
-
/// @solidity memory-safe-assembly
|
|
44
|
-
assembly {
|
|
45
|
-
mstore(add(key, 96), input)
|
|
46
|
-
ptr := keccak256(add(key, 32), mload(key))
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
function associatedStorageLookup(bytes memory key, bytes32 input1, bytes32 input2)
|
|
51
|
-
internal
|
|
52
|
-
pure
|
|
53
|
-
returns (StoragePointer ptr)
|
|
54
|
-
{
|
|
55
|
-
/// @solidity memory-safe-assembly
|
|
56
|
-
assembly {
|
|
57
|
-
mstore(add(key, 96), input1)
|
|
58
|
-
mstore(add(key, 128), input2)
|
|
59
|
-
ptr := keccak256(add(key, 32), mload(key))
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: MIT
|
|
2
|
-
pragma solidity ^0.8.20;
|
|
3
|
-
|
|
4
|
-
import {RESERVED_VALIDATION_DATA_INDEX} from "../helpers/Constants.sol";
|
|
5
|
-
import {getEmptyCalldataSlice} from "../helpers/EmptyCalldataSlice.sol";
|
|
6
|
-
|
|
7
|
-
/// @title Sparse Calldata Segment Library
|
|
8
|
-
/// @notice Library for working with sparsely-packed calldata segments, identified with an index.
|
|
9
|
-
/// @dev The first byte of each segment is the index of the segment.
|
|
10
|
-
/// To prevent accidental stack-to-deep errors, the body and index of the segment are extracted separately, rather
|
|
11
|
-
/// than inline as part of the tuple returned by `getNextSegment`.
|
|
12
|
-
library SparseCalldataSegmentLib {
|
|
13
|
-
error NonCanonicalEncoding();
|
|
14
|
-
error SegmentOutOfOrder();
|
|
15
|
-
error ValidationSignatureSegmentMissing();
|
|
16
|
-
|
|
17
|
-
/// @notice Splits out a segment of calldata, sparsely-packed.
|
|
18
|
-
/// The expected format is:
|
|
19
|
-
/// [uint8(index0), uint32(len(segment0)), segment0, uint8(index1), uint32(len(segment1)), segment1,
|
|
20
|
-
/// ... uint8(indexN), uint32(len(segmentN)), segmentN]
|
|
21
|
-
/// @param source The calldata to extract the segment from.
|
|
22
|
-
/// @return segment The extracted segment. Using the above example, this would be segment0.
|
|
23
|
-
/// @return remainder The remaining calldata. Using the above example,
|
|
24
|
-
/// this would start at uint8(index1) and continue to the end at segmentN.
|
|
25
|
-
function getNextSegment(bytes calldata source)
|
|
26
|
-
internal
|
|
27
|
-
pure
|
|
28
|
-
returns (bytes calldata segment, bytes calldata remainder)
|
|
29
|
-
{
|
|
30
|
-
// The first byte of the segment is the index.
|
|
31
|
-
// The next 4 bytes hold the length of the segment, excluding the index.
|
|
32
|
-
uint32 length = uint32(bytes4(source[1:5]));
|
|
33
|
-
|
|
34
|
-
// The offset of the remainder of the calldata.
|
|
35
|
-
uint256 remainderOffset = 5 + length;
|
|
36
|
-
|
|
37
|
-
// The segment is the next `length` bytes after the first 5 bytes.
|
|
38
|
-
segment = source[5:remainderOffset];
|
|
39
|
-
|
|
40
|
-
// The remainder is the rest of the calldata.
|
|
41
|
-
remainder = source[remainderOffset:];
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/// @notice If the index of the next segment in the source equals the provided index, return the next body and
|
|
45
|
-
/// advance the source by one segment.
|
|
46
|
-
/// @dev Reverts if the index of the next segment is less than the provided index, or if the extracted segment
|
|
47
|
-
/// has length 0.
|
|
48
|
-
/// @param source The calldata to extract the segment from.
|
|
49
|
-
/// @param index The index of the segment to extract.
|
|
50
|
-
/// @return A tuple containing the extracted segment's body, or an empty buffer if the index is not found, and
|
|
51
|
-
/// the remaining calldata.
|
|
52
|
-
function advanceSegmentIfAtIndex(bytes calldata source, uint8 index)
|
|
53
|
-
internal
|
|
54
|
-
pure
|
|
55
|
-
returns (bytes calldata, bytes calldata)
|
|
56
|
-
{
|
|
57
|
-
uint8 nextIndex = getIndex(source);
|
|
58
|
-
|
|
59
|
-
if (nextIndex < index) {
|
|
60
|
-
revert SegmentOutOfOrder();
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
if (nextIndex == index) {
|
|
64
|
-
(bytes calldata segment, bytes calldata remainder) = getNextSegment(source);
|
|
65
|
-
|
|
66
|
-
if (segment.length == 0) {
|
|
67
|
-
revert NonCanonicalEncoding();
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
return (segment, remainder);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
return (getEmptyCalldataSlice(), source);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/// @notice Extracts the final segment from the source.
|
|
77
|
-
/// @dev Reverts if the index of the segment is not RESERVED_VALIDATION_DATA_INDEX.
|
|
78
|
-
/// @param source The calldata to extract the segment from.
|
|
79
|
-
/// @return The final segment.
|
|
80
|
-
function getFinalSegment(bytes calldata source) internal pure returns (bytes calldata) {
|
|
81
|
-
if (getIndex(source) != RESERVED_VALIDATION_DATA_INDEX) {
|
|
82
|
-
revert ValidationSignatureSegmentMissing();
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
return source[1:];
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/// @notice Extracts the index from a segment.
|
|
89
|
-
/// @dev The first byte of the segment is the index.
|
|
90
|
-
/// @param segment The segment to extract the index from
|
|
91
|
-
/// @return The index of the segment
|
|
92
|
-
function getIndex(bytes calldata segment) internal pure returns (uint8) {
|
|
93
|
-
return uint8(segment[0]);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: MIT
|
|
2
|
-
pragma solidity ^0.8.20;
|
|
3
|
-
|
|
4
|
-
import {ModuleEntity, ValidationConfig, ValidationFlags} from "../interfaces/IERC6900Account.sol";
|
|
5
|
-
|
|
6
|
-
// Validation config is a packed representation of a validation function and flags for its configuration.
|
|
7
|
-
// Layout:
|
|
8
|
-
// 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA________________________ // Address
|
|
9
|
-
// 0x________________________________________BBBBBBBB________________ // Entity ID
|
|
10
|
-
// 0x________________________________________________CC______________ // ValidationFlags
|
|
11
|
-
// 0x__________________________________________________00000000000000 // unused
|
|
12
|
-
|
|
13
|
-
// ValidationFlags layout:
|
|
14
|
-
// 0b00000___ // unused
|
|
15
|
-
// 0b_____A__ // isGlobal
|
|
16
|
-
// 0b______B_ // isSignatureValidation
|
|
17
|
-
// 0b_______C // isUserOpValidation
|
|
18
|
-
|
|
19
|
-
library ValidationConfigLib {
|
|
20
|
-
// is user op validation flag stored in last bit of the 25th byte
|
|
21
|
-
bytes32 internal constant _VALIDATION_FLAG_IS_USER_OP = bytes32(uint256(1) << 56);
|
|
22
|
-
// is signature validation flag stored in second to last bit of the 25th byte
|
|
23
|
-
bytes32 internal constant _VALIDATION_FLAG_IS_SIGNATURE = bytes32(uint256(1) << 57);
|
|
24
|
-
// is global flag stored in the third to last bit of the 25th byte
|
|
25
|
-
bytes32 internal constant _VALIDATION_FLAG_IS_GLOBAL = bytes32(uint256(1) << 58);
|
|
26
|
-
|
|
27
|
-
function pack(
|
|
28
|
-
ModuleEntity _validationFunction,
|
|
29
|
-
bool _isGlobal,
|
|
30
|
-
bool _isSignatureValidation,
|
|
31
|
-
bool _isUserOpValidation
|
|
32
|
-
) internal pure returns (ValidationConfig) {
|
|
33
|
-
return ValidationConfig.wrap(
|
|
34
|
-
bytes25(
|
|
35
|
-
bytes25(ModuleEntity.unwrap(_validationFunction))
|
|
36
|
-
| bytes25(bytes32(_isGlobal ? _VALIDATION_FLAG_IS_GLOBAL : bytes32(0)))
|
|
37
|
-
| bytes25(bytes32(_isSignatureValidation ? _VALIDATION_FLAG_IS_SIGNATURE : bytes32(0)))
|
|
38
|
-
| bytes25(bytes32(_isUserOpValidation ? _VALIDATION_FLAG_IS_USER_OP : bytes32(0)))
|
|
39
|
-
)
|
|
40
|
-
);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
function pack(
|
|
44
|
-
address _module,
|
|
45
|
-
uint32 _entityId,
|
|
46
|
-
bool _isGlobal,
|
|
47
|
-
bool _isSignatureValidation,
|
|
48
|
-
bool _isUserOpValidation
|
|
49
|
-
) internal pure returns (ValidationConfig) {
|
|
50
|
-
return ValidationConfig.wrap(
|
|
51
|
-
bytes25(
|
|
52
|
-
// module address stored in the first 20 bytes
|
|
53
|
-
bytes25(bytes20(_module))
|
|
54
|
-
// entityId stored in the 21st - 24th byte
|
|
55
|
-
| bytes25(bytes24(uint192(_entityId)))
|
|
56
|
-
| bytes25(bytes32(_isGlobal ? _VALIDATION_FLAG_IS_GLOBAL : bytes32(0)))
|
|
57
|
-
| bytes25(bytes32(_isSignatureValidation ? _VALIDATION_FLAG_IS_SIGNATURE : bytes32(0)))
|
|
58
|
-
| bytes25(bytes32(_isUserOpValidation ? _VALIDATION_FLAG_IS_USER_OP : bytes32(0)))
|
|
59
|
-
)
|
|
60
|
-
);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function unpackUnderlying(ValidationConfig config)
|
|
64
|
-
internal
|
|
65
|
-
pure
|
|
66
|
-
returns (address _module, uint32 _entityId, ValidationFlags flags)
|
|
67
|
-
{
|
|
68
|
-
bytes25 configBytes = ValidationConfig.unwrap(config);
|
|
69
|
-
_module = address(bytes20(configBytes));
|
|
70
|
-
_entityId = uint32(bytes4(configBytes << 160));
|
|
71
|
-
flags = ValidationFlags.wrap(uint8(configBytes[24]));
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
function unpack(ValidationConfig config)
|
|
75
|
-
internal
|
|
76
|
-
pure
|
|
77
|
-
returns (ModuleEntity _validationFunction, ValidationFlags flags)
|
|
78
|
-
{
|
|
79
|
-
bytes25 configBytes = ValidationConfig.unwrap(config);
|
|
80
|
-
_validationFunction = ModuleEntity.wrap(bytes24(configBytes));
|
|
81
|
-
flags = ValidationFlags.wrap(uint8(configBytes[24]));
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
function module(ValidationConfig config) internal pure returns (address) {
|
|
85
|
-
return address(bytes20(ValidationConfig.unwrap(config)));
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
function entityId(ValidationConfig config) internal pure returns (uint32) {
|
|
89
|
-
return uint32(bytes4(ValidationConfig.unwrap(config) << 160));
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
function moduleEntity(ValidationConfig config) internal pure returns (ModuleEntity) {
|
|
93
|
-
return ModuleEntity.wrap(bytes24(ValidationConfig.unwrap(config)));
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
function isGlobal(ValidationConfig config) internal pure returns (bool) {
|
|
97
|
-
return ValidationConfig.unwrap(config) & _VALIDATION_FLAG_IS_GLOBAL != 0;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
function isGlobal(ValidationFlags flags) internal pure returns (bool) {
|
|
101
|
-
return ValidationFlags.unwrap(flags) & 0x04 != 0;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
function isSignatureValidation(ValidationConfig config) internal pure returns (bool) {
|
|
105
|
-
return ValidationConfig.unwrap(config) & _VALIDATION_FLAG_IS_SIGNATURE != 0;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
function isSignatureValidation(ValidationFlags flags) internal pure returns (bool) {
|
|
109
|
-
return ValidationFlags.unwrap(flags) & 0x02 != 0;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
function isUserOpValidation(ValidationConfig config) internal pure returns (bool) {
|
|
113
|
-
return ValidationConfig.unwrap(config) & _VALIDATION_FLAG_IS_USER_OP != 0;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
function isUserOpValidation(ValidationFlags flags) internal pure returns (bool) {
|
|
117
|
-
return ValidationFlags.unwrap(flags) & 0x01 != 0;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: MIT
|
|
2
|
-
pragma solidity ^0.8.20;
|
|
3
|
-
|
|
4
|
-
import {IAccountExecute} from "@eth-infinitism/account-abstraction/interfaces/IAccountExecute.sol";
|
|
5
|
-
import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interfaces/PackedUserOperation.sol";
|
|
6
|
-
import {ERC165, IERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol";
|
|
7
|
-
|
|
8
|
-
import {IERC6900Module} from "../interfaces/IERC6900Module.sol";
|
|
9
|
-
|
|
10
|
-
/// @title Base contract for modules
|
|
11
|
-
/// @dev Implements ERC-165 to support IERC6900Module's interface, which is a requirement
|
|
12
|
-
/// for module installation. This also ensures that module interactions cannot
|
|
13
|
-
/// happen via the standard execution funtions `execute` and `executeBatch`.
|
|
14
|
-
abstract contract BaseModule is ERC165, IERC6900Module {
|
|
15
|
-
error NotImplemented();
|
|
16
|
-
|
|
17
|
-
/// @dev Returns true if this contract implements the interface defined by
|
|
18
|
-
/// `interfaceId`. See the corresponding
|
|
19
|
-
/// https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
|
|
20
|
-
/// to learn more about how these ids are created.
|
|
21
|
-
///
|
|
22
|
-
/// This function call must use less than 30 000 gas.
|
|
23
|
-
///
|
|
24
|
-
/// Supporting the IERC6900Module interface is a requirement for module installation. This is also used
|
|
25
|
-
/// by the modular account to prevent standard execution functions `execute` and `executeBatch` from
|
|
26
|
-
/// making calls to modules.
|
|
27
|
-
/// @param interfaceId The interface ID to check for support.
|
|
28
|
-
/// @return True if the contract supports `interfaceId`.
|
|
29
|
-
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
|
|
30
|
-
return interfaceId == type(IERC6900Module).interfaceId || super.supportsInterface(interfaceId);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function _getSelectorAndCalldata(bytes calldata data) internal pure returns (bytes4, bytes memory) {
|
|
34
|
-
if (bytes4(data[:4]) == IAccountExecute.executeUserOp.selector) {
|
|
35
|
-
(PackedUserOperation memory uo,) = abi.decode(data[4:], (PackedUserOperation, bytes32));
|
|
36
|
-
bytes4 selector;
|
|
37
|
-
bytes memory callData = uo.callData;
|
|
38
|
-
// Bytes arr representation: [bytes32(len), bytes4(executeUserOp.selector), bytes4(actualSelector),
|
|
39
|
-
// bytes(actualCallData)]
|
|
40
|
-
// 1. Copy actualSelector into a new var
|
|
41
|
-
// 2. Shorten bytes arry by 8 by: store length - 8 into the new pointer location
|
|
42
|
-
// 3. Move the callData pointer by 8
|
|
43
|
-
assembly {
|
|
44
|
-
selector := mload(add(callData, 36))
|
|
45
|
-
|
|
46
|
-
let len := mload(callData)
|
|
47
|
-
mstore(add(callData, 8), sub(len, 8))
|
|
48
|
-
callData := add(callData, 8)
|
|
49
|
-
}
|
|
50
|
-
return (selector, callData);
|
|
51
|
-
}
|
|
52
|
-
return (bytes4(data[:4]), data[4:]);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: MIT
|
|
2
|
-
pragma solidity ^0.8.20;
|
|
3
|
-
|
|
4
|
-
// A base for modules that use EIP-712 structured data signing.
|
|
5
|
-
//
|
|
6
|
-
// Unlike other EIP712 libraries, this mixin uses the salt field to hold the account address.
|
|
7
|
-
//
|
|
8
|
-
// It omits the name and version from the EIP-712 domain, as modules are intended to be deployed as
|
|
9
|
-
// immutable singletons, thus a different versions and instances would have a different module address.
|
|
10
|
-
//
|
|
11
|
-
// Due to depending on the account address to calculate the domain separator, this abstract contract does not
|
|
12
|
-
// implement EIP-5267, as the domain retrieval function does not provide a parameter to use for the account address
|
|
13
|
-
// (internally the verifyingContract), and the computed `msg.sender` for an `eth_call` without an override is
|
|
14
|
-
// address(0).
|
|
15
|
-
abstract contract ModuleEIP712 {
|
|
16
|
-
// keccak256(
|
|
17
|
-
// "EIP712Domain(uint256 chainId,address verifyingContract,bytes32 salt)"
|
|
18
|
-
// )
|
|
19
|
-
bytes32 private constant _DOMAIN_SEPARATOR_TYPEHASH =
|
|
20
|
-
0x71062c282d40422f744945d587dbf4ecfd4f9cfad1d35d62c944373009d96162;
|
|
21
|
-
|
|
22
|
-
function _domainSeparator(address account) internal view returns (bytes32) {
|
|
23
|
-
return keccak256(
|
|
24
|
-
abi.encode(
|
|
25
|
-
_DOMAIN_SEPARATOR_TYPEHASH, block.chainid, address(this), bytes32(uint256(uint160(account)))
|
|
26
|
-
)
|
|
27
|
-
);
|
|
28
|
-
}
|
|
29
|
-
}
|