# \[ARFC\] Add stS to Aave v3 Sonic Instance

**URL:** <https://governance.aave.com/t/arfc-add-sts-to-aave-v3-sonic-instance/21445>\
**Category:** New Asset\
**Created:** [March 15, 2025, 8:38am UTC](https://governance.aave.com/t/arfc-add-sts-to-aave-v3-sonic-instance/21445 "2025-03-15T08:38:37Z")\
**Posts on this page:** 1\
**Showing post:** 7

<div class="post-metadata">

**Author:** ![bgdlabs](https://dub1.discourse-cdn.com/flex013/user_avatar/governance.aave.com/bgdlabs/32/1829_2.png) [@bgdlabs](https://governance.aave.com/u/bgdlabs)\
**Post date:** [April 2, 2025, 10:14am UTC](https://governance.aave.com/t/arfc-add-sts-to-aave-v3-sonic-instance/21445/7 "2025-04-02T10:14:48Z")

</div>

# stS technical analysis
  

# Summary

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

_Disclosure_: This is not an exhaustive security review of the asset like the ones done by the Beets 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

 ![sts-high-level](https://europe1.discourse-cdn.com/flex013/uploads/aave/original/2X/9/93ab04b30f46b6f64ca3c1b53a78bddf843c77d2.png)

  

stS is an LST representing $S staked via the Beets platform on the Sonic blockchain, accruing staking rewards from the $S delegated to Sonic’s PoS validators. Users can mint stS at its current exchange rate by depositing S, and redeem S later on, after a 14-day unstaking period.

  

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, in this case, S.
- A recommendation of pricing strategy to be used in the integration asset \<\> Aave.
- Any miscellaneous aspect of the code we can consider 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

- It relies on a single contract with most dependencies from OZ for access control, tokenization, upgradability, and security. The proxy contract uses the OZ UUPS upgradable pattern.
- The upgradeability admin of the system is an [OZ Timelock](https://sonicscan.org/address/0xf750f4E0813898C544A4349526206e1165F0E5d0#readContract) with a 3-week delay.
- The system uses a role-based access control split across Timelocks, Safe wallets, and one EOA (for automation purposes).

  

## Contracts

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

 ![sts-contracts-arch](https://europe1.discourse-cdn.com/flex013/uploads/aave/original/2X/4/4da76203393d65467ba25f69cb743a457e1b462c.png)

  

### [stS](https://sonicscan.org/address/0xe5da20f15420ad15de0fa650600afc998bbe3955#readProxyContract)

The main contract of the system and entry point for minting stS. Users can deposit S for stS at its current exchange rate. Later, users can request redemption and wait 14 days to withdraw S. It uses a role-based access control, where operators can delegate S to validators via the Special Fee Contract (SFC) to start accruing rewards, a claimer to claim staking rewards, and a default admin in charge of more sensitive permissions. It is an upgradable contract using the OZ UUPS pattern.

| **Permission Owner** | **functions** | **Criticality** | **Risk** |
| --- | --- | --- | --- |
| owner: [3-week Timelock](https://sonicscan.org/address/0xf750f4E0813898C544A4349526206e1165F0E5d0#readContract) | upgradeAndCall | **CRITICAL** | 🟢 |
| `DEFAULT_ADMIN_ROLE`: 1-day Timelock | setWithdrawDelay, setTreasury, setProtocolFeeBIPS, setUndelegatePaused, setUndelegateFromPoolPaused, setWithdrawPaused, setDepositPaused | **HIGH** | 🟢 |
| `OPERATOR_ROLE`: [3-of-6 Safe](https://sonicscan.org/address/0x6840Bd91417373Af296cc263e312DfEBcAb494ae#readProxyContract) | delegate, operatorInitiateClawBack, operatorExecuteClawBack, donate, pause | **HIGH** | 🟢 |
| `CLAIM_ROLE`: [EOA (0xFaC3…1718)](https://sonicscan.org/address/0xFaC37371dFAFbfA0937DF84532D1EDED08b21718) | claimRewards | **HIGH** | 🟢 |
| | | | |

- **Access Control**
  - The `DEFAULT_ADMIN_ROLE` controls the general configuration of the stS system and pauses isolated parts of the system.
  - The Default admin can update the withdrawal delay period, the protocol fee, and the treasury address that receives the fees via the `setWithdrawDelay(delay)`, `setProtocolFeeBIPS(fee)`, `setTreasury(address)` functions, respectively.
  - The default admin can pause deposits, withdrawals, and delegations via the `setDepositPaused(bool)`, `setWithdrawPaused(bool)`, `setUndelegatePaused(bool)`, `setUndelegateFromPoolPaused(bool)` functions, respectively.
  - The operator can delegate S to validators via the `delegate(validatorId, amount)` function. It delegates by calling the `SFC.delegate(validatorId, amount)` contract, which transfers the `amount` of S to the corresponding `validatorId`.
  - The operator can request a withdrawal of the delegated assets from a validator by calling the `operatorInitiateClawBack(validatorId, amount)` function. After the 14-day unstaking period, the operator can finish it by calling the `operatorExecuteClawBack(withdrawId, bool emergency)` function.
  - The operator can pause the entire system (deposits, withdrawals, delegations) via the `pause()` function.
  - The operator can increase the exchange rate via the `donate(msg.value)` function.
  - The claimer can claim staking rewards from multiple validators via the `claimRewards(validatorsIds[])` function.

- **Deposit and Withdrawals**
  - Users can deposit S via the `deposit(amount)` function. Internally, the function verifies that at least `0.01 S` was deposited, calculates the actual exchange rate via the `convertToShares(amount)` function, increases the `totalPool` for internal accounting, and then mints stS shares to the user.
  - Users can request a withdrawal via the `undelegate(validatorId, amount)` and `undelegateFromPool(amount)` functions. The main difference between them is that the first method will undelegate the `amountAssets` from the `validatorId` via the `SFC.undelegate(validatorId, withdrawId, amountAssets)` function decreases the amount from the `totalDelegated`, while the second uses the assets within the stS contract, reducing the amount from the `totalPool` storage variable.
  - The minimum amount that users can request is `0.000001 S`.
  - Both functions will burn the stS shares from the user and create a `withdrawId` for the user, with the kind of withdrawal (`POOL`, `VALIDATOR`) and the amount.
  - After the 14-day `withdrawDelay` period, users can claim their S via the `withdraw(withdrawId, bool emergency)`. The emergency flag is marked as `true` when the user is concerned that his assets have been slashed, and the amount withdrawn will be less than the actual request.

- **Exchange Rate**
  - The stS exchange rate can be obtained by the general ERC4626 function `convertToAssets(shares)`, which internally uses the `totalAssets()` and `totalSupply()`. There is also a `getRate()` function that calls `convertToAssets(1 ether)`.
  - The system relies on a proper internal accounting, where the `totalAssets()` is composed of the sum of `totalPool` (S in the stS contract), `totalDelegated` (S delegated to validators), and the `pendingClawBackAmount` (amount requested to be unstaking from validators).

- **Delegation, staking, and rewards**
  - The delegation of S to Sonic validators starts via the `delegate(validatorId, amount)` function, which will call the SFC (Special Fee Contract), which tracks validators and delegators distributing rewards to them. Internally, the stS contract will decrease the amount from `totalPool` and add to the `totalDelegated` storage variable. There is no minimum S that can be delegated.
  - The undelegation/withdrawal from the SFC contract happens in a two-step process, where first operators request it via the `operatorInitiateClawBack(validatorId, amountAssets)`, which will create a withdrawId with the kind `CLAW_BACK` and call `SFC.undelegate(validatorId, withdrawId, amountAssets)`. It also internally accounts for decreasing the `amountAssets` from `totalDelegated` to adding it to the `pendingClawBackAmount` storage variable.
  - After the 14-day withdrawal waiting period, the operator will call `operatorExecuteClawBack(uint256 withdrawId, bool emergency)`, which internally calls `SFC.withdraw(validatorId, withdrawId)`. Internally, it is accounted for by decreasing the `amountAssets` from the `pendingClawBackAmount` and adding it to the `totalPool` storage variable.
  - The `emergency` parameter flags the acknowledgment of the operator that the `validatorId` might have been slashed, which affects the number of assets withdrawn, and it is **very important to mention that this will decrease the stS \<\> S exchange rate**.
  - The claimer (automated EOA) claims staked rewards via the `claimRewards(validatorIds[])` function, claiming the rewards in the SFC contract of each `validatorId` and verifying that the total claimed is at least `0.000001 S`. Internally, a `protocolFeeBIPS` of 10% is applied to the rewards claimed and sends the fee to the `treasury` address. It finishes by adding the remaining to the `totalPool` storage variable, increasing the stS \<\> S exchange rate.

  
  

## Pricing strategy

We suggest pricing stS by using a CAPO adapter with the exchange rate provided by the stS contract and price component using the S Chainlink Feed.  
We can confirm that the stS is safeguarded against any kind of donation attack due to its internal accounting for S across the system.

However, it is important to mention that the system contains a `donate(msg.value)` function, only callable by the operator, that allows S to be sent to the contract, increasing the exchange rate.

Additionally, even if not in our technical scope, the asset is slashable both high-level and on the smart contract, so risk contributors should take that into account for parameter suggestions.

  
  

## Miscellaneous

- The system has 2 security reviews from Trail of Bits and Spearbit with no High or Critical findings. The reports can be found [here](https://github.com/beethovenxfi/sonic-staking/tree/main/audits).
- The system has an Immunefi bug bounty of 200k. More details can be found [here](https://immunefi.com/bug-bounty/beets/information/).

  

## Conclusion

We think stS doesn’t have any problem in terms of integration with Aave, and there is no major technical blocker for listing.

---

_[View the full topic](https://governance.aave.com/t/arfc-add-sts-to-aave-v3-sonic-instance/21445)._
