Soroban Smart Accounts
Soroban's host-managed authorization model enables programmable spending policy enforcement without agent key custody — the cryptographic foundation of REAPP's safety guarantee.
The Key Custody Problem
When a contract calls require_auth() on a contract account, the Soroban host calls __check_auth with a signature payload plus the list of invocations being authorized — enabling flexible custom authorization policies. The __check_auth function is reserved and only callable through host-managed auth, making certain policy designs inherently safer.
Authorization Flow
MandateRegistry Contract Interface
#[contract]
pub struct MandateRegistry;
#[contractimpl]
impl MandateRegistry {
// Register a new mandate (called by user or their smart wallet)
pub fn register_mandate(env: Env, mandate: MandateConfig) -> MandateId;
// Called by REAPP validator before payment execution
pub fn validate_and_consume(
env: Env,
mandate_id: MandateId,
amount: i128,
token: Address,
merchant: Address
) -> Result<(), Error>;
// Agent-triggered payment within mandate bounds
pub fn execute_payment(
env: Env,
mandate_id: MandateId,
to: Address,
amount: i128,
token: Address
) -> Result<TxHash, Error>;
// Revoke a mandate (user only)
pub fn revoke_mandate(env: Env, mandate_id: MandateId);
}MandateConfig Structure
#[contracttype]
pub struct MandateConfig {
pub user: Address, // mandate owner
pub agent: Address, // authorized agent key
pub token: Address, // USDC, XLM, or any SEP-41 token
pub per_tx_limit: i128, // max per transaction
pub period_limit: i128, // max per time period
pub period_ledgers: u32, // period length in ledgers
pub allowed_merchants: Vec<Address>, // empty = any
pub expiry_ledger: u32, // mandate TTL
pub intent_hash: BytesN<32>, // AP2 IntentMandate hash (audit link)
}The MandateConfig fields above define the enforcement surface, but the specific values used in the testnet MVP (e.g., per_tx_limit, period_limit, period_ledgers, expiry_ledger) are illustrative defaults. Production deployments will require tuning based on real usage patterns — appropriate spending limits, period lengths, and expiry windows depend on the agent use case, merchant category, and user risk tolerance. These parameters are user-configured per mandate, not protocol-fixed.
Storage Architecture
OpenZeppelin Smart Account Integration
REAPP builds on OpenZeppelin's Stellar smart account framework, which supports delegated signers and policy/rule composition. OpenZeppelin has published audits for its Stellar contracts library — meaning REAPP inherits audited building blocks even before its own mandate registry undergoes review.
- Delegated signers scoped to specific contract functions and amounts
- Policy signer registered for
execute_paymentonly — not general wallet access - Time-window constraints enforced at the Smart Account layer
- Revocation propagates immediately — no pending transaction window
The OZ Smart Account framework adds three primitives: Context Rules (what actions are permitted), Signers (who can act — passkeys, ed25519, secp256k1, BLS, RSA), and Policies (how permissions are enforced — threshold multisig, spending limits, sessions, time-based restrictions). For consumer onboarding, smart wallets support passkey authentication via WebAuthn — users authenticate with device biometrics instead of seed phrases.
Agent Spending Authorization via Smart Wallet
The key UX pattern for REAPP — how an AI agent gets limited spending authorization from a smart wallet:
- User creates smart wallet via passkey (one biometric tap)
- User adds AI agent as Ed25519 signer with restricted SignerLimits
- Agent signs with its Ed25519 key;
__check_authenforces limits automatically - For amounts exceeding limits, the primary passkey signer must co-sign
- Using
SignerStore.Temporarymeans the agent's authorization auto-expires
// Add AI agent as restricted signer on smart wallet
const agentLimits = new Map([
['CBIELTK6YBZJU5UP2WWQEUCYKLPU6AUNZ2BQ4WWFEIE3USCIHMXQDAMA', undefined], // USDC contract only
]);
await account.addEd25519(agentPublicKey, agentLimits, SignerStore.Temporary);Stellar Wallets Kit
Stellar Wallets Kit (by Creit Technologies) provides the unified wallet adapter. v2 migrated from npm to JSR — the package is now @creit-tech/stellar-wallets-kit on JSR. Supports Freighter, LOBSTR (via WalletConnect), xBull, Albedo, Hana, Rabet, HOT, and Bitget. Used by Stellar Lab, Blend Capital, FxDAO, and Soroban Domains.
import { StellarWalletsKit } from "@creit-tech/stellar-wallets-kit/sdk";
import { defaultModules } from '@creit-tech/stellar-wallets-kit/modules/utils';
StellarWalletsKit.init({ modules: defaultModules() });
const { address } = await StellarWalletsKit.getAddress();
const { signedTxXdr } = await StellarWalletsKit.signTransaction(tx.toXDR(), {
networkPassphrase: Networks.PUBLIC, address,
});Fee Sponsorship — OZ Relayer Channels
LaunchTube was archived on March 9, 2026. The migration target is the OpenZeppelin Relayer with Channels Plugin. Fee bump sponsorship via the relayer means agent clients need zero XLM.
| Dimension | Freighter | Smart Wallet |
|---|---|---|
| Audience | Developers, DeFi traders | Mainstream consumers |
| Auth | Browser extension + seed phrase | Device biometrics |
| Account type | Classic G-account (ed25519) | Soroban smart wallet (C-account) |
| Onboarding | Install extension → backup seed | Tap → biometric → done |
| Programmability | Standard account | Custom auth, spending limits, policies |
| Fee handling | User pays own fees | Relayer sponsors fees |
Both can coexist — smart wallets support multiple signer types. A single app can offer "Connect Wallet" (Freighter / Wallets Kit) alongside "Sign in with Passkey" for the consumer path.