Skip to content

Commit

Permalink
Feat/sma 828 fuzz invariant tests (#67)
Browse files Browse the repository at this point in the history
* chore: update .solhintignore to exclude contracts/mocks directory

* lint fix

* test: add test for AccountFactory deployment consistency

* chore: Add test for ERC4337Account deposit balance consistency

* invariant test for ERC4337Account ValidateUserOp invariant

* add TestInvariant_ModuleManager to test module management functionality

* test: add fuzz test for AccountFactory deployment

* chore: Add fuzz tests for ERC4337Account and ModuleManager

* Lint fix SmartAccountTestLab.t.sol for readability

* chore: Refactor test setup for Foundry invariant testing

* chore: Add InvariantModuleManagementHandler for module installation and uninstallation tests

* chore: Update solhint npm dependency to version 5.0.0

* Update solhint npm dependency to version 5.0.0

* Add ExecutionInvariantTests contract for testing execution-related invariants

* Add AccountInvariantTests contract for testing account creation invariants

* chore: Add InvariantModuleManagementHandler for module installation and uninstallation tests

* chore: Add InvariantExecutionHandler for testing execution-related invariants

* chore: Add InvariantDepositManagementHandler for testing deposit-related invariants

* feat: Add InvariantAccountCreationHandler for testing account creation invariants

* Add BaseInvariantTest contract for foundational test setup

* chore: Add TestInvariantNexus contract for testing invariant consistency

* Add TestInvariantExecutor contract for testing invariant execution

* Add TestInvariantExecutionHelper contract for testing authorized executor invariants

* feat: Add TestInvariantBaseAccount contract for testing base account invariants

* chore: Refactor TestInvariant_ModuleManager.t.sol for improved readability and consistency

* feat: Refactor TestInvariant_ERC4337Account_ValidateUserOp for improved readability and consistency

* chore: Add ActorManager contract for coordinating test actions across different actors

* feat: Refactor TestInvariant_AccountFactory_Deployment.t.sol for improved readability and consistency

* Refactor TestInvariant_ERC4337Account_DepositBalance.t.sol for improved readability and consistency

* Import IExecutor and MockToken contracts for testing

* 🔥 remove unused test files

* 🔥 Remove unused test files

* Refactor test files for improved readability and consistency

* Add Tests + Invariants + Refactor test files for improved readability and consistency

* BaseInvariantTest.t.sol for improved testing

* ✅ add Handlers for Invariantstest files

* ✅ Add ActorManager for invariant testing

* chore: Update solhint dependency to version 5.0.1

* 🔥 remove unused tests

* Refactor ActorManager test file

* Refactor AccountCreationHandler test file

* Add fuzz testing on TestFuzz_ValidateUserOp contract

* feat: Add TestFuzz_ExecuteFromExecutor contract for fuzz testing

* chore: Exclude VALIDATOR_MODULE in AccountValidateUserOpInvariantTests setup

* refactor: Improve test file structure and naming conventions

* refactor: Update TestAccountFactory_CreateAndGetCounterFactualAddress.t.sol

* refactor: Add fuzz testing for ERC4337Account withdrawal and signature validation

* refactor: Add execute fuzz testing with mocks

* ✅ add fuzz testing on module manager + edge cases

* ✅ add new Uninstall test cases

* refactor: Improve isContract function in Helpers.sol and testFuzz_TokenTransfer in TestFuzz_Execute.t.sol

* refactor: Fix formatting

* 🖼️ fix lint + reorder

* 📄 update Natspec security message

* refactor: Fix module msg installation test case

* chore: Update .solcover.js to skip "contracts/mocks" file in code coverage

* chore: Add hardhat-foundry plugin for Nexus project

* chore: Update post-checkout hook to include forge install command

* chore: Update comment.js to include details in a collapsible section

* chore: Update slither-action to v0.4.0 and node-version to 20

* Rename variable to remove shadowed var

* 🔥 remove unused variables in Nexus.sol

* chore: Add defender.config.json for contract inspector configuration

* ⚙️Update slither-action to exclude additional checks in ci.yml

* 🚀 gas optimization: Improve execution mode decoding in Nexus.sol

* 🔥 Remove unused delegate functions in ExecutionHelper.sol

* chore: Update BaseAccount.sol header comments

* Update ModuleManager.sol slither fix

* Add check for non-zero address slither fix

* chore: Add error handling for zero implementation address

* Add IValidator interface to K1Validator contract - slither fix

* use assertTrue for balance check

* lint fix

* add tests validate user operation from entry point

* add accesscontrol+unauthorized access tests

* refactor: add InvalidSignature error to EventsAndErrors.sol

* add tests cases + fix wrong asserts

* chore: Update deployment account funding amount in test

* Remove unnecessary code in TestERC4337Account_ValidateUserOp.t.sol

* add test for validation of user operation nonce

* Merge branch 'dev' of https://github.com/bcnmy/erc7579-modular-smart-account into dev

* 🖼️ Refactor project architecture / and rename files

* chore: Remove unused functions, improve comments and formatting in CheatCodes.sol

* chore: Update account balance initialization with default method

* chore: Update contract deployment and account labeling in Helpers.sol with default method

* Renamed preparePackedUserOperation to buildPackedUserOperation for consistancy

* Refactor project architecture and rename functions

* Update function name from preparePackedUserOperation to buildPackedUserOperation for consistency

* move functions to helpers

* Refactor helpers and rename functions

* chore: Refactor code and update function names for consistency

* Refactor NexusTest contract and update function names for consistency

* Refactor NexusTest contract and update function names for consistency

* Refactor Imports.sol and update import statement for TestHelper.t.sol

* Refactor SmartAccountTestLab contract and remove unused code

* Refactor imports and update test contracts for consistency

* Refactor NexusTest_Base contract and remove unused code

* Refactor code and remove unused imports and functions

* ✅ fix solc warning compiler

* ✅ Refactor code add negative tests

* chore: Refactor code and update function names for consistency

* Refactor code and add prefunding for smart account in TestFuzz_ValidateUserOp.t.sol

* Refactor code and remove inline comments

* Refactor code and improve inline comments

* Refactor code and improve inline comments add additional tests

* Refactor code, add natspecs, and improve inline comments in InvariantBaseTest contract

* Refactor AccountCreationHandlerTest contract, improve comments, and add validation for account creation

* Refactor DepositManagementHandlerTest contract, improve comments, and update Solidity version to ^0.8.0

* feat: Add ExecutionHandlerTest contract for executing operations on Nexus account and add natspec

* add natspecs

* feat: Add test for AccountDepositBalanceInvariantTest

* refactor: Improve comments and update Solidity version in AccountValidateUserOpInvariantTest

* chore: Update BaseAccountInvariantTest with natspec comments and improve code readability

* chore: Refactor ExecutorInvariantTest for improved code readability and maintainability

* refactor: Improve comments and update natspec in ModuleManagerInvariantTest

* refactor: Improve comments and update natspec in NexusInvariantTest

* refactor: Update TestAccountExecution_Base contract with natspec comments and improve code readability

* refactor: Update TestModuleManagement_Base contract with natspec comments and improve code readability

* refactor: Improve comments and update natspec in TestAccountConfig_AccountId.t.sol

* refactor: Improve comments and update natspec in TestAccountConfig_SupportsExecutionMode.t.sol

* refactor: Improve comments and update natspec in TestAccountExecution_TryExecuteSingle.t.sol

* refactor: Improve comments and update natspec

* renamed file

* refactor: Add missing events and update natspec

* refactor: Update Solidity version to 0.8.24 in multiple files

* refactor: improve and categorize events and errors

* add check on onUninstall hook

* fix test on invariants and fuzz

* fix test on invariants and fuzz

* fix invariant by adding check for installed module in onInstall function

* refactor: Skip precompiles in testFuzz_WithdrawDepositTo function

* fix warning and remove unused variables

* remove empty file

* add accountImplementationAddress test on ArbitrumSmartAccountUpgradeTest

* refactor: Add getImplementation function to IBiconomySmartAccountV2 interface

* refactor: Add UpgradeSmartAccountTest to test smart account implementation upgrade

* refactor: Rename tests

* refactor: Improve UpgradeSmartAccountTest with additional tests

* refactor: Exclude FACTORY contract from BaseAccountInvariantTest

* refactor: Exclude unnecessary contracts from AccountDepositBalanceInvariantTest setup

* fix invariant by ensuring signer has enough ether before adding deposit

* Renamed .t.sol test files + Exclude unnecessary contracts from NexusInvariantTest setup

* refactor: Add givenTheAccountConfiguration modifier to TestAccountConfig_AccountId

* add .tree to comply with BTT testing

* Update Solidity version to >=0.8.0 <0.9.0

* Chore/remove unused funcs (#77)

* refactor: Remove onlyValidatorModule modifier from ModuleManager.sol

* refactor: Add test cases for unsupported call types in TestAccountExecution_ExecuteSingle

* refactor: Update MockExecutor to support tryExecuteViaAccount and customExecuteViaAccount methods

* feat: Add MockInvalidModule contract for testing purposes

* refactor: Update MockExecutor to support tryExecuteViaAccount and customExecuteViaAccount methods

* refactor: Update TestAccountExecution_ExecuteFromExecutor.tree with descriptive test cases

* refactor: Update TestAccountExecution_ExecuteSingle.t.sol with more descriptive test cases

* refactor: Update TestAccountExecution_ExecuteSingle.tree with descriptive test cases for unsupported call types

* refactor: Add test case for installing a module as an invalid module type ID

* refactor: Add test case for installing a module with an invalid module type ID

* refactor: Update Imports.sol to import MockInvalidModule for testing purposes

* refactor: Update EventsAndErrors.sol to add error messages for unsupported module and call types

* Improve Natspecs in invariants

* ⚠️ fix compiler warning

* ⚠️ fix compilers / lint warnings

* 🖼️ lint fix

* chore: Update foundry-gas-diff workflow to continue on error

* chore: Skip posting comment if Slither report is empty

* chore: add warning comment on privatekey

* chore: Update CI workflow to include ARBITRUM_RPC_URL environment variable

* chore: Update ArbitrumSmartAccountUpgradeTest to use environment variable for RPC URL

* chore: Update ArbitrumSettings with default Arbitrum RPC URL

---------

Co-authored-by: livingrockrises <[email protected]>
  • Loading branch information
Aboudjem and livingrockrises committed May 21, 2024
1 parent 6a0ff5d commit 80c968d
Show file tree
Hide file tree
Showing 145 changed files with 5,002 additions and 1,906 deletions.
5 changes: 2 additions & 3 deletions .github/scripts/comment.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,13 @@ module.exports = async ({ github, context, header, body }) => {
## :robot: Slither Analysis Report :mag_right:
${uniqueSlitherHeader}
<details>
${header}
${processedBody}
</details>
_This comment was automatically generated by the GitHub Actions workflow._
`;

// Check if the workflow is triggered by a pull request event
if (!context.payload.pull_request) {
console.log(
Expand Down
17 changes: 12 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ jobs:

- name: Run Forge and Hardhat Tests
run: yarn test
env:
ARBITRUM_RPC_URL: ${{ secrets.ARBITRUM_RPC_URL }}

coverage:
needs: setup
Expand All @@ -106,14 +108,16 @@ jobs:

- name: Generate Hardhat & Foundry Coverage Report
run: yarn coverage:report
env:
ARBITRUM_RPC_URL: ${{ secrets.ARBITRUM_RPC_URL }}

- name: Upload Foundry Coverage Report to Codecov
uses: codecov/[email protected]
with:
file: ./coverage/foundry/lcov.info
flags: foundry
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

- name: Upload Hardhat Coverage Report to Codecov
uses: codecov/[email protected]
Expand All @@ -130,14 +134,13 @@ jobs:
uses: actions/checkout@v4

- name: Run Slither
uses: crytic/slither-action@v0.3.1
uses: crytic/slither-action@v0.4.0
id: slither
with:
slither-version: "0.10.0"
node-version: "18"
node-version: "20"
fail-on: "none"
slither-args: '--exclude assembly --exclude solc-version --filter-paths "contracts/mock|node_modules" --checklist --markdown-root ${{ github.server_url }}/${{ github.repository }}/blob/${{ github.sha }}/contracts/'

slither-args: '--exclude "assembly|solc-version|low-level-calls|naming-convention|write-after-write|divide-before-multiply|incorrect-shift" --exclude-informational --exclude-low --filter-paths "contracts/mock|node_modules" --checklist --markdown-root ${{ github.server_url }}/${{ github.repository }}/blob/${{ github.sha }}/contracts/'
- name: Create/update checklist as PR comment
uses: actions/github-script@v7
env:
Expand All @@ -147,4 +150,8 @@ jobs:
const script = require('.github/scripts/comment')
const header = '# Slither report'
const body = process.env.REPORT
if (!body.trim()) {
console.log("Slither report is empty. No comment will be posted.");
return;
}
await script({ github, context, header, body })
5 changes: 4 additions & 1 deletion .github/workflows/foundry-gas-diff.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ jobs:
# make fuzzing semi-deterministic to avoid noisy gas cost estimation
# due to non-deterministic fuzzing (but still use pseudo-random fuzzing seeds)
FOUNDRY_FUZZ_SEED: 0x${{ github.event.pull_request.base.sha || github.sha }}
ARBITRUM_RPC_URL: ${{ secrets.ARBITRUM_RPC_URL }}
continue-on-error: true

- name: Compare gas reports
uses: Rubilmax/[email protected]
Expand All @@ -46,7 +48,8 @@ jobs:
sortOrders: desc,asc # and directions
ignore: test-foundry/**/* # filter out gas reports from specific paths (test/ is included by default)
id: gas_diff

continue-on-error: true

- name: Add gas diff to sticky comment
if: github.event_name == 'pull_request' || github.event_name == 'pull_request_target'
uses: marocchino/[email protected]
Expand Down
2 changes: 1 addition & 1 deletion .solcover.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module.exports = {
skipFiles: ["test", "lib/ModuleTypeLib", "test/utils", "/mocks"],
skipFiles: ["test", "lib/ModuleTypeLib", "test/utils", "/mocks", "contracts/mocks"],
};
74 changes: 39 additions & 35 deletions contracts/Nexus.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pragma solidity ^0.8.24;
//
// ──────────────────────────────────────────────────────────────────────────────
// Nexus: A suite of contracts for Modular Smart Account compliant with ERC-7579 and ERC-4337, developed by Biconomy.
// Learn more at https://biconomy.io. For security issues, contact: [email protected]
// Learn more at https://biconomy.io. To report security issues, please contact us at: [email protected]

import { UUPSUpgradeable } from "solady/src/utils/UUPSUpgradeable.sol";
import { EIP712 } from "solady/src/utils/EIP712.sol";
Expand Down Expand Up @@ -48,8 +48,7 @@ contract Nexus is INexus, EIP712, BaseAccount, ExecutionHelper, ModuleManager, U
bytes32 private constant _MESSAGE_TYPEHASH = keccak256("BiconomyNexusMessage(bytes32 hash)");

/// @dev `keccak256("PersonalSign(bytes prefixed)")`.
bytes32 internal constant _PERSONAL_SIGN_TYPEHASH =
0x983e65e5148e570cd828ead231ee759a8d7958721a768f93bc4483ba005c32de;
bytes32 internal constant _PERSONAL_SIGN_TYPEHASH = 0x983e65e5148e570cd828ead231ee759a8d7958721a768f93bc4483ba005c32de;

/// @notice Initializes the smart account by setting up the module manager and state.
constructor() {
Expand All @@ -75,9 +74,9 @@ contract Nexus is INexus, EIP712, BaseAccount, ExecutionHelper, ModuleManager, U
uint256 missingAccountFunds
) external virtual payPrefund(missingAccountFunds) onlyEntryPoint returns (uint256 validationData) {
address validator;
uint256 nonce = userOp.nonce;
uint256 userOpnonce = userOp.nonce;
assembly {
validator := shr(96, nonce)
validator := shr(96, userOpnonce)
}
// Check if validator is not enabled. If not, return VALIDATION_FAILED.

Expand All @@ -93,7 +92,7 @@ contract Nexus is INexus, EIP712, BaseAccount, ExecutionHelper, ModuleManager, U
/// @dev This function handles transaction execution flexibility and is protected by the `onlyEntryPointOrSelf` modifier.
/// @dev This function also goes through hook checks via withHook modifier.
function execute(ExecutionMode mode, bytes calldata executionCalldata) external payable onlyEntryPointOrSelf withHook {
(CallType callType, ExecType execType, , ) = mode.decode();
(CallType callType, ExecType execType) = mode.decodeBasic();
if (callType == CALLTYPE_SINGLE) {
_handleSingleExecution(executionCalldata, execType);
} else if (callType == CALLTYPE_BATCH) {
Expand All @@ -120,7 +119,7 @@ contract Nexus is INexus, EIP712, BaseAccount, ExecutionHelper, ModuleManager, U
bytes[] memory returnData // TODO returnData is not used
)
{
(CallType callType, ExecType execType, , ) = mode.decode();
(CallType callType, ExecType execType) = mode.decodeBasic();

// check if calltype is batch or single
if (callType == CALLTYPE_SINGLE) {
Expand Down Expand Up @@ -174,6 +173,7 @@ contract Nexus is INexus, EIP712, BaseAccount, ExecutionHelper, ModuleManager, U
if (_isModuleInstalled(moduleTypeId, module, initData)) {
revert ModuleAlreadyInstalled(moduleTypeId, module);
}
emit ModuleInstalled(moduleTypeId, module);
if (moduleTypeId == MODULE_TYPE_VALIDATOR) {
_installValidator(module, initData);
} else if (moduleTypeId == MODULE_TYPE_EXECUTOR) {
Expand All @@ -185,7 +185,6 @@ contract Nexus is INexus, EIP712, BaseAccount, ExecutionHelper, ModuleManager, U
} else {
revert InvalidModuleTypeId(moduleTypeId);
}
emit ModuleInstalled(moduleTypeId, module);
}

/// @notice Uninstalls a module from the smart account.
Expand All @@ -203,12 +202,12 @@ contract Nexus is INexus, EIP712, BaseAccount, ExecutionHelper, ModuleManager, U
if (!_isModuleInstalled(moduleTypeId, module, deInitData)) {
revert ModuleNotInstalled(moduleTypeId, module);
}
emit ModuleUninstalled(moduleTypeId, module);
if (moduleTypeId == MODULE_TYPE_VALIDATOR) _uninstallValidator(module, deInitData);
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);
emit ModuleUninstalled(moduleTypeId, module);
}

/// @notice Initializes the smart account with a validator.
Expand Down Expand Up @@ -259,11 +258,10 @@ contract Nexus is INexus, EIP712, BaseAccount, ExecutionHelper, ModuleManager, U
/// @param mode The execution mode to evaluate.
/// @return isSupported True if the execution mode is supported, false otherwise.
function supportsExecutionMode(ExecutionMode mode) external view virtual returns (bool isSupported) {
(CallType callType, ExecType execType, , ) = mode.decode();
(CallType callType, ExecType execType) = mode.decodeBasic();

// Return true if both the call type and execution type are supported.
return (callType == CALLTYPE_SINGLE || callType == CALLTYPE_BATCH)
&& (execType == EXECTYPE_DEFAULT || execType == EXECTYPE_TRY);
return (callType == CALLTYPE_SINGLE || callType == CALLTYPE_BATCH) && (execType == EXECTYPE_DEFAULT || execType == EXECTYPE_TRY);
}

/// @notice Determines whether a module is installed on the smart account.
Expand All @@ -275,6 +273,17 @@ contract Nexus is INexus, EIP712, BaseAccount, ExecutionHelper, ModuleManager, U
return _isModuleInstalled(moduleTypeId, module, additionalContext);
}

/// @dev EIP712 hashTypedData method.
function hashTypedData(bytes32 structHash) external view returns (bytes32) {
return _hashTypedData(structHash);
}

/// @dev EIP712 domain separator.
// solhint-disable func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32) {
return _domainSeparator();
}

/// Returns the account's implementation ID.
/// @return The unique identifier for this account implementation.
function accountId() external pure virtual returns (string memory) {
Expand Down Expand Up @@ -307,9 +316,7 @@ contract Nexus is INexus, EIP712, BaseAccount, ExecutionHelper, ModuleManager, U
/// @dev Ensures that only authorized callers can upgrade the smart contract implementation.
/// This is part of the UUPS (Universal Upgradeable Proxy Standard) pattern.
/// @param newImplementation The address of the new implementation to upgrade to.
function _authorizeUpgrade(address newImplementation) internal virtual override(UUPSUpgradeable) onlyEntryPointOrSelf {
newImplementation;
}
function _authorizeUpgrade(address newImplementation) internal virtual override(UUPSUpgradeable) onlyEntryPointOrSelf {}

/// @notice Returns the EIP-712 typed hash of the `BiconomyNexusMessage(bytes32 hash)` data structure.
///
Expand Down Expand Up @@ -392,12 +399,10 @@ contract Nexus is INexus, EIP712, BaseAccount, ExecutionHelper, ModuleManager, U
/// you can choose a more minimalistic signature scheme like
/// `keccak256(abi.encode(address(this), hash))` instead of all these acrobatics.
/// All these are just for widespread out-of-the-box compatibility with other wallet clients.
function _erc1271HashForIsValidSignatureViaNestedEIP712(bytes32 hash, bytes calldata signature)
internal
view
virtual
returns (bytes32, bytes calldata)
{
function _erc1271HashForIsValidSignatureViaNestedEIP712(
bytes32 hash,
bytes calldata signature
) internal view virtual returns (bytes32, bytes calldata) {
assembly {
// Unwraps the ERC6492 wrapper if it exists.
// See: https://eips.ethereum.org/EIPS/eip-6492
Expand All @@ -418,7 +423,11 @@ contract Nexus is INexus, EIP712, BaseAccount, ExecutionHelper, ModuleManager, U
let m := mload(0x40) // Cache the free memory pointer.
// Length of the contents type.
let c := and(0xffff, calldataload(add(signature.offset, sub(signature.length, 0x20))))
for {} 1 {} {
for {

} 1 {

} {
let l := add(0x42, c) // Total length of appended data (32 + 32 + c + 2).
let o := add(signature.offset, sub(signature.length, l))
calldatacopy(0x20, o, 0x40) // Copy the `DOMAIN_SEP_B` and contents struct hash.
Expand All @@ -438,9 +447,15 @@ contract Nexus is INexus, EIP712, BaseAccount, ExecutionHelper, ModuleManager, U
let d := byte(0, mload(p)) // For denoting if the contents name is invalid.
d := or(gt(26, sub(d, 97)), eq(40, d)) // Starts with lowercase or '('.
// Store the end sentinel '(', and advance `p` until we encounter a '(' byte.
for { mstore(add(p, c), 40) } 1 { p := add(p, 1) } {
for {
mstore(add(p, c), 40)
} 1 {
p := add(p, 1)
} {
let b := byte(0, mload(p))
if eq(40, b) { break }
if eq(40, b) {
break
}
d := or(d, shr(b, 0x120100000001)) // Has a byte in ", )\x00".
}
mstore(p, " contents,bytes1 fields,string n")
Expand Down Expand Up @@ -472,16 +487,6 @@ contract Nexus is INexus, EIP712, BaseAccount, ExecutionHelper, ModuleManager, U
version = "0.0.1";
}

/// @dev EIP712 hashTypedData method.
function hashTypedData(bytes32 structHash) external view returns (bytes32) {
return _hashTypedData(structHash);
}

/// @dev EIP712 domain separator.
function DOMAIN_SEPARATOR() external view returns (bytes32) {
return _domainSeparator();
}

/// @dev Executes a single transaction based on the specified execution type.
/// @param executionCalldata The calldata containing the transaction details (target address, value, and data).
/// @param execType The execution type, which can be DEFAULT (revert on failure) or TRY (return on failure).
Expand All @@ -508,7 +513,6 @@ contract Nexus is INexus, EIP712, BaseAccount, ExecutionHelper, ModuleManager, U
/// @param additionalContext Additional context for checking installation.
/// @return True if the module is installed, false otherwise.
function _isModuleInstalled(uint256 moduleTypeId, address module, bytes calldata additionalContext) private view returns (bool) {
additionalContext;
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);
Expand Down
43 changes: 1 addition & 42 deletions contracts/base/ExecutionHelper.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pragma solidity ^0.8.24;
//
// ──────────────────────────────────────────────────────────────────────────────
// Nexus: A suite of contracts for Modular Smart Account compliant with ERC-7579 and ERC-4337, developed by Biconomy.
// Learn more at https://biconomy.io. For security issues, contact: [email protected]
// Learn more at https://biconomy.io. To report security issues, please contact us at: [email protected]

import { Execution } from "../types/DataTypes.sol";
import { IExecutionHelperEventsAndErrors } from "../interfaces/base/IExecutionHelper.sol";
Expand Down Expand Up @@ -95,45 +95,4 @@ contract ExecutionHelper is IExecutionHelperEventsAndErrors {
if (!success) emit TryExecuteUnsuccessful(i, result[i]);
}
}

/// @notice Executes a delegatecall on this contract.
/// @param delegate The address to delegatecall to.
/// @param callData The calldata to send.
/// @return result The bytes returned from the delegatecall.
function _executeDelegatecall(address delegate, bytes calldata callData) internal returns (bytes memory result) {
/// @solidity memory-safe-assembly
assembly {
result := mload(0x40)
calldatacopy(result, callData.offset, callData.length)
// Forwards the `data` to `delegate` via delegatecall.
if iszero(delegatecall(gas(), delegate, result, callData.length, codesize(), 0x00)) {
// Bubble up the revert if the call reverts.
returndatacopy(result, 0x00, returndatasize())
revert(result, returndatasize())
}
mstore(result, returndatasize()) // Store the length.
let o := add(result, 0x20)
returndatacopy(o, 0x00, returndatasize()) // Copy the returndata.
mstore(0x40, add(o, returndatasize())) // Allocate the memory.
}
}

/// @notice Tries to execute a delegatecall and captures if it was successful or not.
/// @param delegate The address to delegatecall to.
/// @param callData The calldata to send.
/// @return success True if the delegatecall was successful, false otherwise.
/// @return result The bytes returned from the delegatecall.
function _tryExecuteDelegatecall(address delegate, bytes calldata callData) internal returns (bool success, bytes memory result) {
/// @solidity memory-safe-assembly
assembly {
result := mload(0x40)
calldatacopy(result, callData.offset, callData.length)
// Forwards the `data` to `delegate` via delegatecall.
success := iszero(delegatecall(gas(), delegate, result, callData.length, codesize(), 0x00))
mstore(result, returndatasize()) // Store the length.
let o := add(result, 0x20)
returndatacopy(o, 0x00, returndatasize()) // Copy the returndata.
mstore(0x40, add(o, returndatasize())) // Allocate the memory.
}
}
}
Loading

0 comments on commit 80c968d

Please sign in to comment.