> ## Documentation Index
> Fetch the complete documentation index at: https://docs.railnet.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Accounting and flow of funds

> How Railnet tracks assets across strategies with sector-based accounting

<Info>In user-facing documentation, a MultiVehicle is referred to as a **Strategy**. See [Glossary](/developers/glossary).</Info>

Multi-Vehicle implements rigorous double-entry accounting to track all asset movements through the system. Understanding the sector model and asset flow is essential for operating multi-vehicle deployments.

## Why sector-based accounting

In a multi-protocol environment, assets are rarely static. They move between being idle in the vault, committed to a deposit query, held as shares in a sub-vehicle, or queued for redemption. Traditional balance-based accounting struggles to track these "in-flight" assets, leading to potential double-counting or inaccurate share pricing.

Multi-Vehicle solves this by partitioning assets into logical **sectors** that represent their current operational state. This allows the protocol to:

* Track the exact lifecycle stage of every asset
* Handle asynchronous settlements without losing track of value
* Provide an accurate `totalAssets()` calculation at any point in time

## The double-entry principle

Every movement of assets within the system has an explicit source and destination sector. The SectorAccountingEngine:

1. Decrements the balance of the source sector
2. Increments the balance of the destination sector
3. Emits a `SectorTransfer` event for a clear audit trail

This ensures total supply of accounted assets remains constant across internal transfers, making the system resistant to accounting leaks or "lost" assets.

## Core sectors

| Sector         | Type     | Description                                                                                          |
| -------------- | -------- | ---------------------------------------------------------------------------------------------------- |
| **ENTRY**      | Virtual  | Assets entering the system. Used as a source for initial deposits; not tracked in internal balances. |
| **DEPOSIT**    | Physical | Idle base assets (e.g., USDC) deposited but not yet allocated to any sub-vehicle.                    |
| **ALLOCATION** | Physical | Sub-vehicle shares representing deployed capital across the portfolio.                               |
| **REDEEM**     | Physical | Base assets redeemed from sub-vehicles and ready for user withdrawal.                                |
| **EXIT**       | Virtual  | Assets leaving the system. Used as a destination for withdrawals; not tracked in internal balances.  |

## Dynamic sectors

Beyond the core sectors, the system creates dynamic sectors for per-vehicle operations:

| Sector             | Purpose                                                                                                            |
| ------------------ | ------------------------------------------------------------------------------------------------------------------ |
| **Vehicle Sector** | Per-vehicle staging area where assets accumulate before a STEAM query is created.                                  |
| **Pending Sector** | Holds assets committed to in-flight queries. Isolates capital from other operations until the query settles.       |
| **Query Sector**   | Temporary sector for complex operations like recovery from a failed sub-query. Provides high-granularity tracking. |

## Deposit flow

Assets flowing from users into sub-vehicles follow this path:

<Steps>
  <Step title="Asset reception">
    The user deposits base assets into the Multi-Vehicle. Assets transfer from ENTRY (virtual) to the DEPOSIT sector.
  </Step>

  <Step title="Allocation decision">
    The QueueStrategyEngine processes the deposit queue and determines which sub-vehicle receives the assets.

    <CodeGroup>
      ```solidity Solidity theme={null}
      // QueueStrategyEngine processes deposit queue
      depositQueue = [{aave, 60k}, {morpho, 30k}]
      // Determines: allocate X to Aave vehicle
      ```

      ```typescript TypeScript theme={null}
      // Coming soon
      ```
    </CodeGroup>
  </Step>

  <Step title="Query dispatch">
    Assets move from DEPOSIT to the Vehicle Sector (staging), then to the Pending Sector when the [STEAM query](/developers/contracts/steam-standard#the-state-machine) is created.
  </Step>

  <Step title="Asset commitment">
    Assets leave the accounting system. `Pending Sector → EXIT` (virtual). Ephemeral accounting estimates the expected shares to keep `totalAssets` accurate during this gap.
  </Step>

  <Step title="Settlement">
    When the sub-vehicle query settles ([sync or async](/developers/contracts/sync-vs-async)), shares enter the accounting system. `ENTRY → ALLOCATION` (virtual). Ephemeral estimates are replaced with actual values.
  </Step>
</Steps>

<Info>
  Between steps 4 and 5, assets exist outside the Multi-Vehicle's accounting system (they are held by the sub-vehicle). Ephemeral accounting tracks their estimated value during this gap to keep `totalAssets()` and share price accurate.
</Info>

```mermaid theme={null}
graph LR
    A[ENTRY] -->|"1. deposit"| B[DEPOSIT]
    B -->|"2. allocate"| C[Vehicle Sector]
    C -->|"3. create query"| D[Pending Sector]
    D -->|"4. commit"| E[EXIT]

    F[ENTRY] -->|"5. settle"| G[ALLOCATION]
```

## Redeem flow

Assets flowing from sub-vehicles back to users follow the reverse path:

<Steps>
  <Step title="Unallocation decision">
    The QueueStrategyEngine processes the redeem queue and determines which sub-vehicle to unallocate from. `ALLOCATION → Vehicle Sector`.
  </Step>

  <Step title="Query dispatch">
    A STEAM redeem query is created. `Vehicle Sector → Pending Sector`.
  </Step>

  <Step title="Share commitment">
    Shares leave the accounting system. `Pending Sector → EXIT` (virtual). Ephemeral accounting estimates the expected base assets to keep `totalAssets` accurate.
  </Step>

  <Step title="Settlement">
    Base assets arrive from the sub-vehicle. `ENTRY → REDEEM` (virtual). Ephemeral estimates are replaced with actual values.
  </Step>

  <Step title="Asset return">
    The user withdraws their base assets. `REDEEM → EXIT`.
  </Step>
</Steps>

```mermaid theme={null}
graph LR
    A[ALLOCATION] -->|"1. unallocate"| B[Vehicle Sector]
    B -->|"2. create query"| C[Pending Sector]
    C -->|"3. commit"| D[EXIT]

    E[ENTRY] -->|"4. settle"| F[REDEEM]
    F -->|"5. withdraw"| G[EXIT]
```

## Example: deposit cycle walkthrough

<Accordion title="Step-by-step sector balances through a 50k deposit">
  A Multi-Vehicle starts with 100k in total assets. A user deposits 50k, which is allocated to an Aave sub-vehicle.

  | Step | Action                                   | DEPOSIT | Ephemeral           | ALLOCATION   | totalAssets |
  | ---- | ---------------------------------------- | ------- | ------------------- | ------------ | ----------- |
  | T0   | Initial state                            | 20k     | —                   | 80k (shares) | 100k        |
  | T1   | User deposits 50k                        | 70k     | —                   | 80k          | 150k        |
  | T2   | Allocate 50k to Aave Vehicle Sector      | 20k     | —                   | 80k          | 150k        |
  | T3   | Query created, assets committed (→ EXIT) | 20k     | \~50k (est. shares) | 80k          | \~150k      |
  | T4   | Settlement: shares received (ENTRY →)    | 20k     | —                   | 130k         | \~150k      |

  **Key insight:** `totalAssets` stays at \~150k through every step. At T3, the 50k has left the system (Pending → EXIT) but shares haven't arrived yet (ENTRY → ALLOCATION hasn't happened). Ephemeral accounting bridges this gap by estimating the expected share value.
</Accordion>

## Asynchronous redemptions

When immediate liquidity is insufficient, the QueryRedeemQueue handles fulfillment over time:

1. User requests a redemption that exceeds available liquidity
2. A **demand** is created in the QueryRedeemQueue for the unfulfilled portion
3. A keeper or operator provides liquidity by calling `feedQueryRedeemQueue`
4. FIFO position-based matching pairs demands with fulfillments as liquidity arrives
5. The user receives assets (full or partial) as liquidity becomes available

<CodeGroup>
  ```solidity Solidity theme={null}
  // User redeems shares worth 2000 USDC
  // Immediate liquidity: 500 USDC
  // Need: 1500 USDC more

  // 1. Immediate portion settles normally
  // 2. QueryRedeemQueue.createDemand(1500 USDC)

  // Later: Operator provides liquidity
  // 3. feedQueryRedeemQueue(1500 USDC)
  // 4. User receives remaining 1500 USDC
  ```

  ```typescript TypeScript theme={null}
  // Coming soon
  ```
</CodeGroup>

## Ephemeral accounting

One of the most critical challenges in async asset management is accounting for value that has been committed but not yet received. When a deposit to a sub-vehicle is PROCESSING, the Multi-Vehicle no longer has the base assets, but it does not yet have the shares.

The SubQueryEngine manages **ephemeral accounting** to bridge this gap:

<Tabs>
  <Tab title="Without ephemeral accounting">
    <CodeGroup>
      ```solidity Solidity theme={null}
      // WITHOUT ephemeral accounting
      // T0: totalAssets = 100k (DEPOSIT: 20k, ALLOCATION: 80k in shares)
      //
      // User deposits 10k → query dispatched to Aave
      // Assets leave system: Pending Sector → EXIT
      // Shares not yet received (ENTRY → ALLOCATION hasn't happened)
      //
      // T1: totalAssets = 100k — the 10k left the system entirely!
      //     Share price drops — new depositors get shares too cheaply
      ```

      ```typescript TypeScript theme={null}
      // Coming soon
      ```
    </CodeGroup>
  </Tab>

  <Tab title="With ephemeral accounting">
    <CodeGroup>
      ```solidity Solidity theme={null}
      // WITH ephemeral accounting
      // T0: totalAssets = 100k (DEPOSIT: 20k, ALLOCATION: 80k in shares)
      //
      // User deposits 10k → query dispatched to Aave
      // Assets leave system: Pending Sector → EXIT
      // Ephemeral: estimate(10k USDC, DEPOSIT) ≈ 9,950 aUSDC
      //
      // T1: totalAssets = 100k + convert(9,950 aUSDC) ≈ 110k ✓
      //
      // Settlement: actual 9,980 aUSDC received → ENTRY → ALLOCATION
      // Ephemeral cleared, real shares replace estimate
      // T2: totalAssets = 100k + convert(9,980 aUSDC) ≈ 110k ✓
      ```

      ```typescript TypeScript theme={null}
      // Coming soon
      ```
    </CodeGroup>
  </Tab>
</Tabs>

When a sub-query enters PROCESSING, assets leave the accounting system (`Pending Sector → EXIT`) and the system uses the vehicle's `estimate()` function to determine the expected output. This estimated value is tracked as ephemeral accounting. On settlement, shares enter the system (`ENTRY → ALLOCATION`) and the ephemeral estimation is replaced with actual values.

## Exchange rate and share price

Multi-Vehicle uses the ERC-4626 standard for pricing:

<CodeGroup>
  ```solidity Solidity theme={null}
  shares = assets * totalSupply / totalAssets()
  ```

  ```typescript TypeScript theme={null}
  // Coming soon
  ```
</CodeGroup>

The `totalAssets()` function aggregates value across all sectors:

<CodeGroup>
  ```solidity Solidity theme={null}
  totalAssets =
      DEPOSIT sector balance                          // idle base assets
    + REDEEM sector balance                           // ready for withdrawal
    + for each active vehicle:
        + assets in vehicle sector                    // awaiting query creation
        + expected assets from PROCESSING redeems     // ephemeral
        + convertToAssets(
            shares in ALLOCATION                      // settled
          + shares in vehicle sector                  // awaiting redeem query
          + expected shares from PROCESSING deposits  // ephemeral
        )
  ```

  ```typescript TypeScript theme={null}
  // Coming soon
  ```
</CodeGroup>

By including both settled and in-flight value, Multi-Vehicle ensures that its share price always reflects the true underlying value of the entire portfolio.

## Monitoring

Operators should track these key metrics:

<AccordionGroup>
  <Accordion title="Sector balances">
    * **DEPOSIT** -- Amount of idle capital
    * **ALLOCATION** -- Total deployed capital
    * **REDEEM** -- Liquidity ready for withdrawal
    * **PENDING** -- Assets in flight
  </Accordion>

  <Accordion title="Queue health">
    * **Demand** -- Total pending redemptions in the QueryRedeemQueue
    * **Fulfillment** -- Available liquidity for matching
    * **Average wait time** -- User experience metric
  </Accordion>

  <Accordion title="Vehicle health">
    * **Per-vehicle** -- totalAssets, share price, query states
    * **Distribution** -- Actual vs target allocations across sub-vehicles
  </Accordion>
</AccordionGroup>

<Tip>
  **Best practices:**

  * Monitor pending sectors for high balances indicating slow query settlement
  * Maintain sufficient DEPOSIT/REDEEM balances for immediate withdrawals
  * Regularly fulfill the QueryRedeemQueue to minimize user wait times
  * Validate sector balances for accounting integrity with regular audits
</Tip>

## Next steps

<CardGroup cols={2}>
  <Card title="Multi-Vehicle architecture" icon="sitemap" href="/developers/contracts/multi-vehicle">
    How Multi-Vehicle orchestrates capital across sub-vehicles.
  </Card>

  <Card title="The STEAM standard" icon="gears" href="/developers/contracts/steam-standard">
    The state machine interface that drives all deposit and redeem queries.
  </Card>

  <Card title="Create an Allocation Strategy" icon="rocket" href="/strategies/allocation/create">
    Deploy an Allocation Strategy (MultiVehicle) ecosystem.
  </Card>

  <Card title="Operate an Allocation Strategy" icon="sliders" href="/strategies/allocation/operate">
    Day-to-day operations including queue management and rebalancing.
  </Card>
</CardGroup>
