Skip to content
aboudjem edited this page Jun 7, 2024 · 3 revisions

Nexus

Git Source

Inherits: INexus, EIP712, BaseAccount, ExecutionHelper, ModuleManager, UUPSUpgradeable

This contract integrates various functionalities to handle modular smart accounts compliant with ERC-7579 and ERC-4337 standards.

Comprehensive suite of methods for managing smart accounts, integrating module management, execution management, and upgradability via UUPS.

Table of Contents

State Variables

_MESSAGE_TYPEHASH

*Precomputed typeHash used to produce EIP-712 compliant hash when applying the anti cross-account-replay layer. The original hash must either be:

  • An EIP-191 hash: keccak256("\x19Ethereum Signed Message:\n" || len(someMessage) || someMessage)
  • An EIP-712 hash: keccak256("\x19\x01" || someDomainSeparator || hashStruct(someStruct)*
bytes32 private constant _MESSAGE_TYPEHASH = keccak256("BiconomyNexusMessage(bytes32 hash)");

Important

This precomputed typeHash ensures that messages adhere to EIP-712 standards, providing a secure way to handle anti cross-account-replay measures.

_SELF

address private immutable _SELF;

Note

The _SELF variable stores the address of the contract itself. This is immutable and set at deployment, ensuring consistency and security in the contract's identity.

_PERSONAL_SIGN_TYPEHASH

keccak256("PersonalSign(bytes prefixed)").

bytes32 internal constant _PERSONAL_SIGN_TYPEHASH = 0x983e65e5148e570cd828ead231ee759a8d7958721a768f93bc4483ba005c32de;

Caution

The _PERSONAL_SIGN_TYPEHASH is crucial for handling personal sign requests securely, adhering to EIP-712 standards to prevent signature replays.

Functions

constructor

Initializes the smart account with the specified entry point.

constructor(address anEntryPoint);

validateUserOp

Validates a user operation against a specified validator, extracted from the operation's nonce. The entryPoint calls this only if validation succeeds. Fails by returning VALIDATION_FAILED for invalid signatures. Other validation failures (e.g., nonce mismatch) should revert.

Expects the validator's address to be encoded in the upper 96 bits of the userOp's nonce. This method forwards the validation task to the extracted validator module address.

function validateUserOp(
    PackedUserOperation calldata userOp,
    bytes32 userOpHash,
    uint256 missingAccountFunds
)
    external
    virtual
    payPrefund(missingAccountFunds)
    onlyEntryPoint
    returns (uint256 validationData);

Parameters

Name Type Description
userOp PackedUserOperation The operation to validate, encapsulating all transaction details.
userOpHash bytes32 Hash of the operation data, used for signature validation.
missingAccountFunds uint256 Funds missing from the account's deposit necessary for transaction execution. This can be zero if covered by a paymaster or sufficient deposit exists.

Returns

Name Type Description
validationData uint256 Encoded validation result or failure, propagated from the validator module. - Encoded format in validationData: - First 20 bytes: Validator address, 0x0 for valid or specific failure modes. - SIG_VALIDATION_FAILED (1) denotes signature validation failure allowing simulation calls without a valid signature.

Warning

Ensure that the validator's address is correctly encoded in the nonce to prevent validation failures.

execute

Executes transactions in single or batch modes as specified by the execution mode.

This function handles transaction execution flexibility and is protected by the onlyEntryPointOrSelf modifier.

This function also goes through hook checks via withHook modifier.

function execute(ExecutionMode mode, bytes calldata executionCalldata) external payable onlyEntryPointOrSelf withHook;

Parameters

Name Type Description
mode ExecutionMode The execution mode detailing how transactions should be handled (single, batch, default, try/catch).
executionCalldata bytes The encoded transaction data to execute.

Note

This function's flexibility allows for handling various transaction execution strategies, making it versatile for different use cases.

executeFromExecutor

Executes transactions from an executor module, supporting both single and batch transactions.

This function is callable only by an executor module and goes through hook checks.

function executeFromExecutor(
    ExecutionMode mode,
    bytes calldata executionCalldata
)
    external
    payable
    onlyExecutorModule
    withHook
    returns (bytes[] memory returnData);

Parameters

Name Type Description
mode ExecutionMode The execution mode (single or batch, default or try).
executionCalldata bytes The transaction data to execute.

Returns

Name Type Description
returnData bytes[] The results of the transaction executions, which may include errors in try mode.

Important

Only executor modules can call this function, ensuring that transaction execution is controlled and secure.

executeUserOp

Executes a user operation via a call using the contract's context.

Only callable by the EntryPoint. Decodes the user operation calldata, skipping the first four bytes, and executes the inner call.

function executeUserOp(PackedUserOperation calldata userOp, bytes32) external payable virtual onlyEntryPoint;

Parameters

Name Type Description
userOp PackedUserOperation The user operation to execute, containing transaction details.
<none> bytes32

Caution

This function should only be called by the EntryPoint to ensure the integrity of the user operation execution.

installModule

Installs a new module to the smart account.

This function can only be called by the EntryPoint or the account itself for security reasons.

This function also goes through hook checks via withHook modifier.

function installModule(uint256 moduleTypeId, address module, bytes calldata initData) external payable onlyEntryPointOrSelf withHook;

Parameters

Name Type Description
moduleTypeId uint256 The type identifier of the module being installed, which determines its role: - 1 for Validator - 2 for Executor - 3 for Fallback - 4 for Hook
module address The address of the module to install.
initData bytes Initialization data for the module.

Note

This function allows the installation of various types of modules (Validator, Executor, Fallback, Hook) to enhance the smart account's functionality.

uninstallModule

Uninstalls a module from the smart account.

Ensures that the operation is authorized and valid before proceeding with the uninstallation.

function uninstallModule(uint256 moduleTypeId, address module, bytes calldata deInitData) external payable onlyEntryPointOrSelf;

Parameters

Name Type Description
moduleTypeId uint256 The type ID of the module to be uninstalled, matching the installation type: - 1 for Validator - 2 for Executor - 3 for Fallback - 4 for Hook
module address The address of the module to uninstall.
deInitData bytes De-initialization data for the module.

Caution

Make sure to provide the correct module type ID and de-initialization data to avoid issues during the uninstallation process.

initializeAccount

Initializes the account with provided data.

function initializeAccount(bytes calldata initData) external payable virtual;

Important

This function should be called to set up the account with necessary initialization parameters.

isValidSignature

Validates a signature according to ERC-1271 standards.

Delegates the validation to a validator module specified within the signature data.

function isValidSignature(bytes32 hash, bytes calldata data) external view virtual override returns (bytes4);

Parameters

Name Type Description
hash bytes32 The hash of the data being validated.
data bytes Signature data that needs to be validated.

Returns

Name Type Description
<none> bytes4 The status code of the signature validation (0x1626ba7e if valid).

Note

This function ensures that the signature conforms to ERC-1271 standards, providing a robust mechanism for signature validation.

getImplementation

Retrieves the address of the current implementation from the EIP-1967 slot.

Checks the 1967 implementation slot, if not found then checks the slot defined by address (Biconomy V2 smart account).

function getImplementation() external view returns (address implementation);

Returns

Name Type Description
implementation address The address of the current contract implementation.

Important

This function is crucial for verifying the current implementation of the contract, ensuring the correct version is in use.

supportsModule

Checks if a specific module type is supported by this smart account.

function supportsModule(uint256 moduleTypeId) external view virtual returns (bool);

Parameters

Name Type Description
moduleTypeId uint256 The identifier of the module type to check.

Returns

Name Type Description
<none> bool True if the module type is supported, false otherwise.

Note

Use this function to verify if a certain type of module can be installed or used with this smart account.

supportsExecutionMode

Determines if a specific execution mode is supported.

function supportsExecutionMode(ExecutionMode mode) external view virtual returns (bool isSupported);

Parameters

Name Type Description
mode ExecutionMode The execution mode to evaluate.

Returns

Name Type Description
isSupported bool True if the execution mode is supported, false otherwise.

Important

Check the support for different execution modes to ensure compatibility with specific transaction types.

isModuleInstalled

Determines whether a module is installed on the smart account.

function isModuleInstalled(uint256 moduleTypeId, address module, bytes calldata additionalContext) external view returns (bool);

Parameters

Name Type Description
moduleTypeId uint256 The ID corresponding to the type of module (Validator, Executor, Fallback, Hook).
module address The address of the module to check.
additionalContext bytes Optional context that may be needed for certain checks.

Returns

Name Type Description
<none> bool True if the module is installed, false otherwise.

Note

Use this function to confirm if a particular module is currently active in the smart account.

hashTypedData

EIP712 hashTypedData method.

function hashTypedData(bytes32 structHash) external view returns (bytes32);

Important

This function helps in generating the EIP-712 compliant hash required for signature verification and replay protection.

DOMAIN_SEPARATOR

EIP712 domain separator.

function DOMAIN_SEPARATOR() external view returns (bytes32);

Note

The DOMAIN_SEPARATOR is essential for EIP-712 compliance, ensuring unique domain separation for the hashing process.

accountId

Returns the account's implementation ID.

function accountId() external pure virtual returns (string memory);

Returns

Name Type Description
<none> string The unique identifier for this account implementation.

Important

The account ID uniquely identifies the implementation, ensuring consistent behavior and identification across different instances.

upgradeToAndCall

Upgrades the contract to a new implementation and calls a function on the new contract.

Updates two slots:

  1. ERC1967 slot and
  2. address() slot in case if it's potentially upgraded earlier from Biconomy V2 account, as Biconomy v2 Account (proxy) reads implementation from the slot that is defined by its address.
function upgradeToAndCall(address newImplementation, bytes calldata data) public payable virtual override onlyEntryPointOrSelf;

Parameters

Name Type Description
newImplementation address The address of the new contract implementation.
data bytes The calldata to be sent to the new implementation.

Warning

Ensure that the new implementation address is valid and the calldata is properly structured to avoid issues during the upgrade process.

replaySafeHash

Wrapper around _eip712Hash() to produce a replay-safe hash from the given hash.

The returned EIP-712 compliant replay-safe hash is the result of: keccak256( \x19\x01 || this.domainSeparator || hashStruct(BiconomyNexusMessage({ hash: hash})) )

function replaySafeHash(bytes32 hash) public view virtual returns (bytes32);

Parameters

Name Type Description
hash bytes32 The original hash.

Returns

Name Type Description
<none> bytes32 The corresponding replay-safe hash.

Note

This function ensures that the hash is replay-safe, preventing replay attacks by generating a unique EIP-712 compliant hash.

_authorizeUpgrade

Ensures that only authorized callers can upgrade the smart contract implementation. This is part of the UUPS (Universal Upgradeable Proxy Standard) pattern.

function _authorizeUpgrade(address newImplementation) internal virtual override(UUPSUpgradeable) onlyEntryPointOrSelf;

Parameters

Name Type Description
newImplementation address The address of the new implementation to upgrade to.

Important

This function ensures that only authorized upgrades are performed, maintaining the integrity and security of the contract.

_eip712Hash

Returns the EIP-712 typed hash of the BiconomyNexusMessage(bytes32 hash) data structure.

Implements encode(domainSeparator : 𝔹²⁵⁶, message : 𝕊) = "\x19\x01" || domainSeparator || hashStruct(message).

See https://eips.ethereum.org/EIPS/eip-712#specification.

function _eip712Hash(bytes32 hash) internal view virtual returns (bytes32);

Parameters

Name Type Description
hash bytes32 The BiconomyNexusMessage.hash field to hash.

Returns

Name Type Description
<none> bytes32 The resulting EIP-712 hash.

Note

This function is crucial for generating EIP-712 compliant hashes used in signature verification, ensuring replay protection and data integrity.

_erc1271HashForIsValidSignatureViaNestedEIP712

ERC1271 signature validation (Nested EIP-712 workflow). This implementation uses a nested EIP-712 approach to prevent signature replays when a single signer owns multiple smart contract accounts, while still enabling wallet UIs (e.g. Metamask) to show the EIP-712 values. Crafted for phishing resistance, efficiency, flexibility.

function _erc1271HashForIsValidSignatureViaNestedEIP712(
    bytes32 hash,
    bytes calldata signature
)
    internal
    view
    virtual
    returns (bytes32, bytes calldata);

Parameters

Name Type Description
hash bytes32 The original hash to be validated.
signature bytes The signature data.

Returns

Name Type Description
<none> bytes32 The resulting EIP-712 hash.
<none> bytes calldata The remaining signature data.

Important

This function enhances security by preventing signature replays, even when a single signer controls multiple smart accounts.

_domainNameAndVersion

EIP712 domain name and version.

function _domainNameAndVersion() internal pure override returns (string memory name, string memory version);

Returns

Name Type Description
name string The domain name.
version string The domain version.

Note

This function provides the domain name and version for EIP-712 compliance, ensuring consistency across different uses.

_handleSingleExecution

Executes a single transaction based on the specified execution type.

function _handleSingleExecution(bytes calldata executionCalldata, ExecType execType) private;

Parameters

Name Type Description
executionCalldata bytes The calldata containing the transaction details (target address, value, and data).
execType ExecType The execution type, which can be DEFAULT (revert on failure) or TRY (return on failure).

Caution

Ensure the execution calldata and type are correctly specified to avoid unintended behavior during transaction execution.

_handleBatchExecution

Executes a batch of transactions based on the specified execution type.

function _handleBatchExecution(bytes calldata executionCalldata, ExecType execType) private;

Parameters

Name Type Description
executionCalldata bytes The calldata for a batch of transactions.
execType ExecType The execution type, which can be DEFAULT (revert on failure) or TRY (return on failure).

Important

Batch execution allows handling multiple transactions in one call, improving efficiency and reducing gas costs.

_isModuleInstalled

Checks if a module is installed on the smart account.

function _isModuleInstalled(uint256 moduleTypeId, address module, bytes calldata additionalContext) private view returns (bool);

Parameters

Name Type Description
moduleTypeId uint256 The module type ID.
module address The module address.
additionalContext bytes Additional context for checking installation.

Returns

Name Type Description
<none> bool True if the module is installed, false otherwise.

Note

Use this function to verify if a specific module is currently active within the smart account.

_typedDataSignFields

For use in _erc1271HashForIsValidSignatureViaNestedEIP712

function _typedDataSignFields() private view returns (bytes32 m);

Important

This function is used internally for EIP-712 signature validation, ensuring signatures are valid and secure.


Clone this wiki locally