-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
convertToPrincipal()
and previewWithdraw()
have got inconsistent implementation which violates EIP-5095
#134
Comments
gzeon-c4 marked the issue as duplicate of #33 |
gzeon-c4 marked the issue as sufficient quality report |
JustDravee marked the issue as not a duplicate |
JustDravee marked the issue as satisfactory |
JustDravee marked the issue as primary issue |
yanisepfl (sponsor) disputed |
The two following points explain why we dispute this issue.I - Reason 1The problem raised here is basically the difference between:
and
in respect with this rule of the 5095: "Note that any unfavorable discrepancy between convertToPrincipal and previewWithdraw SHOULD be considered slippage in price-per-principal-token or some other type of condition." The first difference comes from a call to the IBT's Then, the second difference comes from the rounding up vs rounding down. This slight difference is irrelevant and can be considered as "slippage in price-per-principal-token or some other type of condition." to respect the standards. II - Reason 2Also, when it comes to the erc5095 standard, you can find the following information concerning the convert methods:
ConclusionTherefore, we are confident on the fact that we do follow the standard and we dispute the issue. |
JustDravee marked the issue as unsatisfactory: |
Lines of code
https://github.com/code-423n4/2024-02-spectra/blob/383202d0b84985122fe1ba53cfbbb68f18ba3986/src/tokens/PrincipalToken.sol#L488-L490
tps://github.com/code-423n4/2024-02-spectra/blob/383202d0b84985122fe1ba53cfbbb68f18ba3986/src/tokens/PrincipalToken.sol#L446-L456
Vulnerability details
Impact
According to the provided documentation:
Principal Token is ERC5095
. This is the main invariant defined in the project's description:File: README.md
File: README.md
During the code-review process, some deviations from the EIP-5095 had been detected. Lack of compliance may cause unexpected behavior. Other protocols that integrate with contract may incorrectly assume that it's EIP-5095 compliant - especially that documentation states that it's ERC-5095. Any deviation from this standard will broke the composability and may lead to fund loss. While protocol's implements a contract and describes it as ERC-5095, it should fully conform to ERC-5095 standard.
The current implementation does not correctly implement
convertToPrincipal()
function. BothconvertToPrincipal()
andpreviewWithdraw()
implementation should be consistent, according to EIP-5095 any unfavorable discrepancy between convertToPrincipal and previewWithdraw SHOULD be considered slippage in price-per-principal-token or some other type of condition. However,convertToPrincipal()
implementation differs too much from thepreviewWithdraw()
- thus its implementation should be classified as incorrect one. The implementation ofconvertToPrincipal()
should be changed.During the previous C4 contests, lack of EIP compliance was usually evaluated as High/Medium
Proof of Concept
According to EIP-5095:
This suggests, that
convertToPrincipal()
andpreviewWithdraw()
should have a similar implementation - while any deviation/discrepancy should be considered slippage.Function
convertToPrincipal()
is defined as below:File: PrincipalToken.sol
Function
previewWithdraw()
is defined as below:File: PrincilapToken.sol
which is basically the same as:
This can be summarized as:
convertToPrincipal()
:_convertIBTsToShares(IERC4626(ibt).previewDeposit(X), false);
previewWithdraw()
:_convertIBTsToShares(IERC4626(ibt).previewWithdraw(X), true)
The first function uses ERC4626
previewDeposit()
and rounds down, while the second function usespreviewWithdraw()
and rounds up.Since for ERC4626 the inverse of the
deposit()
function is awithdraw()
function - it suggests thatconvertToPrincipal()
is not correctly implemented. Since according to EIP-5095discrepancy between convertToPrincipal and previewWithdraw SHOULD be considered slippage
, those values should be just slightly different - however, they aren't (previewDeposit()
andpreviewWithdraw()
returns different values).It's obvious, that the implementation of
convertToPrincipal()
is incorrect andpreviewDeposit()
should be changed topreviewWithdraw()
.Tools Used
Manual code review
Recommended Mitigation Steps
Function
convertToPrincipal()
should usepreviewWithdraw()
instead ofpreviewDeposit()
.Assessed type
Other
The text was updated successfully, but these errors were encountered: