Closed c4-bot-4 closed 8 months ago
gzeon-c4 marked the issue as duplicate of #33
gzeon-c4 marked the issue as sufficient quality report
There seem to be a big confusion between convertToUnderlying and convertToPrincipal. Therefore the whole argument using EIP-5095 is wrong
JustDravee marked the issue as not a duplicate
JustDravee marked the issue as unsatisfactory: Invalid
Hello,
Could you elaborate on why this finding is invalid based on convertToPrincipal?
The finding was that the convertToUnderlying implementation is incorrect since it states that it MUST not show any variations based on caller. But since it uses previewDeposit, which is inclusive of deposit fees which can change based on the caller.
I'm not clear why convertToPrincipal has any role here?
Hello @14si2o .
Could you tell me exactly where convertToUnderlying()
is using previewDeposit()
?
I'm mentioning convertToPrincipal()
because you're quoting the standard on convertToUnderlying()
while talking about convertToPrincipal()
code:
/** @dev See {IPrincipalToken-convertToPrincipal}. */
function convertToPrincipal(uint256 underlyingAmount) external view override returns (uint256) {
return _convertIBTsToShares(IERC4626(ibt).previewDeposit(underlyingAmount), false);
}
/** @dev See {IPrincipalToken-convertToUnderlying}. */
function convertToUnderlying(uint256 principalAmount) public view override returns (uint256) {
return IERC4626(ibt).previewRedeem(_convertSharesToIBTs(principalAmount, false));
}
As far as I can see, convertToUnderlying()
is using previewRedeem()
(even by checking the whole call trace).
This is why I said that it seems like there's a big confusion in this issue.
@JustDravee
You are 100% correct, I don't understand how I did not see this.
Lines of code
https://github.com/code-423n4/2024-02-spectra/blob/383202d0b84985122fe1ba53cfbbb68f18ba3986/src/tokens/PrincipalToken.sol#L492-L495 https://github.com/code-423n4/2024-02-spectra/blob/383202d0b84985122fe1ba53cfbbb68f18ba3986/src/tokens/PrincipalToken.sol#L680-L693
Vulnerability details
Impact
The EIP-5095 standard states that the amount returned MUST NOT show any variations depending on the caller.
Yet, the
convertToUnderlying
function utilisespreviewDeposit
.When we check the
previewDeposit
EIP-4626 standard, it states that it MUST be inclusive of deposit fees. Since deposit fees can vary depending on the caller and the specific ERC4626 implementation (f.e. fee reduction as is used in the spectra protocol), it cannot be guaranteed that there is no variation in the amount returned for every caller.The EIP-5095 standard also states that before maturity, the amount of underlying returned is as if the PTs would be at maturity.
However, the
convertToUnderlying
function utilises_convertIBTsToShares
, which uses current rates. These rates are subject to change and have no relation to the rates at maturity.Proof of Concept
From: EIP-5095
PrincipalToken.sol
IERC4626.sol
Tools Used
Manual Review
Recommended Mitigation Steps
Change the function to not use previewDeposit and use the rates at maturity.
Assessed type
Other