From 5303753f3d77280ef4fe05fce7250445059cde42 Mon Sep 17 00:00:00 2001 From: adam Date: Tue, 10 Jun 2025 18:40:01 -0400 Subject: [PATCH 1/3] feat: time range only key benchmarks --- gas-snapshots/ModularAccount.json | 6 + gas-snapshots/SemiModularAccount.json | 6 + gas/modular-account/ModularAccount.gas.t.sol | 320 ++++++++++-------- .../ModularAccountBenchmarkBase.sol | 109 ++++++ .../SemiModularAccount.gas.t.sol | 319 +++++++++-------- 5 files changed, 494 insertions(+), 266 deletions(-) diff --git a/gas-snapshots/ModularAccount.json b/gas-snapshots/ModularAccount.json index db3dc7c5..f406c919 100644 --- a/gas-snapshots/ModularAccount.json +++ b/gas-snapshots/ModularAccount.json @@ -3,14 +3,20 @@ "Runtime_BatchTransfers": "92896", "Runtime_Erc20Transfer": "78331", "Runtime_InstallSessionKey_Case1": "429572", + "Runtime_InstallSessionKey_Case2": "172724", "Runtime_NativeTransfer": "54483", "Runtime_UseSessionKey_Case1_Counter": "78469", "Runtime_UseSessionKey_Case1_Token": "111779", + "Runtime_UseSessionKey_Case2_Counter": "61818", + "Runtime_UseSessionKey_Case2_Token": "86987", "UserOp_BatchTransfers": "197713", "UserOp_Erc20Transfer": "184690", "UserOp_InstallSessionKey_Case1": "537249", + "UserOp_InstallSessionKey_Case2": "279775", "UserOp_NativeTransfer": "160938", "UserOp_UseSessionKey_Case1_Counter": "194376", "UserOp_UseSessionKey_Case1_Token": "225357", + "UserOp_UseSessionKey_Case2_Counter": "175857", + "UserOp_UseSessionKey_Case2_Token": "201145", "UserOp_deferredValidation": "232843" } \ No newline at end of file diff --git a/gas-snapshots/SemiModularAccount.json b/gas-snapshots/SemiModularAccount.json index 8c6f429e..57279e6e 100644 --- a/gas-snapshots/SemiModularAccount.json +++ b/gas-snapshots/SemiModularAccount.json @@ -3,14 +3,20 @@ "Runtime_BatchTransfers": "88740", "Runtime_Erc20Transfer": "74220", "Runtime_InstallSessionKey_Case1": "427790", + "Runtime_InstallSessionKey_Case2": "171042", "Runtime_NativeTransfer": "50382", "Runtime_UseSessionKey_Case1_Counter": "78772", "Runtime_UseSessionKey_Case1_Token": "112082", + "Runtime_UseSessionKey_Case2_Counter": "62185", + "Runtime_UseSessionKey_Case2_Token": "87354", "UserOp_BatchTransfers": "192854", "UserOp_Erc20Transfer": "179911", "UserOp_InstallSessionKey_Case1": "534589", + "UserOp_InstallSessionKey_Case2": "277363", "UserOp_NativeTransfer": "156189", "UserOp_UseSessionKey_Case1_Counter": "194643", "UserOp_UseSessionKey_Case1_Token": "225624", + "UserOp_UseSessionKey_Case2_Counter": "176264", + "UserOp_UseSessionKey_Case2_Token": "201552", "UserOp_deferredValidation": "228832" } \ No newline at end of file diff --git a/gas/modular-account/ModularAccount.gas.t.sol b/gas/modular-account/ModularAccount.gas.t.sol index 97861a2c..d01a6641 100644 --- a/gas/modular-account/ModularAccount.gas.t.sol +++ b/gas/modular-account/ModularAccount.gas.t.sol @@ -300,190 +300,244 @@ contract ModularAccountGasTest is ModularAccountBenchmarkBase("ModularAccount") _snap(USER_OP, "deferredValidation", gasUsed); } - function test_modularAccountGas_runtime_installSessionKey_case1() public { + function test_modularAccountGas_runtime_installSessionKeyCases() public { _deployAccount1(); - uint256 gasUsed = _runtimeBenchmark( - owner1, - address(account1), - abi.encodeCall( - ModularAccountBase.executeWithRuntimeValidation, - (_getInstallDataSessionKeyCase1(), _encodeSignature(signerValidation, GLOBAL_VALIDATION, "")) - ) - ); + for (uint256 i = 0; i < sessionKeyTestCases.length; i++) { + uint256 vmStateSnapshot = vm.snapshotState(); - _verifySessionKeyCase1InstallState(); + SessionKeyTestCase memory testCase = sessionKeyTestCases[i]; - _snap(RUNTIME, "InstallSessionKey_Case1", gasUsed); - } + uint256 gasUsed = _runtimeBenchmark( + owner1, + address(account1), + abi.encodeCall( + ModularAccountBase.executeWithRuntimeValidation, + (testCase.getInstallData(), _encodeSignature(signerValidation, GLOBAL_VALIDATION, "")) + ) + ); - function test_modularAccountGas_userOp_installSessionKey_case1() public { - _deployAccount1(); + testCase.verifyInstallState(); - vm.deal(address(account1), 1 ether); + _snap(RUNTIME, string.concat("InstallSessionKey_Case", vm.toString(i + 1)), gasUsed); - PackedUserOperation memory userOp = PackedUserOperation({ - sender: address(account1), - nonce: _encodeNonce(signerValidation, GLOBAL_V, 0), - initCode: "", - callData: _getInstallDataSessionKeyCase1(), - // don't over-estimate by a lot here, otherwise a fee is assessed. - accountGasLimits: _encodeGasLimits(500_000, 100_000), - preVerificationGas: 0, - gasFees: _encodeGasFees(1, 1), - paymasterAndData: "", - signature: "" - }); + vm.revertToStateAndDelete(vmStateSnapshot); + } + } - bytes32 userOpHash = entryPoint.getUserOpHash(userOp); - (uint8 v, bytes32 r, bytes32 s) = vm.sign(owner1Key, MessageHashUtils.toEthSignedMessageHash(userOpHash)); - userOp.signature = _encodeSignature(abi.encodePacked(EOA_TYPE_SIGNATURE, r, s, v)); + function test_modularAccountGas_userOp_installSessionKeyCases() public { + _deployAccount1(); - uint256 gasUsed = _userOpBenchmark(userOp); + for (uint256 i = 0; i < sessionKeyTestCases.length; i++) { + uint256 vmStateSnapshot = vm.snapshotState(); - _verifySessionKeyCase1InstallState(); + SessionKeyTestCase memory testCase = sessionKeyTestCases[i]; - _snap(USER_OP, "InstallSessionKey_Case1", gasUsed); - } + vm.deal(address(account1), 1 ether); - function test_modularAccountGas_runtime_useSessionKey_case1_counter() public { - _deployAccount1(); + PackedUserOperation memory userOp = PackedUserOperation({ + sender: address(account1), + nonce: _encodeNonce(signerValidation, GLOBAL_V, 0), + initCode: "", + callData: testCase.getInstallData(), + // don't over-estimate by a lot here, otherwise a fee is assessed. + accountGasLimits: _encodeGasLimits(500_000, 100_000), + preVerificationGas: 0, + gasFees: _encodeGasFees(1, 1), + paymasterAndData: "", + signature: "" + }); - ModuleEntity sessionKeyValidation = _installSessionKey_case1(); + bytes32 userOpHash = entryPoint.getUserOpHash(userOp); + (uint8 v, bytes32 r, bytes32 s) = + vm.sign(owner1Key, MessageHashUtils.toEthSignedMessageHash(userOpHash)); + userOp.signature = _encodeSignature(abi.encodePacked(EOA_TYPE_SIGNATURE, r, s, v)); - // Jump to within the valid timestamp range - vm.warp(200); + uint256 gasUsed = _userOpBenchmark(userOp); - uint256 gasUsed = _runtimeBenchmark( - sessionSigner1, - address(account1), - abi.encodeCall( - ModularAccountBase.executeWithRuntimeValidation, - ( - abi.encodeCall( - ModularAccountBase.execute, - (address(counter), 0 wei, abi.encodeCall(counter.increment, ())) - ), - _encodeSignature(sessionKeyValidation, SELECTOR_ASSOCIATED_VALIDATION, "") - ) - ) - ); + testCase.verifyInstallState(); - assertEq(counter.number(), 2); + _snap(USER_OP, string.concat("InstallSessionKey_Case", vm.toString(i + 1)), gasUsed); - _snap(RUNTIME, "UseSessionKey_Case1_Counter", gasUsed); + vm.revertToStateAndDelete(vmStateSnapshot); + } } - function test_modularAccountGas_userOp_useSessionKey_case1_counter() public { + function test_modularAccountGas_runtime_useSessionKeyCases_counter() public { _deployAccount1(); - vm.deal(address(account1), 1 ether); + for (uint256 i = 0; i < sessionKeyTestCases.length; i++) { + uint256 vmStateSnapshot = vm.snapshotState(); - ModuleEntity sessionKeyValidation = _installSessionKey_case1(); + SessionKeyTestCase memory testCase = sessionKeyTestCases[i]; - // Jump to within the valid timestamp range - vm.warp(200); + ModuleEntity sessionKeyValidation = testCase.installSessionKey(); - PackedUserOperation memory userOp = PackedUserOperation({ - sender: address(account1), - nonce: _encodeNonce(sessionKeyValidation, SELECTOR_ASSOCIATED_V, 0), - initCode: "", - callData: abi.encodePacked( - ModularAccountBase.executeUserOp.selector, + // Jump to within the valid timestamp range + vm.warp(200); + + uint256 gasUsed = _runtimeBenchmark( + testCase.sessionSigner, + address(account1), abi.encodeCall( - ModularAccountBase.execute, (address(counter), 0 wei, abi.encodeCall(counter.increment, ())) + ModularAccountBase.executeWithRuntimeValidation, + ( + abi.encodeCall( + ModularAccountBase.execute, + (address(counter), 0 wei, abi.encodeCall(counter.increment, ())) + ), + _encodeSignature( + sessionKeyValidation, + testCase.isGlobal ? GLOBAL_VALIDATION : SELECTOR_ASSOCIATED_VALIDATION, + "" + ) + ) ) - ), - // don't over-estimate by a lot here, otherwise a fee is assessed. - accountGasLimits: _encodeGasLimits(200_000, 200_000), - preVerificationGas: 0, - gasFees: _encodeGasFees(1, 1), - paymasterAndData: "", - signature: "" - }); + ); - bytes32 userOpHash = entryPoint.getUserOpHash(userOp); - (uint8 v, bytes32 r, bytes32 s) = - vm.sign(sessionSigner1Key, MessageHashUtils.toEthSignedMessageHash(userOpHash)); - userOp.signature = _encodeSignature(abi.encodePacked(EOA_TYPE_SIGNATURE, r, s, v)); + assertEq(counter.number(), 2); - uint256 gasUsed = _userOpBenchmark(userOp); + _snap(RUNTIME, string.concat("UseSessionKey_Case", vm.toString(i + 1), "_Counter"), gasUsed); - assertEq(counter.number(), 2); - - _snap(USER_OP, "UseSessionKey_Case1_Counter", gasUsed); + vm.revertToStateAndDelete(vmStateSnapshot); + } } - function test_modularAccountGas_runtime_useSessionKey_case1_token() public { + function test_modularAccountGas_userOp_useSessionKeyCases_counter() public { _deployAccount1(); - ModuleEntity sessionKeyValidation = _installSessionKey_case1(); + for (uint256 i = 0; i < sessionKeyTestCases.length; i++) { + uint256 vmStateSnapshot = vm.snapshotState(); - mockErc20.mint(address(account1), 100 ether); + vm.deal(address(account1), 1 ether); - // Jump to within the valid timestamp range - vm.warp(200); + SessionKeyTestCase memory testCase = sessionKeyTestCases[i]; + ModuleEntity sessionKeyValidation = testCase.installSessionKey(); - uint256 gasUsed = _runtimeBenchmark( - sessionSigner1, - address(account1), - abi.encodeCall( - ModularAccountBase.executeWithRuntimeValidation, - ( + // Jump to within the valid timestamp range + vm.warp(200); + + PackedUserOperation memory userOp = PackedUserOperation({ + sender: address(account1), + nonce: _encodeNonce(sessionKeyValidation, testCase.isGlobal ? GLOBAL_V : SELECTOR_ASSOCIATED_V, 0), + initCode: "", + callData: abi.encodePacked( + ModularAccountBase.executeUserOp.selector, abi.encodeCall( - ModularAccountBase.execute, - (address(mockErc20), 0, abi.encodeCall(mockErc20.transfer, (recipient, 10 ether))) - ), - _encodeSignature(sessionKeyValidation, SELECTOR_ASSOCIATED_VALIDATION, "") + ModularAccountBase.execute, (address(counter), 0 wei, abi.encodeCall(counter.increment, ())) + ) + ), + // don't over-estimate by a lot here, otherwise a fee is assessed. + accountGasLimits: _encodeGasLimits(200_000, 200_000), + preVerificationGas: 0, + gasFees: _encodeGasFees(1, 1), + paymasterAndData: "", + signature: "" + }); + + bytes32 userOpHash = entryPoint.getUserOpHash(userOp); + (uint8 v, bytes32 r, bytes32 s) = + vm.sign(testCase.sessionSignerKey, MessageHashUtils.toEthSignedMessageHash(userOpHash)); + userOp.signature = _encodeSignature(abi.encodePacked(EOA_TYPE_SIGNATURE, r, s, v)); + + uint256 gasUsed = _userOpBenchmark(userOp); + + assertEq(counter.number(), 2); + + _snap(USER_OP, string.concat("UseSessionKey_Case", vm.toString(i + 1), "_Counter"), gasUsed); + + vm.revertToStateAndDelete(vmStateSnapshot); + } + } + + function test_modularAccountGas_runtime_useSessionKeyCases_token() public { + _deployAccount1(); + + for (uint256 i = 0; i < sessionKeyTestCases.length; i++) { + uint256 vmStateSnapshot = vm.snapshotState(); + + SessionKeyTestCase memory testCase = sessionKeyTestCases[i]; + ModuleEntity sessionKeyValidation = testCase.installSessionKey(); + + mockErc20.mint(address(account1), 100 ether); + + // Jump to within the valid timestamp range + vm.warp(200); + + uint256 gasUsed = _runtimeBenchmark( + testCase.sessionSigner, + address(account1), + abi.encodeCall( + ModularAccountBase.executeWithRuntimeValidation, + ( + abi.encodeCall( + ModularAccountBase.execute, + (address(mockErc20), 0, abi.encodeCall(mockErc20.transfer, (recipient, 10 ether))) + ), + _encodeSignature( + sessionKeyValidation, + testCase.isGlobal ? GLOBAL_VALIDATION : SELECTOR_ASSOCIATED_VALIDATION, + "" + ) + ) ) - ) - ); + ); - assertEq(mockErc20.balanceOf(recipient), 10 ether); + assertEq(mockErc20.balanceOf(recipient), 10 ether); + + _snap(RUNTIME, string.concat("UseSessionKey_Case", vm.toString(i + 1), "_Token"), gasUsed); - _snap(RUNTIME, "UseSessionKey_Case1_Token", gasUsed); + vm.revertToStateAndDelete(vmStateSnapshot); + } } - function test_modularAccountGas_userOp_useSessionKey_case1_token() public { + function test_modularAccountGas_userOp_useSessionKeyCases_token() public { _deployAccount1(); - vm.deal(address(account1), 1 ether); + for (uint256 i = 0; i < sessionKeyTestCases.length; i++) { + uint256 vmStateSnapshot = vm.snapshotState(); - ModuleEntity sessionKeyValidation = _installSessionKey_case1(); + vm.deal(address(account1), 1 ether); - mockErc20.mint(address(account1), 100 ether); + SessionKeyTestCase memory testCase = sessionKeyTestCases[i]; + ModuleEntity sessionKeyValidation = testCase.installSessionKey(); - // Jump to within the valid timestamp range - vm.warp(200); + mockErc20.mint(address(account1), 100 ether); - PackedUserOperation memory userOp = PackedUserOperation({ - sender: address(account1), - nonce: _encodeNonce(sessionKeyValidation, SELECTOR_ASSOCIATED_V, 0), - initCode: "", - callData: abi.encodePacked( - ModularAccountBase.executeUserOp.selector, - abi.encodeCall( - ModularAccountBase.execute, - (address(mockErc20), 0, abi.encodeCall(mockErc20.transfer, (recipient, 10 ether))) - ) - ), - // don't over-estimate by a lot here, otherwise a fee is assessed. - accountGasLimits: _encodeGasLimits(200_000, 200_000), - preVerificationGas: 0, - gasFees: _encodeGasFees(1, 1), - paymasterAndData: "", - signature: "" - }); + // Jump to within the valid timestamp range + vm.warp(200); - bytes32 userOpHash = entryPoint.getUserOpHash(userOp); - (uint8 v, bytes32 r, bytes32 s) = - vm.sign(sessionSigner1Key, MessageHashUtils.toEthSignedMessageHash(userOpHash)); - userOp.signature = _encodeSignature(abi.encodePacked(EOA_TYPE_SIGNATURE, r, s, v)); + PackedUserOperation memory userOp = PackedUserOperation({ + sender: address(account1), + nonce: _encodeNonce(sessionKeyValidation, testCase.isGlobal ? GLOBAL_V : SELECTOR_ASSOCIATED_V, 0), + initCode: "", + callData: abi.encodePacked( + ModularAccountBase.executeUserOp.selector, + abi.encodeCall( + ModularAccountBase.execute, + (address(mockErc20), 0, abi.encodeCall(mockErc20.transfer, (recipient, 10 ether))) + ) + ), + // don't over-estimate by a lot here, otherwise a fee is assessed. + accountGasLimits: _encodeGasLimits(200_000, 200_000), + preVerificationGas: 0, + gasFees: _encodeGasFees(1, 1), + paymasterAndData: "", + signature: "" + }); - uint256 gasUsed = _userOpBenchmark(userOp); + bytes32 userOpHash = entryPoint.getUserOpHash(userOp); + (uint8 v, bytes32 r, bytes32 s) = + vm.sign(testCase.sessionSignerKey, MessageHashUtils.toEthSignedMessageHash(userOpHash)); + userOp.signature = _encodeSignature(abi.encodePacked(EOA_TYPE_SIGNATURE, r, s, v)); - assertEq(mockErc20.balanceOf(recipient), 10 ether); + uint256 gasUsed = _userOpBenchmark(userOp); + + assertEq(mockErc20.balanceOf(recipient), 10 ether); + + _snap(USER_OP, string.concat("UseSessionKey_Case", vm.toString(i + 1), "_Token"), gasUsed); - _snap(USER_OP, "UseSessionKey_Case1_Token", gasUsed); + vm.revertToStateAndDelete(vmStateSnapshot); + } } } diff --git a/gas/modular-account/ModularAccountBenchmarkBase.sol b/gas/modular-account/ModularAccountBenchmarkBase.sol index 091af661..feb2c8f2 100644 --- a/gas/modular-account/ModularAccountBenchmarkBase.sol +++ b/gas/modular-account/ModularAccountBenchmarkBase.sol @@ -47,10 +47,25 @@ abstract contract ModularAccountBenchmarkBase is BenchmarkBase, ModuleSignatureU address public sessionSigner1; uint256 public sessionSigner1Key; + address public sessionSigner2; + uint256 public sessionSigner2Key; + Counter public counter; + struct SessionKeyTestCase { + function() internal view returns (bytes memory) getInstallData; + function() internal returns (ModuleEntity) installSessionKey; + function() internal view verifyInstallState; + address sessionSigner; + uint256 sessionSignerKey; + bool isGlobal; + } + + SessionKeyTestCase[] internal sessionKeyTestCases; + constructor(string memory accountImplName) BenchmarkBase(accountImplName) { (sessionSigner1, sessionSigner1Key) = makeAddrAndKey("session1"); + (sessionSigner2, sessionSigner2Key) = makeAddrAndKey("session2"); executionInstallDelegate = new ExecutionInstallDelegate(); accountImpl = _deployModularAccount(IEntryPoint(entryPoint), executionInstallDelegate); @@ -71,6 +86,28 @@ abstract contract ModularAccountBenchmarkBase is BenchmarkBase, ModuleSignatureU counter = new Counter(); counter.increment(); + + // Initialize session key test cases + sessionKeyTestCases.push( + SessionKeyTestCase({ + getInstallData: _getInstallDataSessionKeyCase1, + installSessionKey: _installSessionKey_case1, + verifyInstallState: _verifySessionKeyCase1InstallState, + sessionSigner: sessionSigner1, + sessionSignerKey: sessionSigner1Key, + isGlobal: false + }) + ); + sessionKeyTestCases.push( + SessionKeyTestCase({ + getInstallData: _getInstallDataSessionKeyCase2, + installSessionKey: _installSessionKey_case2, + verifyInstallState: _verifySessionKeyCase2InstallState, + sessionSigner: sessionSigner2, + sessionSignerKey: sessionSigner2Key, + isGlobal: true + }) + ); } function _deployAccount1() internal { @@ -234,4 +271,76 @@ abstract contract ModularAccountBenchmarkBase is BenchmarkBase, ModuleSignatureU uint256 limit = allowlistModule.erc20SpendLimits(0, address(mockErc20), address(account1)); assertEq(limit, 100 ether); } + + // Session key case 2: + // - Uses SingleSignerValidation + // - Has global validation permission. + // - Has hooks for: + // - Time range: only allows within a certain time range + function _getInstallDataSessionKeyCase2() internal view returns (bytes memory) { + uint32 sessionKeyEntityId = 1; + + ValidationConfig validationConfig = ValidationConfigLib.pack({ + _module: address(singleSignerValidationModule), + _entityId: sessionKeyEntityId, + _isGlobal: true, + _isSignatureValidation: false, + _isUserOpValidation: true + }); + + bytes4[] memory selectors = new bytes4[](0); + + bytes memory installData = abi.encode(sessionKeyEntityId, sessionSigner2); + + bytes[] memory hooks = new bytes[](1); + + // Time range hook + hooks[0] = abi.encodePacked( + HookConfigLib.packValidationHook({_module: address(timeRangeModule), _entityId: 1}), + abi.encode(uint32(1), 1000, 100) + ); + + return + abi.encodeCall(ModularAccountBase.installValidation, (validationConfig, selectors, installData, hooks)); + } + + function _installSessionKey_case2() internal returns (ModuleEntity sessionKeyValidation) { + vm.prank(address(entryPoint)); + (bool success,) = address(account1).call(_getInstallDataSessionKeyCase2()); + require(success, "Install Session key 2 failed"); + + return ModuleEntityLib.pack(address(singleSignerValidationModule), 1); + } + + function _verifySessionKeyCase2InstallState() internal view { + // Assert account state is correctly set up + + ValidationDataView memory validationData = + account1.getValidationData(ModuleEntityLib.pack(address(singleSignerValidationModule), 1)); + + // Flags + assertTrue(validationData.validationFlags.isGlobal()); + assertFalse(validationData.validationFlags.isSignatureValidation()); + assertTrue(validationData.validationFlags.isUserOpValidation()); + + // Validation hooks + assertEq(validationData.validationHooks.length, 1); + assertEq( + HookConfig.unwrap(validationData.validationHooks[0]), + HookConfig.unwrap(HookConfigLib.packValidationHook(address(timeRangeModule), 1)) + ); + + // Execution hooks + assertEq(validationData.executionHooks.length, 0); + + // Selectors + assertEq(validationData.selectors.length, 0); + + // Assert hooks state is correctly set up + + // Time range + (uint48 validUntil, uint48 validAfter) = timeRangeModule.timeRanges(1, address(account1)); + assertEq(validUntil, 1000); + assertEq(validAfter, 100); + } } diff --git a/gas/modular-account/SemiModularAccount.gas.t.sol b/gas/modular-account/SemiModularAccount.gas.t.sol index 7ffd7f02..5a6d5f63 100644 --- a/gas/modular-account/SemiModularAccount.gas.t.sol +++ b/gas/modular-account/SemiModularAccount.gas.t.sol @@ -290,190 +290,243 @@ contract ModularAccountGasTest is ModularAccountBenchmarkBase("SemiModularAccoun _snap(USER_OP, "deferredValidation", gasUsed); } - function test_semiModularAccountGas_runtime_installSessionKey_case1() public { + function test_semiModularAccountGas_runtime_installSessionKeyCases() public { _deploySemiModularAccountBytecode1(); - uint256 gasUsed = _runtimeBenchmark( - owner1, - address(account1), - abi.encodeCall( - ModularAccountBase.executeWithRuntimeValidation, - (_getInstallDataSessionKeyCase1(), _encodeSignature(signerValidation, GLOBAL_VALIDATION, "")) - ) - ); + for (uint256 i = 0; i < sessionKeyTestCases.length; i++) { + uint256 vmStateSnapshot = vm.snapshotState(); - _verifySessionKeyCase1InstallState(); + SessionKeyTestCase memory testCase = sessionKeyTestCases[i]; - _snap(RUNTIME, "InstallSessionKey_Case1", gasUsed); - } + uint256 gasUsed = _runtimeBenchmark( + owner1, + address(account1), + abi.encodeCall( + ModularAccountBase.executeWithRuntimeValidation, + (testCase.getInstallData(), _encodeSignature(signerValidation, GLOBAL_VALIDATION, "")) + ) + ); - function test_semiModularAccountGas_userOp_installSessionKey_case1() public { - _deploySemiModularAccountBytecode1(); + testCase.verifyInstallState(); - vm.deal(address(account1), 1 ether); + _snap(RUNTIME, string.concat("InstallSessionKey_Case", vm.toString(i + 1)), gasUsed); - PackedUserOperation memory userOp = PackedUserOperation({ - sender: address(account1), - nonce: _encodeNonce(signerValidation, GLOBAL_V, 0), - initCode: "", - callData: _getInstallDataSessionKeyCase1(), - // don't over-estimate by a lot here, otherwise a fee is assessed. - accountGasLimits: _encodeGasLimits(500_000, 100_000), - preVerificationGas: 0, - gasFees: _encodeGasFees(1, 1), - paymasterAndData: "", - signature: "" - }); + vm.revertToStateAndDelete(vmStateSnapshot); + } + } - bytes32 userOpHash = entryPoint.getUserOpHash(userOp); - (uint8 v, bytes32 r, bytes32 s) = vm.sign(owner1Key, MessageHashUtils.toEthSignedMessageHash(userOpHash)); - userOp.signature = _encodeSignature(abi.encodePacked(EOA_TYPE_SIGNATURE, r, s, v)); + function test_semiModularAccountGas_userOp_installSessionKeyCases() public { + _deploySemiModularAccountBytecode1(); - uint256 gasUsed = _userOpBenchmark(userOp); + for (uint256 i = 0; i < sessionKeyTestCases.length; i++) { + uint256 vmStateSnapshot = vm.snapshotState(); - _verifySessionKeyCase1InstallState(); + vm.deal(address(account1), 1 ether); - _snap(USER_OP, "InstallSessionKey_Case1", gasUsed); - } + SessionKeyTestCase memory testCase = sessionKeyTestCases[i]; - function test_semiModularAccountGas_runtime_useSessionKey_case1_counter() public { - _deploySemiModularAccountBytecode1(); + PackedUserOperation memory userOp = PackedUserOperation({ + sender: address(account1), + nonce: _encodeNonce(signerValidation, GLOBAL_V, 0), + initCode: "", + callData: testCase.getInstallData(), + // don't over-estimate by a lot here, otherwise a fee is assessed. + accountGasLimits: _encodeGasLimits(500_000, 100_000), + preVerificationGas: 0, + gasFees: _encodeGasFees(1, 1), + paymasterAndData: "", + signature: "" + }); - ModuleEntity sessionKeyValidation = _installSessionKey_case1(); + bytes32 userOpHash = entryPoint.getUserOpHash(userOp); + (uint8 v, bytes32 r, bytes32 s) = + vm.sign(owner1Key, MessageHashUtils.toEthSignedMessageHash(userOpHash)); + userOp.signature = _encodeSignature(abi.encodePacked(EOA_TYPE_SIGNATURE, r, s, v)); - // Jump to within the valid timestamp range - vm.warp(200); + uint256 gasUsed = _userOpBenchmark(userOp); - uint256 gasUsed = _runtimeBenchmark( - sessionSigner1, - address(account1), - abi.encodeCall( - ModularAccountBase.executeWithRuntimeValidation, - ( - abi.encodeCall( - ModularAccountBase.execute, - (address(counter), 0 wei, abi.encodeCall(counter.increment, ())) - ), - _encodeSignature(sessionKeyValidation, SELECTOR_ASSOCIATED_VALIDATION, "") - ) - ) - ); + testCase.verifyInstallState(); - assertEq(counter.number(), 2); + _snap(USER_OP, string.concat("InstallSessionKey_Case", vm.toString(i + 1)), gasUsed); - _snap(RUNTIME, "UseSessionKey_Case1_Counter", gasUsed); + vm.revertToStateAndDelete(vmStateSnapshot); + } } - function test_semiModularAccountGas_userOp_useSessionKey_case1_counter() public { + function test_semiModularAccountGas_runtime_useSessionKeyCases_counter() public { _deploySemiModularAccountBytecode1(); - vm.deal(address(account1), 1 ether); + for (uint256 i = 0; i < sessionKeyTestCases.length; i++) { + uint256 vmStateSnapshot = vm.snapshotState(); - ModuleEntity sessionKeyValidation = _installSessionKey_case1(); + SessionKeyTestCase memory testCase = sessionKeyTestCases[i]; + ModuleEntity sessionKeyValidation = testCase.installSessionKey(); - // Jump to within the valid timestamp range - vm.warp(200); + // Jump to within the valid timestamp range + vm.warp(200); - PackedUserOperation memory userOp = PackedUserOperation({ - sender: address(account1), - nonce: _encodeNonce(sessionKeyValidation, SELECTOR_ASSOCIATED_V, 0), - initCode: "", - callData: abi.encodePacked( - ModularAccountBase.executeUserOp.selector, + uint256 gasUsed = _runtimeBenchmark( + testCase.sessionSigner, + address(account1), abi.encodeCall( - ModularAccountBase.execute, (address(counter), 0 wei, abi.encodeCall(counter.increment, ())) + ModularAccountBase.executeWithRuntimeValidation, + ( + abi.encodeCall( + ModularAccountBase.execute, + (address(counter), 0 wei, abi.encodeCall(counter.increment, ())) + ), + _encodeSignature( + sessionKeyValidation, + testCase.isGlobal ? GLOBAL_VALIDATION : SELECTOR_ASSOCIATED_VALIDATION, + "" + ) + ) ) - ), - // don't over-estimate by a lot here, otherwise a fee is assessed. - accountGasLimits: _encodeGasLimits(200_000, 200_000), - preVerificationGas: 0, - gasFees: _encodeGasFees(1, 1), - paymasterAndData: "", - signature: "" - }); + ); - bytes32 userOpHash = entryPoint.getUserOpHash(userOp); - (uint8 v, bytes32 r, bytes32 s) = - vm.sign(sessionSigner1Key, MessageHashUtils.toEthSignedMessageHash(userOpHash)); - userOp.signature = _encodeSignature(abi.encodePacked(EOA_TYPE_SIGNATURE, r, s, v)); + assertEq(counter.number(), 2); - uint256 gasUsed = _userOpBenchmark(userOp); + _snap(RUNTIME, string.concat("UseSessionKey_Case", vm.toString(i + 1), "_Counter"), gasUsed); - assertEq(counter.number(), 2); - - _snap(USER_OP, "UseSessionKey_Case1_Counter", gasUsed); + vm.revertToStateAndDelete(vmStateSnapshot); + } } - function test_semiModularAccountGas_runtime_useSessionKey_case1_token() public { + function test_semiModularAccountGas_userOp_useSessionKeyCases_counter() public { _deploySemiModularAccountBytecode1(); - ModuleEntity sessionKeyValidation = _installSessionKey_case1(); + for (uint256 i = 0; i < sessionKeyTestCases.length; i++) { + uint256 vmStateSnapshot = vm.snapshotState(); - mockErc20.mint(address(account1), 100 ether); + vm.deal(address(account1), 1 ether); - // Jump to within the valid timestamp range - vm.warp(200); + SessionKeyTestCase memory testCase = sessionKeyTestCases[i]; + ModuleEntity sessionKeyValidation = testCase.installSessionKey(); - uint256 gasUsed = _runtimeBenchmark( - sessionSigner1, - address(account1), - abi.encodeCall( - ModularAccountBase.executeWithRuntimeValidation, - ( + // Jump to within the valid timestamp range + vm.warp(200); + + PackedUserOperation memory userOp = PackedUserOperation({ + sender: address(account1), + nonce: _encodeNonce(sessionKeyValidation, testCase.isGlobal ? GLOBAL_V : SELECTOR_ASSOCIATED_V, 0), + initCode: "", + callData: abi.encodePacked( + ModularAccountBase.executeUserOp.selector, abi.encodeCall( - ModularAccountBase.execute, - (address(mockErc20), 0, abi.encodeCall(mockErc20.transfer, (recipient, 10 ether))) - ), - _encodeSignature(sessionKeyValidation, SELECTOR_ASSOCIATED_VALIDATION, "") + ModularAccountBase.execute, (address(counter), 0 wei, abi.encodeCall(counter.increment, ())) + ) + ), + // don't over-estimate by a lot here, otherwise a fee is assessed. + accountGasLimits: _encodeGasLimits(200_000, 200_000), + preVerificationGas: 0, + gasFees: _encodeGasFees(1, 1), + paymasterAndData: "", + signature: "" + }); + + bytes32 userOpHash = entryPoint.getUserOpHash(userOp); + (uint8 v, bytes32 r, bytes32 s) = + vm.sign(testCase.sessionSignerKey, MessageHashUtils.toEthSignedMessageHash(userOpHash)); + userOp.signature = _encodeSignature(abi.encodePacked(EOA_TYPE_SIGNATURE, r, s, v)); + + uint256 gasUsed = _userOpBenchmark(userOp); + + assertEq(counter.number(), 2); + + _snap(USER_OP, string.concat("UseSessionKey_Case", vm.toString(i + 1), "_Counter"), gasUsed); + + vm.revertToStateAndDelete(vmStateSnapshot); + } + } + + function test_semiModularAccountGas_runtime_useSessionKeyCases_token() public { + _deploySemiModularAccountBytecode1(); + + for (uint256 i = 0; i < sessionKeyTestCases.length; i++) { + uint256 vmStateSnapshot = vm.snapshotState(); + + SessionKeyTestCase memory testCase = sessionKeyTestCases[i]; + ModuleEntity sessionKeyValidation = testCase.installSessionKey(); + + mockErc20.mint(address(account1), 100 ether); + + // Jump to within the valid timestamp range + vm.warp(200); + + uint256 gasUsed = _runtimeBenchmark( + testCase.sessionSigner, + address(account1), + abi.encodeCall( + ModularAccountBase.executeWithRuntimeValidation, + ( + abi.encodeCall( + ModularAccountBase.execute, + (address(mockErc20), 0, abi.encodeCall(mockErc20.transfer, (recipient, 10 ether))) + ), + _encodeSignature( + sessionKeyValidation, + testCase.isGlobal ? GLOBAL_VALIDATION : SELECTOR_ASSOCIATED_VALIDATION, + "" + ) + ) ) - ) - ); + ); - assertEq(mockErc20.balanceOf(recipient), 10 ether); + assertEq(mockErc20.balanceOf(recipient), 10 ether); + + _snap(RUNTIME, string.concat("UseSessionKey_Case", vm.toString(i + 1), "_Token"), gasUsed); - _snap(RUNTIME, "UseSessionKey_Case1_Token", gasUsed); + vm.revertToStateAndDelete(vmStateSnapshot); + } } - function test_semiModularAccountGas_userOp_useSessionKey_case1_token() public { + function test_semiModularAccountGas_userOp_useSessionKeyCases_token() public { _deploySemiModularAccountBytecode1(); - vm.deal(address(account1), 1 ether); + for (uint256 i = 0; i < sessionKeyTestCases.length; i++) { + uint256 vmStateSnapshot = vm.snapshotState(); - ModuleEntity sessionKeyValidation = _installSessionKey_case1(); + vm.deal(address(account1), 1 ether); - mockErc20.mint(address(account1), 100 ether); + SessionKeyTestCase memory testCase = sessionKeyTestCases[i]; + ModuleEntity sessionKeyValidation = testCase.installSessionKey(); - // Jump to within the valid timestamp range - vm.warp(200); + mockErc20.mint(address(account1), 100 ether); - PackedUserOperation memory userOp = PackedUserOperation({ - sender: address(account1), - nonce: _encodeNonce(sessionKeyValidation, SELECTOR_ASSOCIATED_V, 0), - initCode: "", - callData: abi.encodePacked( - ModularAccountBase.executeUserOp.selector, - abi.encodeCall( - ModularAccountBase.execute, - (address(mockErc20), 0, abi.encodeCall(mockErc20.transfer, (recipient, 10 ether))) - ) - ), - // don't over-estimate by a lot here, otherwise a fee is assessed. - accountGasLimits: _encodeGasLimits(200_000, 200_000), - preVerificationGas: 0, - gasFees: _encodeGasFees(1, 1), - paymasterAndData: "", - signature: "" - }); + // Jump to within the valid timestamp range + vm.warp(200); - bytes32 userOpHash = entryPoint.getUserOpHash(userOp); - (uint8 v, bytes32 r, bytes32 s) = - vm.sign(sessionSigner1Key, MessageHashUtils.toEthSignedMessageHash(userOpHash)); - userOp.signature = _encodeSignature(abi.encodePacked(EOA_TYPE_SIGNATURE, r, s, v)); + PackedUserOperation memory userOp = PackedUserOperation({ + sender: address(account1), + nonce: _encodeNonce(sessionKeyValidation, testCase.isGlobal ? GLOBAL_V : SELECTOR_ASSOCIATED_V, 0), + initCode: "", + callData: abi.encodePacked( + ModularAccountBase.executeUserOp.selector, + abi.encodeCall( + ModularAccountBase.execute, + (address(mockErc20), 0, abi.encodeCall(mockErc20.transfer, (recipient, 10 ether))) + ) + ), + // don't over-estimate by a lot here, otherwise a fee is assessed. + accountGasLimits: _encodeGasLimits(200_000, 200_000), + preVerificationGas: 0, + gasFees: _encodeGasFees(1, 1), + paymasterAndData: "", + signature: "" + }); - uint256 gasUsed = _userOpBenchmark(userOp); + bytes32 userOpHash = entryPoint.getUserOpHash(userOp); + (uint8 v, bytes32 r, bytes32 s) = + vm.sign(testCase.sessionSignerKey, MessageHashUtils.toEthSignedMessageHash(userOpHash)); + userOp.signature = _encodeSignature(abi.encodePacked(EOA_TYPE_SIGNATURE, r, s, v)); - assertEq(mockErc20.balanceOf(recipient), 10 ether); + uint256 gasUsed = _userOpBenchmark(userOp); + + assertEq(mockErc20.balanceOf(recipient), 10 ether); + + _snap(USER_OP, string.concat("UseSessionKey_Case", vm.toString(i + 1), "_Token"), gasUsed); - _snap(USER_OP, "UseSessionKey_Case1_Token", gasUsed); + vm.revertToStateAndDelete(vmStateSnapshot); + } } } From eb8046ee3346098de9be4a8fe8c6e3cc69e1c961 Mon Sep 17 00:00:00 2001 From: adam Date: Thu, 12 Jun 2025 14:28:54 -0400 Subject: [PATCH 2/3] style: fmt --- gas/modular-account/ModularAccount.gas.t.sol | 24 +++++++++---------- .../ModularAccountBenchmarkBase.sol | 6 ++--- .../SemiModularAccount.gas.t.sol | 24 +++++++++---------- 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/gas/modular-account/ModularAccount.gas.t.sol b/gas/modular-account/ModularAccount.gas.t.sol index d01a6641..e28c0503 100644 --- a/gas/modular-account/ModularAccount.gas.t.sol +++ b/gas/modular-account/ModularAccount.gas.t.sol @@ -303,10 +303,10 @@ contract ModularAccountGasTest is ModularAccountBenchmarkBase("ModularAccount") function test_modularAccountGas_runtime_installSessionKeyCases() public { _deployAccount1(); - for (uint256 i = 0; i < sessionKeyTestCases.length; i++) { + for (uint256 i = 0; i < _sessionKeyTestCases.length; i++) { uint256 vmStateSnapshot = vm.snapshotState(); - SessionKeyTestCase memory testCase = sessionKeyTestCases[i]; + SessionKeyTestCase memory testCase = _sessionKeyTestCases[i]; uint256 gasUsed = _runtimeBenchmark( owner1, @@ -328,10 +328,10 @@ contract ModularAccountGasTest is ModularAccountBenchmarkBase("ModularAccount") function test_modularAccountGas_userOp_installSessionKeyCases() public { _deployAccount1(); - for (uint256 i = 0; i < sessionKeyTestCases.length; i++) { + for (uint256 i = 0; i < _sessionKeyTestCases.length; i++) { uint256 vmStateSnapshot = vm.snapshotState(); - SessionKeyTestCase memory testCase = sessionKeyTestCases[i]; + SessionKeyTestCase memory testCase = _sessionKeyTestCases[i]; vm.deal(address(account1), 1 ether); @@ -366,10 +366,10 @@ contract ModularAccountGasTest is ModularAccountBenchmarkBase("ModularAccount") function test_modularAccountGas_runtime_useSessionKeyCases_counter() public { _deployAccount1(); - for (uint256 i = 0; i < sessionKeyTestCases.length; i++) { + for (uint256 i = 0; i < _sessionKeyTestCases.length; i++) { uint256 vmStateSnapshot = vm.snapshotState(); - SessionKeyTestCase memory testCase = sessionKeyTestCases[i]; + SessionKeyTestCase memory testCase = _sessionKeyTestCases[i]; ModuleEntity sessionKeyValidation = testCase.installSessionKey(); @@ -406,12 +406,12 @@ contract ModularAccountGasTest is ModularAccountBenchmarkBase("ModularAccount") function test_modularAccountGas_userOp_useSessionKeyCases_counter() public { _deployAccount1(); - for (uint256 i = 0; i < sessionKeyTestCases.length; i++) { + for (uint256 i = 0; i < _sessionKeyTestCases.length; i++) { uint256 vmStateSnapshot = vm.snapshotState(); vm.deal(address(account1), 1 ether); - SessionKeyTestCase memory testCase = sessionKeyTestCases[i]; + SessionKeyTestCase memory testCase = _sessionKeyTestCases[i]; ModuleEntity sessionKeyValidation = testCase.installSessionKey(); // Jump to within the valid timestamp range @@ -453,10 +453,10 @@ contract ModularAccountGasTest is ModularAccountBenchmarkBase("ModularAccount") function test_modularAccountGas_runtime_useSessionKeyCases_token() public { _deployAccount1(); - for (uint256 i = 0; i < sessionKeyTestCases.length; i++) { + for (uint256 i = 0; i < _sessionKeyTestCases.length; i++) { uint256 vmStateSnapshot = vm.snapshotState(); - SessionKeyTestCase memory testCase = sessionKeyTestCases[i]; + SessionKeyTestCase memory testCase = _sessionKeyTestCases[i]; ModuleEntity sessionKeyValidation = testCase.installSessionKey(); mockErc20.mint(address(account1), 100 ether); @@ -494,12 +494,12 @@ contract ModularAccountGasTest is ModularAccountBenchmarkBase("ModularAccount") function test_modularAccountGas_userOp_useSessionKeyCases_token() public { _deployAccount1(); - for (uint256 i = 0; i < sessionKeyTestCases.length; i++) { + for (uint256 i = 0; i < _sessionKeyTestCases.length; i++) { uint256 vmStateSnapshot = vm.snapshotState(); vm.deal(address(account1), 1 ether); - SessionKeyTestCase memory testCase = sessionKeyTestCases[i]; + SessionKeyTestCase memory testCase = _sessionKeyTestCases[i]; ModuleEntity sessionKeyValidation = testCase.installSessionKey(); mockErc20.mint(address(account1), 100 ether); diff --git a/gas/modular-account/ModularAccountBenchmarkBase.sol b/gas/modular-account/ModularAccountBenchmarkBase.sol index feb2c8f2..c0659d61 100644 --- a/gas/modular-account/ModularAccountBenchmarkBase.sol +++ b/gas/modular-account/ModularAccountBenchmarkBase.sol @@ -61,7 +61,7 @@ abstract contract ModularAccountBenchmarkBase is BenchmarkBase, ModuleSignatureU bool isGlobal; } - SessionKeyTestCase[] internal sessionKeyTestCases; + SessionKeyTestCase[] internal _sessionKeyTestCases; constructor(string memory accountImplName) BenchmarkBase(accountImplName) { (sessionSigner1, sessionSigner1Key) = makeAddrAndKey("session1"); @@ -88,7 +88,7 @@ abstract contract ModularAccountBenchmarkBase is BenchmarkBase, ModuleSignatureU counter.increment(); // Initialize session key test cases - sessionKeyTestCases.push( + _sessionKeyTestCases.push( SessionKeyTestCase({ getInstallData: _getInstallDataSessionKeyCase1, installSessionKey: _installSessionKey_case1, @@ -98,7 +98,7 @@ abstract contract ModularAccountBenchmarkBase is BenchmarkBase, ModuleSignatureU isGlobal: false }) ); - sessionKeyTestCases.push( + _sessionKeyTestCases.push( SessionKeyTestCase({ getInstallData: _getInstallDataSessionKeyCase2, installSessionKey: _installSessionKey_case2, diff --git a/gas/modular-account/SemiModularAccount.gas.t.sol b/gas/modular-account/SemiModularAccount.gas.t.sol index 5a6d5f63..5df5f967 100644 --- a/gas/modular-account/SemiModularAccount.gas.t.sol +++ b/gas/modular-account/SemiModularAccount.gas.t.sol @@ -293,10 +293,10 @@ contract ModularAccountGasTest is ModularAccountBenchmarkBase("SemiModularAccoun function test_semiModularAccountGas_runtime_installSessionKeyCases() public { _deploySemiModularAccountBytecode1(); - for (uint256 i = 0; i < sessionKeyTestCases.length; i++) { + for (uint256 i = 0; i < _sessionKeyTestCases.length; i++) { uint256 vmStateSnapshot = vm.snapshotState(); - SessionKeyTestCase memory testCase = sessionKeyTestCases[i]; + SessionKeyTestCase memory testCase = _sessionKeyTestCases[i]; uint256 gasUsed = _runtimeBenchmark( owner1, @@ -318,12 +318,12 @@ contract ModularAccountGasTest is ModularAccountBenchmarkBase("SemiModularAccoun function test_semiModularAccountGas_userOp_installSessionKeyCases() public { _deploySemiModularAccountBytecode1(); - for (uint256 i = 0; i < sessionKeyTestCases.length; i++) { + for (uint256 i = 0; i < _sessionKeyTestCases.length; i++) { uint256 vmStateSnapshot = vm.snapshotState(); vm.deal(address(account1), 1 ether); - SessionKeyTestCase memory testCase = sessionKeyTestCases[i]; + SessionKeyTestCase memory testCase = _sessionKeyTestCases[i]; PackedUserOperation memory userOp = PackedUserOperation({ sender: address(account1), @@ -356,10 +356,10 @@ contract ModularAccountGasTest is ModularAccountBenchmarkBase("SemiModularAccoun function test_semiModularAccountGas_runtime_useSessionKeyCases_counter() public { _deploySemiModularAccountBytecode1(); - for (uint256 i = 0; i < sessionKeyTestCases.length; i++) { + for (uint256 i = 0; i < _sessionKeyTestCases.length; i++) { uint256 vmStateSnapshot = vm.snapshotState(); - SessionKeyTestCase memory testCase = sessionKeyTestCases[i]; + SessionKeyTestCase memory testCase = _sessionKeyTestCases[i]; ModuleEntity sessionKeyValidation = testCase.installSessionKey(); // Jump to within the valid timestamp range @@ -395,12 +395,12 @@ contract ModularAccountGasTest is ModularAccountBenchmarkBase("SemiModularAccoun function test_semiModularAccountGas_userOp_useSessionKeyCases_counter() public { _deploySemiModularAccountBytecode1(); - for (uint256 i = 0; i < sessionKeyTestCases.length; i++) { + for (uint256 i = 0; i < _sessionKeyTestCases.length; i++) { uint256 vmStateSnapshot = vm.snapshotState(); vm.deal(address(account1), 1 ether); - SessionKeyTestCase memory testCase = sessionKeyTestCases[i]; + SessionKeyTestCase memory testCase = _sessionKeyTestCases[i]; ModuleEntity sessionKeyValidation = testCase.installSessionKey(); // Jump to within the valid timestamp range @@ -442,10 +442,10 @@ contract ModularAccountGasTest is ModularAccountBenchmarkBase("SemiModularAccoun function test_semiModularAccountGas_runtime_useSessionKeyCases_token() public { _deploySemiModularAccountBytecode1(); - for (uint256 i = 0; i < sessionKeyTestCases.length; i++) { + for (uint256 i = 0; i < _sessionKeyTestCases.length; i++) { uint256 vmStateSnapshot = vm.snapshotState(); - SessionKeyTestCase memory testCase = sessionKeyTestCases[i]; + SessionKeyTestCase memory testCase = _sessionKeyTestCases[i]; ModuleEntity sessionKeyValidation = testCase.installSessionKey(); mockErc20.mint(address(account1), 100 ether); @@ -483,12 +483,12 @@ contract ModularAccountGasTest is ModularAccountBenchmarkBase("SemiModularAccoun function test_semiModularAccountGas_userOp_useSessionKeyCases_token() public { _deploySemiModularAccountBytecode1(); - for (uint256 i = 0; i < sessionKeyTestCases.length; i++) { + for (uint256 i = 0; i < _sessionKeyTestCases.length; i++) { uint256 vmStateSnapshot = vm.snapshotState(); vm.deal(address(account1), 1 ether); - SessionKeyTestCase memory testCase = sessionKeyTestCases[i]; + SessionKeyTestCase memory testCase = _sessionKeyTestCases[i]; ModuleEntity sessionKeyValidation = testCase.installSessionKey(); mockErc20.mint(address(account1), 100 ether); From ac82e997c2669fd51d968c6b01741377bb6fbf84 Mon Sep 17 00:00:00 2001 From: adam Date: Mon, 21 Jul 2025 13:16:21 -0400 Subject: [PATCH 3/3] rebaseme: frozen work log --- gas/modular-account/SemiModularAccount.gas.t.sol | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/gas/modular-account/SemiModularAccount.gas.t.sol b/gas/modular-account/SemiModularAccount.gas.t.sol index 5df5f967..0c098da4 100644 --- a/gas/modular-account/SemiModularAccount.gas.t.sol +++ b/gas/modular-account/SemiModularAccount.gas.t.sol @@ -7,6 +7,7 @@ import { ValidationConfig, ValidationConfigLib } from "@erc6900/reference-implementation/libraries/ValidationConfigLib.sol"; +import {HookConfigLib} from "@erc6900/reference-implementation/libraries/HookConfigLib.sol"; import {PackedUserOperation} from "@eth-infinitism/account-abstraction/interfaces/PackedUserOperation.sol"; import {MessageHashUtils} from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol"; import {Vm} from "forge-std/Vm.sol"; @@ -260,9 +261,18 @@ contract ModularAccountGasTest is ModularAccountBenchmarkBase("SemiModularAccoun ValidationConfig newUOValidation = ValidationConfigLib.pack(address(newValidationModule), newEntityId, true, false, true); + bytes[] memory hooks = new bytes[](1); + + // Time range hook + hooks[0] = abi.encodePacked( + HookConfigLib.packValidationHook({_module: address(timeRangeModule), _entityId: 1}), + abi.encode(uint32(1), 1000, 100) + ); + + bytes memory deferredValidationInstallCall = abi.encodeCall( ModularAccountBase.installValidation, - (newUOValidation, new bytes4[](0), abi.encode(newEntityId, owner2), new bytes[](0)) + (newUOValidation, new bytes4[](0), abi.encode(newEntityId, owner2), hooks) ); uint48 deferredInstallDeadline = 0;