Platform: Code4rena
Start Date: 15/06/2022
Pot Size: $30,000 USDC
Total HM: 5
Participants: 55
Period: 3 days
Judge: Jack the Pug
Id: 138
League: ETH
Rank: 6/55
Findings: 3
Award: $1,881.47
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: Picodes
Also found by: 0x1f8b, 0x52, Chom, GimelSec, IllIllI, berndartmueller, cccz, defsec, georgypetrov, hyh, kenzo, minhquanym, oyc_109, scaraven, unforgiven
50.7077 USDC - $50.71
Function _harvest()
does multiple swaps from auraBAL -> BAL/ETH BPT -> WETH -> AURA using BalancerVault. But it doesn’t use minAmountsOut
or have a check for mimimum return amount. It makes this function vulnerable to sandwich attack.
An attacker (which can be a malicious keeper) can front-run swap in BalancerVault before harvest()
to make a profit.
Please refer to yDai Incident to check the severity of a harvest function without slippage control.
Please refer to Mushrooms-finance-theft to check how likely this kind of attack might happen.
Should add a min return param or check the slippage.
#0 - GalloDaSballo
2022-06-22T00:40:05Z
Dup of #155
note that yDAI is Single-Sided-Exposure not the same risk
🌟 Selected for report: berndartmueller
Also found by: minhquanym
1773.2447 USDC - $1,773.24
Function withdrawToVault()
in BaseStrategy will withdraw all funds from strategy to vault, it uses an internal function _withdrawAll()
in MyStrategy. In this function, there is a check that no locked balance is still in AuraLocker.
An attacker can keep deposit small amount (1 wei) for MyStrategy in AuraLocker by calling lock(address(MyStrategy), 1)
in AuraLocker to keep locked balance of MyStrategy never be 0, making the function withdrawToVault()
being in denial of service.
lock(address(MyStrategy), 1)
in AuraLocker every lockDuration
.withdrawToVault()
will always revertAdd manualProcessExpiredLocks
in function _withdrawAll()
and remove the check if no locked balance.
#0 - GalloDaSballo
2022-06-18T16:10:58Z
Dup of #92
🌟 Selected for report: IllIllI
Also found by: 0v3rf10w, 0x1f8b, 0xDjango, 0xFar5eer, 0xNazgul, 0xNineDec, 242, Chom, Czar102, Funen, GimelSec, Meera, Picodes, Sm4rty, Tadashi, TerrierLover, Waze, _Adam, a12jmx, asutorufos, codexploder, cryptphi, defsec, gzeon, hyh, joestakey, minhquanym, oyc_109, reassor, robee, saian, sorrynotsorry, unforgiven, zzzitron
57.5155 USDC - $57.52
whenNotPaused
modifierIn MyStrategy
contract, there are 2 functions (manualProcessExpiredLocks
and performUpkeep
) basically do the same thing which is call processExpiredLocks()
on LOCKER. Function manualProcessExpiredLocks()
has whenNotPaused
modifier but performUpkeep
doesn’t.
Add or remove whenNotPaused
for both functions to keep consistency
balanceOfWant()
consistentlyIn MyStrategy
contract, function balanceOfWant()
simply return balance of want
token in this strategy.
But instead of using it, this code do call balanceOf
manually
uint256 toDeposit = IERC20Upgradeable(want).balanceOf(address(this));
Should change to use balanceOfWant()
function.