Platform: Code4rena
Start Date: 21/11/2022
Pot Size: $90,500 USDC
Total HM: 18
Participants: 101
Period: 7 days
Judge: Picodes
Total Solo HM: 4
Id: 183
League: ETH
Rank: 97/101
Findings: 1
Award: $25.32
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: Jeiwan
Also found by: 0xLad, 0xSmartContract, 8olidity, HE1M, JohnSmith, KingNFT, Koolex, Lambda, R2, __141345__, carrotsmuggler, cccz, gogo, hl_, joestakey, koxuan, ladboy233, pashov, peanuts, rbserver, rvierdiiev, seyni, unforgiven, xiaoming90, yongskiws
25.3241 USDC - $25.32
https://github.com/code-423n4/2022-11-redactedcartel/blob/main/src/vaults/PirexERC4626.sol#L60-L78 https://github.com/code-423n4/2022-11-redactedcartel/blob/main/src/vaults/PirexERC4626.sol#L80-L97
Early malicious user will profit from future users' deposits while future users' will loose funds/value.
An early user can call the deposit
function of any of the ERC4626 vaults with only 1 wei
of the asset and respectively get 1 wei
of the shares in return. After that the attacker may send 10000 * 10 ** 18 wei
of the asset to inflate the share price from 1
to 1 * 10 ** 22
((1 + 10000e18 - 1) / 1
). The next user who deposits some amount of asset will receive significatly less shares - if the next user deposits 20000 * 10 ** 18 wei
of the asset they will receive only 2 wei of shares which means they have lost half of their money if they redeem right after that.
https://github.com/code-423n4/2022-11-redactedcartel/blob/main/src/vaults/PirexERC4626.sol#L60-L78
https://github.com/code-423n4/2022-11-redactedcartel/blob/main/src/vaults/PirexERC4626.sol#L80-L97
manula review
Require a minimum amount of initial deposit and burn a portion of the initial shares.
function deposit(uint256 assets, address receiver) public virtual returns (uint256 shares) { if (totalAssets() != 0) beforeDeposit(receiver, assets, shares); // Check for rounding error since we round down in previewDeposit. require((shares = previewDeposit(assets)) != 0, "ZERO_SHARES"); if (totalAssets() == 0) { _mint(address(0), initialShares); } // Need to transfer before minting or ERC777s could reenter. asset.safeTransferFrom(msg.sender, address(this), assets); _mint(receiver, shares); emit Deposit(msg.sender, receiver, assets, shares); afterDeposit(receiver, assets, shares); } function mint(uint256 shares, address receiver) public virtual returns (uint256 assets) { if (totalAssets() != 0) beforeDeposit(receiver, assets, shares); assets = previewMint(shares); // No need to check for rounding error, previewMint rounds up. if (totalAssets() == 0) { _mint(address(0), initialShares); } // Need to transfer before minting or ERC777s could reenter. asset.safeTransferFrom(msg.sender, address(this), assets); _mint(receiver, shares); emit Deposit(msg.sender, receiver, assets, shares); afterDeposit(receiver, assets, shares); }
Reference to how another protocol has fixed this same issue:
https://github.com/sentimentxyz/protocol/pull/232/commits/16557a3e82dce3c6a03d5e8f7280e1af12fe3bf0
#0 - Picodes
2022-12-03T16:13:16Z
Computations of the Proof of Concept are incorrect but the finding is
#1 - c4-judge
2022-12-03T16:13:57Z
Picodes marked the issue as duplicate of #407
#2 - c4-judge
2022-12-21T07:23:59Z
Picodes marked the issue as satisfactory
#3 - C4-Staff
2023-01-10T21:54:30Z
JeeberC4 marked the issue as duplicate of #275