Skip to content

Latest commit

Β 

History

588 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

ACBU Soroban Smart Contracts

Soroban (Stellar) smart contracts for the ACBU (African Currency Basket Unit) stablecoin platform.

Contracts

  • Minting Contract (acbu_minting) β€” Converts USDC, fiat deposits, and S-token baskets into ACBU
  • Burning Contract (acbu_burning) β€” Redeems ACBU back to fiat currency or S-tokens
  • Oracle Contract (acbu_oracle) β€” Aggregates exchange rates from multiple validators
  • Reserve Tracker Contract (acbu_reserve_tracker) β€” Tracks and verifies reserve balances
  • Savings Vault Contract (acbu_savings_vault) β€” Interest-bearing savings accounts for ACBU
  • Lending Pool Contract (acbu_lending_pool) β€” Peer-to-peer ACBU lending
  • Escrow Contract (acbu_escrow) β€” Conditional and time-locked ACBU transfers
  • Multisig Contract (acbu_multisig) β€” M-of-N threshold authorization for admin actions

Architecture

The eight contracts are divided into three logical layers:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        USER / FRONTEND                          β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
             β”‚            β”‚          β”‚          β”‚
     β”Œβ”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β” β”Œβ–Όβ”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
     β”‚    Minting   β”‚ β”‚  Burning β”‚ β”‚ Savings β”‚ β”‚   Lending    β”‚
     β”‚   Contract   β”‚ β”‚ Contract β”‚ β”‚  Vault  β”‚ β”‚     Pool     β”‚
     β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
            β”‚              β”‚            β”‚              β”‚
            β”‚         β”Œβ”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
            β”‚         β”‚        Escrow Contract    β”‚   β”‚
            β”‚         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
            β”‚                                          β”‚
     β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”
     β”‚               INFRASTRUCTURE LAYER                      β”‚
     β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
     β”‚  β”‚  Oracle Contract  β”‚   β”‚  Reserve Tracker Contract β”‚  β”‚
     β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                             β”‚
     β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
     β”‚              SHARED / GOVERNANCE LAYER                   β”‚
     β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
     β”‚  β”‚   Multisig Contract    β”‚  β”‚   Shared Library     β”‚   β”‚
     β”‚  β”‚  (M-of-N admin auth)   β”‚  β”‚  (types, utilities)  β”‚   β”‚
     β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
     β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Data Flow

Minting Flow (USDC β†’ ACBU)

User
 β”‚
 β”‚  1. Transfer USDC to MintingContract vault
 β–Ό
MintingContract
 β”‚  2. Query ACBU/USD rate          ──────────────► OracleContract
 β”‚  3. Verify reserves sufficient   ──────────────► ReserveTrackerContract
 β”‚                                                       β”‚
 β”‚                                      4. Oracle rate β—„β”€β”˜
 β”‚  5. Calculate ACBU amount (rate Γ— USDC, minus fee)
 β”‚  6. Mint ACBU to user            ──────────────► ACBU Token Contract
 β”‚  7. Emit MintEvent
 β–Ό
User receives ACBU

Burning Flow (ACBU β†’ Fiat or S-tokens)

User
 β”‚
 β”‚  1. Transfer ACBU to BurningContract
 β–Ό
BurningContract
 β”‚  2. Query currency/USD rate      ──────────────► OracleContract
 β”‚  3. Verify reserves sufficient   ──────────────► ReserveTrackerContract
 β”‚  4. Burn ACBU from user          ──────────────► ACBU Token Contract
 β”‚  5a. S-token redemption:
 β”‚       transfer_from vault        ──────────────► S-Token Contract (vault allowance)
 β”‚  5b. Fiat redemption:
 β”‚       emit BurnEvent             ──────────────► Off-chain withdrawal processor
 β”‚  6. Emit BurnEvent
 β–Ό
User receives S-tokens or fiat (via backend)

Oracle Rate Update Flow

External Data Sources (e.g. Chainlink, Pyth, CEX APIs)
 β”‚
 β”‚  Each validator submits an independent rate
 β–Ό
OracleContract.update_rate()  (validator-gated, multisig-authorized)
 β”‚
 β”‚  1. Verify caller is a registered validator
 β”‚  2. Check update interval has elapsed
 β”‚  3. Store new rate from this validator
 β”‚  4. Compute median across β‰₯3 validator submissions
 β”‚  5. Outlier detection: reject if >3% deviation from median
 β”‚  6. Emergency path: if move >5%, require N-of-M validator consensus
 β”‚  7. Emit RateUpdateEvent (or EmergencyBypassEvent)
 β–Ό
Consumers: MintingContract, BurningContract, ReserveTrackerContract

Reserve Verification Flow

Admin / Custodian
 β”‚
 β”‚  1. Submit reserve attestation (Merkle proof of off-chain reserves)
 β–Ό
ReserveTrackerContract
 β”‚  2. Verify proof and custodian identity
 β”‚  3. Update reserve balances per currency
 β”‚  4. Cross-check value_usd against Oracle rates   ──► OracleContract
 β–Ό
MintingContract / BurningContract
 β”‚  5. Call is_sufficient() before each mint or burn
 β”‚     β†’ Ensures reserve_usd β‰₯ acbu_supply Γ— min_ratio
 β–Ό
Gate: transaction proceeds only if reserves are adequate

Savings Vault Flow

User
 β”œβ”€β–Ί deposit(amount)          ──► SavingsVault stores balance + timestamp
 β”œβ”€β–Ί lock(amount, term)       ──► SavingsVault records lock period, higher rate
 └─► withdraw(amount)         ──► SavingsVault calculates accrued interest,
                                   transfers principal + interest to user

Lending Pool Flow

Lender
 └─► deposit(amount)          ──► LendingPool records lender liquidity

Borrower + Lender (dual authorization)
 └─► borrow(lender, amount)   ──► LendingPool transfers ACBU to borrower,
                                   records LoanData (uncollateralized)

Borrower
 └─► repay(loan_id, amount)   ──► LendingPool transfers ACBU back,
                                   updates loan balance

Lender
 └─► withdraw(amount)         ──► LendingPool transfers principal + interest

Escrow Flow

Creator
 └─► create_escrow(beneficiary, amount, conditions)
          β”‚
          β–Ό
     EscrowContract holds ACBU
          β”‚
    β”Œβ”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚ Admin / condition met      β”‚ Admin cancels
    β–Ό                           β–Ό
release_escrow()          cancel_escrow()
    β”‚                           β”‚
    β–Ό                           β–Ό
Beneficiary receives ACBU   Creator refunded

Multisig Authorization Flow

Proposer (any signer)
 └─► propose(action, params)   ──► MultisigContract stores proposal + nonce

Signers (M-of-N required)
 └─► approve(proposal_id)      ──► MultisigContract records approvals

Any signer (once threshold met)
 └─► execute(proposal_id)      ──► MultisigContract dispatches admin action
                                    to target contract (e.g. add_validator,
                                    set_fee_rate, upgrade contract)

Contract Interaction Patterns

Cross-Contract Calls (Read)

Caller Callee Method Purpose
MintingContract OracleContract get_acbu_usd_rate ACBU/USD rate for mint calculation
MintingContract OracleContract get_rate Per-currency rate for basket mints
MintingContract ReserveTracker is_sufficient Reserve adequacy check before mint
BurningContract OracleContract get_rate Per-currency rate for burn payout
BurningContract ReserveTracker is_sufficient Reserve adequacy check before burn
ReserveTracker OracleContract get_rate Validate reserve value_usd integrity
ReserveTracker ACBU Token total_supply Compare supply against reserves

Cross-Contract Calls (Write / Token Transfers)

Caller Callee Action Direction
MintingContract ACBU Token mint(user, amount) Creates new ACBU
BurningContract ACBU Token burn(user, amount) Destroys ACBU
BurningContract S-Token Vault transfer_from(vault, user) Vault allowance pull model
MintingContract USDC Token receive deposit (push model) User pushes USDC in advance

Authorization Matrix

Contract Admin actions gated by Validator actions gated by
OracleContract Multisig (timelock) Validator allowlist
ReserveTracker Multisig (timelock) Custodian address
MintingContract Multisig (timelock) Operator address
BurningContract Multisig (timelock) n/a
SavingsVault Admin address n/a
LendingPool Admin address n/a
EscrowContract Admin address n/a
MultisigContract M-of-N signers n/a

Shared Library Dependencies

All contracts import from the shared crate:

shared/
β”œβ”€β”€ ContractError       β€” common error enum
β”œβ”€β”€ CurrencyCode        β€” currency type (e.g. "USD", "NGN")
β”œβ”€β”€ RateData            β€” oracle rate struct
β”œβ”€β”€ ReserveData         β€” reserve balance struct
β”œβ”€β”€ reentrancy_guard    β€” re-entrancy protection helper
β”œβ”€β”€ MintEvent           β€” standardised mint event type
β”œβ”€β”€ BurnEvent           β€” standardised burn event type
└── constants           β€” DECIMALS, BASIS_POINTS, MAX_VALIDATORS, …

Prerequisites

  • Rust 1.87.0 (pinned in rust-toolchain.toml)
  • Soroban CLI (cargo install --locked soroban-cli)
  • Stellar account with XLM for deployment fees

Building

You can use the Makefile for common commands.

# Build all contracts in the workspace
make build

# Build a specific contract
make build-minting

Testing

# Run all tests in the workspace
make test

# Run tests for a specific contract
make test-minting

Deployment

Testnet

export STELLAR_SECRET_KEY="your-secret-key"
make deploy-testnet

Mainnet

export STELLAR_SECRET_KEY="your-secret-key"
make deploy-mainnet

Git Hooks Setup

After cloning, run:

make setup-hooks

This configures the pre-commit hook for WASM integrity checks.

Contract Addresses

After deployment, contract addresses are saved to .soroban/deployment_{network}.json

Development

Project Structure

.
β”œβ”€β”€ acbu_minting/           # Minting contract
β”œβ”€β”€ acbu_burning/           # Burning contract
β”œβ”€β”€ acbu_oracle/            # Oracle contract
β”œβ”€β”€ acbu_reserve_tracker/   # Reserve tracker contract
β”œβ”€β”€ acbu_savings_vault/     # Savings vault contract
β”œβ”€β”€ acbu_lending_pool/      # Lending pool contract
β”œβ”€β”€ acbu_escrow/            # Escrow contract
β”œβ”€β”€ acbu_multisig/          # Multisig shared contract
β”œβ”€β”€ shared/                 # Shared types and utilities
β”œβ”€β”€ scripts/                # Deployment scripts
β”œβ”€β”€ docs/                   # Documentation
└── tests/                  # Integration tests

Adding a New Contract

  1. Create contract directory: mkdir new_contract
  2. Add to workspace Cargo.toml members
  3. Create Cargo.toml and src/lib.rs
  4. Update deployment scripts

Security

  • All admin functions require multisig (3 of 5)
  • Rate limits on transactions
  • Circuit breakers for anomalies
  • Time locks for critical operations

Documentation

About

No description, website, or topics provided.

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages