> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/reserve-protocol/reserve-index-dtf/llms.txt
> Use this file to discover all available pages before exploring further.

# System Architecture

> Deep dive into Reserve Folio's architecture, rebalancing mechanism, auction system, and governance structure.

## System Overview

Reserve Folio implements a sophisticated multi-layer architecture designed for secure, efficient portfolio management under governance constraints.

<Note>
  The architecture is specifically designed to enable high-fidelity asset management and rebalancing even when operating under timelock delays.
</Note>

## Contract Architecture

### Layer 0: DAO Contracts

The foundational layer managing ecosystem-wide concerns:

```mermaid theme={null}
graph TD
    A[FolioVersionRegistry] -->|tracks| B[FolioDeployer versions]
    C[FolioDAOFeeRegistry] -->|manages| D[DAO fee configuration]
    E[RoleRegistry] -->|provides| F[role management]
    
    style A fill:#e1f5ff
    style C fill:#e1f5ff
    style E fill:#e1f5ff
```

<AccordionGroup>
  <Accordion title="FolioVersionRegistry.sol" icon="code-branch">
    Maintains a registry of approved `FolioDeployer` versions. Owned by the DAO, this contract ensures only vetted deployer contracts can create new Folios.

    **Key Functions:**

    * Track approved deployer versions
    * Enable/disable specific versions
    * Prevent deployment from deprecated versions
  </Accordion>

  <Accordion title="FolioDAOFeeRegistry.sol" icon="coins">
    Handles ecosystem-wide fee configuration, including the universal 15 bps minimum floor.

    **Key Features:**

    * Set global minimum fee floor
    * Configure per-Folio fee overrides (can only lower)
    * Manage DAO fee recipients
    * Track fee distribution
  </Accordion>

  <Accordion title="RoleRegistry (Interface)" icon="users">
    External contract providing role-based access control. Must implement `IRoleRegistry` interface.
  </Accordion>
</AccordionGroup>

### Layer 1: Folio Contracts

Core portfolio management contracts:

```solidity theme={null}
// contracts/Folio.sol (excerpt)
contract Folio is 
    IFolio,
    ERC20Upgradeable,
    AccessControlEnumerableUpgradeable,
    ReentrancyGuardUpgradeable,
    Versioned
{
    // Basket of ERC20 tokens
    EnumerableSet.AddressSet private basket;
    
    // Fee configuration
    FeeRecipient[] public feeRecipients;
    uint256 public tvlFee;  // D18{1/s}
    uint256 public mintFee; // D18{1}
    
    // Rebalancing state
    Rebalance private rebalance;
    Auction private auction;
    uint256 public maxAuctionLength; // {s}
    
    // ...
}
```

<CardGroup cols={3}>
  <Card title="Folio.sol" icon="folder">
    The heart of the system. An ERC20 token backed by a flexible basket of assets with built-in auction logic for rebalancing.
  </Card>

  <Card title="FolioDeployer.sol" icon="rocket">
    Factory contract for deploying new Folio instances with initial configuration and role assignments.
  </Card>

  <Card title="FolioProxy.sol" icon="arrow-up">
    Upgradeable proxy enabling contract evolution while preserving storage. Checks upgrades against FolioVersionRegistry.
  </Card>
</CardGroup>

### Layer 2: Governance System

```solidity theme={null}
// contracts/governance/FolioGovernor.sol (excerpt)
contract FolioGovernor is 
    Governor,
    GovernorSettings,
    GovernorCountingSimple,
    GovernorVotes,
    GovernorVotesQuorumFraction,
    GovernorTimelockControl
{
    // Time-based governance with timelock
}
```

<Steps>
  <Step title="StakingVault">
    ERC4626 vault where users stake Folio tokens to receive voting power. Supports:

    * Multi-token reward streams
    * Unstaking delays for security
    * ERC20Votes for governance participation
    * Optimistic governance with slashing (v5.0.0+)
  </Step>

  <Step title="FolioGovernor">
    Time-based governance system managing protocol parameters through proposals and voting.
  </Step>

  <Step title="GovernanceDeployer">
    Deploys complete governance systems including staking vaults and governors.
  </Step>
</Steps>

### Layer 3: Staking and Rewards

```solidity theme={null}
// contracts/staking/StakingVault.sol (excerpt)
contract StakingVault is 
    ERC4626Upgradeable,
    ERC20VotesUpgradeable,
    OwnableUpgradeable
{
    struct RewardInfo {
        uint256 payoutLastPaid;    // {s}
        uint256 rewardIndex;       // D18+decimals{reward/share}
        uint256 balanceAccounted;  // {reward}
        uint256 totalClaimed;      // {reward}
    }
    
    mapping(address => RewardInfo) public rewardTrackers;
    
    // Multi-reward system with exponential decay
}
```

<Info>
  StakingVault implements a sophisticated multi-reward system where rewards decay exponentially based on a configurable half-life (1 day to 2 weeks).
</Info>

## Rebalancing Architecture

### Rebalance Lifecycle

<Steps>
  <Step title="Initiation: startRebalance()">
    **Called by:** `REBALANCE_MANAGER`

    The rebalance manager defines comprehensive ranges for the rebalancing operation:

    ```solidity theme={null}
    struct TokenRebalanceParams {
        address token;
        WeightRange weight;     // D27{tok/BU} [low, spot, high]
        PriceRange price;       // D27{UoA/tok} [low, high]
        uint256 maxAuctionSize; // {tok}
        bool inRebalance;
    }

    struct RebalanceLimits {
        uint256 low;   // D18{BU/share} - buy up to
        uint256 spot;  // D18{BU/share} - point estimate
        uint256 high;  // D18{BU/share} - sell down to
    }
    ```

    **Time periods created:**

    * `restrictedUntil`: Only AUCTION\_LAUNCHER can act (minimum 120s buffer)
    * `availableUntil`: Rebalance TTL, after which no new auctions can start
  </Step>

  <Step title="Restricted Period: openAuction()">
    **Called by:** `AUCTION_LAUNCHER`

    During the restricted period, the auction launcher opens auctions with optional parameter adjustments:

    * **Token selection:** Subset of tokens in rebalance
    * **Basket limits:** Progressive narrowing (monotonic convergence)
    * **Weights:** Progressive narrowing if `weightControl == true`
    * **Prices:** Subset of ranges if `priceControl != NONE`

    The restricted period auto-extends when the auction launcher is active, ensuring they always have time to act.
  </Step>

  <Step title="Unrestricted Period: openAuctionUnrestricted()">
    **Called by:** Anyone

    After the restricted period expires (or if AUCTION\_LAUNCHER is inactive), anyone can open auctions using spot estimates:

    * All tokens in rebalance are included
    * Uses spot prices and weights
    * No parameter customization allowed

    This ensures the system remains functional even without the AUCTION\_LAUNCHER.
  </Step>

  <Step title="Trading: bid() or createTrustedFill()">
    **Called by:** Anyone (for bid) or Trusted Fillers

    Participants execute trades at current auction prices. Trades are validated against:

    * Current auction price curve
    * Available sell amounts
    * Required buy amounts
    * Maximum auction sizes
  </Step>

  <Step title="Completion: closeAuction() or endRebalance()">
    **Called by:** `AUCTION_LAUNCHER`, `REBALANCE_MANAGER`, or `DEFAULT_ADMIN_ROLE`

    Auctions close automatically after their duration. Rebalances can be ended early by authorized roles.
  </Step>
</Steps>

### Auction Mechanics

#### Price Curve: Exponential Decay

Auctions use exponential decay between optimistic and pessimistic price bounds:

```
Price(t) = startPrice * (endPrice/startPrice)^(t/duration)

Where:
- startPrice: Most optimistic exchange rate
- endPrice: Most pessimistic exchange rate  
- t: Time elapsed since auction start
- duration: Total auction length
```

<Warning>
  **Important:** Prices on the first and last blocks may not exactly match `startPrice` and `endPrice` unless transactions occur at precise `start` and `end` timestamps.
</Warning>

#### Auction Warmup Period

Auctions include a 30-second warmup before bidding begins:

```solidity theme={null}
uint256 constant AUCTION_WARMUP = 30; // {s}
```

<Note>
  The warmup ensures fair competition from the first tradeable block. It is bypassed only when `priceControl == ATOMIC_SWAP` and start price equals end price.
</Note>

#### Lot Sizing Algorithm

Auction sizes are calculated based on surpluses and deficits:

```solidity theme={null}
// For surplus tokens (selling):
surplus = balance - (high_limit * high_weight * totalShares)

// For deficit tokens (buying):
deficit = (low_limit * low_weight * totalShares) - balance

// Sell amount is the minimum that satisfies both constraints
sellAmount = min(
    surplus_of_sell_token,
    deficit_of_buy_token * price
)
```

**Key insights:**

1. **Surplus grows over time:** If selling token surplus is limiting, `sellAmount` increases with each auction as `high_limit` decreases
2. **Deficit shrinks over time:** If buying token deficit is limiting, `sellAmount` decreases as `low_limit` increases

<Info>
  The `AUCTION_LAUNCHER` progressively narrows the `[low, high]` ranges to implement Dollar Cost Averaging (DCA) into the target allocation.
</Info>

#### Pairwise Auction System

Auctions run simultaneously on **all possible token pairs** in the auction:

```
For tokens [A, B, C] in an auction:
- A→B, A→C (if A is surplus)
- B→A, B→C (if B is surplus)  
- C→A, C→B (if C is surplus)
```

Eligibility requirements:

* **Sell token:** Must be in surplus (balance > high\_limit \* high\_weight \* shares)
* **Buy token:** Must be in deficit (balance \< low\_limit \* low\_weight \* shares)

### Rebalance Targeting

Rebalances are considered "complete" when all ranges have converged:

```solidity theme={null}
// Complete rebalance conditions:
rebalanceLimits.low == rebalanceLimits.spot == rebalanceLimits.high

for each token:
    weight.low == weight.spot == weight.high
    // (prices don't need to converge)
```

## Price Control Levels

The `priceControl` setting determines auction launcher authority:

<Tabs>
  <Tab title="NONE">
    **Security:** Highest\
    **Flexibility:** Lowest

    The `AUCTION_LAUNCHER` cannot adjust prices. All auctions use the full price ranges specified by `REBALANCE_MANAGER`.

    **Use case:** Maximum security when AUCTION\_LAUNCHER trust is limited.
  </Tab>

  <Tab title="PARTIAL">
    **Security:** Medium\
    **Flexibility:** Medium

    The `AUCTION_LAUNCHER` can narrow price ranges within the original bounds to improve execution.

    **Risk:** Can start auctions at dishonest prices, leaking value to MEV searchers. Cannot guarantee they capture the MEV themselves.

    **Use case:** Trusted operators who need pricing flexibility for optimal execution.
  </Tab>

  <Tab title="ATOMIC_SWAP">
    **Security:** Lowest\
    **Flexibility:** Highest

    The `AUCTION_LAUNCHER` can:

    * Set `startPrice == endPrice` for instant execution
    * Fill auctions atomically in the same transaction
    * Capture MEV directly

    **Risk:** Can extract value and guarantee they are the beneficiary.

    **Use case:** Highly trusted operators (e.g., same entity as governance) who need maximum execution efficiency.
  </Tab>
</Tabs>

<Warning>
  **Best Practice for ATOMIC\_SWAP:**
  The `AUCTION_LAUNCHER` should:

  1. Open auction with fixed price
  2. Fill auction atomically in same transaction
  3. End rebalance immediately after

  All three operations should be bundled for security.
</Warning>

## Weight Control

When `weightControl == true`, the `AUCTION_LAUNCHER` can adjust individual token weights:

```solidity theme={null}
struct WeightRange {
    uint256 low;   // D27{tok/BU} - buy up to this weight
    uint256 spot;  // D27{tok/BU} - point estimate
    uint256 high;  // D27{tok/BU} - sell down to this weight
}
```

**Use cases:**

* **Percentage-based portfolios:** Maintain specific asset percentages throughout rebalancing
* **Dynamic rebalancing:** Adjust targets as market conditions change
* **Progressive convergence:** Narrow weight ranges auction-by-auction for precise DCA

**Without weight control:**

* Only `RebalanceLimits` (basket units per share) define rebalancing targets
* Best for portfolios with fixed quarterly/monthly targets

## Trusted Fillers Integration

Folios can integrate with the Trusted Fillers system for async order matching:

```solidity theme={null}
struct FolioFlags {
    bool trustedFillerEnabled;
    RebalanceControl rebalanceControl;
    bool bidsEnabled;
}
```

<CardGroup cols={2}>
  <Card title="Supported Fillers" icon="handshake">
    Currently supports CoW Swap for better price discovery and MEV protection through batch auctions.
  </Card>

  <Card title="Configuration" icon="gear">
    Enabled per-Folio by governance. When enabled, trusted fillers can compete alongside regular bidders.
  </Card>
</CardGroup>

<Info>
  Trusted fillers must respect all auction limitations including price curves, lot sizes, and timing constraints.
</Info>

### Disabling Permissionless Bids

In version 5.0.0+, governance can restrict trading to trusted fillers only:

```solidity theme={null}
// Disable permissionless bids (v5.0.0+)
folio.setBidsEnabled(false);
```

This forces all auction fills through trusted filler protocols, potentially improving execution quality and MEV protection.

## Fee Distribution Architecture

### Dual-Layer Fee System

```
User pays fee → Split between DAO and Folio recipients
              |
              ├─→ DAO: minimum 15 bps (configurable)
              └─→ Folio recipients: remaining portion
```

### TVL Fee Mechanics

```solidity theme={null}
// Applied once every 24 hours
uint256 constant ONE_DAY = 86400; // {s}

// Supply inflation calculation
if (block.timestamp >= lastPoke + ONE_DAY) {
    uint256 periods = (block.timestamp - lastPoke) / ONE_DAY;
    uint256 inflation = totalSupply * tvlFee * periods;
    
    // Split between DAO and fee recipients
    uint256 daoShares = inflation * daoFeeFraction;
    uint256 folioShares = inflation - daoShares;
}
```

<Note>
  Changing from per-block to daily inflation in v4.0.0 reduced gas costs without changing the economic model.
</Note>

### Mint Fee Mechanics

```solidity theme={null}
// Applied during mint()
uint256 sharesBeforeFee = calculateShares(assets);
uint256 feeAmount = sharesBeforeFee * mintFee / D18;
uint256 sharesAfterFee = sharesBeforeFee - feeAmount;

// Fee distributed to DAO and recipients (no inflation)
```

## Security Considerations

### Reentrancy Protection

All state-changing functions use `nonReentrant` modifier:

```solidity theme={null}
modifier nonReentrant() {
    require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
    _status = _ENTERED;
    _;
    _status = _NOT_ENTERED;
}
```

<Warning>
  **Read-Only Reentrancy:**
  While the Folio itself is protected, consuming protocols must check `stateChangeActive()` before using view functions:

  ```solidity theme={null}
  (bool isRebalancing, bool isAuction) = folio.stateChangeActive();
  require(!isRebalancing && !isAuction, "State change active");
  ```
</Warning>

### Upgrade Safety

Upgrades are checked against the version registry:

```solidity theme={null}
// contracts/folio/FolioProxy.sol
function _authorizeUpgrade(address newImplementation) internal override {
    require(
        IFolioVersionRegistry(versionRegistry).isVersionValid(newImplementation),
        "Invalid version"
    );
}
```

### Token Safety Boundaries

| Parameter                                | Maximum Value | Decimals | Type       |
| ---------------------------------------- | ------------- | -------- | ---------- |
| Folio Supply                             | 1e36          | -        | {share}    |
| Folio Collateral Decimals                | -             | 27       | -          |
| StakingVault Underlying/Rewards Decimals | -             | 21       | -          |
| Rebalance Limits                         | 1e36          | 18 (D18) | {BU/share} |
| Basket Weights                           | 1e54          | 27 (D27) | {tok/BU}   |
| Token Prices (UoA)                       | 1e45          | 27 (D27) | {UoA/tok}  |
| Price Range Ratio                        | 1e2           | -        | ratio      |

<Warning>
  **Governance Responsibility:**
  It is governance's duty to ensure Folio supply never exceeds 1e36. Consider implementing supply caps or monitoring systems.
</Warning>

## State Management

### Rebalance State Machine

```
NO_REBALANCE
    ↓ startRebalance()
RESTRICTED_PERIOD (only AUCTION_LAUNCHER can act)
    ↓ time passes OR AUCTION_LAUNCHER inactive
UNRESTRICTED_PERIOD (anyone can act)
    ↓ TTL expires OR endRebalance() called
NO_REBALANCE
```

### Auction State Machine

```
UNINITIALIZED (startTime == 0, endTime == 0)
    ↓ openAuction() / openAuctionUnrestricted()
PENDING (block.timestamp < startTime)
    ↓ time passes
OPEN (startTime ≤ block.timestamp ≤ endTime)
    ↓ time passes OR closeAuction()
CLOSED (block.timestamp > endTime)
    ↓ openAuction() [if rebalance still active]
OPEN ...
```

## Utility Libraries

<AccordionGroup>
  <Accordion title="RebalancingLib.sol" icon="calculator">
    Core rebalancing calculations:

    * Lot size calculations
    * Surplus/deficit determination
    * Price curve interpolation
    * Range validation and narrowing logic
  </Accordion>

  <Accordion title="FolioLib.sol" icon="book">
    Folio-specific utilities:

    * Basket value calculations
    * Share price computations
    * Fee calculations
    * Asset amount conversions
  </Accordion>

  <Accordion title="MathLib.sol" icon="square-root-alt">
    Mathematical operations:

    * Safe arithmetic
    * Fixed-point math (D18, D27)
    * Exponential decay calculations
  </Accordion>

  <Accordion title="Constants.sol" icon="hashtag">
    System-wide constants:

    ```solidity theme={null}
    uint256 constant D18 = 1e18;
    uint256 constant D27 = 1e27;
    uint256 constant AUCTION_WARMUP = 30; // {s}
    uint256 constant MIN_AUCTION_LENGTH = 60; // {s}
    uint256 constant MAX_AUCTION_LENGTH = 7 days;
    uint256 constant RESTRICTED_AUCTION_BUFFER = 120; // {s}
    uint256 constant ONE_DAY = 86400; // {s}
    ```
  </Accordion>
</AccordionGroup>

## Deprecation Mechanism

Folios can be deprecated by the `DEFAULT_ADMIN_ROLE`:

```solidity theme={null}
function deprecateFolio() external onlyRole(DEFAULT_ADMIN_ROLE) {
    isDeprecated = true;
    emit FolioDeprecated();
}
```

**Effects:**

* Minting disabled
* Rebalancing disabled
* Redemption still enabled (redemption-only mode)

<Info>
  Use deprecation when a Folio needs to wind down gracefully, allowing holders to exit but preventing new capital inflows.
</Info>

## Performance Optimizations

### Gas Optimizations (v5.0.0)

1. **Daily fee inflation:** Reduced from per-block to once-per-day calculations
2. **EnumerableSet usage:** Efficient basket token tracking
3. **Calldata over memory:** Where possible for external functions
4. **Packed structs:** Optimized storage layout

### Scalability Considerations

* **Max auction length:** 7 days (configurable down to 60 seconds)
* **Basket size:** No hard limit, but gas costs scale linearly
* **Fee recipients:** Limited to prevent gas issues during distribution
* **Concurrent auctions:** 1 active auction at a time per Folio

## Peripheral Contracts

### FolioLens.sol

View-only helper contract for batch queries:

```solidity theme={null}
interface IFolioLens {
    function getBasketValues(address folio) external view returns (...);
    function getRebalanceStatus(address folio) external view returns (...);
    function getAuctionDetails(address folio, uint256 auctionId) external view returns (...);
}
```

Use this for frontend integrations to minimize RPC calls.

## Next Steps

<CardGroup cols={2}>
  <Card title="Quick Start" icon="rocket" href="/quickstart">
    Deploy your first Folio with practical examples
  </Card>

  <Card title="API Reference" icon="code" href="/api-reference">
    Complete function reference with parameters and return values
  </Card>
</CardGroup>
