Platform: Code4rena
Start Date: 21/04/2022
Pot Size: $100,000 USDC
Total HM: 18
Participants: 60
Period: 7 days
Judge: gzeon
Total Solo HM: 10
Id: 112
League: ETH
Rank: 29/60
Findings: 3
Award: $327.20
๐ Selected for report: 0
๐ Solo Findings: 0
๐ Selected for report: cccz
Also found by: 0x1f8b, 0xDjango, 0xkatana, Dravee, IllIllI, WatchPug, berndartmueller, defsec, horsefacts, hyh, kenta, rayn, reassor, sorrynotsorry
58.8714 USDC - $58.87
https://github.com/code-423n4/2022-04-backd/blob/main/backd/contracts/oracles/ChainlinkUsdWrapper.sol#L64 https://github.com/code-423n4/2022-04-backd/blob/main/backd/contracts/oracles/ChainlinkUsdWrapper.sol#L55 https://github.com/code-423n4/2022-04-backd/blob/main/backd/contracts/oracles/ChainlinkOracleProvider.sol#L55
In ChainlinkUsdWrapper there are no validations for answer(the price) if the price is 0 or not. I checked _ethOracle(0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419)..latestRoundData(). However, this contract has no validation for the price too. In addition to that, the price feed must be checked if the data is really updated or not.
In ChainlinkOracleProvider answeredInRound >= roundId must be checked too.
https://github.com/code-423n4/2022-04-backd/blob/main/backd/contracts/oracles/ChainlinkUsdWrapper.sol#L55 https://github.com/code-423n4/2022-04-backd/blob/main/backd/contracts/oracles/ChainlinkUsdWrapper.sol#L64 https://github.com/code-423n4/2022-04-backd/blob/main/backd/contracts/oracles/ChainlinkOracleProvider.sol#L55
code review
require(answer > 0, "error message"); require(answeredInRound >= roundId, "error message"); require(updatedAt > 0, "error message");
#0 - chase-manning
2022-04-28T11:25:45Z
Duplicate of #17
๐ Selected for report: IllIllI
Also found by: 0v3rf10w, 0x52, 0xDjango, 0xkatana, Dravee, Funen, Kenshin, Ruhum, StyxRave, Tadashi, TerrierLover, TrungOre, antonttc, berndartmueller, catchup, csanuragjain, defsec, dipp, fatherOfBlocks, hake, horsefacts, hubble, jayjonah8, joestakey, kebabsec, kenta, m4rio_eth, oyc_109, pauliax, peritoflores, rayn, remora, robee, securerodd, simon135, sorrynotsorry, sseefried, z3s
159.3125 USDC - $159.31
2022-04-backd
The following function returns _getBalanceUnderlying without any other executions. You can use _getBalanceUnderlying.
https://github.com/code-423n4/2022-04-backd/blob/main/backd/contracts/pool/Erc20Pool.sol#L42-L44
Delete the function.
##2 use call instead of transfer to transfer ETH in _doTransferOut.
To transfer ETH the use of call is recommended now.
https://github.com/code-423n4/2022-04-backd/blob/main/backd/contracts/pool/EthPool.sol#L30
(bool sent, ) = _to.call{value: amount}(""); require(sent, โerror messageโ);
๐ Selected for report: joestakey
Also found by: 0v3rf10w, 0x1f8b, 0x4non, 0xDjango, 0xNazgul, 0xkatana, 0xmint, Dravee, Funen, IllIllI, MaratCerby, NoamYakov, Tadashi, TerrierLover, Tomio, WatchPug, catchup, defsec, fatherOfBlocks, hake, horsefacts, kenta, oyc_109, pauliax, rayn, rfa, robee, saian, securerodd, simon135, slywaters, sorrynotsorry, tin537, z3s
109.0232 USDC - $109.02
2022-04-backd optimization
The following input for function can be calldata instead of memory to save gas.
https://github.com/code-423n4/2022-04-backd/blob/main/backd/contracts/pool/Erc20Pool.sol#L15 https://github.com/code-423n4/2022-04-backd/blob/main/backd/contracts/pool/EthPool.sol#L13 https://github.com/code-423n4/2022-04-backd/blob/main/backd/contracts/pool/LiquidityPool.sol#L702 https://github.com/code-423n4/2022-04-backd/blob/main/backd/interfaces/pool/IEthPool.sol#L6 https://github.com/code-423n4/2022-04-backd/blob/main/backd/interfaces/pool/IErc20Pool.sol#L6
string calldata name_,
The other require statements need to read the state variable. So you can save gas if the input _depositCap is 0 and the execution is reverted.
https://github.com/code-423n4/2022-04-backd/blob/main/backd/contracts/pool/LiquidityPool.sol#L401
Place the require statement at the beginning of updateDepositCap.
The underflow must happen never because the calculation tries to subtract after balance from before balance.
https://github.com/code-423n4/2022-04-backd/blob/main/backd/contracts/StakerVault.sol#L384
uint256 unstaked; unchecked { unstaked = oldBal - IERC20(token).balanceOf(address(this)); }
The local variables allowanceNew, srcTokensNew, and dstTokensNew are used only one time in transferFrom, so you can delete them and set these calculations directly for state variables.
https://github.com/code-423n4/2022-04-backd/blob/main/backd/contracts/StakerVault.sol#L163-L165
balances[src] = srcTokens - amount; balances[dst] = balances[dst] + amount;
if (startingAllowance != type(uint256).max) { _allowances[src][spender] = startingAllowance - amount; }
The underflow is checked already in if sentence, so you can use unchecked to save gas costs.
https://github.com/code-423n4/2022-04-backd/blob/main/backd/contracts/StakerVault.sol#L231
unchecked { actionLockedBalances[account] -= amount; }
https://github.com/code-423n4/2022-04-backd/blob/main/backd/contracts/StakerVault.sol#L260 https://github.com/code-423n4/2022-04-backd/blob/main/backd/contracts/BkdLocker.sol#L310
for (uint256 i; i < length;) { // do something unchecked { ++i; } }
The underflow for the following calculation is already checked in the next lines, so you can use unchecked to save gas costs.
https://github.com/code-423n4/2022-04-backd/blob/main/backd/contracts/GasBank.sol#L87
https://github.com/code-423n4/2022-04-backd/blob/main/backd/contracts/GasBank.sol#L68 https://github.com/code-423n4/2022-04-backd/blob/main/backd/contracts/GasBank.sol#L76
In withdrawUnused the underflow is also checked because the unused amount will be transferred.
unchecked { _balances[account] = currentBalance - amount; }