srUSDe (Strata) technical analysis
Summary
This is a technical analysis of all the smart contracts of the srUSDe asset and its main dependencies.
Disclosure: This is not an exhaustive security review of the asset like the ones done by Strata Team, 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
Senior USDe (srUSDe) is a yield-bearing token backed by USDe and represents the senior risk tranche within Strata’s system, which is composed of senior and junior tranches. The senior tranche receives a guaranteed yield tied to the benchmark rate, with uncapped upside to sUSDe APY, and pays a risk premium to the junior tranche for protection. Junior receives the base yield from sUSDe plus the risk premium paid by the senior tranche, adjusted by the TVL ratio, and absorbs shortfalls if sUSDe APY drops below the benchmark. Users can deposit USDe, sUSDe, and pUSDe to receive srUSDe. While they can redeem sUSDe immediately, they must wait for Ethena’s unstaking period to redeem USDe.
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 that can be considered important.
- 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 Strata system relies on a set of upgradable contracts, with main dependencies from OZ for access control, tokenization, math, and upgradability. It also uses the PRBMath library.
-
The srUSDe and jrUSDe are receipt tokens that implement the OZ ERC4626 pattern.
-
For proxies, it uses OZ Transparent pattern.
-
The system upgradability is controlled by a 2-day Timelock.
-
General access control is managed via the Access Controlled contract, which is a wrapper around the OZ access control. The admin is shared between timelocks and a safe wallet.
Contracts
The following is a non-exhaustive overview of the main smart contracts involved with srUSDe.
srUSDe (Tranche)
The Senior tranche srUSDe is the core system’s contract. It implements the OZ ERC4626, which users interact with to mint and burn srUSDe shares by depositing USDe and sUSDe. It forwards deposits and withdrawals to StrataCDO, orchestrated via the sUSDeStrategy. The Junior tranche (jrUSDe) uses the same contract infrastructure (Tranche) as srUSDe. It is an upgradable Transparent Proxy with ownable access control via the AccessControlled contract.
| Permission Owner | functions | Criticality | Risk |
|---|---|---|---|
| Upgradable admin: Proxy Admin → 2-day Timelock | upgradeAndCall | CRITICAL | |
| owner: 2-day Timelock | setAccessControlManager, setTwoStepConfigManager | HIGH | |
| StrataCDO | configure | HIGH |
- Access Control
-
The owner can configure the AccessControlManager and TwoStepConfigManager addresses via
setAccessControlManager(address)andsetTwoStepConfigManager(address)functions respectfully. -
The StrataCDO contract can call
configure(), which sets the maximum allowance of the underlying assets toward the sUSDeStrategy contract. This is called once.
-
- Deposit and Redemptions
-
All deposit and redemption operations first updates the accounting index via
cdo.updateAccounting(), syncing the total assets under the strategy’s control. After the inflow/outflow of assets into the strategy, thecdoadjusts the NAV for Senior and Junior tranches via theaccounting.updateBalanceFlow()method. -
Users can deposit USDe and sUSDe via the
deposit(token, tokenAmount, receiver)function. Internally, it calculates the user’s srUSDe shares viastrategy.convertToAssets(token, tokenAmount), mints them, and transfers them to thereceiver. -
The deposit assets flow to a Strategy contract where they are transformed into sUSDe.
-
Users can redeem sUSDe instantly via the
redeem(token, shares, receiver, owner)function. Internally, it calculates thebaseAssetsviapreviewRedeem(shares)and uses them to calculate the assetsstrategy.convertToTokens(token, baseAssets), burns theowner’s srUSDe shares and transfers sUSDe to the ERC20Cooldown contract. Since the cooldown period for withdraws of sUSDe is zero, the ERC20Cooldown contract transfers the sUSDe to the receiver immediately. -
Users who want to redeem USDe are subject to Ethena’s unstaking period. In that case, the sUSDe goes to the UnstakeCooldown contract, which handles the unstaking period, and later users can finalize and claim USDe.
-
- Exchange Rate
-
The exchange rate of srUSDe <> USDe is calculate through the StrataCDO, Accounting and sUSDeStrategy contracts. The system uses two distinct exchange rates: one for processing new deposits and the other for finalizing redemptions.
-
Deposit exchange rate: Relies on the
previewDeposit(assets)function, which is calculated using the standard ERC4626 pattern ofassets * totalSupply() / totalAssets(). -
Redemption exchange rate: Relies into the
previewRedeem(shares)function, which takes a0.025%fee from the srUSDesharesand then uses the standard ERC4626 ofshares * totalAssets() / totalSupply(). -
The
totalAssets()is fetched fromcdo.totalAssets(), which internally queries thetotalUSDeheld by the sUSDeStrategy contract and extracts the srUSDe portion fromaccounting.totalAssets(totalUSDe)function, which splits thetotalUSDeinto srUSDe and jrUSDe portions. -
It’s important to note that totalUSDe is derived from the total sUSDe shares held by the Strategy,
sUSDe.balanceOf(strategy), and the sUSDe <> USDe exchange rate,sUSDe.convertToAssets(shares). -
By relying on
balanceOf(), the Strata system is not fully donation-resistant, meaning that sUSDe donations to the Strategy can change the generaltotalUSDevalue. -
Given the system dynamics, where the Accounting contract splits the
totalUSDein portions, the Junior tranche receives all donation because the Senior tranche -
Given the system dynamics, in a scenario where a large amount of sUSDe is donated to the Strategy, the Junior tranche would absorb the entire donation because the Senior tranche’s totalAssets gains are capped at the Senior target APR (set via risk params).
-
-
AccessControlManager
The AccessControlManager contract coordinates access control for the Strata system. It’s a non-upgradable wrapper of the OZ Access control.
| Role | Function | Criticality | Risk |
|---|---|---|---|
DEFAULT_ADMIN_ROLE: 2-day Timelock, 1-day Timelock |
grantRole, revokeRole | CRITICAL |
- Access Control
- The
DEFAULT_ADMIN_ROLEmanages all role assignments in the Strata system through thegrantRole(role, address)function. It can also revoke roles from accounts using therevokeRole(role, address)function.
- The
StrataCDO
The StrataCDO contract is the core orchestrator of the Strata system. It orchestrates the Senior and Junior tranches, accounting, and sUSDe strategy; Deposits and withdrawals are routed through the CDO. It enforces tranche-level pause states and exit fees. It is an upgradeable OZ Transparent Proxy controlled via an ownable, role-based access control implemented by the AccessControlled contract.
| Role | Function | Criticality | Risk |
|---|---|---|---|
| upgrade admin: ProxyAdmin → 2-day Timelock | upgradeAndCall | CRITICAL | |
| owner: 2-day Timelock | configure, setAccessControlManager, setTwoStepConfigManager | CRITICAL | |
| srUSDe, jrUSDe | accrueFee, updateAccounting, deposit, withdraw | HIGH | |
RESERVE_MANAGER_ROLE : 1-day timelock |
reduceReserve, distributeReserve, setReserveTreasury | HIGH | |
PAUSER_ROLE: Safe 2-of-3 |
setActionStates, setJrtShortfallPausePrice | MEDIUM | |
| TwoStepConfigManager | setExitFees | MEDIUM |
- Access Control
-
The owner can configure the AccessControlManager and TwoStepConfigManager addresses via
setAccessControlManager(address)andsetTwoStepConfigManager(address)functions, respectively. -
The owner can call
configure(), which calls theconfigure()functions in the Senior and Junior tranche contracts. This is called once after deployment. -
Senior and Junior tranches can call
deposit()andwithdraw()functions, which internally orchestrate the inflow and outflow of assets to the sUSDeStrategy contract. During these operations,updateAccounting()is called, andaccrueFee()is called only during withdrawals. -
The
RESERVE_MANAGER_ROLEcan configure the treasury address via thesetReserveTreasury(address)function, redistribute reserve back to tranche TVL via thedistributeReserve(uint jrAmountIn, uint srAmountIn)function, or withdraw protocol reserve to the treasury address via thereduceReserve(token, amount)function. -
The
PAUSER_ROLEcan pause and resume deposits and redemptions in the Senior and Junior tranches via thesetActionStates(tranche, isDepositEnabled, isWithdrawEnabled)function. It can also pause Junior deposits via thesetJrtShortfallPausePrice(shortfallPrice)function; TheshortfallPricemust be below the current Junior sUSDe share price.
-
sUSDeStrategy
The Strategy manages USDe stakes into sUSDe during CDO deposits, holds sUSDe, and fulfills withdrawals via cooldown contracts for each tranche. It is an upgradeable OZ Transparent Proxy controlled via an ownable, role-based access control implemented by the AccessControlled contract.
| Role | Function | Criticality | Risk |
|---|---|---|---|
| upgrade admin: ProxyAdmin → 2-day Timelock | upgradeAndCall | CRITICAL | |
| owner: 2-day Timelock | setAccessControlManager, setTwoStepConfigManager | HIGH | |
UPDATER_STRAT_CONFIG_ROLE: 1-day Timelock |
setCooldowns | HIGH | |
| StrataCDO | deposit, withdraw, reduceReserve | HIGH |
- Access Control
-
The owner can configure the AccessControlManager and TwoStepConfigManager addresses via
setAccessControlManager(address)andsetTwoStepConfigManager(address)functions respectfully. -
The
UPDATER_STRAT_CONFIG_ROLEcan adjusts and disable tranche-specific sUSDe cooldowns via thesetCooldowns(uint sUSDeCooldownJrt, uint sUSDeCooldownSrt)function. -
StrataCDO contract can move assets into/out of the strategy through the
deposit(tranche, token, amount, baseAssets, owner)andwithdraw(tranche, token, amount, baseAssets, sender, receiver)methods and the reserve via thereduceReserve(token, amount, receiver)method.
-
Accounting
The Accounting contract tracks the tranches’ TVL, calculates Net Asset Value (NAV), and implements the so-called Dynamic Yield Split (DYS) mechanism, which splits NAV between Senior and Junior tranches, based on the risk parameters and benchmark rate set in the contract. It is an upgradeable OZ Transparent Proxy controlled via an ownable, role-based access control implemented by the AccessControlled contract.
| Role | Function | Criticality | Risk |
|---|---|---|---|
| upgrade admin: ProxyAdmin → 2-day timelock | upgradeAndCall | CRITICAL | |
| owner: 2-day timelock | setAprPairFeed, setReserveBps, setFeeRetentionBps, setMinimumJrtSrtRatio, setMinimumJrtSrtRatioBuffer | HIGH | |
UPDATER_STRAT_CONFIG_ROLE: 1-day Timelock |
setRiskParameters | HIGH | |
UPDATER_FEED_ROLE : Safe 2-of-3 |
onAprChanged | MEDIUM | |
| StrataCDO | updateAccounting, updateBalanceFlow, reduceReserve, accrueFee | MEDIUM |
- Access Control
-
The owner can configure the AprPairFeed contract using the
setAprPairFeed(address)method. -
The owner can adjust the protocol gains and the fee allocation for each tranche via the
setReserveBps(uint bps)andsetFeeRetentionBps(uint jrBps, uint srBps)methods, respectively. The owner can also adjust the minimum ratio and buffer between Junior and Senior tranches (the ratio at which Jr withdrawals are blocked and deposits are halted) by calling thesetMinimumJrtSrtRatio(uint ratio)andsetMinimumJrtSrtRatioBuffer(uint ratio)functions. -
The
UPDATER_STRAT_CONFIG_ROLEcan configure risk parameters used by the NAV calculation via thesetRiskParameters(x, y, k)function, where:x: Minimum risk premium.y: additional premium applied on top ofx.k: Exponential scaling factor controlling premium growth.
-
The
UPDATER_FEED_ROLEcan trigger an update in thesrtTargetIndexby fetching new APRs via theonAprChanged()function. -
The strataCDO calls the
updateAccounting(),updateBalanceFlow(), andaccrueFee()methods during the assets’ inflow/outflow (already explained in the StrataCDO).
-
AprPairFeed
The AprPairFeed contract aggregates base and target APR data, checking for pushed updates or pulling from a provider when stale. It is primarily used by the Accounting contract during asset inflows/outflows to update the Senior and Junior NAVs. It is an upgradeable OZ Transparent Proxy controlled via an ownable, role-based access control implemented by the AccessControlled contract.
| Role | Function | Criticality | Risk |
|---|---|---|---|
| upgrade admin: ProxyAdmin → 2-day Timelock | upgradeAndCall | CRITICAL | |
| owner: 2-day Timelock | setProvider, setRoundStaleAfter | HIGH | |
UPDATER_FEED_ROLE: Safe 2-of-3 |
updateRoundData (pull/push) | MEDIUM |
- Access Control
-
The owner can set the provider contract, from which the contract pulls data via the
setProvider(address)method. The owner can also configure the time duration after which a round is considered stale via thesetRoundStaleAfter(uint value)function. -
The
UPDATER_FEED_ROLEcan pull APR data via theupdateRoundData()or push off-chain APR data via theupdateRoundData(int aprTarget, int aprBase, uint timestamp)function. Both fall back to an internal function that checks whether the update is not stale and whether both APRs are within the acceptable bounds (-50% and 200%).
-
AaveAprPairProvider
The AaveAprPairProvider contract is a stateless APR source that computes the target APR from Aave’s USDC and USDT reserves data, and the base APR from sUSDe’s vesting. It is primarily used by the AprPairFeed contract and has no privileged access controls.
ERC20Cooldown
The ERC20Cooldown holds sUSDe during cooldown-based withdrawals and releases funds after the unlock time. It is an upgradeable OZ Transparent Proxy controlled via an ownable, role-based access control implemented by the AccessControlled contract.
| Role | Function | Criticality | Risk |
|---|---|---|---|
| upgrade admin: ProxyAdmin → 2-day Timelock | upgradeAndCall | CRITICAL | |
| owner: 2-day Timelock | setAccessControlManager, setTwoStepConfigManager | HIGH | |
COOLDOWN_WORKER_ROLE: sUSDeStrategy |
transfer, setCooldownDisabled | HIGH |
- Access Control
-
The owner can configure the AccessControlManager and TwoStepConfigManager addresses via
setAccessControlManager(address)andsetTwoStepConfigManager(address)functions respectfully. -
Cooldowns are enabled or disabled by calling the
setCooldownDisabled(token, bool)function, which is initiated via the strategy contract. Currently, there’s no cooldown for sUSDe withdrawals, so after the strategy callstransfer(), it immediately transfers the assets to the user.
-
UnstakeCooldown
UnstakeCooldown manages token-specific unstake handlers via per-user clone proxies and finalizes requests after underlying cooldowns; it is upgradeable via TransparentUpgradeableProxy with AccessControlled roles and a CRITICAL ProxyAdmin.
| Role | Function | Criticality | Risk |
|---|---|---|---|
| upgrade admin: ProxyAdmin → 2-day Timelock | upgrade | CRITICAL | |
| owner: 2-day Timelock | setImplementations, setAccessControlManager, setTwoStepConfigManager | HIGH | |
COOLDOWN_WORKER_ROLE: sUSDeStrategy |
transfer | HIGH |
- Access Control
-
The owner can configure the AccessControlManager and TwoStepConfigManager addresses via
setAccessControlManager(address)andsetTwoStepConfigManager(address)functions respectfully. -
The owner can configure token implementations that handle the unstake from sUSDe via the
setImplementations(token, address)function. -
When a user requests a USDe redemption, the strategy calls
transfer(), and the UnstakeCooldown initiates the sUSDe unstake from Ethena. After the unstake period finishes, the user callsfinalize(), which transfers USDe to the user.
-
Pricing strategy
Although srUSDe is not initially planned to be listed on Aave, it’s important to provide our recommendation, as the DAO is considering listing its PT token. Our suggestion is to price srUSDe using a CAPO adapter, applying the srUSDe <> USDe redemption exchange rate along with the USDT stable CAPO feed.
This recommendation follows the USDe price strategy across Aave instances.
We also must highlight that the Strata system is not donation-resistant, and sUSDe can manipulate the underlying assets. However, as explained in the exchange rate section, given the split dynamics, the Senior tranche caps its total assets at the target APR, and donations are redirected to the Junior tranche’s total assets. Still, we recommend not listing this asset (and definitely not jrUSDe) as collateral without a deep review of the analysis.
Miscellaneous
- The system has undergone several security reviews by Quantstamp, Cyfrin and Guardian. They can be found in the Strata documentation here.
Conclusion
We believe srUSDe has no issues with Aave integration and no major blockers for listing.

