> For the complete documentation index, see [llms.txt](https://docs.convexfinance.com/convexfinanceintegration/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.convexfinance.com/convexfinanceintegration/convex-frax-staking-cvxfxs.md).

# Convex Frax Staking (cvxFXS)

The Convex-Frax staking platform lets users trustlessly stake positions on the **Frax Finance gauge system** while borrowing Convex's boosting power via **veFXS**. The Convex system creates a unique proxy vault for each `(pool, user)` pair which only that user can operate for principal changes. This isolates deposits and keeps the user in control of their funds. Each vault is given permission to share in Convex's **veFXS** boost, which increases farming efficiency. In return, Convex takes a percentage of the **FXS** farmed and routes it via `FeeDepositV2` to the configured receivers — see the Fee flow section below.

GitHub: <https://github.com/convex-eth/frax-cvx-platform>

### Core architecture

Unlike the mainnet platform's shared-reward-pool model, the Frax platform is **vault-per-user**:

| Contract                                                     | Role                                                                   |
| ------------------------------------------------------------ | ---------------------------------------------------------------------- |
| **VoterProxy** (`voteProxy`)                                 | holds the protocol's veFXS; is the source of boosting power            |
| **Booster**                                                  | management entry point; creates vaults, manages pools, fees, and roles |
| **PoolRegistry**                                             | pool configuration (implementation, staking address, staking token)    |
| **StakingProxyBase / StakingProxyERC20 / StakingProxyUniV3** | per-user vault implementations (proxy to the Frax gauge)               |
| **MultiRewards**                                             | extra rewards contract for a pool (outside the gauge)                  |
| **FeeRegistry**                                              | holds the fee split used when fees are applied                         |
| **FeeDepositV2**                                             | receives farmed FXS fees and routes them to receivers                  |
| **cvxFxs**                                                   | the Convex-Frax token (receipt for deposited FXS that is veFXS-locked) |
| **cvxFxsStaking**                                            | staking contract for cvxFXS                                            |
| **cvxFXS/FXS pool**                                          | the canonical liquidity for cvxFXS (on the Convex platform)            |

### Vault-per-user model

1. **Convex creates a vault implementation** — an implementation contract that is a proxy staking interface to the Frax gauge. Different implementations adapt to different staking products (`StakingProxyERC20`, `StakingProxyConvex`, `StakingProxyUniV3`, joint/temple variants).
2. **Convex creates a pool and assigns an implementation** — via the Booster/PoolRegistry (fields: implementation, staking address, staking token). A `MultiRewards` contract is also created for extra rewards outside the gauge.
3. **A user creates their own vault** — `booster.createVault(_pid)` clones the pool's implementation and assigns the caller as owner (`initialize(_owner, _stakingAddress, _stakingToken, _rewardsAddress)`). One vault per `(pool, user)`; only the owner can perform principal operations (deposit/withdraw/stake).
4. **Convex enables the vault to use the protocol's veFXS boost** at creation time by telling the Frax staking contract the vault may share Convex's boosting power.
5. **The user stakes through their vault** exactly as they would interact with the main Frax staking contract (`stakeLocked`, `lockAdditional`, `lockLonger`, `withdrawLocked`).
6. **When rewards are claimed**, a fee on **FXS** is applied (see below); the rest goes to the vault owner.

Because vaults are user owned, each user determines their own lock timing, and user funds are never co-mingled. Users interact with their vault as a proxy to the Frax gauge — no wrapper tokens are minted; the vault itself is the position.

Permission model to keep in mind: **principal operations are owner-only, but reward claims are permissionless** — the vault's `getReward()` is unguarded (anyone can trigger it; rewards flow to the configured destination/redirect), so integrators should not assume a single privileged caller. There is no separate `earmark` selector on the Frax vault; reward state is updated by the claim path itself.

#### Vault interface

```javascript
//vault owner stakes on the frax gauge (locks for _secs)
await vault.stakeLocked( liquidity, secs )
await vault.lockAdditional( kek_id, addl_liq )
await vault.lockLonger( kek_id, new_ending_ts )
await vault.withdrawLocked( kek_id )

//claim
await vault.getReward()                       //claim FXS + extra rewards
await vault.getReward(false)                  //do NOT call the frax farm's claim (no compounding step here)
await vault.getReward(claim, tokenList)       //claim; tokenList filters which non-FXS vault balances are forwarded
await vault.earned()                          //returns (tokens[], amounts[])
```

### Fee flow

The `FeeRegistry` (mainnet `0xC9aCB83ADa68413a6Aa57007BC720EE2E2b3C46D`) defines the fee split in basis points. When a vault claims, the fee portion of **FXS** is sent to the fee deposit; the remainder goes to the vault owner. Current fee split:

| Component             | Fee (bps)      | Destination                                                  |
| --------------------- | -------------- | ------------------------------------------------------------ |
| cvxFXS incentive      | 1000 (10%)     | `cvxfxsReceiver` (operator-set — re-read on-chain)           |
| cvx (vlCVX) incentive | 500 (5%)       | vlCVX via the vlCVX fee receiver (`notifyRewardAmount(FXS)`) |
| platform              | 500 (5%)       | platform fee receiver                                        |
| **Total**             | **2000 (20%)** | capped at `maxFees` = 2000 bps                               |

Fees are routed via `FeeDepositV2` (`0x7A527d8bB09f7D70C148aB5DE919e9BF68a0d769`), which forwards **FXS** to the configured receivers on `distribute()`: `cvxfxsReceiver`, `vlcvxReceiver`, and `platformReceiver`. The repo also contains a `FeeReceiverCvxFxs` contract intended to forward **FXS** to the `cvxFxsStaking` reward stream — note the live `cvxfxsReceiver` on `FeeDepositV2` may differ (it is operator-set), so always read `FeeDepositV2.cvxfxsReceiver()` before describing the destination. The `FeeRegistry.getFeeDepositor(_from)` lookup supports per-source redirects.

```
vault.getReward() → FeeRegistry (Frax) split → FeeDepositV2 → configured receivers
```

Fee weights themselves are governance-adjustable — re-read the registry on-chain before publishing if you print them.

### cvxFXS token

[FxsDepositor.sol](https://github.com/convex-eth/frax-cvx-platform/blob/main/contracts/contracts/FxsDepositor.sol) (`0x8f55d7c21bDFf1A51AFAa60f3De7590222A3181e`) lets users deposit **FXS** to receive **cvxFXS**. The deposited FXS is locked into the **veFXS** system (`Escrow` `0xc8418aF6358FFddA74e09Ca9CC3Fe03Ca6aDC5b0`) and the resulting **veFXS** power is what boosts the Frax-platform user vaults. `cvxFxs` (`0xFEEf77d3f69374f66429C91d732A244f074bdf74`) is a standard ERC20 with operator-controlled mint/burn. **cvxFXS** can be staked in `cvxFxsStaking` for configured rewards, and trades against **FXS** in a Convex-managed liquidity pool — **cvxFXS** holders receive the value accrual of that yield/liquidity, not a direct per-holder boost.

### Fraxtal / cross-chain

A related deployment lives on Fraxtal (`cvxFXB`, `FraxtalBooster`, `FraxtalFxsDepositor`, `FraxtalVoterProxy`) for Frax's own L2; see the `contracts/fraxtal/` folder in the repo. Addresses for every deployment are in `contracts/contracts.json` (per-chain sections).

Mainnet key addresses: Booster `0xD8Bd5Cdd145ed2197CB16ddB172DF954e3F28659`, PoolRegistry `0x41a5881c17185383e19Df6FA4EC158a6F4851A69`, voteProxy `0x59CFCD384746ec3035299D90782Be065e466800B`. Query `poolLength()` for the live pool count.
