Repository navigation
·
100 commits
to master
since this release
Smaller installs
The library and the CLI are still two crates, and each one now compiles only what it uses:
cargo install safe-rs-cli --locked # the `safe` CLI, with Ledger support
cargo install safe-rs-cli --locked --no-default-features # without Ledger (no libusb)[dependencies]
safe-rs = "0.13" # with fork simulation
safe-rs = { version = "0.13", default-features = false } # without revm
safe-rs = { version = "0.13", features = ["hd-wallet"] } # + keystores and RotatingSafe| Feature | Default | Adds |
|---|---|---|
simulation |
yes | Fork simulation with revm: simulate() on the builders, ForkSession, simulate_exec* |
hd-wallet |
no | Encrypted mnemonic keystores, HD keys and RotatingSafe (implies simulation) |
ledger |
no | Owner keys on a Ledger (implies hd-wallet) |
Neither crate enables alloy's full or tokio's full any more, which dropped the WebSocket and IPC transports, pubsub and the anvil/txpool/debug provider APIs. A library build without default features compiles 242 crates instead of 331, without revm, c-kzg, blst or secp256k1-sys. Without simulation, the builders still execute(), with gas from eth_estimateGas, so a reverting call still fails before anything is broadcast.
Multi-owner Safes
SignedSafeTxholds several owners' signatures, sorted. New functions pack, unpack and recover them, and buildapproveHashcalldata.safe send,safe send --rotateandsafe rotateread the Safe's owners, threshold and on-chainapprovedHashes. They then pick one of:- collecting signatures offchain in a bundle file (
--bundle,--sign-only,--merge-bundle) - approving the hash on chain (
--approve-hash) - executing
- collecting signatures offchain in a bundle file (
- New library functions:
read_approved_owners,simulate_exec_with_threshold,simulate_approve_hashandOuterTxParams::approve_hash.
One-time owner keys
Every transaction can swap the Safe's owner for a fresh key, so the key that signed is no longer an owner once its signature is public.
- CLI:
safe send --rotate --hd-wallet <name>appends the swap and then moves the old key's ETH to the new one.safe rotatedoes the swap on its own, finds the Safe when you don't name one, and moves an existing Safe onto the wallet.safe create --hd-walletdeploys from a funding key, so the owner key has never signed anything.safe wallet new|import|list|address|status|sync|sweepmanage the encrypted phrase and the record of used keys.
- Library: the
hd-walletfeature addsRotatingSafe,HdWallet, encrypted keystores, and rebuilding the rotation state from on-chain owner events.
Ledger
- CLI:
--ledgertakes the owner keys from a Ledger, wherever--hd-walletis accepted. It uses the same derivation path, so a Ledger seeded with a phrase shares that phrase's state. It's a default feature of the CLI. - Library: the
ledgerfeature addsLedgerKeys. Safe transactions are now signed as EIP-712 typed data, which the device can display. For a local key the signatures are unchanged.
Safe v1.5.0
safe createdeploys v1.5.0 Safes by default. Pass--safe-version 1.4.1for the old version.- Owner rotation works on v1.5.0.
- Batches go through the MultiSend contracts of the Safe's own version (
ChainAddresses::for_version,detect_addresses).
Breaking changes
- safe-rs no longer turns on alloy's
fullfeature. If your code relied on it for WebSocket, IPC or the extra provider APIs, enable those on your ownalloydependency. CallBuilder::simulate,simulation_resultandsimulation_successexist only with thesimulationfeature, which is on by default.safe infotakes the Safe address as a positional argument, defaults to the signer's own Safe, and no longer readsSAFE_ADDRESS.SignedSafeTxholds a map of signatures instead of a single signature.
Fixes
execute()estimates gas itself, so a send that fails estimation no longer leaves the provider a nonce ahead with the next transaction stuck.- A batch whose MultiSend target has no code is refused before signing. That applies to
SafeBuilderand toRotatingSafe. Before, it looked successful while none of the calls ran. - The fork backend runs on the caller's runtime, so
simulate()followed by another call on the same provider can no longer hang. WalletBuilder::connect_with_configkeeps the configured contract addresses.- Every sweep still owed from an earlier key stays on record across later rotations.
- Deployment checks no longer fail on a stale read from another RPC node.
Full changelog: v0.12.0...v0.13.0