Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/clean refactor #80

Merged
merged 133 commits into from
May 29, 2024
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
133 commits
Select commit Hold shift + click to select a range
075ab3f
refactor: Add unit tests for module support in TestModuleManager_Supp…
Aboudjem May 22, 2024
1520c3d
chore: Update Solidity version to 0.8.24
Aboudjem May 22, 2024
b074e89
refactor: Remove unnecessary imports in TestModuleManager_UninstallMo…
Aboudjem May 22, 2024
f9cb0e9
Add test_RevertIf_UninstallNonInstalledFallbackHandler test + support…
Aboudjem May 22, 2024
c7d0b37
Add Fallback testcases
Aboudjem May 22, 2024
071789b
remove unrreachable condition on uninstall for unsupported module typ…
Aboudjem May 22, 2024
1dfdb06
refactor: Improve module support unit tests in TestModuleManager_Supp…
Aboudjem May 22, 2024
a36529c
chore: Update Solidity version to 0.8.24
Aboudjem May 22, 2024
890570e
Add new test cases + coverage
Aboudjem May 22, 2024
f6ea776
fix bug where additional iszero check make the success to not returns…
Aboudjem May 22, 2024
744e1cb
Update Solidity version to 0.8.24 + remove unused imports
Aboudjem May 22, 2024
64e81d9
refactor: Remove unused imports in TestHelper.t.sol
Aboudjem May 22, 2024
a1346ec
Add withdrawDepositTo tests
Aboudjem May 22, 2024
53529a5
test: Add test for addDeposit function with wrong entry point
Aboudjem May 22, 2024
9f40d25
fix tests + Add test for TryExecuteBatch_RevertIf_HandleFailure_WithP…
Aboudjem May 22, 2024
7123420
test: Add batch execution tests with failure scenarios
Aboudjem May 22, 2024
eb6d79a
test: Add test for unauthorized access during smart account upgrade
Aboudjem May 22, 2024
82106fc
refactor: Remove unused test function in K1Validator.sol
Aboudjem May 22, 2024
857d865
fix fallback handler onuninstall
Aboudjem May 22, 2024
60acc0e
Update Solidity version to 0.8.24
Aboudjem May 22, 2024
6a6468c
remove unused imports
Aboudjem May 22, 2024
ed1dcbb
Add new functions for testing purpose + Remove unused imports and upd…
Aboudjem May 22, 2024
37bcaa6
remove compiler warnings
Aboudjem May 23, 2024
86cc7fc
Remove compiler warnings
Aboudjem May 23, 2024
a84971b
remove compiler warnings
Aboudjem May 23, 2024
8c4b5d3
[tmp] Refactor invariant tests
Aboudjem May 23, 2024
d35f1d4
chore: Remove unused _mint function call in NFT.sol
Aboudjem May 25, 2024
ab25f37
chore: Update BUNDLER_ADDRESS to be payable in TestHelper contract
Aboudjem May 25, 2024
7192249
chore: Add MockPaymaster import in Imports.sol
Aboudjem May 25, 2024
4d93618
chore: Add ERC20 and Uniswap interfaces
Aboudjem May 25, 2024
0e65964
chore: Add TestNexusERC721Integration contract for testing Nexus smar…
Aboudjem May 25, 2024
af72332
chore: Refactor code for testing Nexus smart account functionalities …
Aboudjem May 25, 2024
2b1284e
chore: Refactor code for testing Nexus smart account functionalities …
Aboudjem May 25, 2024
a4d2df3
chore: Add MockPaymaster contract for testing Nexus smart account fun…
Aboudjem May 25, 2024
aa9c0d4
chore: Update MockPaymaster instantiation in integration tests
Aboudjem May 25, 2024
691be4a
chore: Refactor TestFuzz_ERC4337Account contract to use ENTRYPOINT.ha…
Aboudjem May 25, 2024
6ba0e69
chore: Add BaseSettings contract for setting up constants required fo…
Aboudjem May 25, 2024
6b56bb1
chore: Refactor Invariant tests
Aboudjem May 25, 2024
f166ccf
Merge branch 'feat/SMA-809-potential-account-factory' into feat/clean…
Aboudjem May 25, 2024
276f27d
remove invariants temp
Aboudjem May 25, 2024
6ae517f
handle additional context length in fallback handler check, which revert
Aboudjem May 25, 2024
b7d267c
chore: Update gas report command to include test_Gas match and fixed …
Aboudjem May 25, 2024
9525b20
feat: Add gas benchmark tests
Aboudjem May 25, 2024
9e37609
lint fix
Aboudjem May 25, 2024
250b6eb
Rename NFT.sol -> MockNFT.sol
Aboudjem May 25, 2024
4a7995b
Merge branch 'dev' into feat/clean-refactor
livingrockrises May 26, 2024
f949ef3
refactor and fix conflicts
livingrockrises May 26, 2024
ba95ca5
chore: Update BASE_RPC_URL in CI configuration
Aboudjem May 26, 2024
beb87b9
Merge branch 'feat/clean-refactor' of https://github.com/bcnmy/erc757…
Aboudjem May 26, 2024
0af6ef5
coverage: Add unsupported exec type revert tests
Aboudjem May 26, 2024
3056a36
chore: Add script to generate coverage report
Aboudjem May 27, 2024
b923ab2
chore: Update lcov command in generate_coverage_report.sh
Aboudjem May 27, 2024
0d74b51
chore: Update generate_coverage_report.sh to use forge coverage comma…
Aboudjem May 27, 2024
ed10447
chore: Update coverage report script to use new generate_coverage_rep…
Aboudjem May 27, 2024
cc23848
chore: Update changed-files action to latest version
Aboudjem May 27, 2024
c834498
chore: Update actions/checkout to v4.1.6 in ci.yml
Aboudjem May 27, 2024
bbde8be
chore: Update actions/checkout to v4.1.6
Aboudjem May 27, 2024
a0787f2
chore: Remove unused `test()` functions
Aboudjem May 27, 2024
53a074b
chore: Update generate_coverage_report.sh to use forge coverage comma…
Aboudjem May 27, 2024
b7da49d
chore: Update skipFiles in .solcover.js to exclude more directories
Aboudjem May 27, 2024
ae3529f
chore: Update generate_coverage_report.sh to create necessary directo…
Aboudjem May 27, 2024
11047dd
chore: Update file path for Foundry Coverage Report in ci.yml
Aboudjem May 27, 2024
a297a36
compiler warning: Update test_SupportsModule functions to be view fun…
Aboudjem May 27, 2024
33d93d6
fix compiler warnings
Aboudjem May 27, 2024
d21a711
warning fix
Aboudjem May 27, 2024
038d701
chore: Update ci.yml to enable verbose mode and fail CI on error
Aboudjem May 27, 2024
0486674
chore: Update ci.yml to enable verbose mode and fail CI on error
Aboudjem May 27, 2024
be74960
chore: Update ci.yml to enable verbose mode and fail CI on error
Aboudjem May 27, 2024
b14f064
chore: Update generate_coverage_report.sh to check if coverage file i…
Aboudjem May 27, 2024
c130094
revert solc warning
Aboudjem May 27, 2024
f2c4e42
chore: Refactor TestAccountExecution_ExecuteFromExecutor.t.sol
Aboudjem May 27, 2024
901f3e1
chore: Remove hardhat-foundry import from hardhat.config.ts
Aboudjem May 27, 2024
420f613
chore: Update ci.yml to enable verbose mode and fail CI on error
Aboudjem May 27, 2024
4ee00da
chore: Update codecov-action configuration to use the correct file pa…
Aboudjem May 27, 2024
22acf18
chore: Update ci.yml to exclude additional Slither checks
Aboudjem May 27, 2024
dd3f562
chore: Update ci.yml to include coverage/foundry directory for Codeco…
Aboudjem May 27, 2024
d043cb9
chore: Update comment.js to handle empty Slither reports
Aboudjem May 27, 2024
ab02048
chore: Refactor comment.js to handle empty Slither reports more effic…
Aboudjem May 27, 2024
8cf6f33
Refactor comment.js to handle empty Slither reports more efficiently
Aboudjem May 27, 2024
db6adfd
lint fix + Refactor comment.js to handle empty Slither reports more e…
Aboudjem May 27, 2024
e455342
chore: Update ci.yml to only trigger on pull requests
Aboudjem May 27, 2024
331b027
Refactor comment.js to handle empty Slither reports more efficiently
Aboudjem May 27, 2024
528bb6e
Refactor comment.js to handle empty Slither reports more efficiently
Aboudjem May 27, 2024
42a6e3a
fix comment.js
Aboudjem May 27, 2024
5676601
Refactor comment.js to handle empty Slither reports more efficiently
Aboudjem May 27, 2024
e264fee
Refactor comment.js to handle empty Slither reports more efficiently
Aboudjem May 27, 2024
a278c75
Refactor comment.js to handle empty Slither reports more efficiently
Aboudjem May 27, 2024
77b026a
Refactor comment.js to handle empty Slither reports more efficiently
Aboudjem May 27, 2024
6e02ce8
revert changes
Aboudjem May 27, 2024
cd743cc
Merge pull request #82 from bcnmy/feat/ci-fix
livingrockrises May 27, 2024
b2fb9fc
refactor wording in 1271
livingrockrises May 27, 2024
26aa643
chore: Refactor contracts names
Aboudjem May 28, 2024
1dd5424
refactor: Update MockPaymaster to extend VerifyingPaymaster
Aboudjem May 28, 2024
57ccfd0
feat: Add NexusTest_Base import to ArbitrumSettings
Aboudjem May 28, 2024
d120913
refactor: Remove unused function getArbitrumRpcUrl
Aboudjem May 28, 2024
a430ecd
refactor: Update BaseSettings to include NexusTest_Base import and ge…
Aboudjem May 28, 2024
3f561f5
lint fix
Aboudjem May 28, 2024
f7f6753
refactor: Update BaseSettings to include NexusTest_Base import and ge…
Aboudjem May 28, 2024
881aca8
refactor: Update BaseSettings to include NexusTest_Base import and ge…
Aboudjem May 28, 2024
9f1cfa3
refactor: Update MockPaymaster to extend VerifyingPaymaster
Aboudjem May 28, 2024
dc3d989
refactor: Adjust preVerificationGas in buildPackedUserOp function
Aboudjem May 28, 2024
7672740
remove duplicate test
Aboudjem May 29, 2024
441571b
refactor: Add MockPaymaster import to TestHelper.t.sol
Aboudjem May 29, 2024
bbf5017
refactor: Add checkPaymasterBalance modifier to NexusTest_Base
Aboudjem May 29, 2024
565144d
refactor paymaster tests, fix issues
Aboudjem May 29, 2024
5976aab
refactor: Generate Gas Report script
Aboudjem May 29, 2024
7d3463c
refactor: Add generate-and-push-gas-report script
Aboudjem May 29, 2024
0a9de28
refactor: Add gas consumption test for swapping ETH for USDC with dep…
Aboudjem May 29, 2024
890afea
refactor: Remove unused Husky hooks
Aboudjem May 29, 2024
e5beacd
refactor: Add gas consumption test for swapping WETH for USDC with de…
Aboudjem May 29, 2024
6154833
refactor: Remove unused Husky hooks
Aboudjem May 29, 2024
051733c
refactor: Update prepare script in package.json
Aboudjem May 29, 2024
5479e0c
refactor: Add gas consumption test for transferring ERC20 tokens from…
Aboudjem May 29, 2024
2b5c247
refactor: Remove unused Husky hooks
Aboudjem May 29, 2024
61890d8
refactor: Update pre-push Husky hook to include lint-fix and generate…
Aboudjem May 29, 2024
faa9dc7
refactor: Add gas consumption test for transferring ERC20 tokens from…
Aboudjem May 29, 2024
7e3fec1
refactor: Add gas consumption test for transferring ERC721 tokens fro…
Aboudjem May 29, 2024
2f9e4e4
refactor: Add gas consumption test for transferring ETH from an alrea…
Aboudjem May 29, 2024
0328c50
refactor: Add gas consumption test for transferring ERC721 tokens fro…
Aboudjem May 29, 2024
02cbbba
refactor: Update pre-push Husky hook to include lint:fix and generate…
Aboudjem May 29, 2024
364f9e2
refactor: Add gas consumption test for transferring ETH from an alrea…
Aboudjem May 29, 2024
d07507f
refactor: Update gas consumption test for transferring ERC20 tokens f…
Aboudjem May 29, 2024
b931b3b
Update gas report
Aboudjem May 29, 2024
38ed342
fix lint
Aboudjem May 29, 2024
a199c38
Update gas report
Aboudjem May 29, 2024
3d9bc0c
refactor: Update fallback function tests to use successFunction inste…
Aboudjem May 29, 2024
583d509
refactor: Update MockHandler contract to remove unused functions and …
Aboudjem May 29, 2024
ac3f03b
Update gas report
Aboudjem May 29, 2024
6a0b757
refactor: Remove gasIntensiveFunction from MockHandler contract
Aboudjem May 29, 2024
11f9c3c
Update gas report
Aboudjem May 29, 2024
7abeae1
Update gas report
Aboudjem May 29, 2024
1d771c6
Update gas report
Aboudjem May 29, 2024
3d2c210
Update gas report
Aboudjem May 29, 2024
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
3 changes: 1 addition & 2 deletions contracts/Nexus.sol
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,6 @@ contract Nexus is INexus, EIP712, BaseAccount, ExecutionHelper, ModuleManager, U
else if (moduleTypeId == MODULE_TYPE_EXECUTOR) _uninstallExecutor(module, deInitData);
else if (moduleTypeId == MODULE_TYPE_FALLBACK) _uninstallFallbackHandler(module, deInitData);
else if (moduleTypeId == MODULE_TYPE_HOOK) _uninstallHook(module, deInitData);
else revert UnsupportedModuleType(moduleTypeId);
livingrockrises marked this conversation as resolved.
Show resolved Hide resolved
}

function initializeAccount(bytes calldata initData) external payable virtual {
Expand Down Expand Up @@ -512,7 +511,7 @@ contract Nexus is INexus, EIP712, BaseAccount, ExecutionHelper, ModuleManager, U
function _isModuleInstalled(uint256 moduleTypeId, address module, bytes calldata additionalContext) private view returns (bool) {
if (moduleTypeId == MODULE_TYPE_VALIDATOR) return _isValidatorInstalled(module);
else if (moduleTypeId == MODULE_TYPE_EXECUTOR) return _isExecutorInstalled(module);
else if (moduleTypeId == MODULE_TYPE_FALLBACK) return _isFallbackHandlerInstalled(abi.decode(additionalContext, (bytes4)), module);
else if (moduleTypeId == MODULE_TYPE_FALLBACK) return _isFallbackHandlerInstalled(bytes4(additionalContext[0:4]), module);
else if (moduleTypeId == MODULE_TYPE_HOOK) return _isHookInstalled(module);
else return false;
}
Expand Down
2 changes: 1 addition & 1 deletion contracts/base/ExecutionHelper.sol
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ contract ExecutionHelper is IExecutionHelperEventsAndErrors {
assembly {
result := mload(0x40)
calldatacopy(result, callData.offset, callData.length)
success := iszero(call(gas(), target, value, result, callData.length, codesize(), 0x00))
success := call(gas(), target, value, result, callData.length, codesize(), 0x00)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you open a PR for this on reference-implementation repo please and describe in PR discussion

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mstore(result, returndatasize()) // Store the length.
let o := add(result, 0x20)
returndatacopy(o, 0x00, returndatasize()) // Copy the returndata.
Expand Down
7 changes: 2 additions & 5 deletions contracts/base/ModuleManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -225,11 +225,8 @@ contract ModuleManager is Storage, Receiver, IModuleManagerEventsAndErrors {
/// @param fallbackHandler The address of the fallback handler to uninstall.
/// @param data The de-initialization data containing the selector.
function _uninstallFallbackHandler(address fallbackHandler, bytes calldata data) internal virtual {
bytes4 selector = bytes4(data[0:4]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we revert this, prev is more readable

bytes memory deInitData = data[4:];
if (!_isFallbackHandlerInstalled(selector)) revert FallbackNotInstalledForSelector(selector);
_getAccountStorage().fallbacks[selector] = FallbackHandler(address(0), CallType.wrap(0x00));
IFallback(fallbackHandler).onUninstall(deInitData);
_getAccountStorage().fallbacks[bytes4(data[0:4])] = FallbackHandler(address(0), CallType.wrap(0x00));
IFallback(fallbackHandler).onUninstall(data[4:]);
}

/// @dev Checks if a fallback handler is set for a given selector.
Expand Down
2 changes: 1 addition & 1 deletion contracts/mocks/MockExecutor.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;
pragma solidity ^0.8.24;

import { IModule } from "contracts/interfaces/modules/IModule.sol";
import { EncodedModuleTypes } from "contracts/lib/ModuleTypeLib.sol";
Expand Down
46 changes: 41 additions & 5 deletions contracts/mocks/MockHandler.sol
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity ^0.8.23;
pragma solidity ^0.8.24;

import { IERC721Receiver } from "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
import { IModule } from "contracts/interfaces/modules/IModule.sol";
import { IFallback } from "contracts/interfaces/modules/IFallback.sol";
import { EncodedModuleTypes } from "contracts/lib/ModuleTypeLib.sol";
import { MODULE_TYPE_FALLBACK } from "../../contracts/types/Constants.sol";

contract MockHandler is IFallback {

uint256 public count;
string public constant NAME = "Default Handler";
string public constant VERSION = "1.0.0";

Expand Down Expand Up @@ -37,4 +35,42 @@ contract MockHandler is IFallback {
function isInitialized(address) external pure override returns (bool) {
return false;
}

function staticFunction() external pure returns (bytes32) {
return keccak256("STATIC_CALL");
}

function stateChangingFunction() external {
count++;
}

function singleFunction() external pure returns (bytes32) {
Aboudjem marked this conversation as resolved.
Show resolved Hide resolved
return keccak256("SINGLE_CALL");
}

function batchFunction() external pure returns (bytes32) {
return keccak256("BATCH_CALL");
}

function revertingStaticFunction() external pure {
require(false, "Static call revert reason");
}

function revertingSingleFunction() external pure {
require(false, "Single call revert reason");
}

function gasIntensiveFunction() external {
while (true) {
count++;
}
}

function dynamicFunction() external pure returns (bytes32) {
return keccak256("DYNAMIC_CALL");
}

function getState() external view returns (uint256) {
return count;
}
}
2 changes: 1 addition & 1 deletion contracts/mocks/MockHook.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;
pragma solidity ^0.8.24;

import { IModule } from "contracts/interfaces/modules/IModule.sol";
import { EncodedModuleTypes } from "contracts/lib/ModuleTypeLib.sol";
Expand Down
4 changes: 0 additions & 4 deletions contracts/modules/validators/K1Validator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,4 @@ contract K1Validator is IValidator {
function isModuleType(uint256 typeID) external pure returns (bool) {
return typeID == MODULE_TYPE_VALIDATOR;
}

function test() public pure {
// TODO To be removed: This function is used to ignore file in coverage report
}
}
5 changes: 2 additions & 3 deletions contracts/utils/BootstrapUtil.sol
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;
pragma solidity ^0.8.24;

import { Bootstrap, BootstrapConfig } from "./Bootstrap.sol";
import { IModule } from "../interfaces/modules/IModule.sol";
import { BootstrapConfig } from "./Bootstrap.sol";

// Review: can make this a library?
contract BootstrapUtil {
Expand Down
11 changes: 11 additions & 0 deletions test/foundry/integration/UpgradeSmartAccountTest.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,15 @@ contract UpgradeSmartAccountTest is NexusTest_Base {
test_currentImplementationAddress();
test_upgradeImplementation();
}

/// @notice Tests the entire upgrade process
function test_RevertIf_AccessUnauthorized_upgradeSmartAccount() public {
test_proxiableUUIDSlot();
test_currentImplementationAddress();

Nexus newSmartAccount = new Nexus();
Aboudjem marked this conversation as resolved.
Show resolved Hide resolved

vm.expectRevert(abi.encodeWithSelector(AccountAccessUnauthorized.selector));
BOB_ACCOUNT.upgradeToAndCall(address(newSmartAccount), "");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -348,4 +348,110 @@ contract TestAccountExecution_ExecuteFromExecutor is TestAccountExecution_Base {
);
}
}


/// @notice Tests a batch execution with one failing operation.
function test_TryExecuteBatch_SingleFailure() public {
// Verify initial state
assertEq(counter.getNumber(), 0, "Counter should start at 0");

// Prepare batch execution with one failing operation
Execution[] memory executions = new Execution[](2);
executions[0] = Execution(address(counter), 0, abi.encodeWithSelector(Counter.incrementNumber.selector));
executions[1] = Execution(address(counter), 0, abi.encodeWithSelector(Counter.revertOperation.selector));

// Expect the TryExecuteUnsuccessful event to be emitted
vm.expectEmit(true, true, true, true);
emit TryExecuteUnsuccessful(1, abi.encodeWithSignature("Error(string)", "Counter: Revert operation"));

// Execute batch operation via MockExecutor
mockExecutor.tryExecuteBatchViaAccount(BOB_ACCOUNT, executions);

// Verify the counter state
assertEq(counter.getNumber(), 1, "Counter should have been incremented once");
}

/// @notice Tests a batch execution with one failing operation using prank.
function test_TryExecuteBatch_SingleFailure_WithPrank() public {
// Verify initial state
assertEq(counter.getNumber(), 0, "Counter should start at 0");

// Prepare batch execution with one failing operation
Execution[] memory executions = new Execution[](2);
executions[0] = Execution(address(counter), 0, abi.encodeWithSelector(Counter.incrementNumber.selector));
executions[1] = Execution(address(counter), 0, abi.encodeWithSelector(Counter.revertOperation.selector));

// Expect the TryExecuteUnsuccessful event to be emitted
vm.expectEmit(true, true, true, true);
emit TryExecuteUnsuccessful(1, abi.encodeWithSignature("Error(string)", "Counter: Revert operation"));

// Prank and execute batch operation via BOB_ACCOUNT
prank(address(mockExecutor));
BOB_ACCOUNT.executeFromExecutor(ModeLib.encodeTryBatch(), ExecLib.encodeBatch(executions));

// Verify the counter state
assertEq(counter.getNumber(), 1, "Counter should have been incremented once");
}

/// @notice Tests a batch execution with multiple failing operations.
function test_TryExecuteBatch_MultipleFailures() public {
// Verify initial state
assertEq(counter.getNumber(), 0, "Counter should start at 0");

// Prepare batch execution with multiple failing operations
Execution[] memory executions = new Execution[](3);
executions[0] = Execution(address(counter), 0, abi.encodeWithSelector(Counter.revertOperation.selector));
executions[1] = Execution(address(counter), 0, abi.encodeWithSelector(Counter.revertOperation.selector));
executions[2] = Execution(address(counter), 0, abi.encodeWithSelector(Counter.incrementNumber.selector));

// Expect the TryExecuteUnsuccessful event to be emitted for each failure
vm.expectEmit(true, true, true, true);
emit TryExecuteUnsuccessful(0, abi.encodeWithSignature("Error(string)", "Counter: Revert operation"));
vm.expectEmit(true, true, true, true);
emit TryExecuteUnsuccessful(1, abi.encodeWithSignature("Error(string)", "Counter: Revert operation"));

// Execute batch operation via MockExecutor
mockExecutor.tryExecuteBatchViaAccount(BOB_ACCOUNT, executions);

// Verify the counter state
assertEq(counter.getNumber(), 1, "Counter should have been incremented once");
}

/// @notice Tests a batch execution with empty call data.
function test_TryExecuteBatch_EmptyCallData() public {
// Verify initial state
assertEq(counter.getNumber(), 0, "Counter should start at 0");

// Prepare batch execution with empty call data
Execution[] memory executions = new Execution[](1);
executions[0] = Execution(address(counter), 0, "");

// Expect the TryExecuteUnsuccessful event to be emitted
vm.expectEmit(true, true, true, true);
emit TryExecuteUnsuccessful(0, "");

// Execute batch operation via MockExecutor
mockExecutor.tryExecuteBatchViaAccount(BOB_ACCOUNT, executions);

// Verify the counter state remains unchanged
assertEq(counter.getNumber(), 0, "Counter should remain unchanged");
}

/// @notice Tests a batch execution with insufficient gas.
function test_TryExecuteBatch_InsufficientGas() public {
// Verify initial state
assertEq(counter.getNumber(), 0, "Counter should start at 0");

// Prepare batch execution with insufficient gas
Execution[] memory executions = new Execution[](1);
executions[0] = Execution(address(counter), 0, abi.encodeWithSelector(Counter.incrementNumber.selector));

// Expect revert due to insufficient gas
vm.expectRevert();

// Execute batch operation with limited gas via MockExecutor
address(mockExecutor).call{ gas: 10000 }(
abi.encodeWithSelector(mockExecutor.tryExecuteBatchViaAccount.selector, BOB_ACCOUNT, executions)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,32 @@ contract TestAccountExecution_TryExecuteBatch is TestAccountExecution_Base {
PackedUserOperation[] memory userOps = buildPackedUserOperation(BOB, BOB_ACCOUNT, EXECTYPE_TRY, executions, address(VALIDATOR_MODULE));

vm.expectEmit(true, true, true, true);
emit TryExecuteUnsuccessful(2, "");
emit TryExecuteUnsuccessful(1, abi.encodeWithSignature("Error(string)", "Counter: Revert operation"));
ENTRYPOINT.handleOps(userOps, payable(BOB.addr));

assertEq(counter.getNumber(), 2, "Counter should have been incremented even after revert operation in batch execution");
}

/// @notice Tests handling of a batch operation with one failure.
function test_TryExecuteBatch_RevertIf_HandleFailure_WithPrank() public {
assertEq(counter.getNumber(), 0, "Counter should start at 0");

// Preparing a batch execution with three operations: increment, revert, increment
Execution[] memory executions = new Execution[](3);
executions[0] = Execution(address(counter), 0, abi.encodeWithSelector(Counter.incrementNumber.selector));
executions[1] = Execution(address(counter), 0, abi.encodeWithSelector(Counter.revertOperation.selector));
executions[2] = Execution(address(counter), 0, abi.encodeWithSelector(Counter.incrementNumber.selector));

// Execute batch operation
prank(address(BOB_ACCOUNT));
vm.expectEmit(true, true, true, true);
emit TryExecuteUnsuccessful(1, abi.encodeWithSignature("Error(string)", "Counter: Revert operation"));

BOB_ACCOUNT.execute(ModeLib.encodeTryBatch(), abi.encode(executions));

assertEq(counter.getNumber(), 2, "Counter should have been incremented even after revert operation in batch execution");
}

/// @notice Tests handling of a batch operation with multiple failures.
function test_TryExecuteBatch_RevertIf_HandleMultipleFailures() public {
// Preparing a batch execution with three operations: revert, zero address, empty calldata
Expand All @@ -61,9 +81,7 @@ contract TestAccountExecution_TryExecuteBatch is TestAccountExecution_Base {
PackedUserOperation[] memory userOps = buildPackedUserOperation(BOB, BOB_ACCOUNT, EXECTYPE_TRY, executions, address(VALIDATOR_MODULE));

vm.expectEmit(true, true, true, true);
emit TryExecuteUnsuccessful(1, "");
vm.expectEmit(true, true, true, true);
emit TryExecuteUnsuccessful(2, "");
emit TryExecuteUnsuccessful(0, abi.encodeWithSignature("Error(string)", "Counter: Revert operation"));
ENTRYPOINT.handleOps(userOps, payable(BOB.addr));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,11 @@ contract TestERC4337Account_AddDeposit is NexusTest_Base {
defaultMaxPercentDelta
);
}

/// @notice Tests that the addDeposit function reverts if calling the wrong entryPoint.
function test_AddDeposit_RevertIf_WrongEntryPoint() public {
vm.etch(address(0x0000000071727De22E5E9d8BAf0edAc6f37da032), address(VALIDATOR_MODULE).code);
vm.expectRevert();
BOB_ACCOUNT.addDeposit{ value: defaultDepositAmount }();
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import "../../../utils/Imports.sol";
import "../../../utils/NexusTest_Base.t.sol";

/// @title TestERC4337Account_OnlyEntryPointOrSelf
Expand All @@ -22,7 +21,7 @@ contract TestERC4337Account_OnlyEntryPointOrSelf is NexusTest_Base {
}

/// @notice Tests execution of user operations from a non-EntryPoint address, expecting failure.
function test_ExecuteUserOp_Invalid_FromNonEntryPoint() public {
function test_RevertIf_ExecuteUserOp_FromNonEntryPoint() public {
startPrank(ALICE.addr);
Execution[] memory execution = new Execution[](1);
execution[0] = Execution(address(BOB_ACCOUNT), 0, "");
Expand All @@ -33,6 +32,14 @@ contract TestERC4337Account_OnlyEntryPointOrSelf is NexusTest_Base {
stopPrank();
}

/// @notice Tests installation of a module from an unauthorized address, expecting failure.
function test_RevertIf_InstallModuleFromUnauthorized() public {
startPrank(address(ALICE_ACCOUNT));
vm.expectRevert(abi.encodeWithSelector(AccountAccessUnauthorized.selector));
BOB_ACCOUNT.installModule(MODULE_TYPE_EXECUTOR, address(EXECUTOR_MODULE), "");
stopPrank();
}

/// @notice Tests installation of a module from the EntryPoint.
function test_InstallModuleFromEntryPoint_Success() public {
startPrank(address(ENTRYPOINT));
Expand All @@ -44,6 +51,7 @@ contract TestERC4337Account_OnlyEntryPointOrSelf is NexusTest_Base {
function test_InstallModuleFromSelf_Success() public {
startPrank(address(BOB_ACCOUNT));
BOB_ACCOUNT.installModule(MODULE_TYPE_EXECUTOR, address(EXECUTOR_MODULE), "");
stopPrank();
}

/// @notice Tests uninstallation of a module from a non-EntryPoint or self address, expecting failure.
Expand All @@ -65,6 +73,7 @@ contract TestERC4337Account_OnlyEntryPointOrSelf is NexusTest_Base {
function test_WithdrawDepositFromSelf_Success() public {
startPrank(address(BOB_ACCOUNT));
BOB_ACCOUNT.withdrawDepositTo(BOB.addr, 0.5 ether);
stopPrank();
}

/// @notice Tests withdrawal of deposit from an unauthorized address, expecting failure.
Expand Down
Loading
Loading