Platform: Code4rena
Start Date: 07/07/2023
Pot Size: $121,650 USDC
Total HM: 36
Participants: 111
Period: 7 days
Judge: Picodes
Total Solo HM: 13
Id: 258
League: ETH
Rank: 37/111
Findings: 2
Award: $446.12
🌟 Selected for report: 1
🚀 Solo Findings: 0
🌟 Selected for report: Udsen
Also found by: 0xMirce, 0xPsuedoPandit, 0xStalin, 0xbepresent, Aymen0909, Bobface, Co0nan, GREY-HAWK-REACH, Jeiwan, John, KupiaSec, LuchoLeonel1, Nyx, Praise, RedTiger, alexweb3, bin2chen, btk, dacian, dirk_y, josephdara, keccak123, ktg, mahdirostami, markus_ether, minhtrng, ni8mare, peanuts, ptsanev, ravikiranweb3, rvierdiiev, seeques, serial-coder, shaka, teawaterwire, wangxx2026, zzzitron
2.2492 USDC - $2.25
Anyone can call mintYieldFee
in the Vault
contract to mint shares for themselves, which are supposed to go to the _yieldFeeRecipient
.
The comment above the function mintYieldFee
says the following:
@notice Mint Vault shares to the yield fee _recipient
.
So, the intention is clearly to mint Vault shares to the _yieldFeeRecipient
. But, the function lacks any check to verify whether the _recipient
argument is equal to the _yieldFeeRecipient
. Hence, it allows, anyone to mint themselves shares by subtracting that amount from the _yieldFeeTotalSupply
.
Manual Review
It is recommended that the function include a modifier to prevent this or check that the _recipient
be equal to the _yieldFeeRecipient
require(_yieldFeeRecipient == _recipient, "_recipient is not the same as _yieldFeeRecipient");
Access Control
#0 - c4-judge
2023-07-14T22:17:57Z
Picodes marked the issue as duplicate of #396
#1 - c4-judge
2023-08-05T22:04:37Z
Picodes marked the issue as satisfactory
443.8749 USDC - $443.87
Theoretically, it is possible to mint more than the maxMint
amount using the mintYieldFee
function in the Vault
contract.
The functions in Vault
contract like mint
, mintWithPermit
call the _beforeMint
function which checks whether _shares
are greater than maxMint
amount and reverts if it's indeed the case. But, the mintYieldFee
amount does not check this. The yieldFeeTotalSupply
is a unit256 which gets subtracted with shares
, but the maxMint only allows for uint96. So theoretically, it is possible to mint more shares than maxMint, because shares are a uint256 value, not uint96 in the function.
But, there is a scenario where the protocol should be mindful. There is no limit on the decimals of the asset tokens that are used as the vaults can be created permissionless by anyone. And shares also have the same amount of decimals. So, yieldFeeTotalSupply
could accumulate in amount (even if the underlying value is less) to be greater than max(uint96) value, which makes it possible for a share greater than maxMint
(max(uint96)) amount to be subtracted from yieldFeeTotalSupply
and hence possible to mint shares greater than max(uint96) value.
Manual review
It is recommended that the protocol add the maxMint
check in the mintYieldFee
function.
Invalid Validation
#0 - c4-sponsor
2023-07-20T22:52:51Z
asselstine marked the issue as sponsor confirmed
#1 - c4-judge
2023-08-07T16:30:05Z
Picodes marked the issue as satisfactory
#2 - Picodes
2023-08-07T16:30:52Z
This finding, https://github.com/code-423n4/2023-07-pooltogether-findings/issues/89 and https://github.com/code-423n4/2023-07-pooltogether-findings/issues/458 would all be mitigated by having the check at the _mint
level. Because of this I'll flag them as duplicates.
#3 - c4-judge
2023-08-07T16:31:34Z
Picodes marked the issue as primary issue
#4 - c4-judge
2023-08-07T16:32:26Z
Picodes marked issue #458 as primary and marked this issue as a duplicate of 458
#5 - PierrickGT
2023-08-09T23:42:55Z
I've moved the maxMint
check into the _mint
function in this PR: https://github.com/GenerationSoftware/pt-v5-vault/pull/11
There is also another edge case we need to check for.
When the Vault is partially collateralized, meaning users can withdraw their full deposit but there are not enough yield available in the YieldVault to back the amount of shares minted by mintYieldFee
, then the transaction should revert to avoid minting more shares and enter in an undercollateralization state.
This issue has been fixed in the following PR: https://github.com/GenerationSoftware/pt-v5-vault/pull/13
443.8749 USDC - $443.87
It is theoretically possible for the deposit amount to mint shares more than the maxMint
amount
The deposit function has a check for maxDeposit
and reverts if the deposit value is more than max(uint96). But, it does not check the shares to be less than maxMint
amount and hence bypasses this check. Theoretically, if the assets are equal to max(uint96) and if the vault is under-collateralised, the ratio of _assetUnit
to _exchangeRate
is greater than or equal to 2, then the calculation in _convertToShares
:
_assets.mulDiv(_assetUnit, _exchangeRate, _rounding);
could return a value more than the maxMint
amount. This is possible in those scenarios where the _assetUnit
is a big enough number (possible, as there is no limit on the decimals of the underlying asset, and _assetUnit = 10 ** super.decimals()
) and the Vault is severely under-collateralized.
Manual Review
Include the maxMint check in the deposit function to prevent this problem.
Invalid Validation
#0 - c4-sponsor
2023-07-20T23:30:53Z
asselstine marked the issue as sponsor confirmed
#1 - c4-judge
2023-08-07T15:19:55Z
Picodes marked the issue as satisfactory
#2 - c4-judge
2023-08-07T15:20:00Z
Picodes marked the issue as primary issue
#3 - c4-judge
2023-08-07T16:32:13Z
Picodes marked the issue as duplicate of #435
#4 - Picodes
2023-08-07T16:32:27Z
#5 - c4-judge
2023-08-07T16:32:28Z
Picodes marked the issue as selected for report
#6 - PierrickGT
2023-08-14T23:16:03Z
Fixed in the following PR: https://github.com/GenerationSoftware/pt-v5-vault/pull/11