A malicious user can front run syncRewards() with a flashloan attack to cause lastRewardAmount to equal zero. With this users will lose on rewards until the next rewardsCycleEnd.
Proof of Concept
Alice calls deposit() with 1_000 tokens
storedTotalAssets = 1_000
lastRewardAmount = 100
asset.balanceOf(address(this)) = 1_100
Mallory flashloans 800 tokens and calls deposit()
storedTotalAssets = 1_800
lastRewardAmount = 100
asset.balanceOf(address(this)) = 1_900
Mallory then calls syncRewards()
storedTotalAssets = 2_000
lastRewardAmount = 0
asset.balanceOf(address(this)) = 1_900
Mallory withdraws and pays back flashloan
Alice, with others, will now get no rewards next sync losing out on funds
Lines of code
https://github.com/corddry/ERC4626/blob/643cd044fac34bcbf64e1c3790a5126fec0dbec1/src/xERC4626.sol#L78
Vulnerability details
Impact
A malicious user can front run
syncRewards()
with a flashloan attack to causelastRewardAmount
to equal zero. With this users will lose on rewards until the nextrewardsCycleEnd
.Proof of Concept
Alice calls
deposit()
with 1_000 tokensstoredTotalAssets
= 1_000lastRewardAmount
= 100asset.balanceOf(address(this))
= 1_100Mallory flashloans 800 tokens and calls
deposit()
storedTotalAssets
= 1_800lastRewardAmount
= 100asset.balanceOf(address(this))
= 1_900Mallory then calls
syncRewards()
storedTotalAssets
= 2_000lastRewardAmount
= 0asset.balanceOf(address(this))
= 1_900Mallory withdraws and pays back flashloan
Tools Used
Manual Review
Recommended Mitigation Steps
Consider adding a check for
nextRewards #L85
: