Platform: Code4rena
Start Date: 04/03/2024
Pot Size: $36,500 USDC
Total HM: 9
Participants: 80
Period: 7 days
Judge: hansfriese
Total Solo HM: 2
Id: 332
League: ETH
Rank: 5/80
Findings: 2
Award: $915.44
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: DarkTower
Also found by: 0xJaeger, 0xJoyBoy03, 0xRiO, 0xkeesmark, 0xlemon, 0xmystery, Abdessamed, AcT3R, Afriauditor, AgileJune, Al-Qa-qa, Aymen0909, Daniel526, DanielTan_MetaTrust, Dots, FastChecker, Fitro, GoSlang, Greed, Krace, McToady, SoosheeTheWise, Tripathi, asui, aua_oo7, btk, crypticdefense, d3e4, dd0x7e8, dvrkzy, gesha17, iberry, kR1s, leegh, marqymarq10, n1punp, pa6kuda, radin100, sammy, smbv-1923, trachev, turvy_fuzz, valentin_s2304, wangxx2026, y4y, yotov721, yvuchev, zhaojie
1.4652 USDC - $1.47
In scenario where totaldebt > totalasset. such as when where is loss of asset in the underlying yieldvault. The conversion from underlying token to prize vault shares changes from 1:1 with more prize vault share required to be exchanged for underlying token. In the function Implementation
function claimYieldFeeShares(uint256 _shares) external onlyYieldFeeRecipient { if (_shares == 0) revert MintZeroShares(); uint256 _yieldFeeBalance = yieldFeeBalance; >>>> if (_shares > _yieldFeeBalance) revert SharesExceedsYieldFeeBalance(_shares, _yieldFeeBalance); yieldFeeBalance -= _yieldFeeBalance; _mint(msg.sender, _shares); emit ClaimYieldFeeShares(msg.sender, _shares); }
the function takes in number of shares as parameter and also has a logic causing a revert when if (_shares > _yieldFeeBalance) revert
This assumes conversion rate will always be 1:1. The implication here is yield fee recipient will be force to convert just a portion of their Yield fee balance to avoid a revert. leaving behind the rest of the yeild fee balance.
also there is a poor implementation here yieldFeeBalance -= _yieldFeeBalance;
causing the yeildfee recipient to loose all balance regardless of the number of shares he decides to mint loosing his entire fees either the tokens are minted or not
manual
++ function claimYieldFeeShares(uint256 _Yieldfeebalancetowithdraw) external onlyYieldFeeRecipient { if (_shares == 0) revert MintZeroShares(); uint256 _yieldFeeBalance = yieldFeeBalance; + uint256 Yieldfeeshare = convertToshare(_Yieldfeebalancetowithdraw) + yieldFeeBalance -= _Yieldfeebalancetowithdraw + _mint(msg.sender, Yieldfeeshare); emit ClaimYieldFeeShares(msg.sender, Yieldfeeshare); }
Other
#0 - c4-pre-sort
2024-03-11T22:17:16Z
raymondfam marked the issue as sufficient quality report
#1 - c4-pre-sort
2024-03-11T22:17:27Z
raymondfam marked the issue as duplicate of #10
#2 - raymondfam
2024-03-11T22:22:45Z
convertToshare() in your mitigation step is unnecessary because the input parameter is already treated as shares. The shares are minted 1:1 regardless of normal or lossy state. It only incurs a loss if the shares minted are withdrawn in a lossy state. Treated as insufficient as the assumption leading to loss of remainder yield is incorrect.
#3 - c4-pre-sort
2024-03-11T22:31:22Z
raymondfam marked the issue as insufficient quality report
#4 - c4-pre-sort
2024-03-13T04:38:41Z
raymondfam marked the issue as duplicate of #59
#5 - c4-judge
2024-03-15T07:38:16Z
hansfriese marked the issue as satisfactory
🌟 Selected for report: pa6kuda
Also found by: 0xhunter20, Afriauditor
913.9683 USDC - $913.97
While not yet minted, the accrued yieldFeeBalance
is an inherent part of PrizeVault's shares(totalsupply), impacting the overall totalsupply. This is because minting the yieldFeeBalance
as prizevault shares is inevitable (as long as yield fee recipient desires his fees) and really the only way to withdraw YieldFeeBalance. This poses a potential issue as the _twabSupplyLimit function, vital for calculating maxdeposits and maxamountout in liquidatableBalanceOf
, omits consideration of minting yieldFeeBalance by yield fee recipient. In extreme scenarios, this oversight could render withdrawals unfeasible by yield fee recipient upon reaching the maximum total supply because it would mean minting prizevault shares exceeding TWAB limits. Which was what the Prizevault:_twabSupplyLimit
was implemented to prevent.
function maxDeposit(address) public view returns (uint256) { uint256 _totalSupply = _maxDeposit(); uint256 totalDebt_ = _totalDebt(_totalSupply); if (totalAssets() < totalDebt_) return 0; // the vault will never mint more than 1 share per asset, so no need to convert supply limit to assets >>> uint256 twabSupplyLimit_ = _twabSupplyLimit(_totalSupply); uint256 _maxDeposit; uint256 _latentBalance = _asset.balanceOf(address(this)); uint256 _maxYieldVaultDeposit = yieldVault.maxDeposit(address(this)); if (_latentBalance >= _maxYieldVaultDeposit) { return 0; } else { unchecked { _maxDeposit = _maxYieldVaultDeposit - _latentBalance; } // @audit would return invalid number number return twabSupplyLimit_ < _maxDeposit ? twabSupplyLimit_ : _maxDeposit; } }
If this is implemented and a user hypothetically decides to use the twabSupplyLimit_
to make a deposit. It would mean TWAB controller's share supply limit is reached. So even when a yield fee recipient wants to claim Yield fee he would be unable to do so. Similar issue will arise from using maxamountout in liquidatableBalanceOf
function in the link above.
Manual
function _twabSupplyLimit(uint256 _totalSupply) internal pure returns (uint256) { unchecked { return type(uint96).max - _totalSupply - YieldFeebalance } }
DoS
#0 - c4-pre-sort
2024-03-13T01:48:08Z
raymondfam marked the issue as insufficient quality report
#1 - c4-pre-sort
2024-03-13T01:48:56Z
raymondfam marked the issue as duplicate of #64
#2 - c4-judge
2024-03-18T01:56:18Z
hansfriese marked the issue as not a duplicate
#3 - c4-judge
2024-03-18T01:57:38Z
hansfriese marked the issue as duplicate of #91
#4 - c4-judge
2024-03-18T01:58:25Z
hansfriese marked the issue as unsatisfactory: Invalid
#5 - c4-judge
2024-03-18T14:34:18Z
hansfriese marked the issue as satisfactory