Incorrect maturity calculations for YieldToken #130
Labels
2 (Med Risk)
Assets not at direct risk, but function/availability of the protocol could be impacted or leak value
bug
Something isn't working
🤖_130_group
AI based duplicate group recommendation
sufficient quality report
This report is of sufficient quality
unsatisfactory
does not satisfy C4 submission criteria; not eligible for awards
Lines of code
https://github.com/code-423n4/2024-02-spectra/blob/383202d0b84985122fe1ba53cfbbb68f18ba3986/src/tokens/YieldToken.sol#L124
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 define the maturity. According to EIP-5095:
Principal Tokens become redeemable for underlying at or after this timestamp
. However, the current implementation treats tokens at the timestamp as non-mature (even though, according to EIP-5095, they are matured).During the previous C4 contests, lack of EIP compliance was usually evaluated as High/Medium
Proof of Concept
EIP-5095 defines, that:
Now, let's take a look how a matuirity is being check:
File: YieldToken.sol
According to above EIP, when
block.timestamp == IPrincipalToken(pt).maturity()
, PT reaches the maturity, thus functionbalanceOf()
should returnsuper.balanceOf(account)
instead of0
.The current implementation, however, when
block.timestamp == IPrincipalToken(pt).maturity()
returns0
. This violates the EIP-5095, because PT reaches maturity not only after the timestamp, but:at or after this timestamp
. Thus, PT should be treated as matured whenblock.timestamp == IPrincipalToken(pt).maturity()
.Tools Used
Manual code review
Recommended Mitigation Steps
Line:
return (block.timestamp < IPrincipalToken(pt).maturity()) ? super.balanceOf(account) : 0;
should be changed to:
return (block.timestamp <= IPrincipalToken(pt).maturity()) ? super.balanceOf(account) : 0;
Assessed type
Other
The text was updated successfully, but these errors were encountered: