The vault contract is designed to interact with any standard ERC4626 vault and relies on the ratio of _withdrawableAssets(maxWithdraw) and _totalSupplyAmount when calculating exchangeRate.
For maxWithdraw, the ERC4626 standard describes it this way:
Maximum amount of the underlying asset that can be withdrawn from the owner balance in the Vault, through a withdraw call.
MUST factor in both global and user-specific limits, like if withdrawals are entirely disabled (even temporarily) it MUST return 0.
When the vault restricts partial withdrawal, maxWithdraw decreases but does not set to 0. At this time, exchangeRate calculation decreases: the shares minted by the same amount of asset increase, while the same amount of shares withdrawn decreases, resulting in capital loss.
When users withdraw funds at this time, they will suffer losses, and the lost funds will be permanently stuck in the underlying vault and cannot be withdrawn, because of the burn of shares.
ExchangeRate calculations depend on maxWithdraw. When the underlying vault restricts withdrawals, maxWithdraw and exchangeRate decrease, resulting in manipulated ratios.
Although the code is protected by _isVaultCollateralized, but which will pass if exchangeRate greater than assetUnit.
Tools Used
Manual review
Recommended Mitigation Steps
exchangeRate should not rely on variable maxWithdraw
Lines of code
https://github.com/GenerationSoftware/pt-v5-vault/blob/b1deb5d494c25f885c34c83f014c8a855c5e2749/src/Vault.sol#L1176-L1184
Vulnerability details
Impact
The vault contract is designed to interact with any standard ERC4626 vault and relies on the ratio of
_withdrawableAssets(maxWithdraw)
and_totalSupplyAmount
when calculating exchangeRate. For maxWithdraw, the ERC4626 standard describes it this way:When the vault restricts partial withdrawal,
maxWithdraw
decreases but does not set to 0. At this time, exchangeRate calculation decreases: the shares minted by the same amount of asset increase, while the same amount of shares withdrawn decreases, resulting in capital loss. When users withdraw funds at this time, they will suffer losses, and the lost funds will be permanently stuck in the underlying vault and cannot be withdrawn, because of the burn of shares.Proof of Concept
ExchangeRate calculations depend on maxWithdraw. When the underlying vault restricts withdrawals, maxWithdraw and exchangeRate decrease, resulting in manipulated ratios. Although the code is protected by
_isVaultCollateralized
, but which will pass if exchangeRate greater than assetUnit.Tools Used
Manual review
Recommended Mitigation Steps
exchangeRate should not rely on variable maxWithdraw
Assessed type
ERC4626