[ARFC] Onboarding sfrxETH to Aave V3 Ethereum

sfrxETH security/technical analysis



Introduction

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

Disclosure: This is not an exhaustive security review of the asset like the ones done by the Frax team, but an analysis from an Aave technical service provider on different aspects we consider critical to review before new listings. Consequently, like with any security review, this is not an absolute statement that the asset is flawless or not, only a disclosure of any potential problem or trust assumptions.

We appreciate the responsiveness of the Frax team answering all our questions during the process.




Analysis


sfrxETH is a staked version of frxETH that accrues the staking yield ETH PoS validation.

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

  • Mechanism to update the exchange rate of the asset for the underlying ETH.
  • Access control (ownerships, admin roles) and nature of the entities involved.
  • Any miscellaneous aspect of the code and system’s security we can consider of importance.


General points

  • The main contracts are non-upgradable, with well-known dependencies like OZ or Solmate.
  • The system’s admin roles are mainly controlled by the Frax Team 3-of-5 Gnosis Safe and a Timelock smart contract with a 2-day lock period owned by the Frax Comptroller (Gnosis Safe 3-of-5).


Contracts

The following is a non-exhaustive overview of the main smart contracts involved in sfrxETH.


sfrxETH

A staked token version of frxETH that accrues staking rewards. The exchange rate of frxETH per sfrxETH increases over time as staking rewards are added to the vault.

  • It’s a non-upgradable xERC4626 inheriting from a Solmate ERC4626 Vault contract.
  • The exchange rate is obtained by calling the pricePerShare() function. Where the formula is totalAssets() / total sfrxETH supply.
  • totalAssets() is the sum of storedTotalAssets + lastRewardAmount_, where lastRewardAmount_ is distributed linearly during the rewards cycle. This cycle is a time period of seven days during which the exchange rate increases linearly, in order to make this process progressive and protect the system.
  • Any rewards accrued from staking ETH are sent to the Gnosis Safe address, converted to frxETH, and then transferred to the sfrxETH to account for rewards in the next cycle. There’s no limit to the amount of frxETH that can be added, but since the rewards are distributed linearly, this may reduce a rapid increase in the exchange rate within a short period of time, spreading it out over seven days.
  • The principal interaction functions (mint, deposit, redeem, withdraw) have an andSync modifier that calls syncRewards() when the reward cycle is completed. syncRewards() function takes into account any additional frxETH injected into the Vault over its internal balance. The next reward value is calculated as asset.balanceOf(address(this)) - storedTotalAssets_ - lastRewardAmount_. Then the storedTotalAssets_ is incremented with the lastRewardAmount_, and the lastRewardAmount_ becomes the nextRewards.

frxETH

A token pegged to ETH, not accrue staking rewards.

  • It’s a non-upgradeable ERC20 contract controlled by a 3-of-5 Gnosis safe and a Timelock, control regulated in the onlyByOwnGov() modifier.
  • The functions minter_mint() and minter_burn_from() are used for minting and burning frxETH. Both functions have an onlyMinters modifier, which allows the frxETHMinter contract and the Gnosis safe to call them.
  • The Timelock and the Gnosis safe can add/remove minters, due to the previously mentioned onlyByOwnGov() modifier.
  • Mint/burn functions are not limited by a maximum amount, meaning authorised addresses can mint any amount of frxETH.

frxETHMinter

Contract to mint frxETH and sfrxETH from ETH.

  • It’s a non-upgradeable contract controlled by a 3-of-5 Gnosis safe and a Timelock.
  • frxETH is minted to the user who sends/deposits ETH in this contract.
  • It’s possible to mint sfrxETH for ETH by calling the submitAndDeposit() function.
  • This contract also keeps track of all allowed validators added by the admins via the addValidator() function.
  • Whenever 32 ETH become available for staking, the depositEther() function is called (anyone can call it), and the ETH is sent to the ETH 2.0 deposit contract to be delegated to a validator (obtained by calling getNextValidator()). The contract restricts each validator to receive only 32 ETH.

FraxEtherRedemptionQueue

Contract for redeeming ETH from frxETH or sfrxETH.

  • It’s a non-upgradeable contract controlled by the general Timelock.
  • Users can send their frxETH at any time by calling the enterRedemptionQueue() function or srfxETH (via the enterRedemptionQueueViaSfrxEth() function) for a redemption NFT, which adds the requested amount to the redemption queue.
  • The frxETH redemption queue waiting time is 11 days and can fetched in the queueLengthSecs variable by calling redemptionQueueState().
  • After the waiting time, users can redeem ETH by calling the burnRedemptionTicketNft() function.

Miscellaneous

  • In its totality, the system has undergone one audit by Code4rena.
  • The possibility of minting an unlimited amount of frxETH is quite dangerous. To reduce the risk, the Frax team has set the mint roles to a Timelock and the Frax Multisig. However, the Timelock admin and the Frax Multisig share three common signers, and this overlap undermines the security and independence of both systems. Generally, the community should be aware that important trust on signers of the system’s multi-sig is expected.



Conclusion

sfrxETH is an asset with good maturity in the market and no incident, however we believe the following points could be improved:

  • Having access for both a timelock and multi-sig on the onlyByOwnGov() is problematic, as it makes possible to skip any timelock on a critical functionality like adding new minters. We recommend make this more strict to always respect the timelock.
  • Adding extra limitations for minting dynamics, for example having a maximum mint per period of time/blocks.
  • Adding extra limitations for the amount of rewards that can be “injected” for a rewards cycle.
  • Study the addition of higher multi-sig threshold, but prioritising on-chain protections like the previously mentioned.
  • We believe at least an extra audit of the system apart for the existing Code4rena should be done.

Considering the criticality of ETH LSTs listings on Aave v3, our recommendation is for the community to wait until the previous points are addressed.

3 Likes