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 |
|---|---|
| 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. | |
| The role is controlled in a way that could expose the system and users to some risk depending on the actions it can control. | |
| 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 | proxyAdmin → Safe 3-of-5 | upgradeTo, upgradeToAndCall | CRITICAL | |
| owner | Safe 3-of-5 | addMinter, removeMinter, freeze, freezeMany, thaw, thawMany, burn, burnMany, pause, unpause | HIGH | |
| minters | Safe 3-of-5, FrxUSDCustodianWithOracle, FrxUSDCustodian (0xE827…4E9c), FrxUSDCustodian (0xFE2E…0a29), FrxUSDCustodianUsdc, FrxUSDCustodianWithReceiver, FraxOFTMintableAdapterUpgradeable | minter_mint, minter_burn_from | HIGH |
- Access Control
-
The owner can add and remove addresses to the minters list by calling the
addMinter(address)andremoveMinter(address)functions. -
The owner can freeze/unfreeze funds in addresses via the
freeze(address)andthaw(address)functions. There are also batch functions for these actions. -
The owner can pause/unpause system actions using the
pause()andunpause()methods.
-
- Minting and burn
-
Permissioned minters can mint and burn any frxUSD tokens amount via
minter_mint(address to, uint amount)andminter_burn_from(address from, uint amount)methods. -
The owner can burn any token’s amount from any address via the
burn(address, amount)orburnMany(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 | proxyAdmin → Safe 3-of-5 | proxyAdmin → Safe 3-of-5 | upgradeTo, upgradeToAndCall | CRITICAL | |
| owner | Safe 3-of-5 | Safe 3-of-5 | setMintRedeemFee, setMintCap, recoverERC20 | HIGH |
- Access Control
-
The owner can set the minting cap, minting and redemption fees via the
setMintCap(uint amount)andsetMintRedeemFee(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_mintto issue frxUSD, and withdrawals/redeems callminter_burn_fromto 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 callsfrxUSD.minter_mint(receiver, amount), which mints frxUSD and transfers it to thereceiver. -
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 callsfrxUSD.minter_burn_from(owner, amount), which burns frxUSD from theownerand transfers the custodian tokens to thereceiver.
-
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 | proxyAdmin → Safe 3-of-5 | upgradeTo, upgradeToAndCall | CRITICAL | |
| owner | Safe 3-of-5 | setMintRedeemFee, setMintCap, recoverERC20, setMinAfterShuffle, setApprovedOperator | HIGH | |
| operators (bots) | EOA (0xb84c…7D94), EOA (0x9032…bc6F) | shuffleToRwa | HIGH | |
| WTGXX Custodian | FrxUSDCustodianWithReceiver | redeemWtgxx | HIGH |
- 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’sshuffleToWtgxx(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 WTGXXamountto 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 | proxyAdmin → Safe 3-of-5 | upgradeTo, upgradeToAndCall | CRITICAL | |
| owner | Safe 3-of-5 | setMintRedeemFee, setMintCap, recoverERC20, setApprovedOperator, setMinAfterShuffle | HIGH | |
| operators | EOA (0xb84c…7D94), EOA (0x9032…bc6F) | redeemForUsdcAsync | HIGH | |
| USDC Custodian | FrxUSDCustodianUsdc | shuffleToWtgxx | HIGH |
- 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 WTGXXamountto the USDC Custodian and invokes the USDC Custodian’sredeemWtgxx(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 USDCamountto 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 | proxyAdmin → Safe 3-of-5 | upgradeTo, upgradeToAndCall | CRITICAL | |
| owner | Safe 3-of-5 | setCustodianOracle, setMintRedeemFee, setMintCap, recoverERC20 | HIGH |
-
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.
- Deposits and redemptions work the same way as the FrxUSDCustodian contract explained previously, except that these flows refresh the oracle price through an
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 |
-
Access Control
- The owner can change the maximum price delta via the
setMaximumAcceptablePriceDelta(delta)function. This method limits how far a newly checkpointnavmay deviate from the last checkpoint’s nav.
- The owner can change the maximum price delta via the
-
Price data
-
The owner injects new price data by calling the
addCheckpoint(timestamp, effectiveAt, navs, shouldOverride)method. Internally, it validates thattimestampis in the past andeffectiveAtis set to now or in the future, indicating that the injected checkpoint will be “scheduled” for use in the future. Before storing the newnavsin the checkpoints list, it also verifies that thenavsis 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 | proxyAdmin → Safe 3-of-5 | upgradeTo, upgradeToAndCall | CRITICAL | |
| owner | Safe 3-of-5 | setPeer, setDelegate, setEnforcedOptions, setMsgInspector, setPreCrime, setInitialTotalSupply, recover | HIGH |
-
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.

