Quantstamp reviewed Sturdy on 13 Oct 2022: 26 findings, 0 critical; 12 marked fixed, 12 acknowledged, 2 open.
Report hosted on certificate.quantstamp.com.
Trustblock does not review code.
Statuses are the security firm’s own, from its report.
| Severity | Open | Acknowledged | Fixed |
|---|---|---|---|
| Critical | 0 | 0 | 0 |
| High | 0 | 0 | 0 |
| Medium | 2 | 0 | 5 |
| Low | 0 | 12 | 7 |
Unlike AAVE, the Sturdy protocol draws a line between collateral and debt assets. A collateral asset can never be a debt asset and vice versa. However, additional care must be taken to ensure that certain actions can only be performed on reserves of a particular type (debt or collateral). We have listed the cases where additional checks must be added to ensure that each reserve type is acted on appropriately: * `LendingPool` * `depositYield()`: Validate that `asset` is not a collateral asset. * `getYield()`: Validate that `asset` is a collateral asset. * `_withdraw()`: Only emit `ReserveUsedAsCollateralDisabled` if `user.isUsingAsCollateral()` was `true` before. * `finalizeTransfer()`: * Only emit `ReserveUsedAsCollateralDisabled` if `user.isUsingAsCollateral()` was `true` before. * Only set `toConfig.setUsingAsCollateral(reserveId, true)` if the reserve represents a collateral asset. * `LendingPoolConfigurator`: * `updateVariableDebtToken()`: Validate that `input.asset` is not a collateral asset. * `configureReserveAsCollateral()`: * If `asset` is a collateral asset, then validate that `ltv`, `liquidationThreshold` and `liquidationBonus` are non-zero. * It `asset` is not a collateral asset, then validate that `ltv`, `liquidationThreshold` and `liquidationBonus` are zero. * `ValidationLogic` * `validateSetUseReserveAsCollateral()`: Validate that `reserve` represents a collateral asset if `useAsCollateral` is `true`.
Several critical functions on the `LendingPool` contract are only callable by vaults and can be used to remove an arbitrary amount of any asset. These functions include `LendingPool.withdrawFrom()` and `LendingPool.getYield()`. However, both of these functions allow any vault to remove any asset from the `LendingPool` as seen on `LendingPool.sol#L196:require(_availableVaults[msg.sender] == true, Errors.VT_PROCESS_YIELD_INVALID);`. This violates the principle of least privilege as vaults should only be able to remove assets they deal with. For example, the `LidoVault` should only be able to withdraw stETH from the `LendingPool`. Currently, if even one vault was compromised, it could be used to drain the entire `LendingPool` of all assets. We also note that any vault can deposit any asset through the `LendingPool.deposit()` and `LendingPool.depositYield()` functions. While the impact of this is less obvious, vaults should only be able to deposit assets that they deal with.
The report names a repository or files. Open the report to see its scope.
Repository and files the report names (24)
236 projects reviewed · 332 reports · latest Oct 2026
See Quantstamp’s auditsSomething wrong on this page? A missing report, a wrong date, a finding that was fixed since. Tell us and we check it against its source.
Tell us