[ARFC] Onboard frxUSD to Aave V3 Core Instance on Ethereum

frxUSD technical analysis

Summary

This is a technical analysis of all the smart contracts of the frxUSD asset and its main dependencies.

Disclosure: This is not an exhaustive security review of the asset like the ones done by Frax Finance, but an analysis from an Aave technical service provider on different aspects we consider critical to review before a new type of listing. Consequently, like with any security review, this is not an absolute statement that the asset is flawless, only that, in our opinion, we don’t see significant problems with its integration with Aave, apart from different trust points.


Analysis

frxUSD is categorized as a reserve-backed stablecoin on the Aave Asset Class Allowlist (AAcA). Its tokenized U.S. Treasury reserves include WTGXX, USTB, BUIDL, USDB, and USDC, managed by institutions such as WisdomTree, Superstate, BlackRock, and others. Users can mint and redeem frxUSD through approved custodians. To mint, users deposit cash-equivalent assets or backed stablecoins with a custodian, who issues an equal amount of frxUSD and sends it to the user without minting fees. For redemption, users send frxUSD to a designated custodian contract, which burns the tokens, takes any applicable fees, and returns the equivalent cash or backed assets.



For the context of this analysis, our focus has been on the following aspects, critical for the correct and secure integration with Aave:

  • A recommendation of pricing strategy to be used in the integration asset <> Aave.
  • Any miscellaneous aspect of the code we can consider of importance.
  • Analysis of the access control (ownerships, admin roles) and the nature of the entities involved in the system. Regarding the table permissions’ holders and their criticality/risk, it is done following these guidelines:
Criticality Description
CRITICAL Usually super-admin functionality: it can compromise the system by completely changing its fundamentals, leading to loss of funds if misused or exploited. E.g. proxy admin, default admin
HIGH It can control several parts of the system with some risk of losing funds. E.g., general owners or admin roles involved in the flow of funds
MEDIUM It can cause malfunction and/or minor financial losses if misused or exploited. E.g., fee setter, fee recipient addresses
LOW It can cause system malfunctions but on non-critical parts without meaningful/direct financial losses. E.g., updating descriptions or certain non-critical parameters.
Risk Description
:green_circle: The role is controlled via a mechanism we consider safe, such as on-chain governance, a timelock contract, or setups involving multi-sigs under certain circumstances.
:yellow_circle: The role is controlled in a way that could expose the system and users to some risk depending on the actions it can control.
:red_circle: The role is controlled via a clearly non-secure method, representing risks for the system and users.

General points

  • The system relies on multiple contracts, with the token itself as the principal, and minting/burning management delegated to different Frax’s custody contracts with custom features.

  • Most dependencies in the system are from OZ for tokenization, access control, security, and upgradability; Chainlink-style aggregator interfaces in the oracle-backed custodian; and LayerZero OFT for cross-chain transfers.

  • For access control, it uses ownable 2-step pattern.

  • For proxies, it uses the OZ Transparent Proxy.

  • The upgradable admin and owner of system’s contract is the Safe 3-of-5.

  • The system relies on trust assumptions regarding the multisig owner for upgrades, minter permissions, and changes to custodian parameters.


Contracts

The following is a non-exhaustive overview of the main smart contracts involved with frxUSD.



FrxUSD

The FrxUSD contract is an ERC20 stablecoin implementation with OZ Ownable2Step access control that manages minting, freezing, and pausing. Permissioned minters (custodian vaults and a LayerZero OFT adapter) can mint/burn unlimited frxUSD tokens. It’s an OZ Transparent Proxy.

Role Holder(s) Function Criticality Risk
Upgradable Admin proxyAdminSafe 3-of-5 upgradeTo, upgradeToAndCall CRITICAL :yellow_circle:
owner Safe 3-of-5 addMinter, removeMinter, freeze, freezeMany, thaw, thawMany, burn, burnMany, pause, unpause HIGH :yellow_circle:
minters Safe 3-of-5, FrxUSDCustodianWithOracle, FrxUSDCustodian (0xE827…4E9c), FrxUSDCustodian (0xFE2E…0a29), FrxUSDCustodianUsdc, FrxUSDCustodianWithReceiver, FraxOFTMintableAdapterUpgradeable minter_mint, minter_burn_from HIGH :yellow_circle:

  • Access Control
    • The owner can add and remove addresses to the minters list by calling the addMinter(address) and removeMinter(address) functions.

    • The owner can freeze/unfreeze funds in addresses via the freeze(address) and thaw(address) functions. There are also batch functions for these actions.

    • The owner can pause/unpause system actions using the pause() and unpause() methods.

  • Minting and burn
    • Permissioned minters can mint and burn any frxUSD tokens amount via minter_mint(address to, uint amount) and minter_burn_from(address from, uint amount) methods.

    • The owner can burn any token’s amount from any address via the burn(address, amount) or burnMany(address[], amounts[]) functions.


Custodians (minters)

The frxUSD Custodians are contracts with mint/burn permissions on the frxUSD token. The base custodian (FrxUSDCustodian contract) is an ERC4626-like vault that mints/burns frxUSD against a custodian token at a 1:1 rate, with configurable fees and mint caps. Other custodians inherit the base FrxUSDCustodian contract, with some implementing custom redemption hooks with ERC721 support, mint/burn based on an oracle price, and async USDC/WTGXX flows, adding operator-gated shuffling and redemption paths. Below is a reference table with each Custodian vault token, caps, and mint and redemption fees.

Custodian vault Custodian token Mint Cap Mint Fee Redemption Fee
FrxUSDCustodian (0xFE2E…0a29) USDB 100k 0 0
FrxUSDCustodian (0xE827…4E9c) BUIDL 100k 0 1 bps
FrxUSDCustodianWithOracle USTB 5M 0 1 bps
FrxUSDCustodianWithReceiver WTGXX 100k 0 1 bps
FrxUSDCustodianUsdc USDC 200M 0 0

FrxUSDCustodian

The FrxUSDCustodian contract is the base custodian contract, an ERC4626-like vault with ownable access control for configuring fees and mint caps. Users can mint or redeem frxUSD for the custodian token at a 1:1 ratio at any time. It’s an upgradable OZ Transparent Proxy.

Role 0xE827…4E9c Holder(s) 0xFE2E…0a29 Holder(s) Function Criticality Risk
upgradable admin proxyAdminSafe 3-of-5 proxyAdminSafe 3-of-5 upgradeTo, upgradeToAndCall CRITICAL :yellow_circle:
owner Safe 3-of-5 Safe 3-of-5 setMintRedeemFee, setMintCap, recoverERC20 HIGH :yellow_circle:

  • Access Control
    • The owner can set the minting cap, minting and redemption fees via the setMintCap(uint amount) and setMintRedeemFee(uint mintFee, uint redeemFee) functions.

    • The owner can also rescue any token in this contract via the recoverERC20(address token, uint amount) function. The amount is then sent to the owner’s address.

  • Deposit and Redemption
    • Deposits/mints call minter_mint to issue frxUSD, and withdrawals/redeems call minter_burn_from to burn frxUSD.

    • Users can deposit BUIDL (in the 0xE827…4E9c vault) or USDB (in the 0xFE2E…0a29 vault) for frxUSD at a 1:1 ratio via the deposit(amount, receiver) function. Internally, it validates mint cap constraints, transfers the tokens to the vault, discounts minting fees if any, and calls frxUSD.minter_mint(receiver, amount), which mints frxUSD and transfers it to the receiver.

    • Users can withdraw BUIDL or USDB in their respective vaults at a 1:1 ratio by calling the redeem(amount, receiver, owner) function. Internally, it validates the vault has enough tokens, discounts redemption fees if applicable, and calls frxUSD.minter_burn_from(owner, amount), which burns frxUSD from the owner and transfers the custodian tokens to the receiver.


FrxUSDCustodianUsdc

The FrxUSDCustodianUsdc contract extends the base custodian to support async USDC/WTGXX flows, adds operator-gated swaps to RWA yield strategies, and includes a redemption hook with ERC721 receiver support (required for WTGXX transfers). It’s an upgradable OZ Transparent Proxy.

Role Holder(s) Function Criticality Risk
upgradable admin proxyAdminSafe 3-of-5 upgradeTo, upgradeToAndCall CRITICAL :yellow_circle:
owner Safe 3-of-5 setMintRedeemFee, setMintCap, recoverERC20, setMinAfterShuffle, setApprovedOperator HIGH :yellow_circle:
operators (bots) EOA (0xb84c…7D94), EOA (0x9032…bc6F) shuffleToRwa HIGH :green_circle:
WTGXX Custodian FrxUSDCustodianWithReceiver redeemWtgxx HIGH :green_circle:

  • Access Control
    • The owner extends the FrxUSDCustodian features explained previously.

    • The owner can whitelist operators (bots) via the setApprovedOperator(address, bool) function.

    • The owner can set the minimum amount of custodian token that should stay in the contract after swapping USDC for WTGXX via the setMinAfterShuffle(amount) method.

    • Operators can move excess USDC held by this contract into an RWA yield strategy while enforcing a minimum remaining USDC balance by calling the shuffleToRwa(amount, minOut, assetToShuffleTo) function. Internally, it either mints USTB with USDC to the USTB Custodian (FrxUSDCustodianWithOracle) with slippage checks, or transfers USDC to the WTGXX Custodian and triggers the WTGXX Custodian’s shuffleToWtgxx(amount) method. In both cases, the excess USDC will be deposited into a Custodian recipient wallet (USTB or WTGXX), which is later transferred directly to Circle, meaning it is redeemed for cash equivalents.

  • Deposit and Redemption
    • Deposits and redemptions works in the same way as the FrxUSDCustodian contract, explained previously.

    • The WTGXX custodian (FrxUSDCustodianWithReceiver) can call redeemWtgxx(amount) which facilitates WTGXX redemptions to USDC async. Internally it forwards the WTGXX amount to the hardcoded on-receipt address (EOA 0x63a8…cBf8).


FrxUSDCustodianWithReceiver

The FrxUSDCustodianWithReceiver contract extends the base custodian to support async USDC/WTGXX redemptions via operators. It’s an upgradable OZ Transparent Proxy.

Role Holder(s) Function Criticality Risk
upgradable admin proxyAdminSafe 3-of-5 upgradeTo, upgradeToAndCall CRITICAL :yellow_circle:
owner Safe 3-of-5 setMintRedeemFee, setMintCap, recoverERC20, setApprovedOperator, setMinAfterShuffle HIGH :yellow_circle:
operators EOA (0xb84c…7D94), EOA (0x9032…bc6F) redeemForUsdcAsync HIGH :green_circle:
USDC Custodian FrxUSDCustodianUsdc shuffleToWtgxx HIGH :green_circle:

  • Access Control
    • The owner extends the FrxUSDCustodianUsdc features explained previously, except for the shuffleToRwa() function, which is not implemented.

    • Operators can redeem WTGXX for USDC asynchronously by calling the redeemForUsdcAsync(amount) function. Internally, it transfers the WTGXX amount to the USDC Custodian and invokes the USDC Custodian’s redeemWtgxx(amount) function, which was explained previously in the FrxUSDCustodianUsdc contract section.

  • Minting and burn
    • Deposits and redemptions works in the same way as the FrxUSDCustodian contract, explained previously.

    • The USDC Custodian (FrxUSDCustodianUsdc contract) can call the shuffleToWtgxx(amount) function, which just forwards the USDC amount to the hardcoded on-receipt address (EOA 0x63a8…cBf8). This method is part of the RWA yield-strategy flow, that facilitates async USDC/WTGXX redemptions.


FrxUSDCustodianWithOracle

The FrxUSDCustodianWithOracle contract is an ownable custodian vault that mints/burns frxUSD against a custodian token, with asset/share conversion driven by a Chainlink-style oracle and freshness checks. It is deployed behind a Transparent Proxy.

The FrxUSDCustodianWithOracle extends all the FrxUSDCustodian functionalities and features the minting/burning frxUSD against the custodian token, with the exchange rate driven by a Chainlink-style oracle. It’s an upgradable OZ Transparent Proxy.

Role Holder(s) Function Criticality Risk
Upgradable Admin proxyAdminSafe 3-of-5 upgradeTo, upgradeToAndCall CRITICAL :yellow_circle:
owner Safe 3-of-5 setCustodianOracle, setMintRedeemFee, setMintCap, recoverERC20 HIGH :yellow_circle:

  • Access Control

    • The owner extends the FrxUSDCustodian features explained previously.

    • The owner can set the oracle and its maximum delay for stale prices via the setCustodianOracle(address, maxDelay) function.

  • Minting and burn

    • Deposits and redemptions work the same way as the FrxUSDCustodian contract explained previously, except that these flows refresh the oracle price through an updateOracle() modifier. It’s important to note that if the price is stale, the operation reverts.

SuperstateOracle

The SuperstateOracle contract pushes USTB NAV prices to a Chainlink Aggregator-style feed. It uses ownable access control to store NAV/s checkpoints and, in a Chainlink-style format, returns the “real-time” extrapolated price computed from the two most effective checkpoints. It’s a non-upgradable contract.

Role Holder(s) Function Criticality Risk
owner EOA addCheckpoint, addCheckpoints, setMaximumAcceptablePriceDelta HIGH :yellow_circle:

  • Access Control

    • The owner can change the maximum price delta via the setMaximumAcceptablePriceDelta(delta) function. This method limits how far a newly checkpoint nav may deviate from the last checkpoint’s nav.
  • Price data

    • The owner injects new price data by calling the addCheckpoint(timestamp, effectiveAt, navs, shouldOverride) method. Internally, it validates that timestamp is in the past and effectiveAt is set to now or in the future, indicating that the injected checkpoint will be “scheduled” for use in the future. Before storing the new navs in the checkpoints list, it also verifies that the navs is within the maximum delta range and that no other NAV is scheduled, unless it’s marked (shouldOverride) to override the scheduled one.

    • The price is calculated based on the latest two effective checkpoints by measuring the absolute NAV change between them (navDelta), deriving a linear rate from the time difference between their checkpoint timestamps, and extrapolating that rate forward from the latest checkpoint timestamp to the current block timestamp using
      extrapolatedChange = (navDelta * timeSinceLastNav) / timeBetweenNavs, which is then added to or subtracted from the latest NAV depending on the direction of the previous change.


FraxOFTMintableAdapterUpgradeable

The FraxOFTMintableAdapterUpgradeable contract is a LayerZero OFT adapter that facilitates cross-chain frxUSD transfers via the LZ endpoint and tracks cross-chain supply. It’s an upgradable OZ Transparent Proxy.

Role Holder(s) Function Criticality Risk
upgradable admin proxyAdminSafe 3-of-5 upgradeTo, upgradeToAndCall CRITICAL :yellow_circle:
owner Safe 3-of-5 setPeer, setDelegate, setEnforcedOptions, setMsgInspector, setPreCrime, setInitialTotalSupply, recover HIGH :green_circle:

  • Access Control

    • The owner can configure LayerZero’s peers/options/inspectors and can recover tokens held by the adapter.
  • Bridging

    • The adapter send and receives LZ cross-chain messages of enabled peers to mint and burn frxUSD tokens.

Pricing strategy

We recommend pricing frxUSD using the Chainlink frxUSD/USD market price feed through a stable CAPO adapter. Although the reserves backing frxUSD are tokenized U.S. Treasury funds, we don’t recommend fixed-price feeds for assets being listed as collateral.


Miscellaneous

  • The system has undergone one security review by Zellic; we still recommend additional reviews.

  • Frax has an internal Bug bounty program at Bug Bounty | Fraxtal Docs.

  • Frax provides a reserves dashboard indicating the custodian composition at Frax.com.


Conclusion

We do not identify material issues with the integration of frxUSD into Aave. However, enabling the asset as collateral should remain conditional on timelock protection being added to the critical upgradeability and minting paths.
Based on our discussions with the Frax team, they indicated that they plan to introduce a timelock for contract upgrades and the addMinter path, as well as apply explicit minting caps to the 3-of-5 Safe, currently one of the active minters.
As such, we recommend waiting for these changes to be implemented before proceeding with collateral enablement.

1 Like