Rust SDK
The ZeroDev Rust SDK is part of the Omni SDK — a single Zig core shipped with first-class bindings for Rust, Swift, Kotlin, Go, Python, and C. Published to crates.io as zerodev-aa. The crate's build.rs auto-downloads precompiled native libraries from GitHub Releases — no Zig toolchain required to build. It supports smart-account creation, signing, sponsored transactions, and EIP-7702 delegation on any EVM chain.
Install
cargo add zerodev-aaOr add to Cargo.toml directly:
[dependencies]
zerodev-aa = "0.0.1-alpha.2"Setup
use zerodev_aa::{Context, Signer, KernelVersion, GasMiddleware, PaymasterMiddleware};
let ctx = Context::new(
project_id,
"", // RPC URL (empty → derive from project_id)
"", // Bundler URL (empty → derive from project_id)
11155111, // Sepolia
GasMiddleware::ZeroDev,
PaymasterMiddleware::ZeroDev,
)?;
let signer = Signer::local(&private_key)?;
let account = ctx.new_account(&signer, KernelVersion::V3_3, 0)?;Signer::generate() is useful for demos when you don't need to reuse a key. All handles implement Drop — native resources are released automatically.
Example — sponsored UserOp
use zerodev_aa::{Context, Signer, Call, KernelVersion, GasMiddleware, PaymasterMiddleware};
let ctx = Context::new(project_id, "", "", 11155111,
GasMiddleware::ZeroDev, PaymasterMiddleware::ZeroDev)?;
let signer = Signer::local(&private_key)?;
let account = ctx.new_account(&signer, KernelVersion::V3_3, 0)?;
let recipient = /* 20-byte address */;
let hash = account.send_user_op(&[Call {
target: recipient,
value: [0u8; 32],
calldata: vec![],
}])?;
let receipt = account.wait_for_user_operation_receipt(&hash, 60, 2)?;
println!("Success: {}", receipt.success);
println!("Tx: {}", receipt.transaction_hash);Custom signers
Implement the SignerImpl trait to integrate any signing backend (Privy, HSM, MPC, custom keystore):
use zerodev_aa::{Signer, SignerImpl};
struct MySigner { /* ... */ }
impl SignerImpl for MySigner {
fn sign_hash(&self, hash: [u8; 32]) -> Result<[u8; 65], _> { todo!() }
fn sign_message(&self, msg: &[u8]) -> Result<[u8; 65], _> { todo!() }
fn sign_typed_data_hash(&self, hash: [u8; 32]) -> Result<[u8; 65], _> { todo!() }
fn get_address(&self) -> [u8; 20] { todo!() }
}
let signer = Signer::custom(MySigner { /* ... */ })?;EIP-7702 delegation
EIP-7702 lets an EOA delegate its code to a Kernel contract so its address is the smart-account address — no CREATE2, no init code, no index. The SDK signs an authorization tuple on the first UserOp and attaches it via the eip7702Auth field; subsequent ops skip the auth once delegation is installed on-chain.
let signer = Signer::generate()?; // fresh EOA
let account = ctx.new_account_7702(&signer, KernelVersion::V3_3)?;
// account.get_address()? == signer's EOA address
let hash = account.send_user_op(&[Call {
target: account.get_address()?,
value: [0u8; 32],
calldata: vec![],
}])?;Custom signers can override SignerImpl::sign_authorization (and set provides_sign_authorization() to return true) to sign EIP-7702 tuples natively. Otherwise the SDK falls back to hashing the tuple and calling sign_hash.