Platform: Code4rena
Start Date: 29/04/2022
Pot Size: $22,000 USDC
Total HM: 6
Participants: 40
Period: 3 days
Judge: Justin Goro
Total Solo HM: 2
Id: 114
League: ETH
Rank: 7/40
Findings: 2
Award: $810.00
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: WatchPug
Also found by: 0xDjango, CertoraInc, Tadashi, berndartmueller, kebabsec, leastwood, unforgiven
The first depositor into the yield source is able to maliciously manipulate the share price by depositing the lowest possible amount (1 wei
) and then artificially blowing up the token balance. Following depositors will have to supply a larger amount of tokens to receive shares > 0.
No funds are lost as deposits are checked if received shares > 0
(see AaveV3YieldSource.sol#L233) but it prevents supplying smaller amounts of assets.
This is a well known issue, Uniswap and other protocols had similar issues when supply == 0
.
1 wei
via supplyTokenTo()
1 wei
shares1000
aToken via transfer()
to yield source contract to artificially blow up balance without minting new shares. Balance is now 1001
aToken -> share price is now very high (= 1001
wei)The formula _supply == 0 ? _tokens : _tokens.mul(_supply).div(balance)
(see AaveV3YieldSource.sol#L361) calculates for deposits of e.g. 100
asset tokens in case of such a high share price the following:
(100 * 1) / 1001
=> shares = 0
(precision issues)
This is due to balance
>
(_tokens * _supply)
.
Manual review
For the first, initial, deposit, mint fixed amount of shares
, e.g. 10**decimals()
instead of minting same amount of supplied _tokens
.
Similarly, for _sharesToToken()
, return fixed amount of tokens
, e.g. 10**decimals()
if _supply == 0
Fix inspired by Uniswap V2 and Harvest Finance
#0 - PierrickGT
2022-05-04T16:36:55Z
#1 - PierrickGT
2022-05-04T20:32:00Z
Great report with a solution proposed, should get extra points.
🌟 Selected for report: MaratCerby
Also found by: CertoraInc, IllIllI, berndartmueller, cccz, reassor
There are ERC20 tokens that may make certain customizations to their ERC20 contracts.
One type of these tokens is deflationary tokens that charge a certain fee for every transfer()
or transferFrom()
.
Manual review
Get the actual received amount by calculating the difference of token balance before and after the transfer. e.g.:
uint256 _beforeBalance = _underlyingAssetAddress.balanceOf(address(this)); IERC20(_underlyingAssetAddress).safeTransferFrom(msg.sender, address(this), _depositAmount); uint256 _afterBalance = _underlyingAssetAddress.balanceOf(address(this));
#0 - PierrickGT
2022-05-04T16:35:07Z