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

# Security Considerations

> Reentrancy protection, weird ERC20 compatibility, and security best practices

## Overview

Reserve Folio implements multiple security mechanisms to protect against common vulnerabilities while supporting a wide range of ERC20 tokens. Understanding these protections is critical for both governance and consuming protocols.

## Reentrancy Protection

Folio uses OpenZeppelin's `ReentrancyGuardUpgradeable` to prevent reentrancy attacks:

```solidity theme={null}
contract Folio is ReentrancyGuardUpgradeable {
    // All state-changing external functions are protected
    function mint(...) external nonReentrant { ... }
    function redeem(...) external nonReentrant { ... }
    function bid(...) external nonReentrant { ... }
    function createTrustedFill(...) external nonReentrant { ... }
}
```

### Protected Functions

All mutating external functions use the `nonReentrant` modifier:

* `mint()`, `redeem()`
* `bid()`, `createTrustedFill()`
* `openAuction()`, `openAuctionUnrestricted()`, `closeAuction()`
* `startRebalance()`, `endRebalance()`
* `distributeFees()`, `poke()`
* Governance functions: `addToBasket()`, `removeFromBasket()`, etc.

### Read-Only Reentrancy

<Warning>
  While Folio itself is protected from reentrancy, **read-only reentrancy** is still possible for consuming protocols. View functions can be called during state changes and return inconsistent data.
</Warning>

#### Checking for Active State Changes

Consuming protocols must check `stateChangeActive()` before trusting view data:

```solidity theme={null}
function getSafeData() external view returns (uint256) {
    (bool syncActive, bool asyncActive) = folio.stateChangeActive();
    
    // Synchronous state change (reentrancy guard entered)
    require(!syncActive, "Sync state change active");
    
    // Asynchronous state change (trusted fill in progress)
    require(!asyncActive, "Async state change active");
    
    // Safe to read view functions
    return folio.totalSupply();
}
```

**When state changes are active:**

* `syncActive = true`: Folio is in the middle of a transaction (reentrancy)
* `asyncActive = true`: A trusted fill swap is ongoing (CoW Swap order pending)

<Warning>
  The `asyncActive` check can be DoS'd for the current block if a malicious actor repeatedly creates and cancels trusted fills. Implement appropriate safeguards in consuming protocols.
</Warning>

## Weird ERC20 Support

Folio supports most ERC20 tokens with the following compatibility matrix:

### Folio Compatibility

| Token Behavior                     | Folio | StakingVault | Notes                                       |
| ---------------------------------- | ----- | ------------ | ------------------------------------------- |
| **Multiple Entrypoints**           | ❌     | ❌            | Tokens like old TUSD with `transferProxy()` |
| **Pausable / Blocklist**           | ❌     | ❌            | USDC, USDT pause functionality              |
| **Fee-on-transfer**                | ❌     | ❌            | Breaks balance accounting                   |
| **ERC777 / Callback**              | ❌     | ❌            | Reentrancy risk via hooks                   |
| **Upward-rebasing**                | ✅     | ❌            | stETH, but accounting may be off            |
| **Downward-rebasing**              | ✅     | ❌            | Accounting may be off                       |
| **Revert on zero-value transfers** | ✅     | ✅            | No issue with SafeERC20                     |
| **Flash mint**                     | ✅     | ✅            | Not a problem for Folio                     |
| **Missing return values**          | ✅     | ✅            | SafeERC20 handles this                      |
| **No revert on failure**           | ✅     | ✅            | SafeERC20 handles this                      |

### Unsupported Token Types

#### Multiple Entrypoints

Tokens with non-standard transfer functions:

```solidity theme={null}
// ❌ Not supported
contract TUSDOld {
    function transfer(address to, uint amount) external;
    function transferProxy(address from, address to, uint amount) external;
}
```

#### Pausable / Blocklist

Tokens that can be paused or have blocklists:

```solidity theme={null}
// ❌ Not supported
contract USDC {
    bool public paused;
    mapping(address => bool) public isBlacklisted;
    
    function transfer(address to, uint amount) external {
        require(!paused, "Paused");
        require(!isBlacklisted[msg.sender], "Blacklisted");
        // ...
    }
}
```

**Risk**: Folio could become stuck if tokens are paused or the Folio address is blacklisted.

#### Fee-on-Transfer

Tokens that charge a fee on transfer:

```solidity theme={null}
// ❌ Not supported
contract FeeToken {
    uint256 public transferFee = 100; // 1%
    
    function transfer(address to, uint amount) external {
        uint256 fee = amount * transferFee / 10000;
        balances[to] += amount - fee;
        balances[feeRecipient] += fee;
    }
}
```

**Risk**: Balance accounting breaks as actual received amount differs from transfer amount.

#### ERC777 / Callback Tokens

Tokens with transfer hooks:

```solidity theme={null}
// ❌ Not supported
contract ERC777Token {
    function transfer(address to, uint amount) external {
        // Calls tokensToSend hook on sender
        IERC777Sender(msg.sender).tokensToSend(...);
        
        // Transfer
        balances[to] += amount;
        
        // Calls tokensReceived hook on recipient
        IERC777Recipient(to).tokensReceived(...);
    }
}
```

**Risk**: Reentrancy attacks via callback hooks.

### Supported with Caveats

#### Rebasing Tokens

Tokens where balances change automatically:

```solidity theme={null}
// ⚠️ Supported but accounting may be off
contract RebaseToken {
    uint256 public rebaseMultiplier = 1e18;
    
    function balanceOf(address account) external view returns (uint256) {
        return (sharesOf[account] * rebaseMultiplier) / 1e18;
    }
}
```

**Risk**: Folio's auction accounting relies on balance deltas. Large rebases between auctions can cause misreporting of bought/sold amounts.

<Warning>
  Avoid using rebasing tokens with non-incremental rebases (large jumps). Daily incremental rebases like stETH are generally acceptable, but governance should understand the accounting implications.
</Warning>

### SafeERC20 Wrapper

Folio uses OpenZeppelin's `SafeERC20` for all token operations:

```solidity theme={null}
using SafeERC20 for IERC20;

// Handles:
// - Missing return values
// - False return values (converts to revert)
// - Zero-value transfers that revert
SafeERC20.safeTransfer(token, to, amount);
SafeERC20.safeTransferFrom(token, from, to, amount);
SafeERC20.forceApprove(token, spender, amount);
```

## Trusted Filler Token Restrictions

<Warning>
  If trusted fillers are enabled, tokens must be supported by **both** the Folio and the external filler (e.g., CoW Swap). Check the trusted filler's documentation for their token compatibility requirements.
</Warning>

For CoW Swap specifically:

* Token must be listed on CoW Protocol
* Must have liquidity routing available
* Cannot be pausable or have callbacks
* Should have reasonable slippage characteristics

## Chain Assumptions

The protocol assumes specific chain characteristics:

### Block Time

```solidity theme={null}
// Assumed maximum block time
require(blockTime <= 30 seconds, "Chain not supported");
```

Auction timing mechanisms assume block times ≤ 30 seconds. Chains with longer block times may experience:

* Less precise auction pricing
* Larger time gaps in exponential decay curve
* Reduced warmup period effectiveness

### Supported Chains

* Ethereum Mainnet (12s blocks) ✅
* Base (2s blocks) ✅
* Arbitrum (0.25s blocks) ✅
* Optimism (2s blocks) ✅

## Value Range Assumptions

The protocol has defined bounds for all numeric values:

### Token Supplies

```solidity theme={null}
// Maximum token supply: 1e36
// Folio collateral: 27 decimals max
// StakingVault underlying: 21 decimals max
```

<Warning>
  Governance must ensure the Folio supply never grows beyond `1e36`. This is a hard limit to prevent overflow in calculations.
</Warning>

### Exchange Rates & Prices

```solidity theme={null}
// Rebalance limits: D18{BU/share} up to 1e27
require(limits.low > 0 && limits.high <= 1e27, "Invalid limits");

// Basket weights: D27{tok/BU} up to 1e54
require(weight.high <= 1e54, "Weight too high");

// Prices: D27{UoA/tok} up to 1e45
require(price.low > 0 && price.high <= 1e45, "Invalid price");

// Price range: Maximum 100x spread
require(price.high / price.low <= 100, "Price range too wide");
```

## Governance Safety Guidelines

### Token Removal

<Warning>
  When removing a token from the basket via `removeFromBasket()`, users have limited time to redeem before the token becomes inaccessible. Only remove tokens if they have become malicious or compromised.
</Warning>

```solidity theme={null}
// Safe removal process:
1. Announce removal with sufficient warning (days/weeks)
2. Set token weight to zero in next rebalance
3. Complete rebalance to sell all tokens
4. Call removeFromBasket() after balance reaches zero
```

### Rebalance Price Monitoring

<Warning>
  If prices move outside the initially-provided price ranges during a rebalance, MEV searchers can extract value from the Folio. The `AUCTION_LAUNCHER` must actively monitor markets and end dangerous rebalances.
</Warning>

```solidity theme={null}
// AUCTION_LAUNCHER responsibility
if (currentPrice < initialPriceRange.low || 
    currentPrice > initialPriceRange.high) {
    // Value leakage imminent!
    folio.endRebalance();
}
```

## MEV Considerations

### Auction MEV

Dutch auctions are inherently MEV-prone:

```solidity theme={null}
// Price decays over time
// First bidder at profitable price wins
// → Gas war / priority auction
```

**Mitigations:**

1. Use `PriceControl.ATOMIC_SWAP` to eliminate public MEV
2. Use trusted fillers (CoW Swap) for MEV-protected execution
3. Set narrow price ranges to limit extractable value
4. Use 30-second warmup period to enable competition

### Mint/Redeem MEV

Permissionless mint/redeem can be exploited:

```solidity theme={null}
// Sandwich attack pattern:
1. Detect profitable rebalance completion
2. Mint shares at old basket composition
3. Rebalance completes
4. Redeem at new basket composition
5. Profit from composition change
```

**Mitigations:**

* Governance should rebalance gradually (multiple small auctions)
* Large rebalances should use trusted fillers or atomic execution
* Consider mint/redeem fees to make attacks unprofitable

## Denial of Service Vectors

### Dust Donations

Governance can be griefed by dust token donations:

```solidity theme={null}
// Permissionless removal requires:
// 1. Token weight set to zero
// 2. Token balance is exactly zero

// Attacker can donate 1 wei to prevent removal
dustToken.transfer(address(folio), 1);
```

**Mitigation**: Use `DEFAULT_ADMIN_ROLE` to forcibly remove tokens.

### Async Fill DoS

```solidity theme={null}
// Attacker can DoS asyncActive check:
while (inCurrentBlock) {
    folio.createTrustedFill(...);
    folio.closeTrustedFill();
}
// asyncActive = true for the entire block
```

**Mitigation**: Consuming protocols should implement rate limiting or use synchronous checks only.

## Best Practices for Integrators

### 1. Always Check State Changes

```solidity theme={null}
function safeRead() external view returns (uint256) {
    (bool syncActive, bool asyncActive) = folio.stateChangeActive();
    require(!syncActive && !asyncActive, "State changing");
    return folio.totalSupply();
}
```

### 2. Use Slippage Protection

```solidity theme={null}
// Minting
folio.mint(shares, receiver, minSharesOut);

// Redeeming
folio.redeem(shares, receiver, assets, minAmountsOut);
```

### 3. Understand Token Risks

```solidity theme={null}
// Check token compatibility before adding to Folio
if (tokenHasPause || tokenHasBlocklist || tokenIsFeeOnTransfer) {
    revert("Incompatible token");
}
```

### 4. Monitor Deprecation

Before relying on a Folio:

```solidity theme={null}
bool deprecated = folio.isDeprecated();
require(!deprecated, "Folio deprecated");
```

## Audit History

Reserve Folio has undergone multiple security audits:

* **Version 1.0.0**: [Audit Report](https://github.com/reserve-protocol/reserve-index-dtf/releases/tag/r1.0.0)
* **Version 2.0.0**: [Audit Report](https://github.com/reserve-protocol/reserve-index-dtf/releases/tag/r2.0.0)
* **Version 4.0.0**: Latest audit (current)

Review audit reports before integrating or upgrading.

## Emergency Procedures

### Folio Deprecation

In case of critical vulnerability:

```solidity theme={null}
// DEFAULT_ADMIN_ROLE can deprecate
folio.deprecateFolio();

// Effects:
// - Minting disabled
// - Auctions cannot be opened/bid
// - Rebalancing disabled
// - Redemption still works (users can exit)
```

### Version Deprecation

DAO or emergency council can deprecate a Folio version:

```solidity theme={null}
versionRegistry.deprecateVersion(versionHash);

// Effects:
// - Cannot upgrade TO this version
// - Existing Folios continue working
// - Folio admins should upgrade to new version
```

## Related

* [Upgradeability](/advanced/upgradeability)
* [Weird ERC20s Guide](https://github.com/d-xo/weird-erc20)
* [Governance](/concepts/governance)
