# Contract Suite

The rwaUSD system is modular. Each contract has a narrow responsibility and an explicit permission boundary.

#### 1. Overview diagram

```mermaid
flowchart TB
  subgraph User
    U[EOA / Safe]
  end

  subgraph Core
    L[Ledger Core]
    R[Account Manager]
    X[Risk Registry]
    F[Fee Accumulator]
  end

  subgraph Collateral
    A1[Asset Adapter: TBill]
    A2[Asset Adapter: Stable]
    A3[Asset Adapter: Gold]
  end

  subgraph Pricing
    P[Price Router]
    G[Price Guards]
    S[Signed Feed Verifier]
  end

  subgraph Liquidation
    W[Unwind Engine]
    H[Auction House]
  end

  subgraph Peg
    PR[Peg Rail]
  end

  subgraph Backstop
    B[Reserve Buffer]
    D[Deficit Recorder]
    C[Recap Mechanism]
  end

  U --> R
  R --> A1
  R --> A2
  R --> A3
  A1 --> L
  A2 --> L
  A3 --> L

  P --> L
  X --> L
  F --> L

  W --> L
  W --> H
  H --> L

  PR --> L
  L --> B
  D --> L
  B --> C
```

***

#### 2. rwaUSD Token (`RwaUsdToken`)

**Type:** ERC‑20 (+ EIP‑2612 permit recommended)

**Responsibilities**

* Maintain rwaUSD balances
* Mint/burn only by authorized core module(s)

**Key rules**

* `mint(to, amount)` only callable by `Ledger Core`
* `burn(from, amount)` only callable by `Ledger Core` (or via allowance-based `burnFrom` gated to core)

**Interfaces (Solidity-style)**

```solidity
function mint(address to, uint256 amt) external;
function burn(address from, uint256 amt) external;
function permit(...) external; // optional
```

***

#### 3. Ledger Core (`Ledger`)

This is the accounting kernel. Keep it small, boring, and difficult to upgrade.

**Responsibilities**

* Store collateral balances per account/profile
* Store principal per account/profile
* Enforce all solvency checks using prices and parameters
* Mint/burn rwaUSD
* Record protocol revenue and deficits

**Key storage**

* `locked[accountId][profileId] -> uint256`
* `principal[accountId][profileId] -> uint256`
* `index[profileId] -> uint256` (fee index)
* `totalPrincipal[profileId] -> uint256`
* `pausedFlags -> bitmask`
* `badDebt -> uint256` (explicit deficit tally)

**External entrypoints (only from authorized modules)**

* `lock(profile, account, amount)`
* `unlock(profile, account, amount)`
* `increasePrincipal(profile, account, delta)`
* `decreasePrincipal(profile, account, delta)`
* `applyIndex(profile)` (or invoked by Fee Accumulator)
* `startUnwind(account)` (called by Unwind Engine)
* `settleUnwind(account, clearedPrincipal, clearedFees, collateralOut)` (called by Auction House)

**Important:** the Ledger never calls untrusted external contracts. Anything that touches tokens goes through adapters. Anything that moves collateral in liquidation goes through the Auction House.

***

#### 4. Account Manager (`AccountManager`)

User-facing orchestration: creates accounts, manages permissions, bundles operations.

**Responsibilities**

* Create Collateral Accounts (`accountId`)
* Operator permissions per account
* Convenience methods: deposit+mint, repay+withdraw, multi-call sequences

**Permissions model**

* account owner can grant operators
* operators can be scoped:
  * collateral management
  * issuance/repayment
  * withdrawals
  * full control

**Recommended interfaces**

```solidity
function openAccount(address owner) external returns (uint256 accountId);
function setOperator(uint256 accountId, address operator, uint256 permissions) external;

function deposit(uint256 accountId, bytes32 profileId, uint256 amount) external;
function withdraw(uint256 accountId, bytes32 profileId, uint256 amount, address to) external;

function mint(uint256 accountId, bytes32 profileId, uint256 amount, address to) external;
function repay(uint256 accountId, bytes32 profileId, uint256 amount, address from) external;

// Convenience
function depositAndMint(...) external;
function repayAndWithdraw(...) external;
```

***

#### 5. Asset Adapters (`AssetAdapter` per profile)

Each collateral token requires an adapter to normalize token behavior and enforce custody constraints.

**Responsibilities**

* Pull collateral tokens from user and hold in adapter custody
* Push collateral tokens to user (withdrawals) or Auction House (unwinds)
* Normalize decimals and non-standard ERC‑20 behavior
* Enforce allowlist constraints if token requires eligible holders

**Non-negotiables**

* No collateral leaves an adapter without a corresponding Ledger state update
* Adapter must be approved holder if upstream token has restrictions
* Adapter must handle tokens with:
  * 6 decimals
  * missing return values
  * fee-on-transfer (ideally disallowed for v1)

**Interfaces**

```solidity
function deposit(uint256 accountId, uint256 amount) external;
function withdraw(uint256 accountId, uint256 amount, address to) external;
function seizeToAuction(uint256 accountId, uint256 amount, address auctionHouse) external;
```

***

#### 6. Risk Registry (`RiskRegistry`)

On-chain parameter store for collateral profiles and global settings.

**Per-profile parameters**

* `safetyFactor` (min coverage multiplier)
* `haircut` (price discount used for solvency checks)
* `mintCap` (max principal allowed for profile)
* `minPosition` (dust threshold)
* `penaltyFactor` (extra charge when unwound)
* `auctionConfig` (see Auction House section)
* `oracleConfig` (feed set + guardrails)
* `borrowEnabled` / `collateralEnabled` flags

**Global parameters**

* global issuance cap (optional)
* peg rail limits
* pause flags

**Update rules**

* all changes via governance timelock
* emergency roles may only tighten risk or pause modules

***

#### 7. Fee Accumulator (`FeeAccumulator`)

Maintains fee indices for profiles.

**Model**

* Each profile has a per-second growth factor `ratePerSecond` in RATE precision
* `index[p]` increases over time

**Mechanics**

* Lazy update: `accrue(profile)` updates index based on `block.timestamp - lastAccrual[p]`
* Mint/repay operations call `accrue(profile)` before computing new liability

**Interfaces**

```solidity
function accrue(bytes32 profileId) external;
function setRate(bytes32 profileId, uint256 ratePerSecond) external; // timelock
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.multipli.fi/technical-architecture/contract-suite.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
