Skip to content
Open
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
28 changes: 14 additions & 14 deletions gas-snapshots/ModularAccount.json
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
{
"Runtime_AccountCreation": "176125",
"Runtime_BatchTransfers": "93045",
"Runtime_Erc20Transfer": "78454",
"Runtime_InstallSessionKey_Case1": "423148",
"Runtime_NativeTransfer": "54603",
"Runtime_UseSessionKey_Case1_Counter": "78606",
"Runtime_UseSessionKey_Case1_Token": "111919",
"UserOp_BatchTransfers": "198366",
"UserOp_Erc20Transfer": "185331",
"UserOp_InstallSessionKey_Case1": "531355",
"UserOp_NativeTransfer": "161588",
"UserOp_UseSessionKey_Case1_Counter": "195233",
"UserOp_UseSessionKey_Case1_Token": "226217",
"UserOp_deferredValidation": "258080"
"Runtime_AccountCreation": "176375",
"Runtime_BatchTransfers": "92862",
"Runtime_Erc20Transfer": "78271",
"Runtime_InstallSessionKey_Case1": "423228",
"Runtime_NativeTransfer": "54420",
"Runtime_UseSessionKey_Case1_Counter": "78495",
"Runtime_UseSessionKey_Case1_Token": "111808",
"UserOp_BatchTransfers": "197831",
"UserOp_Erc20Transfer": "184796",
"UserOp_InstallSessionKey_Case1": "531083",
"UserOp_NativeTransfer": "161053",
"UserOp_UseSessionKey_Case1_Counter": "194545",
"UserOp_UseSessionKey_Case1_Token": "225517",
"UserOp_deferredValidation": "257235"
}
26 changes: 13 additions & 13 deletions gas-snapshots/SemiModularAccount.json
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
{
"Runtime_AccountCreation": "97745",
"Runtime_BatchTransfers": "89031",
"Runtime_Erc20Transfer": "74488",
"Runtime_InstallSessionKey_Case1": "421700",
"Runtime_NativeTransfer": "50647",
"Runtime_UseSessionKey_Case1_Counter": "78956",
"Runtime_UseSessionKey_Case1_Token": "112269",
"UserOp_BatchTransfers": "193522",
"UserOp_Erc20Transfer": "180558",
"UserOp_InstallSessionKey_Case1": "528878",
"UserOp_NativeTransfer": "156833",
"UserOp_UseSessionKey_Case1_Counter": "195473",
"UserOp_UseSessionKey_Case1_Token": "226457",
"UserOp_deferredValidation": "254131"
"Runtime_BatchTransfers": "89064",
"Runtime_Erc20Transfer": "74521",
"Runtime_InstallSessionKey_Case1": "421959",
"Runtime_NativeTransfer": "50680",
"Runtime_UseSessionKey_Case1_Counter": "78762",
"Runtime_UseSessionKey_Case1_Token": "112075",
"UserOp_BatchTransfers": "193140",
"UserOp_Erc20Transfer": "180176",
"UserOp_InstallSessionKey_Case1": "528710",
"UserOp_NativeTransfer": "156439",
"UserOp_UseSessionKey_Case1_Counter": "194821",
"UserOp_UseSessionKey_Case1_Token": "225805",
"UserOp_deferredValidation": "253193"
}
43 changes: 17 additions & 26 deletions gas/modular-account/ModularAccount.gas.t.sol
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.26;

import {ModuleEntity} from "@erc6900/reference-implementation/interfaces/IModularAccount.sol";

import {Call} from "@erc6900/reference-implementation/interfaces/IModularAccount.sol";
import {ModuleEntity, ModuleEntityLib} from "@erc6900/reference-implementation/libraries/ModuleEntityLib.sol";
import {
ValidationConfig,
ValidationConfigLib
Expand Down Expand Up @@ -81,7 +80,7 @@ contract ModularAccountGasTest is ModularAccountBenchmarkBase("ModularAccount")

PackedUserOperation memory userOp = PackedUserOperation({
sender: address(account1),
nonce: 0,
nonce: _encodeNonce(signerValidation, GLOBAL_V, 0),
initCode: "",
callData: abi.encodeCall(ModularAccountBase.execute, (recipient, 0.1 ether, "")),
// don't over-estimate by a lot here, otherwise a fee is assessed.
Expand All @@ -94,8 +93,7 @@ contract ModularAccountGasTest is ModularAccountBenchmarkBase("ModularAccount")

bytes32 userOpHash = entryPoint.getUserOpHash(userOp);
(uint8 v, bytes32 r, bytes32 s) = vm.sign(owner1Key, MessageHashUtils.toEthSignedMessageHash(userOpHash));
userOp.signature =
_encodeSignature(signerValidation, GLOBAL_VALIDATION, abi.encodePacked(EOA_TYPE_SIGNATURE, r, s, v));
userOp.signature = _encodeSignature(abi.encodePacked(EOA_TYPE_SIGNATURE, r, s, v));

uint256 gasUsed = _userOpBenchmark(userOp);

Expand Down Expand Up @@ -138,7 +136,7 @@ contract ModularAccountGasTest is ModularAccountBenchmarkBase("ModularAccount")

PackedUserOperation memory userOp = PackedUserOperation({
sender: address(account1),
nonce: 0,
nonce: _encodeNonce(signerValidation, GLOBAL_V, 0),
initCode: "",
callData: abi.encodeCall(
ModularAccountBase.execute,
Expand All @@ -154,8 +152,7 @@ contract ModularAccountGasTest is ModularAccountBenchmarkBase("ModularAccount")

bytes32 userOpHash = entryPoint.getUserOpHash(userOp);
(uint8 v, bytes32 r, bytes32 s) = vm.sign(owner1Key, MessageHashUtils.toEthSignedMessageHash(userOpHash));
userOp.signature =
_encodeSignature(signerValidation, GLOBAL_VALIDATION, abi.encodePacked(EOA_TYPE_SIGNATURE, r, s, v));
userOp.signature = _encodeSignature(abi.encodePacked(EOA_TYPE_SIGNATURE, r, s, v));

uint256 gasUsed = _userOpBenchmark(userOp);

Expand Down Expand Up @@ -214,7 +211,7 @@ contract ModularAccountGasTest is ModularAccountBenchmarkBase("ModularAccount")

PackedUserOperation memory userOp = PackedUserOperation({
sender: address(account1),
nonce: 0,
nonce: _encodeNonce(signerValidation, GLOBAL_V, 0),
initCode: "",
callData: abi.encodeCall(ModularAccountBase.executeBatch, (calls)),
// don't over-estimate by a lot here, otherwise a fee is assessed.
Expand All @@ -227,8 +224,7 @@ contract ModularAccountGasTest is ModularAccountBenchmarkBase("ModularAccount")

bytes32 userOpHash = entryPoint.getUserOpHash(userOp);
(uint8 v, bytes32 r, bytes32 s) = vm.sign(owner1Key, MessageHashUtils.toEthSignedMessageHash(userOpHash));
userOp.signature =
_encodeSignature(signerValidation, GLOBAL_VALIDATION, abi.encodePacked(EOA_TYPE_SIGNATURE, r, s, v));
userOp.signature = _encodeSignature(abi.encodePacked(EOA_TYPE_SIGNATURE, r, s, v));

uint256 gasUsed = _userOpBenchmark(userOp);

Expand All @@ -244,12 +240,14 @@ contract ModularAccountGasTest is ModularAccountBenchmarkBase("ModularAccount")
vm.deal(address(account1), 1 ether);

SingleSignerValidationModule newValidationModule = _deploySingleSignerValidationModule();
uint32 newEntityId = 0;
uint32 newEntityId = 1;
(address owner2, uint256 owner2Key) = makeAddrAndKey("owner2");

ModuleEntity newUOValidationEntity = ModuleEntityLib.pack(address(newValidationModule), newEntityId);

PackedUserOperation memory userOp = PackedUserOperation({
sender: address(account1),
nonce: 0,
nonce: _encodeNonceDefAction(newUOValidationEntity, GLOBAL_V, 0),
initCode: "",
callData: abi.encodeCall(ModularAccountBase.execute, (recipient, 0.1 ether, "")),
// don't over-estimate by a lot here, otherwise a fee is assessed.
Expand Down Expand Up @@ -286,8 +284,6 @@ contract ModularAccountGasTest is ModularAccountBenchmarkBase("ModularAccount")
);

userOp.signature = _encodeDeferredInstallUOSignature(
ValidationConfigLib.moduleEntity(newUOValidation),
GLOBAL_VALIDATION,
_packDeferredInstallData(
deferredInstallNonce,
deferredInstallDeadline,
Expand Down Expand Up @@ -329,7 +325,7 @@ contract ModularAccountGasTest is ModularAccountBenchmarkBase("ModularAccount")

PackedUserOperation memory userOp = PackedUserOperation({
sender: address(account1),
nonce: 0,
nonce: _encodeNonce(signerValidation, GLOBAL_V, 0),
initCode: "",
callData: _getInstallDataSessionKeyCase1(),
// don't over-estimate by a lot here, otherwise a fee is assessed.
Expand All @@ -342,8 +338,7 @@ contract ModularAccountGasTest is ModularAccountBenchmarkBase("ModularAccount")

bytes32 userOpHash = entryPoint.getUserOpHash(userOp);
(uint8 v, bytes32 r, bytes32 s) = vm.sign(owner1Key, MessageHashUtils.toEthSignedMessageHash(userOpHash));
userOp.signature =
_encodeSignature(signerValidation, GLOBAL_VALIDATION, abi.encodePacked(EOA_TYPE_SIGNATURE, r, s, v));
userOp.signature = _encodeSignature(abi.encodePacked(EOA_TYPE_SIGNATURE, r, s, v));

uint256 gasUsed = _userOpBenchmark(userOp);

Expand Down Expand Up @@ -392,7 +387,7 @@ contract ModularAccountGasTest is ModularAccountBenchmarkBase("ModularAccount")

PackedUserOperation memory userOp = PackedUserOperation({
sender: address(account1),
nonce: 0,
nonce: _encodeNonce(sessionKeyValidation, SELECTOR_ASSOCIATED_V, 0),
initCode: "",
callData: abi.encodePacked(
ModularAccountBase.executeUserOp.selector,
Expand All @@ -411,9 +406,7 @@ contract ModularAccountGasTest is ModularAccountBenchmarkBase("ModularAccount")
bytes32 userOpHash = entryPoint.getUserOpHash(userOp);
(uint8 v, bytes32 r, bytes32 s) =
vm.sign(sessionSigner1Key, MessageHashUtils.toEthSignedMessageHash(userOpHash));
userOp.signature = _encodeSignature(
sessionKeyValidation, SELECTOR_ASSOCIATED_VALIDATION, abi.encodePacked(EOA_TYPE_SIGNATURE, r, s, v)
);
userOp.signature = _encodeSignature(abi.encodePacked(EOA_TYPE_SIGNATURE, r, s, v));

uint256 gasUsed = _userOpBenchmark(userOp);

Expand Down Expand Up @@ -466,7 +459,7 @@ contract ModularAccountGasTest is ModularAccountBenchmarkBase("ModularAccount")

PackedUserOperation memory userOp = PackedUserOperation({
sender: address(account1),
nonce: 0,
nonce: _encodeNonce(sessionKeyValidation, SELECTOR_ASSOCIATED_V, 0),
initCode: "",
callData: abi.encodePacked(
ModularAccountBase.executeUserOp.selector,
Expand All @@ -486,9 +479,7 @@ contract ModularAccountGasTest is ModularAccountBenchmarkBase("ModularAccount")
bytes32 userOpHash = entryPoint.getUserOpHash(userOp);
(uint8 v, bytes32 r, bytes32 s) =
vm.sign(sessionSigner1Key, MessageHashUtils.toEthSignedMessageHash(userOpHash));
userOp.signature = _encodeSignature(
sessionKeyValidation, SELECTOR_ASSOCIATED_VALIDATION, abi.encodePacked(EOA_TYPE_SIGNATURE, r, s, v)
);
userOp.signature = _encodeSignature(abi.encodePacked(EOA_TYPE_SIGNATURE, r, s, v));

uint256 gasUsed = _userOpBenchmark(userOp);

Expand Down
43 changes: 17 additions & 26 deletions gas/modular-account/SemiModularAccount.gas.t.sol
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.26;

import {ModuleEntity} from "@erc6900/reference-implementation/interfaces/IModularAccount.sol";

import {Call} from "@erc6900/reference-implementation/interfaces/IModularAccount.sol";
import {ModuleEntity, ModuleEntityLib} from "@erc6900/reference-implementation/libraries/ModuleEntityLib.sol";
import {
ValidationConfig,
ValidationConfigLib
Expand Down Expand Up @@ -75,7 +74,7 @@ contract ModularAccountGasTest is ModularAccountBenchmarkBase("SemiModularAccoun

PackedUserOperation memory userOp = PackedUserOperation({
sender: address(account1),
nonce: 0,
nonce: _encodeNonce(signerValidation, GLOBAL_V, 0),
initCode: "",
callData: abi.encodeCall(ModularAccountBase.execute, (recipient, 0.1 ether, "")),
// don't over-estimate by a lot here, otherwise a fee is assessed.
Expand All @@ -88,8 +87,7 @@ contract ModularAccountGasTest is ModularAccountBenchmarkBase("SemiModularAccoun

bytes32 userOpHash = entryPoint.getUserOpHash(userOp);
(uint8 v, bytes32 r, bytes32 s) = vm.sign(owner1Key, MessageHashUtils.toEthSignedMessageHash(userOpHash));
userOp.signature =
_encodeSignature(signerValidation, GLOBAL_VALIDATION, abi.encodePacked(EOA_TYPE_SIGNATURE, r, s, v));
userOp.signature = _encodeSignature(abi.encodePacked(EOA_TYPE_SIGNATURE, r, s, v));

uint256 gasUsed = _userOpBenchmark(userOp);

Expand Down Expand Up @@ -132,7 +130,7 @@ contract ModularAccountGasTest is ModularAccountBenchmarkBase("SemiModularAccoun

PackedUserOperation memory userOp = PackedUserOperation({
sender: address(account1),
nonce: 0,
nonce: _encodeNonce(signerValidation, GLOBAL_V, 0),
initCode: "",
callData: abi.encodeCall(
ModularAccountBase.execute,
Expand All @@ -148,8 +146,7 @@ contract ModularAccountGasTest is ModularAccountBenchmarkBase("SemiModularAccoun

bytes32 userOpHash = entryPoint.getUserOpHash(userOp);
(uint8 v, bytes32 r, bytes32 s) = vm.sign(owner1Key, MessageHashUtils.toEthSignedMessageHash(userOpHash));
userOp.signature =
_encodeSignature(signerValidation, GLOBAL_VALIDATION, abi.encodePacked(EOA_TYPE_SIGNATURE, r, s, v));
userOp.signature = _encodeSignature(abi.encodePacked(EOA_TYPE_SIGNATURE, r, s, v));

uint256 gasUsed = _userOpBenchmark(userOp);

Expand Down Expand Up @@ -208,7 +205,7 @@ contract ModularAccountGasTest is ModularAccountBenchmarkBase("SemiModularAccoun

PackedUserOperation memory userOp = PackedUserOperation({
sender: address(account1),
nonce: 0,
nonce: _encodeNonce(signerValidation, GLOBAL_V, 0),
initCode: "",
callData: abi.encodeCall(ModularAccountBase.executeBatch, (calls)),
// don't over-estimate by a lot here, otherwise a fee is assessed.
Expand All @@ -221,8 +218,7 @@ contract ModularAccountGasTest is ModularAccountBenchmarkBase("SemiModularAccoun

bytes32 userOpHash = entryPoint.getUserOpHash(userOp);
(uint8 v, bytes32 r, bytes32 s) = vm.sign(owner1Key, MessageHashUtils.toEthSignedMessageHash(userOpHash));
userOp.signature =
_encodeSignature(signerValidation, GLOBAL_VALIDATION, abi.encodePacked(EOA_TYPE_SIGNATURE, r, s, v));
userOp.signature = _encodeSignature(abi.encodePacked(EOA_TYPE_SIGNATURE, r, s, v));

uint256 gasUsed = _userOpBenchmark(userOp);

Expand All @@ -238,12 +234,14 @@ contract ModularAccountGasTest is ModularAccountBenchmarkBase("SemiModularAccoun
vm.deal(address(account1), 1 ether);

SingleSignerValidationModule newValidationModule = _deploySingleSignerValidationModule();
uint32 newEntityId = 0;
uint32 newEntityId = 1;
(address owner2, uint256 owner2Key) = makeAddrAndKey("owner2");

ModuleEntity newUOValidationEntity = ModuleEntityLib.pack(address(newValidationModule), newEntityId);

PackedUserOperation memory userOp = PackedUserOperation({
sender: address(account1),
nonce: 0,
nonce: _encodeNonceDefAction(newUOValidationEntity, GLOBAL_V, 0),
initCode: "",
callData: abi.encodeCall(ModularAccountBase.execute, (recipient, 0.1 ether, "")),
// don't over-estimate by a lot here, otherwise a fee is assessed.
Expand Down Expand Up @@ -276,8 +274,6 @@ contract ModularAccountGasTest is ModularAccountBenchmarkBase("SemiModularAccoun
bytes memory deferredValidationSig = _signRawHash(vm, owner1Key, digest);

userOp.signature = _encodeDeferredInstallUOSignature(
ValidationConfigLib.moduleEntity(newUOValidation),
GLOBAL_VALIDATION,
_packDeferredInstallData(
deferredInstallNonce,
deferredInstallDeadline,
Expand Down Expand Up @@ -319,7 +315,7 @@ contract ModularAccountGasTest is ModularAccountBenchmarkBase("SemiModularAccoun

PackedUserOperation memory userOp = PackedUserOperation({
sender: address(account1),
nonce: 0,
nonce: _encodeNonce(signerValidation, GLOBAL_V, 0),
initCode: "",
callData: _getInstallDataSessionKeyCase1(),
// don't over-estimate by a lot here, otherwise a fee is assessed.
Expand All @@ -332,8 +328,7 @@ contract ModularAccountGasTest is ModularAccountBenchmarkBase("SemiModularAccoun

bytes32 userOpHash = entryPoint.getUserOpHash(userOp);
(uint8 v, bytes32 r, bytes32 s) = vm.sign(owner1Key, MessageHashUtils.toEthSignedMessageHash(userOpHash));
userOp.signature =
_encodeSignature(signerValidation, GLOBAL_VALIDATION, abi.encodePacked(EOA_TYPE_SIGNATURE, r, s, v));
userOp.signature = _encodeSignature(abi.encodePacked(EOA_TYPE_SIGNATURE, r, s, v));

uint256 gasUsed = _userOpBenchmark(userOp);

Expand Down Expand Up @@ -382,7 +377,7 @@ contract ModularAccountGasTest is ModularAccountBenchmarkBase("SemiModularAccoun

PackedUserOperation memory userOp = PackedUserOperation({
sender: address(account1),
nonce: 0,
nonce: _encodeNonce(sessionKeyValidation, SELECTOR_ASSOCIATED_V, 0),
initCode: "",
callData: abi.encodePacked(
ModularAccountBase.executeUserOp.selector,
Expand All @@ -401,9 +396,7 @@ contract ModularAccountGasTest is ModularAccountBenchmarkBase("SemiModularAccoun
bytes32 userOpHash = entryPoint.getUserOpHash(userOp);
(uint8 v, bytes32 r, bytes32 s) =
vm.sign(sessionSigner1Key, MessageHashUtils.toEthSignedMessageHash(userOpHash));
userOp.signature = _encodeSignature(
sessionKeyValidation, SELECTOR_ASSOCIATED_VALIDATION, abi.encodePacked(EOA_TYPE_SIGNATURE, r, s, v)
);
userOp.signature = _encodeSignature(abi.encodePacked(EOA_TYPE_SIGNATURE, r, s, v));

uint256 gasUsed = _userOpBenchmark(userOp);

Expand Down Expand Up @@ -456,7 +449,7 @@ contract ModularAccountGasTest is ModularAccountBenchmarkBase("SemiModularAccoun

PackedUserOperation memory userOp = PackedUserOperation({
sender: address(account1),
nonce: 0,
nonce: _encodeNonce(sessionKeyValidation, SELECTOR_ASSOCIATED_V, 0),
initCode: "",
callData: abi.encodePacked(
ModularAccountBase.executeUserOp.selector,
Expand All @@ -476,9 +469,7 @@ contract ModularAccountGasTest is ModularAccountBenchmarkBase("SemiModularAccoun
bytes32 userOpHash = entryPoint.getUserOpHash(userOp);
(uint8 v, bytes32 r, bytes32 s) =
vm.sign(sessionSigner1Key, MessageHashUtils.toEthSignedMessageHash(userOpHash));
userOp.signature = _encodeSignature(
sessionKeyValidation, SELECTOR_ASSOCIATED_VALIDATION, abi.encodePacked(EOA_TYPE_SIGNATURE, r, s, v)
);
userOp.signature = _encodeSignature(abi.encodePacked(EOA_TYPE_SIGNATURE, r, s, v));

uint256 gasUsed = _userOpBenchmark(userOp);

Expand Down
7 changes: 5 additions & 2 deletions src/account/AccountStorage.sol
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.26;

import {HookConfig, ModuleEntity} from "@erc6900/reference-implementation/interfaces/IModularAccount.sol";
import {HookConfig} from "@erc6900/reference-implementation/interfaces/IModularAccount.sol";

import {ValidationLookupKey} from "../../src/libraries/ValidationLocatorLib.sol";
import {LinkedListSet, SetValue} from "../libraries/LinkedListSetLib.sol";

// ERC-7201 derived storage slot.
Expand All @@ -27,6 +28,8 @@ struct ExecutionStorage {

/// @notice Represents data associated with a specific validation function.
struct ValidationStorage {
// The address of the validation module.
address module;
// Whether or not this validation can be used as a global validation function.
bool isGlobal;
// Whether or not this validation is allowed to validate ERC-1271 signatures.
Expand Down Expand Up @@ -55,7 +58,7 @@ struct AccountStorage {
// Execution functions and their associated functions.
mapping(bytes4 selector => ExecutionStorage) executionStorage;
// Validation functions and their associated functions.
mapping(ModuleEntity validationFunction => ValidationStorage) validationStorage;
mapping(ValidationLookupKey lookupKey => ValidationStorage) validationStorage;
// Module-defined ERC-165 interfaces installed on the account.
mapping(bytes4 => uint256) supportedIfaces;
// Nonce usage state for deferred actions.
Expand Down
Loading