Skip to content
Merged
Changes from all commits
Commits
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
68 changes: 62 additions & 6 deletions src/account/Safe/SafeMultiChainSigAccount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,41 @@ import type {
} from "./types";

/**
* Safe account variant that supports multi-chain signatures via Merkle trees:
* sign UserOperations for multiple chains under one signature on EntryPoint v0.9.
* Safe account on EntryPoint v0.9. Use it as a regular single-chain Safe
* account, and opt into multi-chain signatures via Merkle trees when you want
* to sign UserOperations for several chains under one signature.
*
* API-compatible with {@link SafeAccountV0_3_0}: same {@link SafeAccount} base,
* same method signatures, same {@link InitCodeOverrides} shape, so building on
* EntryPoint v0.9 is not a separate integration. The multi-op methods
* ({@link signUserOperations}, {@link signUserOperationsWithSigners}) and the
* Merkle-root EIP-712 helpers are additive; ignore them and the account
* behaves as a single-chain Safe.
*
* Which account this class refers to, however, is not interchangeable with
* `SafeAccountV0_3_0`:
*
* - **New accounts** derive a different counterfactual address for the same
* owners, since the module and EntryPoint addresses feed that derivation.
* - **Deployed accounts** keep the address they have, but must be migrated
* before this class can operate on them. Attaching this class to a Safe
* deployed through `SafeAccountV0_3_0` is not enough: two pieces of Safe
* configuration have to change first — the v0.9 module must be enabled on
* the Safe, and the Safe's fallback handler must be updated to point at it.
* Until both land, UserOperations sent to the account will fail. Use
* {@link SafeAccountV0_3_0.createMigrateToSafeMultiChainSigAccountV1MetaTransactions},
* whose batch must be sent as a UserOperation from the v0.7 account itself.
*
* @example Single-chain use — the common case
* ```ts
* const account = SafeMultiChainSigAccountV1.initializeNewAccount([owner]);
* const userOp = await account.createUserOperation([tx], nodeRpc, bundlerRpc);
* userOp.signature = await account.signUserOperationWithSigners(
* userOp,
* [signer],
* chainId,
* );
* ```
*
* Uses Safe Passkey module v0.2.1 WebAuthn verifiers by default (Daimo P256
* verifier instead of the base class's FCL P256).
Expand Down Expand Up @@ -81,6 +114,12 @@ export class SafeMultiChainSigAccountV1 extends SafeAccount {

/**
* Create a SafeMultiChainSigAccount instance for an existing or new account.
*
* An existing account must already have the v0.9 module enabled, and its
* fallback handler pointing at that module. A Safe deployed through
* {@link SafeAccountV0_3_0} has neither until it is migrated — see the
* class documentation.
*
* @param accountAddress - the Safe account address
* @param overrides - optional overrides for module, entrypoint, and singleton addresses
*/
Expand Down Expand Up @@ -575,7 +614,16 @@ export class SafeMultiChainSigAccountV1 extends SafeAccount {
}

/**
* create a useroperation signature
* Create a signature for a single UserOperation. This is the regular
* signing path — use it for ordinary single-chain transactions. To sign
* several UserOperations under one signature, use
* {@link signUserOperations}.
*
* The multi-chain flag is set automatically, which only affects how the
* signature is encoded: this account's module validates single-chain
* UserOperations through the same scheme, signing the leaf SafeOp hash
* directly rather than a Merkle root.
*
* @param useroperation - useroperation to sign
* @param privateKeys - for the signers
* @param chainId - target chain id
Expand Down Expand Up @@ -610,10 +658,18 @@ export class SafeMultiChainSigAccountV1 extends SafeAccount {
}

/**
* Sign a single UserOperation for multi-chain using one or more
* {@link ExternalSigner} instances. See
* Sign a single UserOperation using one or more {@link ExternalSigner}
* instances. This is the regular signing path — use it for ordinary
* single-chain transactions. See
* {@link SafeAccountV0_3_0.signUserOperationWithSigners} for the full
* design rationale. Sets the multi-chain flag automatically.
* design rationale.
*
* The multi-chain flag is set automatically, which only affects how the
* signature is encoded: this account's module validates single-chain
* UserOperations through the same scheme, signing the leaf SafeOp hash
* directly rather than a Merkle root. Signing several UserOperations under
* one signature is a separate method,
* {@link signUserOperationsWithSigners}.
*
* Note the chainId plumbing asymmetry vs the multi-op variant:
* - **Singular** (this method): `chainId` is a positional argument.
Expand Down
Loading