CertiK reviewed Solv Protocol (Solv Protocol stUSD - Audit) on 28 Dec 2023: 8 findings, 0 critical; 4 marked fixed, 4 open.
Report hosted on skynet.certik.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 | 2 | 0 | 1 |
| Medium | 1 | 0 | 1 |
| Low | 1 | 0 | 2 |
Upon detailed review of the `burn()` function, it is discovered that it lacks proper validation checks for scenarios where the input `sftId_` corresponds to the `holdingValueSftId` managed by the contract itself. In such cases, users engage the `burn()` function, expecting to exchange their ERC-20 tokens for an equivalent amount of ERC-3525 tokens. However, due to the absence of a check verifying that `sftId_` is distinct from `holdingSftId` and ensuring the caller is indeed the owner of `sftId_`, the ERC-20 tokens are burned without the corresponding release of ERC-3525 tokens to the user. This constitutes a critical flaw as it leads to a unilateral loss for the user without the anticipated token exchange.
This [EIP](https://eips.ethereum.org/EIPS/eip-3525#erc-3525-token-receiver) defines a simple ‘Check, Notify and Response’ model for better flexibility as well as simplicity: 1. No extra `safeTransferFrom` methods are needed, all callers only need to call one kind of transfer; 2. All ERC-3525 contracts MUST check for the existence of `onERC3525Received` on the recipient contract and call the function when it exists; 3. Any smart contract can implement `onERC3525Received` function for the purpose of being notified after receiving values; this function MUST return 0x009ce20b (i.e. `bytes4(keccak256('onERC3525Received(address,uint256,uint256,uint256,bytes)'))`) if the transfer is accepted, or any other value if the transfer is rejected. There is a special case for this notification/acceptance mechanism: since ERC-3525 allows value transfer from an address to itself, when a smart contract which implements `onERC3525Received` transfers value to itself, `onERC3525Received` will also be called. This allows for the contract to implement different rules of acceptance between self-value-transfer and receiving value from other addresses. However, this contract does not follow the above rule and does not implement the `onERC3525Received()`.
Addresses are not validated before assignment or external calls, potentially allowing the use of zero addresses and leading to unexpected behavior or vulnerabilities. For example, transferring tokens to a zero address can result in a permanent loss of those tokens. ```solidity=61 wrappedSftAddress = wrappedSftAddress_; ``` - `wrappedSftAddress_` is not zero-checked before being used. --- ```solidity=63 navOracle = navOracle_; ``` - `navOracle_` is not zero-checked before being used. --- ```solidity=30 pendingAdmin = newPendingAdmin_; ``` - `newPendingAdmin_` is not zero-checked before being used. --- ```solidity=30 pendingGovernor = newPendingGovernor_; ``` - `newPendingGovernor_` is not zero-checked before being used.
Performing division by zero would raise an error and revert the transaction. ```solidity=132 return value * (10 ** decimals()) / latestNav; ``` The expression `value * (10 ** decimals()) / latestNav` may divide by zero. Its divisor has has estimated interval [0, 115792089237316195423570985008687907853269984665640564039457584007913129639935].
The report names a repository or files. Open the report to see its scope.
Repository and files the report names (6)
1,044 projects reviewed · 1,375 reports · latest May 2025
See CertiK’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