Smart Accounts
SimpleAccount deployment, address derivation, and UserOperation construction
Smart Accounts
The SimpleAccount class implements ERC-4337 compliant smart contract accounts. The MPC-derived EOA serves as the owner of the smart account, and addresses are determined before deployment through counterfactual derivation.
EOA Address Derivation
The wallet's primary identity begins as an EOA derived from the distributedly generated public key using standard Ethereum protocol.
The derivation logic (src/wallet/address-derivation.ts):
- Strip existing
0xor04prefixes from the public key string - Validate the resulting hex string represents a valid 64-byte uncompressed key
- Apply Keccak-256 hashing to raw key bytes
- Take the last 20 bytes (40 hex characters) of the hash
- Apply EIP-55 checksum encoding to the resulting address
Key Functions
| Function | Description |
|---|---|
deriveEOAAddress(publicKey) | Converts MPC public key to EVM address |
checksumAddress(address) | Implements EIP-55 for mixed-case checksums |
isValidAddress(address) | Validates 20-byte Ethereum address format |
Smart Account Address Derivation
Smart account addresses are counterfactual (determined before deployment) and depend on:
factoryAddress-- TheSimpleAccountFactorycontract addressownerAddress-- The MPC-derived EOAsalt-- A deterministic constant (typically 0)
The SDK retrieves this address by calling the getAddress function on the factory contract via RPC call:
address = factory.getAddress(owner, salt)The account contract does not need to be deployed on-chain until the first transaction. The deployment cost is included automatically in the first UserOperation via initCode.
UserOperation Construction
The buildUserOperation Method
Building a UserOperation involves six stages:
- Encoding CallData -- Converts
TransactionRequestobjects intoexecuteorexecuteBatchcalldata - Deployment Check -- Checks if the contract is deployed; generates
initCodeif not - Nonce Management -- Retrieves current nonce from EntryPoint contract
- Gas Estimation -- Communicates with the bundler to estimate gas limits
- Paymaster Integration -- If configured, requests
paymasterAndDatato sponsor fees - Dummy Signature -- Initially populates the
signaturefield with a dummy value for accurate gas estimation
UserOperation Hash
The computeUserOpHash method packs operation fields and hashes them with the entryPointAddress and chainId. This hash is what gets signed by the MPC protocol.
Function Selectors
| Constant | Value | Purpose |
|---|---|---|
EXECUTE_SELECTOR | b61d27f6 | Standard execute(address, uint256, bytes) |
EXECUTE_BATCH_SELECTOR | 18dfb3c7 | Standard executeBatch(address[], uint256[], bytes[]) |
CREATE_ACCOUNT_SELECTOR | 5fbfb9cf | Factory method createAccount(address, uint256) |
GET_ADDRESS_SELECTOR | 8cb84e18 | Factory method getAddress(address, uint256) |
Source Files
src/__tests__/address-derivation.test.ts-- Test vectors and usage examplessrc/aa/simple-account.ts-- SimpleAccount implementation with selector definitionssrc/wallet/address-derivation.ts-- Address derivation logic