Platform: Code4rena
Start Date: 31/01/2023
Pot Size: $90,500 USDC
Total HM: 47
Participants: 169
Period: 7 days
Judge: LSDan
Total Solo HM: 9
Id: 211
League: ETH
Rank: 52/169
Findings: 1
Award: $305.80
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: IllIllI
Also found by: 0x3b, 0xAgro, 0xBeirao, 0xMirce, 0xNineDec, 0xRobocop, 0xSmartContract, 0xTraub, 0xWeiss, 2997ms, 41i3xn, Awesome, Aymen0909, Bauer, Bnke0x0, Breeje, Cryptor, DadeKuma, Deathstore, Deekshith99, DevABDee, DevTimSch, Dewaxindo, Diana, Ermaniwe, Guild_3, H0, IceBear, Inspectah, JDeryl, Kaiziron, Kaysoft, Kenshin, Mukund, Praise, RaymondFam, Rickard, Rolezn, Ruhum, Sathish9098, SkyWalkerMan, SleepingBugs, UdarTeam, Udsen, Walter, aashar, adeolu, apvlki, arialblack14, ast3ros, btk, chaduke, chandkommanaboyina, chrisdior4, climber2002, codetilda, cryptonue, cryptostellar5, csanuragjain, ddimitrov22, descharre, dharma09, doublesharp, eccentricexit, ethernomad, fs0c, georgits, halden, hansfriese, hashminer0725, immeas, lukris02, luxartvinsec, matrix_0wl, merlin, mookimgo, mrpathfindr, nadin, olegthegoat, pavankv, rbserver, rebase, savi0ur, sayan, scokaf, seeu, shark, simon135, tnevler, tsvetanovv, ulqiorra, ustas, waldenyan20, y1cunhui, yongskiws, yosuke
305.798 USDC - $305.80
L-N | Issue | Instances |
---|---|---|
[L‑01] | Signature malleability for ecrecover | 2 |
[L‑02] | Decimals() not part of ERC20 standard | 2 |
[L‑03] | Missing zero address check | 1 |
[L‑04] | Insufficient input validation | 1 |
Total: 6 instances over 4 issues
N-N | Issue | Instances |
---|---|---|
[N‑01] | Missing NatSpec documentation | 2 |
[N‑02] | Do not use floating pragma, use a concrete version instead | 17 |
[N‑03] | Unused custom error in AdapterBase.sol | 1 |
[N‑04] | Typos in the comments | 3 |
[N‑05] | Components in the contract are not neatly organised | 1 |
[N‑06] | Open TODO in the code | 1 |
Total: 25 instances over 6 issues
ecrecover
Files: Vault.sol
and AdapterBase.sol
The implementation of a cryptographic signature system in Ethereum contracts often assumes that the signature is unique, but signatures can be altered without the possession of the private key and still be valid. The EVM specification defines several so-called ‘precompiled’ contracts one of them being ecrecover which executes the elliptic curve public key recovery. A malicious user can slightly modify the three values v, r and s to create other valid signatures. A system that performs signature verification on contract level might be susceptible to attacks if the signature is part of the signed message hash. Valid signatures could be created by a malicious user to replay previously signed messages.
address recoveredAddress = ecrecover(
address recoveredAddress = ecrecover(
Lines of code:
Use OpenZeppelin ECDSA library
File: AdapterBase.sol
The __ERC4626_init
method is making a check if the smart contract of the underlying assset has decimals() implemented and if not - handles it. But here:
_decimals = IERC20Metadata(asset).decimals();
the code written in this way, assume that the underlying asset will have decimals() implemented. However decimals() is not part of the official ERC20 standard and might fall for tokens that do not implement it. While in practice it is very unlikely, as usually most of the tokens implement it, this should still be considered as a potential issue.
The same problem occurs also in Vault.sol
_decimals = IERC20Metadata(address(asset_)).decimals();
Lines of code for the two files respectively:
Consider using a helper function to safely retrieve token decimals.
File: AdapterBase.sol
In _withdraw()
assets are sent to receiver
but his address is not checked. This way there is a risk for the funds to stuck forever in 0 address.
IERC20(asset()).safeTransfer(receiver, assets);
Lines of code:
Add zero address check for receiver
parameter in withdraw()
.
In MultiRewardEscrow::lock we have parameter duration
which only requirement is not to be equal to zero. Accidentally user can input 1 as an argument and if the start time is now and the offset is set to 0 (because we do not have ZeroAmount check for this param), the end time will be calculated by adding 1 to it, meaning only 1 second after the start, the funds will be available for transfer to account
.
function lock( IERC20 token, address account, uint256 amount, uint32 duration, uint32 offset ) external { if (token == IERC20(address(0))) revert ZeroAddress(); if (account == address(0)) revert ZeroAddress(); if (amount == 0) revert ZeroAmount(); if (duration == 0) revert ZeroAmount();
uint32 start = block.timestamp.safeCastTo32() + offset; escrows[id] = Escrow({ token: token, start: start, end: start + duration, lastUpdateTime: start, initialBalance: amount, balance: amount, account: account });
If this is not a problem for the protocol, remove the duration should be different from 0 check, because it will make no big difference, if the funds will be unlocked now
or now
+ 1 second.
File: AdapterBase.sol
There are couple of places that @param field in the NatSpec is missing. Here is an example:
/** * @notice Allows the strategy to withdraw assets from the underlying protocol without burning adapter shares. * @dev This can be used e.g. for a leverage strategy to reduce leverage without the need for the strategy to hold any adapter shares. */ function strategyWithdraw(uint256 amount, uint256 shares) public onlyStrategy { _protocolWithdraw(amount, shares); }
Consider adding full NatSpec documentation in all the contracts.
Currently the smart contracts are using a floating pragma, change it to concrete 0.8.18 version.
AdapterBase.sol
error ZeroAmount();
Consider using it or removing it from the contract.
File: VaultController.sol
ownes
-> owns
informations
-> information
File: YearnAdapter.sol
profts
-> profits
File: AdapterBase.sol
Its best practice to group all events at one place, as well as custom errors and put them in the interface of the implementation contract, or at least put them right after the contract declaration, before the functions. Here the declarations are not well structured.
BeefyAdapte.sol
is a perfect example of how the contracts should be organised
There is an open TODO in AdapterBase.sol
this implies changes that might not be audited. Resolve it or remove it
// TODO use deterministic fee recipient proxy
Lines of code:
#0 - c4-judge
2023-03-01T00:10:36Z
dmvt marked the issue as grade-a