Early prototype · testnet demo in progress

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-roles

Illustrative scenario

  1. 03:12

    A stablecoin starts to lose its peg.

  2. 03:14

    The operator on call exits with one signature, and the funds return to the treasury.

  3. 03:40

    Anything new waits for three approvals.

SetupSignatures to exitSignatures to enter
A classic 2-of-3 multisig22
Baradd's example policy13

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

Denied

EXIT needs 1 signature; 0 counted.

0 of 1 required

EXIT rule

How it works

Operators
Approvers
Governance
EXIT rule
1 signature
ENTRY rule
M signatures
ADMIN rule
N of M
Policy contract — checks every call against the rule
CLI prepares and verifies configurations before anyone signs

Evaluation, in order

  1. 1Read the call: which contract, which function, which arguments.
  2. 2Find the contract on the rule's list — if it isn't there, deny.
  3. 3Find the function on that contract's list — if it isn't there, deny.
  4. 4Check every condition on the arguments — if one fails, deny.
  5. 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

ComponentState today
contracts/roles-policyImplemented against OpenZeppelin's stellar-accounts 0.8.0; 14 tests (11 unit, 3 property-based); builds to Wasm.
@baradd/sdk and @baradd/cli: lint, diffReal, offline, work on local TOML files.
@baradd/cli: simulate, applyHonest stubs that explain what infrastructure they need.
frontendNext.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; CINot added yet.
External auditNone. Soroban Audit Bank eligibility is unconfirmed.
Protocol presetsNone verified; candidates are unverified.
Testnet and mainnet deploymentsNone.
Users, design partners, tractionNone confirmed.
LicenseMIT
Honest limit. If an operator key is stolen, the thief can only send funds back to the treasury — they cannot enter a position, approve a token, or change the rules. They can still force exits, which has a cost; per-period caps and delays are planned, not built.

Audit: planned, not started.

License: MIT.

Specification and validations log

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.