Leave with one key. Enter with many.
Baradd is a treasury wallet for Soroban smart accounts. One operator can pull funds out of a DeFi position and back to the treasury; adding risk takes more signatures. The rule is enforced on-chain.
github.com/bleu/baradd-rolesIllustrative scenario
- 03:12
A stablecoin starts to lose its peg.
- 03:14
The operator on call exits with one signature, and the funds return to the treasury.
- 03:40
Anything new waits for three approvals.
| Setup | Signatures to exit | Signatures to enter |
|---|---|---|
| A classic 2-of-3 multisig | 2 | 2 |
| Baradd's example policy | 1 | 3 |
Source: Stellar docs, multisig.
Try to move the treasury
Simulated in your browser. Not a live treasury. A testnet version is coming.
Who signs
What they try to do
Result
EXIT needs 1 signature; 0 counted.
0 of 1 required
EXIT rule
How it works
1 signature
M signatures
N of M
Evaluation, in order
- 1Read the call: which contract, which function, which arguments.
- 2Find the contract on the rule's list — if it isn't there, deny.
- 3Find the function on that contract's list — if it isn't there, deny.
- 4Check every condition on the arguments — if one fails, deny.
- 5Allow, and nothing else.
A failure at any step denies the whole call. There is no other path to approval.
What a policy looks like
Real example from examples/defindex-exit.toml in the repository. Addresses are placeholders — they stay visibly placeholders.
# Illustrative only — CDEFINDEX/GOPERATOR* are placeholders, not real
# deployed addresses. See docs/spec.md, "Week 1", item 3: the exact function
# names and arguments still need verifying against a real DeFindex testnet
# transaction before this is used for anything but a CLI demo.
[account]
address = "CTREASURYACCOUNT"
[[rule]]
name = "exit-defindex"
mode = "exit"
threshold = 1
signers = ["GOPERATOR1", "GOPERATOR2"]
[[rule.target]]
contract = "CDEFINDEXVAULT"
label = "DeFindex vault"
[[rule.target.fn]]
name = "withdraw"
[[rule.target.fn.cond]]
op = "eq_self"
arg = 0
In plain language
- One operator (of 2 possible signers) may call withdraw on the DeFindex vault.
- Argument 0 of that call must equal the account's own address — the funds can only return to the treasury.
- Anything else — a different function, a different contract, a different destination — is denied.
Tooling
Real terminal output, run against the example files in this repository.
$ roles lint examples/defindex-exit.toml
✓ examples/defindex-exit.toml: no findings.$ roles diff examples/defindex-entry.toml examples/defindex-entry-widened.toml
+ [widening] rule[entry-defindex]
threshold changed from 2 to 1.
+ [widening] rule[entry-defindex].target[DeFindex vault].fn[deposit]
range on arg 1 widened to [0, 5000000000000] (was [0, 500000000000]).
2 change(s), 2 widening permissions.Coming
roles simulate— needs a Soroban RPC endpoint (or a local fork) and a deployed roles-policy instance.roles apply— needs a deployed roles-policy contract address and Smart Account Kit transaction helpers.
Why not the alternatives
Each approach solves part of the problem. We found none that makes the entry/exit asymmetry easy for a treasury team — sourced and dated 2 November 2026; the search was broad, not exhaustive.
Classic Stellar multisigLOBSTR Vault, Stellar Stratum
Strength: Native, simple, widely supported
Gap for entry vs. exit: One threshold per operation category
Source: Stellar docs, multisig, as of November 2026.
Contract-level rules in smart accountsOpenZeppelin stellar-accounts, Smart Account Kit
Strength: Framework with signers, thresholds, and spending limits; had an external audit of its RC v0.7.0
Gap for entry vs. exit: Rules scope by contract address, not function or arguments (per that audit)
Source: RC v0.7.0 audit, as of November 2026.
Policy librariesPerch, Mandate, Policywright
Strength: Function and argument constraints; reviewable policy documents; policy generation
Gap for entry vs. exit: Libraries and toolchains, not treasury wallets; maturity varies (Perch calls itself design phase)
Source: Perch README, as of November 2026.
Treasury applicationsVaultDAO, Smart Treasury Account (an SCF submission)
Strength: Roles, timelocks, spending limits, and payment workflows for organizations
Gap for entry vs. exit: We found no entry/exit semantics for DeFi positions
Source: VaultDAO, as of November 2026.
Protocol-level rolesDeFindex vault roles (Manager, Emergency Manager, Rebalance Manager), Templar vault roles
Strength: Emergency exit roles built into the protocol
Gap for entry vs. exit: Exist only where each protocol builds them, and differ per protocol
Source: DeFindex vault contract, as of November 2026.
MPC custody with policy enginesFireblocks, Dfns, BitGo
Strength: Mature operations, approval workflows
Gap for entry vs. exit: Policy is enforced off-chain by the vendor
Source: Fireblocks: contract call method rules, as of November 2026.
Safe with Zodiac Roles (Ethereum)The model asset managers use on Ethereum
Strength: Scoped permissions per contract, function, and argument
Gap for entry vs. exit: Not on Stellar
Source: reference point, not an equivalence claim, as of November 2026.
Security and status
| Component | State today |
|---|---|
| contracts/roles-policy | Implemented against OpenZeppelin's stellar-accounts 0.8.0; 14 tests (11 unit, 3 property-based); builds to Wasm. |
| @baradd/sdk and @baradd/cli: lint, diff | Real, offline, work on local TOML files. |
| @baradd/cli: simulate, apply | Honest stubs that explain what infrastructure they need. |
| frontend | Next.js UI over illustrative data in mock-data.ts: treasury dashboard, ADMIN/EXIT/ENTRY rule cards, plain-language policy viewer; Freighter connect is read-only. |
| Fork, fuzz and invariant tests; CI | Not added yet. |
| External audit | None. Soroban Audit Bank eligibility is unconfirmed. |
| Protocol presets | None verified; candidates are unverified. |
| Testnet and mainnet deployments | None. |
| Users, design partners, traction | None confirmed. |
| License | MIT |
Who it's for
Asset managers
You run positions across several Stellar DeFi protocols for a fund or a client treasury.
One operator can pull out of a losing position immediately; adding a new position needs the rest of the desk to sign off.
DAO treasuries
Your treasury holds tokens deployed into lending or liquidity protocols, decided by governance.
A delegate on call can retreat from a protocol in trouble with one key; entering a new protocol still needs the multisig the DAO already trusts.
RWA issuers
You manage on-chain reserves backing a tokenized asset and need to move fast if a counterpart protocol is compromised.
Reserve funds can exit to the issuer's own treasury with one signature; nothing new can be approved without the full signer set.
Roadmap
No dates. “Planned” only.
Done
- Policy contract (roles-policy), implemented and tested
- CLI: roles lint and roles diff
- Wallet UI shell over demo data
Next
- Testnet deployment and the four demo cases, on real transactions
- Verified protocol presets
- Fork, fuzz, and invariant tests, with CI
Later
- External audit
- Mainnet deployment
- Timelocks and per-period caps
- A policy review interface
Frequently asked
Follow the build
The code is open.
