circle-info
The Frgmnt Project is Coming Soon!
Page cover

coin-blankToken System Specifications

Overview

Token
Type
Purpose
Standard

fUSD

Stablecoin

Entry asset, 1:1 backed by approved stablecoins

ERC20 (Upgradeable)

sfUSD

Share Token

Yield-bearing staked position

ERC20 (Upgradeable)

Both tokens are upgradeable via the UUPS (Universal Upgradeable Proxy Standard) pattern, allowing the protocol to evolve while preserving user balances and state.


fUSD : Frgmnt Stable Asset

Token Details

Property
Value

Name

fUSD

Symbol

fUSD

Decimals

18

Standard

ERC20Upgradeable

Upgrade Pattern

UUPS

Minting Mechanism

fUSD is minted through deposits of approved stablecoins. The mint amount is calculated using oracle-sourced USD prices:

fUSD Minted = Deposit Amount × Oracle Price

Approved Assets: The protocol maintains a whitelist of accepted stablecoins (e.g., USDC, DAI, USDT). Each asset must be explicitly approved through governance before it can be used for minting.

Deposit Flow

  1. User approves stablecoin spending for fUSD contract

  2. User calls deposit with approved stablecoin

  3. Contract validates asset is on the allowlist

  4. Oracle provides current USD price for the asset

  5. Deposit transfers to the sfUSD sink (staking pool)

  6. fUSD minted to user at equivalent USD value

Access Control

Role
Permissions

DEFAULT_ADMIN_ROLE

Grant and revoke other roles

GOVERNANCE_ROLE

Manage oracle, sfUSD sink, allowed assets, authorize upgrades

EMERGENCY_ROLE

Pause/unpause deposits

Security Features

  • Reentrancy Guard : Prevents recursive call exploits

  • Pausable : Emergency pause capability for deposits

  • Role-Based Access : Granular permission system


sfUSD : Staked FUSD

Token Details

Property
Value

Name

Staked fUSD (configurable)

Symbol

sfUSD (configurable)

Decimals

18

Standard

ERC20Upgradeable

Upgrade Pattern

UUPS

Share Pricing

sfUSD uses a share-based model where the token price represents the value of one sfUSD share in terms of underlying assets:

As the pool generates yield, the token price increases, meaning each sfUSD share is worth more over time.

Staking (fUSD → sfUSD)

When staking fUSD, shares are minted based on the current token price:

Entry Fee: Applied as additional shares minted to the manager; not deducted from the user's deposit. This means users receive shares worth their full deposit amount.

Unstaking (sfUSD → Assets)

Immediate Mode: Users burn sfUSD and receive proportional pool assets instantly.

Exit Fee: Applied as shares burned from the user before calculating withdrawal amount.

Queued Mode: For pools with queued withdrawals enabled:

  1. requestWithdraw(shares) Lock shares, receive request ID

  2. Manager calls finalizeWithdraw(requestId) Burns shares, locks fUSD amount

  3. claimWithdraw(requestId) User receives finalized fUSD

Yield Mechanics

sfUSD implements a dual yield system that separates principal appreciation from harvestable rewards:

1. Token Price Growth (Principal Appreciation)

The core share price increases as the pool generates value:

This happens automatically as:

  • Strategy positions generate PnL

  • The pool collects fees from other activities

  • External yield sources accrue to the pool

2. Harvestable Yield Accumulator

A separate mechanism converts token price growth into claimable fUSD rewards using a global accumulator pattern:

Variable
Purpose

yieldPerShare

Cumulative fUSD yield per share (scaled 1e18)

lastTokenPriceForYield

Token price checkpoint for yield calculation

userYields[address].rewardDebt

User's last yieldPerShare checkpoint

userYields[address].claimable

Accumulated fUSD pending harvest

How it works:

On every user interaction (stake, unstake, harvest), the updateFeesAndYieldFor modifier:

  1. Mints any pending manager fees

  2. Calculates current token price

  3. If price increased since lastTokenPriceForYield:

  4. For the specific user:

Harvesting:

Users call harvest() to claim accumulated fUSD without touching their sfUSD shares:

This design means users can choose to:

  • Hold sfUSD and let both principal and harvestable yield compound

  • Harvest regularly to realize fUSD gains while maintaining their staked position

  • Unstake to exit entirely with their proportional share of pool assets

Fee Minting

Performance and management fees are minted as new sfUSD shares to the manager and DAO:

Fee Type
Mechanism

Performance Fee

Percentage of token price growth since tokenPriceAtLastFeeMint

Management Fee

Time-weighted streaming fee based on lastFeeMintTime

The DAO receives a percentage of total fees (configured in factory), remainder goes to the manager. This dilutes all holders proportionally rather than transferring from individual accounts.

Withdrawal Modes

Mode
Behavior

Immediate

Direct burn-for-assets, subject to liquidity and cooldown

Queued

Lido-style: lock shares → manager finalizes → user claims

Pool managers can toggle between modes based on pool strategy requirements.

Queued Withdrawal Flow:

  1. Request (requestWithdraw): User locks sfUSD shares, exit fee taken upfront in shares

  2. Finalize (finalizeWithdraw): Manager burns the locked shares, calculates fUSD amount at current price

  3. Claim (claimWithdraw): User receives the finalized fUSD amount

This pattern allows managers to handle illiquid positions gracefully without forcing immediate liquidation.


Pool Manager Logic Integration

Both tokens integrate with PoolManagerLogic for:

Asset Management

Valuation

Fee Configuration

Fee Changes: Fee increases require an announcement period before they can be committed, protecting users from sudden changes:

  1. announceFeeIncrease() Propose new fees

  2. Wait for timelock period

  3. commitFeeIncrease() Apply new fees

  4. Or renounceFeeIncrease() Cancel proposal

Access Control

Pools can be configured as private (whitelist only) or public, with optional NFT-gated access.


Guard System

All external protocol interactions are validated through a two-layer guard system managed by the Governance contract:

Contract Guards

Assigned per external contract address (e.g., Aave, Uniswap routers). When sfUSD calls execTransaction():

  1. The guard's txGuard() function parses the calldata

  2. Returns a txType (transaction classification) and isPublic flag

  3. If txType > 0, the transaction is allowed

  4. If not public, only manager or trader can execute

Available contract guards include:

  • AaveLendingPoolGuardV2/V3 Deposit, withdraw, borrow, repay

  • UniswapV2RouterGuard Swaps and liquidity operations

  • UniswapV3RouterGuard V3 swaps with path validation

  • MorphoContractGuard Morpho lending operations

  • CompoundV3CometContractGuard Compound V3 supply/withdraw

Asset Guards

Assigned per asset type ID. Handle balance calculation and withdrawal processing for different asset classes:

Transaction Execution Flow

Post-Transaction Hooks

Guards implementing ITxTrackingGuard can run logic after transaction execution:

  • Uniswap V3 NFT Guard: Tracks minted/burned NFT position IDs

  • Aave V3 L2 Guard: Validates health factor stays above 1.01


Events

fUSD Events

Event
Description

Deposit(user, asset, amount, fusdMinted)

User deposited stablecoins for fUSD

sfUSD Events

Event
Description

Stake(user, fusdAmount, mintedShares, entryFeeShares)

User staked fUSD

Harvest(user, fusdAmount)

User claimed yield

WithdrawRequested(id, user, sharesLocked, exitFeeShares)

Queued withdrawal initiated

WithdrawFinalized(id, fusdAmount)

Manager finalized withdrawal

WithdrawClaimed(id, user, fusdAmount)

User claimed withdrawal

ManagerFeeMinted(pool, manager, available, daoFee, managerFee, tokenPrice)

Fees minted

TransactionExecuted(pool, manager, txType, time)

Guarded transaction completed


Security Considerations

Reentrancy Protection

Both tokens implement ReentrancyGuardUpgradeable on all state-changing external functions.

Cooldown Mechanisms

sfUSD implements a weighted cooldown system to prevent flash-loan exploits:

Storage Variable
Purpose

lastDeposit[address]

Timestamp of user's last stake

lastExitCooldown[address]

Calculated cooldown duration for user

Cooldown Calculation:

When staking, the cooldown is weighted based on new vs existing position size:

Transfer Restriction:

The _update() hook blocks transfers if cooldown is active, unless the recipient is whitelisted:

Upgrade Safety

Storage layout must be preserved across upgrades:

  • Never remove or rename existing state variables

  • Append new variables before __gap

  • Maintain __gap array for future expansion

Decimal Handling

All calculations account for varying decimals across stablecoins. Oracle prices normalize to 18 decimals for consistent math.


Contract Addresses

Addresses will be published here after mainnet deployment.

Contract
Network
Address

fUSD Proxy

BASE - 8453

TBD

sfUSD Proxy

BASE - 8453

TBD

PoolManagerLogic

BASE - 8453

TBD

Governance

BASE - 8453BASE - 8453

TBD


Integration Guide

Reading Token Price

Calculating Share Value

Checking Claimable Yield

Staking fUSD

Harvesting Yield

Unstaking (Immediate Mode)

Last updated