Closed c4-bot-1 closed 8 months ago
gzeon-c4 marked the issue as sufficient quality report
gzeon-c4 marked the issue as primary issue
gzeon-c4 marked the issue as insufficient quality report
rate round down should mean share rounded up
JustDravee marked the issue as unsatisfactory: Invalid
Lines of code
https://github.com/code-423n4/2024-02-spectra/blob/383202d0b84985122fe1ba53cfbbb68f18ba3986/src/tokens/PrincipalToken.sol#L284 https://github.com/code-423n4/2024-02-spectra/blob/383202d0b84985122fe1ba53cfbbb68f18ba3986/src/tokens/PrincipalToken.sol#L309
Vulnerability details
Impact
The current implementation of
withdraw()
andwithdrawIBT()
rounds in incorrect direction. Rounding in the incorrect direction may cause loss to the protocol.Proof of Concept
According to [EIP-5095](https://github.com/ethereum/ercs/blob/master/ERCS/erc-5095.md#reference-implementation, we can see the example of
withdraw()
implementation:As demonstrated in the code above - it should round up:
No need to check for rounding error, previewWithdraw rounds up
Since
previewWithdraw()
rounds up - similarly -withdraw()
should also round up. Let's take a look at its implementation in thePrincipalToken.sol
:File: PrincipalToken.sol:
Function
_getPTandIBTRates()
's parameter defines if the result should be rounded up (parameter should betrue
) or down (parameter should befalse
). The current implementation rounds down (parameter isfalse
) for the withdraw function - which is incorrect. While we deposit assets, the rounding should be down (in favor on the protocol) - withdrawing should also work in favor of the protocol - thus the rounding should be up. However, the current implementation rounds down, instead of up.It's important to notice, that in some cases, ERC-5095 should be cross-compatible with ERC-4626 - since it shares the same functionality. When we take a look at ERC-4626 implementation (OZ's implementation) - we can confirm, that withdrawing requires rounding up:
However, the current implementation rounds down
_getPTandIBTRates()
is set tofalse
instead oftrue
.The same issue occurs for
withdrawIBT()
- it also rounds down, instead of rounding up.Tools Used
Manual code review
Recommended Mitigation Steps
Change line
(uint256 _ptRate, uint256 _ibtRate) = _getPTandIBTRates(false);
to(uint256 _ptRate, uint256 _ibtRate) = _getPTandIBTRates(true);
Assessed type
Math