@runonflux/aa-schnorr-multisig-sdk
v1.5.0
Published
Account Abstraction Schnorr Multi-Signatures SDK
Readme
Account Abstraction Schnorr Multi Signatures SDK
A typescript library for creating ERC-4337 Account Abstraction which utilizes Schnorr Signatures for multi signatures.
About
Current library provide utilities to sign/send User Operation's with Schnorr Signer. Alchemy Account Kit used to send User Operations. To better understand usage of library go to Examples section.
⚠️ Critical Information
Public Nonces
Never reuse public nonces. Reusing them will cryptographically expose your private keys and lead to a loss of funds. Implement robust nonce management in your application is crucial for security, make sure to delete nonce after usage and never use it again.
The SDK's own guard is in memory only (keyed by the public nonce) and is lost on a restart. Give the signer a persistent burned-nonce ledger and sign with the *Async methods, which check the ledger and persist the burn before the partial signature is computed:
const signer = createSchnorrSigner(privKey, {
nonceStore: {
isNonceBurned: async (kPublicHex) => burnedSet.has(kPublicHex),
markNonceBurned: async (kPublicHex) => persistBurn(kPublicHex), // resolve only once stored
},
})
await signer.restorePubNoncesAsync(k, kTwo)
const partial = await signer.signMultiSigHashAsync(opHash, publicKeys, publicNonces)
// with a MultiSigUserOp (records the partial signature on the op only on success)
await multiSigUserOp.signMultiSigHashAsync(signer)With a nonceStore configured, the synchronous signMultiSigHash / signMultiSigMsg (and MultiSigUserOp.signMultiSigHash) throw, so switch every signing call to the async variant when you adopt the store. Without a store, the synchronous methods behave exactly as before. Verify co-signers' partial signatures with Schnorrkel.verifyPartialSignatureHash (or sum them with Schnorrkel.sumVerifiedSigsHash) before combining them.
Owner lists
Owner (combined-address) lists are validated before an address or initCode is computed from them: no zero address, no duplicates, and at most 255 entries (MultiSigSmartAccount.initialize uses a uint8 loop counter). The combination helpers refuse inputs that would produce more than 255 combinations.
Salts
Construction of multisignature address uses salts. Ensure salts are deterministic and consistent to maintain cross-wallet compatibility. Usage of different salts will lead to different multisignature address. Use the following salts that are used by SSP Wallet:
accountSalt:aasaltfactorySalt:aafactorysalt
📦 Installation
Install via npm:
npm install @runonflux/aa-schnorr-multisig-sdkOr clone the repository:
git clone https://github.com/RunOnFlux/account-abstraction.git
cd account-abstraction/aa-schnorr-multisig-sdk
npm i🛠️ Usage
To get started, explore our examples and documentation. Ensure you have a .env file configured with the necessary environment variables as shown in .env.sample.
Examples
🐛 Reporting Issues
Found a bug? Please report it on our issue tracker.
📜 License
This project is licensed under the MIT License.
🌐 Associated Packages
SSP Wallet
SSP Wallet is a multi-signature multi-asset wallet that uses this AA Schnorr Multi-Signature SDK for EVM chains. Check out the SSP Wallet repository for more information and proper usage of the library
Inspiration, Credits & Acknowledgements
- This library is based on Borislav Itskov research and draws inspiration from the schnorrkel.js implementation.
- Account Abstraction ERC4337 eth-infinitism/account-abstraction
Security Audits
The smart contracts and SDK underwent a comprehensive security audit by Halborn finalised in February 2025.
Audit Reports
📄 Smart Contracts Audit
📄 SDK Audit
- Halborn Audit Report – SDK (GitHub)
- Halborn Public Report – SDK (Halborn)
Findings & Notes
- Smart Contracts: All findings were in unused code, which has been removed in the
mainbranch. Contracts were redeployed, and themainbranch is recommended for production whilemasterbranch is an archive where audits were assessed and perfectly safe to continue using. (Fix PR) - SDK: All important findigs were addressed in the
mainbranch. Be noted that examples are using hard coded values, furthermore this library requires proper nonce management on the client side, and following a strict error-throwing approach. (Fix PR)
