The 2-of-3 Model
A fully set up Zhentan wallet has three owners and a threshold of 2:
Your two keys meet the threshold — so the agent is an advisory speed bump, not a gatekeeper. If it ever blocks something you want (or disappears entirely), you can execute from app.safe.global with your embedded + backup keys and go around it.
Two hard invariants, enforced server-side on every proposal:
- The agent never reaches the threshold alone — it cannot move funds without you.
- The agent never signs a transaction it didn’t screen — when screening is off, your own keys must meet the threshold and the agent only relays.
Wallet Profiles
Profiles are computed from the live owner set and threshold — never stored. Every wallet is exactly one of:Transitions
All transitions are hard-validated owner-management SafeTxs on the same address — your Safe address never changes:
Every account keeps an immutable creation snapshot (creation owners, threshold, salt nonce, derivation version — frozen by a database trigger), so its address stays re-derivable forever even after transitions rewrite the live owner set.
Transaction Flow
Every user transaction is a standard Safe transaction (EIP-712 SafeTx) — visible and actionable in the official Safe app at every stage: Key properties:- The agent relays and pays gas. Users never need BNB — the agent EOA submits
execTransactionon-chain. - Rejections never leave nonce holes. Every proposal pre-signs a same-nonce empty cancel transaction, so a rejection consumes the nonce cleanly and later proposals aren’t blocked.
- The Safe app is a first-class surface. A sync worker reconciles transactions confirmed or executed directly from app.safe.global — the override path is fully supported, not an afterthought.
Relay-Only Execution
Whenever your own signatures meet the threshold, the agent contributes no signature — it only submits the transaction and pays gas:- Starter (threshold 1): your signature alone.
- Protected with screening off: your embedded + backup signatures.
Screening Off: Queue and Co-Sign
In a Protected wallet you can pause screening. Your transactions then need both of your keys:- You propose and sign as usual — the transaction queues at 1 of 2 and is mirrored to the Safe Transaction Service.
- Complete it whenever you like, from either surface:
- In-app — open the transaction in your history and tap Sign with [your backup wallet]. If the backup wallet isn’t connected, the app walks you through a signature-free connection first. The agent then relay-executes.
- Safe app — confirm with your backup key at app.safe.global; Zhentan’s sync worker picks up the execution automatically.
Address Derivation
Safe addresses are derived server-side only, through a versioned registry:
The client never derives locally — it asks
GET /users/by-signer (returning users) or POST /safe/derive (new users, with their chosen profile). Owner order for derivation is canonical [embedded, backup, agent]; deployed Safes read their live owner set from chain. Derivation runs once at account creation; the frozen creation snapshot keeps every address auditable and re-derivable — the server ships safe:verify-derivations to re-derive and check every account.
Safes are deployed eagerly at onboarding (the agent pays deployment gas), because the Safe Transaction Service only indexes deployed Safes.