Lux Standard

Smart Account Factory

Deploy and manage smart account instances

Smart Account Factory

The factory contract for deploying smart accounts with deterministic addresses (CREATE2).

SmartAccountFactory

import "@luxfi/standard/src/eoa/contracts/smart-account/factory/SmartAccountFactory.sol";

Functions

deployCounterFactualAccount

Deploy a new smart account with deterministic address.

function deployCounterFactualAccount(
    address moduleSetupContract,
    bytes calldata moduleSetupData,
    uint256 index
) external returns (address proxy);

Parameters:

  • moduleSetupContract: Initial module setup contract
  • moduleSetupData: Initialization data for modules
  • index: Salt for address derivation

Returns:

  • proxy: Deployed smart account address

deployAccount

Deploy a new smart account.

function deployAccount(
    address moduleSetupContract,
    bytes calldata moduleSetupData
) external returns (address proxy);

getAddressForCounterFactualAccount

Compute the address of a smart account before deployment.

function getAddressForCounterFactualAccount(
    address moduleSetupContract,
    bytes calldata moduleSetupData,
    uint256 index
) external view returns (address _account);

Address Derivation

Smart account addresses are deterministic based on:

address = keccak256(
    0xff,
    factoryAddress,
    salt,           // keccak256(moduleSetupContract, moduleSetupData, index)
    initCodeHash    // Hash of proxy creation code
)

This enables:

  • Pre-computing addresses before deployment
  • Receiving funds before account exists
  • Counterfactual account deployment

Usage

Deploy New Account

SmartAccountFactory factory = SmartAccountFactory(FACTORY_ADDRESS);

// Setup data for ECDSA module
bytes memory setupData = abi.encodeWithSignature(
    "initForSmartAccount(address)",
    ownerAddress
);

// Deploy with index 0
address account = factory.deployCounterFactualAccount(
    ecdsaModule,
    setupData,
    0
);

Pre-compute Address

// Get address before deployment
address futureAccount = factory.getAddressForCounterFactualAccount(
    ecdsaModule,
    setupData,
    0
);

// Send funds to the future address
payable(futureAccount).transfer(1 ether);

// Later, deploy the account
address account = factory.deployCounterFactualAccount(
    ecdsaModule,
    setupData,
    0
);

// account == futureAccount

Deploy via UserOperation

// Include initCode in UserOperation for deployment
UserOperation memory userOp = UserOperation({
    sender: futureAccountAddress,
    nonce: 0,
    initCode: abi.encodePacked(
        factoryAddress,
        abi.encodeWithSignature(
            "deployCounterFactualAccount(address,bytes,uint256)",
            ecdsaModule,
            setupData,
            0
        )
    ),
    callData: abi.encodeWithSignature(
        "execute(address,uint256,bytes)",
        target, value, data
    ),
    // ... rest of UserOp
});

Events

event AccountCreation(
    address indexed account,
    address indexed initialAuthModule,
    uint256 indexed index
);

Security

  • Factory is immutable after deployment
  • Implementation address is fixed
  • Only authorized bundlers can deploy via EntryPoint
  • Salt prevents address collision

On this page