> ## 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.

# Folio Contract

> Core ERC20 token with permissionless minting/redemption and semi-permissioned rebalancing

## Overview

The **Folio** contract is the heart of the Reserve Folio protocol. It's a backed ERC20 token that allows permissionless minting and redemption while maintaining a flexible basket of underlying assets. The contract supports semi-permissioned rebalancing through a sophisticated auction mechanism.

### Key Features

* **Flexible Basket**: Supports multiple ERC20 tokens of any denomination
* **Permissionless Mint/Redeem**: Anyone can mint or redeem shares proportionally
* **Dutch Auction Rebalancing**: Uses exponential decay curves for efficient price discovery
* **Fee System**: TVL fees and mint fees with DAO revenue sharing
* **Role-Based Access**: Three main roles for governance and operations

### Architecture

Folio implements:

* ERC20Upgradeable (share token)
* AccessControlEnumerableUpgradeable (role management)
* ReentrancyGuardUpgradeable (security)

## Roles

The Folio contract operates with three primary roles:

<ParamField path="DEFAULT_ADMIN_ROLE" type="bytes32">
  Can set assets, fees, auction parameters, and deprecate the Folio
</ParamField>

<ParamField path="REBALANCE_MANAGER" type="bytes32">
  Can start/end rebalances and manage individual auctions (typically a timelock)
</ParamField>

<ParamField path="AUCTION_LAUNCHER" type="bytes32">
  Can open auctions and end rebalances/auctions (typically an EOA or multisig)
</ParamField>

<ParamField path="BRAND_MANAGER" type="bytes32">
  Optional role for off-chain use with no on-chain permissions
</ParamField>

## Minting and Redeeming

### Mint

Mint new Folio shares by depositing the basket of tokens proportionally.

<ParamField path="shares" type="uint256">
  Amount of shares to mint (before fees)
</ParamField>

<ParamField path="receiver" type="address">
  Address to receive the minted shares
</ParamField>

<ParamField path="minSharesOut" type="uint256">
  Minimum shares to receive after fees (slippage protection)
</ParamField>

```solidity Folio.sol theme={null}
function mint(
    uint256 shares,
    address receiver,
    uint256 minSharesOut
) external returns (address[] memory _assets, uint256[] memory _amounts)
```

<Info>
  Minting incurs fees: (1) DAO fee shares, (2) fee recipient shares, (3) self-fee shares that are burned.
</Info>

### Redeem

Burn Folio shares to receive the underlying basket proportionally.

<ParamField path="shares" type="uint256">
  Amount of shares to burn
</ParamField>

<ParamField path="receiver" type="address">
  Address to receive the underlying tokens
</ParamField>

<ParamField path="assets" type="address[]">
  Array of asset addresses (must match basket)
</ParamField>

<ParamField path="minAmountsOut" type="uint256[]">
  Minimum amounts of each asset to receive
</ParamField>

```solidity Folio.sol theme={null}
function redeem(
    uint256 shares,
    address receiver,
    address[] calldata assets,
    uint256[] calldata minAmountsOut
) external returns (uint256[] memory _amounts)
```

## Rebalancing

### Start Rebalance

Initiate a new rebalancing operation with target basket weights and prices.

<ParamField path="tokens" type="TokenRebalanceParams[]">
  Rebalance parameters for each token including weights and price ranges
</ParamField>

<ParamField path="limits" type="RebalanceLimits">
  Target basket unit (BU) limits: low, spot, and high
</ParamField>

<ParamField path="auctionLauncherWindow" type="uint256">
  Time (in seconds) that AUCTION\_LAUNCHER has exclusive access
</ParamField>

<ParamField path="ttl" type="uint256">
  Total time-to-live for the entire rebalance
</ParamField>

```solidity Folio.sol theme={null}
function startRebalance(
    TokenRebalanceParams[] calldata tokens,
    RebalanceLimits calldata limits,
    uint256 auctionLauncherWindow,
    uint256 ttl
) external onlyRole(REBALANCE_MANAGER)
```

### Open Auction (Restricted)

AUCTION\_LAUNCHER opens an auction with specific parameters.

<ParamField path="rebalanceNonce" type="uint256">
  Nonce of the target rebalance
</ParamField>

<ParamField path="tokens" type="address[]">
  Subset of rebalance tokens to include in this auction
</ParamField>

<ParamField path="newWeights" type="WeightRange[]">
  New basket weight ranges (can be progressively tightened)
</ParamField>

<ParamField path="newPrices" type="PriceRange[]">
  New price ranges (subject to PriceControl setting)
</ParamField>

<ParamField path="newLimits" type="RebalanceLimits">
  New BU limits (must be within existing range)
</ParamField>

<ParamField path="auctionLength" type="uint256">
  Desired auction length in seconds
</ParamField>

```solidity Folio.sol theme={null}
function openAuction(
    uint256 rebalanceNonce,
    address[] calldata tokens,
    WeightRange[] calldata newWeights,
    PriceRange[] calldata newPrices,
    RebalanceLimits calldata newLimits,
    uint256 auctionLength
) external onlyRole(AUCTION_LAUNCHER) returns (uint256 auctionId)
```

### Bidding

Participate in an ongoing auction by swapping tokens.

<ParamField path="auctionId" type="uint256">
  ID of the auction to bid on
</ParamField>

<ParamField path="sellToken" type="IERC20">
  Token being sold by the Folio
</ParamField>

<ParamField path="buyToken" type="IERC20">
  Token being bought by the Folio
</ParamField>

<ParamField path="sellAmount" type="uint256">
  Amount of sell token to receive
</ParamField>

<ParamField path="maxBuyAmount" type="uint256">
  Maximum amount of buy token willing to pay
</ParamField>

<ParamField path="withCallback" type="bool">
  If true, uses callback pattern (caller must implement IBidderCallee)
</ParamField>

<ParamField path="data" type="bytes">
  Arbitrary data passed to callback
</ParamField>

```solidity Folio.sol theme={null}
function bid(
    uint256 auctionId,
    IERC20 sellToken,
    IERC20 buyToken,
    uint256 sellAmount,
    uint256 maxBuyAmount,
    bool withCallback,
    bytes calldata data
) external returns (uint256 boughtAmt)
```

<Warning>
  Bidding requires `rebalance.bidsEnabled` to be true. Check this before attempting to bid.
</Warning>

## Fee Management

### Set TVL Fee

Set the annual TVL fee (demurrage fee on AUM).

<ParamField path="_newFee" type="uint256">
  New annual fee as D18 (e.g., 0.1e18 = 10%)
</ParamField>

```solidity Folio.sol theme={null}
function setTVLFee(uint256 _newFee) external onlyRole(DEFAULT_ADMIN_ROLE)
```

### Set Mint Fee

Set the fee charged on minting operations.

<ParamField path="_newFee" type="uint256">
  New mint fee as D18 (e.g., 0.01e18 = 1%)
</ParamField>

```solidity Folio.sol theme={null}
function setMintFee(uint256 _newFee) external onlyRole(DEFAULT_ADMIN_ROLE)
```

### Distribute Fees

Distribute accumulated fees to DAO and fee recipients.

```solidity Folio.sol theme={null}
function distributeFees() public
```

<Info>
  Fees accumulate as "pending shares" and are distributed proportionally based on the configured fee recipients and DAO split.
</Info>

## View Functions

### Total Assets

Get all assets and amounts held by the Folio.

```solidity Folio.sol theme={null}
function totalAssets() external view returns (
    address[] memory _assets,
    uint256[] memory _amounts
)
```

### To Assets

Convert shares to underlying asset amounts.

<ParamField path="shares" type="uint256">
  Number of shares to convert
</ParamField>

<ParamField path="rounding" type="Math.Rounding">
  Rounding direction (Floor or Ceil)
</ParamField>

```solidity Folio.sol theme={null}
function toAssets(
    uint256 shares,
    Math.Rounding rounding
) external view returns (
    address[] memory _assets,
    uint256[] memory _amounts
)
```

### Get Rebalance

Get current rebalance state.

```solidity Folio.sol theme={null}
function getRebalance() external view returns (
    uint256 nonce,
    PriceControl priceControl,
    TokenRebalanceParams[] memory tokens,
    RebalanceLimits memory limits,
    RebalanceTimestamps memory timestamps,
    bool bidsEnabled_
)
```

## Events

<ResponseField name="AuctionOpened" type="event">
  Emitted when a new auction is opened

  **Parameters:**

  * `rebalanceNonce` - Rebalance nonce
  * `auctionId` - New auction ID
  * `tokens` - Tokens in auction
  * `weights` - Weight ranges
  * `prices` - Price ranges
  * `limits` - BU limits
  * `startTime` - Auction start timestamp
  * `endTime` - Auction end timestamp
</ResponseField>

<ResponseField name="AuctionBid" type="event">
  Emitted when a bid is placed

  **Parameters:**

  * `auctionId` - Auction ID
  * `sellToken` - Token sold
  * `buyToken` - Token bought
  * `sellAmount` - Amount sold
  * `buyAmount` - Amount bought
</ResponseField>

<ResponseField name="RebalanceStarted" type="event">
  Emitted when rebalancing begins

  **Parameters:**

  * `nonce` - Rebalance nonce
  * `priceControl` - Price control setting
  * `tokens` - Token parameters
  * `limits` - BU limits
  * `startedAt` - Start timestamp
  * `restrictedUntil` - Restricted period end
  * `availableUntil` - Total expiration
  * `bidsEnabled` - Whether bids are enabled
</ResponseField>

<ResponseField name="FolioFeePaid" type="event">
  Emitted when fees are distributed

  **Parameters:**

  * `recipient` - Fee recipient address
  * `amount` - Shares distributed
</ResponseField>

## Constants

<ParamField path="D18" type="uint256" default="1e18">
  18-decimal fixed point scaling factor
</ParamField>

<ParamField path="D27" type="uint256" default="1e27">
  27-decimal fixed point scaling factor (for high precision)
</ParamField>

<ParamField path="MAX_MINT_FEE" type="uint256" default="0.05e18">
  Maximum mint fee: 5%
</ParamField>

<ParamField path="MAX_TVL_FEE" type="uint256" default="0.1e18">
  Maximum annual TVL fee: 10%
</ParamField>

<ParamField path="AUCTION_WARMUP" type="uint256" default="30">
  Auction warmup period in seconds
</ParamField>
