maxWithdraw
implementation is not EIP-5095 compliant
#128
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
duplicate-210
edited-by-warden
partial-50
Incomplete articulation of vulnerability; eligible for partial credit only (50%)
🤖_33_group
AI based duplicate group recommendation
sufficient quality report
This report is of sufficient quality
Lines of code
https://github.com/code-423n4/2024-02-spectra/blob/383202d0b84985122fe1ba53cfbbb68f18ba3986/src/tokens/PrincipalToken.sol#L460-L461
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.
According to EIP-5095, function
maxWithdraw()
MUST return 0 when withdrawals are entirely (or even temporarily) disabled. The current implementation does not follow this requirement. Moreover, according to EIP-5095, functionmaxWithdraw()
MUST NOT revert. The current implementation does not follow this requirement.The very similar issue (functions
maxWithdraw
andmaxRedeem
do not return zero - when withdrawal is paused) was evaluated as Medium during the previous Code4rena contest:The very similar issue (functions
max*
do not return 0 when contract is paused) was evaluated as High during the previous Code4rena contest:Moreover, during the previous C4 contests, lack of EIP compliance was usually evaluated as High/Medium
Taking into consideration the previous contests, I've decided to evaluate this issue as Medium.
Proof of Concept
PrincipalToken
inherits fromPausableUpgradeable
and implements externalpause()
/unPause()
functions - thus it can be paused.According to the provided documentation,
PrincipalToken.sol
should be compliant with ERC5095:File: README.md
According to EIP-5095, function
maxWithdraw()
:However, the current implementation of
maxWithdraw
does not obey above rules.While protocol is paused, according to EIP-5095 - function
maxWithdraw
MUST return 0:if withdrawals are entirely disabled (even temporarily) it MUST return 0.
.Moreover, function
MUST NOT revert.
The current implementation implements
whenNotPaused
modifier. This implies, that when protocol is paused - functionmaxWithdraw
won't return 0 - but it will revert.This violates two EIP-5095 rules (
MUST NOT revert
andif withdrawals are entirely disabled (even temporarily) it MUST return 0
)File: PrincipalToken.sol
Tools Used
Manual code review
Recommended Mitigation Steps
When protocol is paused,
maxWithdraw()
should return 0, instead of reverting.Assessed type
Other
The text was updated successfully, but these errors were encountered: