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

# FolioProxy and FolioProxyAdmin

> Upgradeable proxy infrastructure for Folio contracts

## Overview

The Folio protocol uses an upgradeable proxy pattern with two contracts:

1. **FolioProxy**: ERC1967-compliant transparent proxy
2. **FolioProxyAdmin**: Admin contract managing upgrades with version control

This architecture enables protocol upgrades while maintaining state and user balances.

## FolioProxyAdmin

The **FolioProxyAdmin** contract manages upgrades for Folio proxies with built-in version registry integration.

### Features

* Version-controlled upgrades
* Ownership-based access control
* Deprecation protection
* Single admin per proxy

### Constructor

```solidity FolioProxy.sol theme={null}
constructor(address initialOwner, address _versionRegistry) Ownable(initialOwner)
```

<ParamField path="initialOwner" type="address">
  Initial owner of the ProxyAdmin (typically a timelock)
</ParamField>

<ParamField path="_versionRegistry" type="address">
  FolioVersionRegistry address for version validation
</ParamField>

### Upgrade to Version

Upgrade a proxy to a specific version from the registry.

<ParamField path="proxyTarget" type="address">
  Address of the FolioProxy to upgrade
</ParamField>

<ParamField path="versionHash" type="bytes32">
  Hash of the version to upgrade to
</ParamField>

<ParamField path="data" type="bytes">
  Calldata to execute after upgrade (typically for re-initialization)
</ParamField>

```solidity FolioProxy.sol theme={null}
function upgradeToVersion(
    address proxyTarget,
    bytes32 versionHash,
    bytes memory data
) external onlyOwner
```

<Warning>
  The function will revert if:

  * Version is deprecated in the registry
  * Version doesn't exist in the registry
  * Caller is not the owner
</Warning>

### Version Validation

The upgrade process includes automatic validation:

```solidity Upgrade Flow theme={null}
// 1. Check version is not deprecated
require(!folioRegistry.isDeprecated(versionHash), VersionDeprecated());

// 2. Verify version exists
require(
    address(folioRegistry.deployments(versionHash)) != address(0),
    InvalidVersion()
);

// 3. Get implementation address
address folioImpl = folioRegistry.getImplementationForVersion(versionHash);

// 4. Perform upgrade
ITransparentUpgradeableProxy(proxyTarget).upgradeToAndCall(folioImpl, data);
```

## FolioProxy

The **FolioProxy** contract is a minimal transparent proxy implementation following ERC1967.

### Features

* Transparent proxy pattern
* Immutable admin (cannot change after deployment)
* Restricted admin interface
* Fallback delegation to implementation

### Constructor

```solidity FolioProxy.sol theme={null}
constructor(address _logic, address _admin) ERC1967Proxy(_logic, "")
```

<ParamField path="_logic" type="address">
  Initial implementation address (Folio contract)
</ParamField>

<ParamField path="_admin" type="address">
  ProxyAdmin address (immutable after deployment)
</ParamField>

<Info>
  The admin is stored in the ERC1967 admin slot and cannot be changed after deployment.
</Info>

### Proxy Behavior

The proxy uses a custom `_fallback()` implementation:

```solidity FolioProxy.sol theme={null}
function _fallback() internal virtual override {
    if (msg.sender == ERC1967Utils.getAdmin()) {
        // Admin can only call upgradeToAndCall
        require(
            msg.sig == ITransparentUpgradeableProxy.upgradeToAndCall.selector,
            ProxyDeniedAdminAccess()
        );

        (address newImplementation, bytes memory data) = abi.decode(
            msg.data[4:],
            (address, bytes)
        );

        ERC1967Utils.upgradeToAndCall(newImplementation, data);
    } else {
        // All other callers are delegated to implementation
        super._fallback();
    }
}
```

### Access Control

<ParamField path="Admin" type="address">
  Can only call `upgradeToAndCall()` - no access to implementation functions
</ParamField>

<ParamField path="Users" type="address">
  All calls are delegated to the implementation contract
</ParamField>

## Upgrade Process

### Step-by-Step Upgrade

1. **Deploy New Implementation**
   ```solidity theme={null}
   Folio newImplementation = new Folio();
   ```

2. **Register Version** (via FolioVersionRegistry)
   ```solidity theme={null}
   versionRegistry.registerVersion(newDeployer);
   ```

3. **Prepare Upgrade Data** (if needed)
   ```solidity theme={null}
   bytes memory initData = abi.encodeWithSignature(
       "reinitialize(uint256)",
       newVersion
   );
   ```

4. **Execute Upgrade** (via ProxyAdmin)
   ```solidity theme={null}
   bytes32 versionHash = keccak256(abi.encodePacked("4.0.0"));
   proxyAdmin.upgradeToVersion(folioProxy, versionHash, initData);
   ```

### Governance Upgrade Example

```solidity Timelock Upgrade theme={null}
// Proposal to upgrade Folio
address[] memory targets = new address[](1);
targets[0] = address(proxyAdmin);

uint256[] memory values = new uint256[](1);
values[0] = 0;

bytes[] memory calldatas = new bytes[](1);
calldatas[0] = abi.encodeWithSignature(
    "upgradeToVersion(address,bytes32,bytes)",
    folioProxy,
    versionHash,
    ""
);

governor.propose(
    targets,
    values,
    calldatas,
    "Upgrade Folio to v4.0.0"
);
```

## Storage Layout

### ERC1967 Storage Slots

The proxy follows ERC1967 standard storage slots:

```solidity Storage Slots theme={null}
// Implementation slot
bytes32 IMPLEMENTATION_SLOT = 
    bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1);

// Admin slot
bytes32 ADMIN_SLOT = 
    bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1);
```

<Warning>
  Never use these slots in the implementation contract to avoid storage collisions.
</Warning>

## Security Considerations

### Transparent Proxy Pattern

The transparent proxy ensures:

* Admin cannot call implementation functions
* Users cannot call admin functions
* No function selector collisions

### Admin Immutability

<Info>
  The admin address is set once during deployment and cannot be changed. This ensures:

  * Predictable upgrade permissions
  * No admin takeover attacks
  * Clear governance structure
</Info>

### Version Control

Integration with FolioVersionRegistry provides:

* **Deprecation Protection**: Prevents upgrades to deprecated versions
* **Version Validation**: Ensures implementation exists before upgrade
* **Audit Trail**: All versions registered on-chain

## Events

The proxy emits standard ERC1967 events:

<ResponseField name="Upgraded" type="event">
  Emitted when implementation is upgraded

  **Parameters:**

  * `implementation` - New implementation address
</ResponseField>

<ResponseField name="AdminChanged" type="event">
  Emitted when admin changes (only during deployment)

  **Parameters:**

  * `previousAdmin` - Previous admin (address(0) initially)
  * `newAdmin` - New admin address
</ResponseField>

## Errors

<ResponseField name="ProxyDeniedAdminAccess" type="error">
  Thrown when admin tries to call non-upgrade functions
</ResponseField>

<ResponseField name="VersionDeprecated" type="error">
  Thrown when trying to upgrade to a deprecated version
</ResponseField>

<ResponseField name="InvalidVersion" type="error">
  Thrown when version doesn't exist in registry
</ResponseField>

## Best Practices

<Tip>
  **Upgrade Safety**

  * Always test upgrades on testnet first
  * Use initialization functions for new storage variables
  * Follow the upgrade pattern for storage layout
  * Verify version registration before upgrade proposals
</Tip>

<Tip>
  **Admin Management**

  * Use timelock contracts as ProxyAdmin owner
  * Implement multi-sig or governance for upgrade decisions
  * Monitor version registry for deprecations
  * Keep upgrade proposals transparent
</Tip>
