Multisig wallets with Safe
Create and operate EVM multisig Safe accounts with owner approvals and ERC-4337 submission.
Use @tetherto/wdk-wallet-multisig-safe to propose transactions, collect owner signatures, and submit approved Safe operations through an ERC-4337 bundler. This documentation covers 1.0.0-beta.2.
The Safe holds assets; each owner controls a separate signer account. An owner signature is one approval, not permission to spend alone when the threshold requires more owners.
To use an external signer, pass its compatible EVM owner account to the account constructor. The supplied account remains caller-owned when the Safe account is disposed.
| Task | Start here |
|---|---|
| Connect an owner to an existing Safe | Get started |
| Create a Safe from owners and a threshold | Deploy a Safe |
| Propose, approve and submit a payment | Manage proposals |
| Change owners or the threshold | Manage owners |
| Collect and verify message signatures | Sign messages |
| Share proposals between owners | Coordinate approvals |
Integration Requirements
- An EVM RPC and bundler on the same chain. Beta.2 uses Safe modules 0.2.0 and defaults to EntryPoint v0.6. The single-owner ERC-4337 wallet uses different configuration; do not copy its module version into this package.
- An existing compatible Safe, or a predicted Safe with an agreed owner list and threshold.
- A Safe Transaction Service endpoint/API key or a custom coordinator that all owners use.
- A fee mode: native coins, sponsored operations, or a supported paymaster token. Deploying a new Safe through this package still needs native gas in the deploying owner's EOA.
Submission and Confirmation
executeProposal() returns a UserOperation hash after bundler submission. An auto-executing proposal can report status: 'executed' at this point, before inclusion. Confirm the UserOperation receipt and its success before treating a payment as complete. Proposal reads depend on coordinator data and do not replace receipts.
This module provides proposal APIs rather than a direct sendTransaction() or transfer() flow. Its inherited normalized transaction lookup is not implemented in beta.2. Use the documented receipt lookup.