Skip to content
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

maxWithdraw implementation is not EIP-5095 compliant #128

Closed
c4-bot-7 opened this issue Mar 1, 2024 · 5 comments
Closed

maxWithdraw implementation is not EIP-5095 compliant #128

c4-bot-7 opened this issue Mar 1, 2024 · 5 comments
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

Comments

@c4-bot-7
Copy link
Contributor

c4-bot-7 commented Mar 1, 2024

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

This is the core contract of Spectra. The Principal Token is [EIP-5095](https://eips.ethereum.org/EIPS/eip-5095)

File: README.md

**Principal Token is ERC5095**

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, function maxWithdraw() MUST NOT revert. The current implementation does not follow this requirement.

The very similar issue (functions maxWithdraw and maxRedeem 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 from PausableUpgradeable and implements external pause()/unPause() functions - thus it can be paused.

According to the provided documentation, PrincipalToken.sol should be compliant with ERC5095:

File: README.md

EIP Compliance:
PrincipalToken.sol : Should comply with ERC5095 and ERC2612

According to EIP-5095, function maxWithdraw():

MUST factor in both global and user-specific limits, like if withdrawals are entirely disabled (even temporarily) it MUST return 0.

MUST NOT revert.

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 - function maxWithdraw won't return 0 - but it will revert.
This violates two EIP-5095 rules (MUST NOT revert and if withdrawals are entirely disabled (even temporarily) it MUST return 0)

File: PrincipalToken.sol

    function maxWithdraw(address owner) public view override whenNotPaused returns (uint256) {
        return convertToUnderlying(_maxBurnable(owner));
    }

Tools Used

Manual code review

Recommended Mitigation Steps

When protocol is paused, maxWithdraw() should return 0, instead of reverting.

Assessed type

Other

@c4-bot-7 c4-bot-7 added 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 labels Mar 1, 2024
c4-bot-8 added a commit that referenced this issue Mar 1, 2024
@c4-bot-13 c4-bot-13 added the 🤖_33_group AI based duplicate group recommendation label Mar 1, 2024
@c4-pre-sort
Copy link

gzeon-c4 marked the issue as duplicate of #33

@c4-pre-sort c4-pre-sort added duplicate-33 sufficient quality report This report is of sufficient quality labels Mar 3, 2024
@c4-pre-sort
Copy link

gzeon-c4 marked the issue as sufficient quality report

@c4-judge
Copy link
Contributor

JustDravee marked the issue as partial-50

@c4-judge c4-judge added the partial-50 Incomplete articulation of vulnerability; eligible for partial credit only (50%) label Mar 11, 2024
@c4-judge
Copy link
Contributor

JustDravee marked the issue as satisfactory

@c4-judge c4-judge added satisfactory satisfies C4 submission criteria; eligible for awards duplicate-210 and removed partial-50 Incomplete articulation of vulnerability; eligible for partial credit only (50%) duplicate-33 labels Mar 11, 2024
@c4-judge
Copy link
Contributor

JustDravee marked the issue as partial-50

@c4-judge c4-judge added partial-50 Incomplete articulation of vulnerability; eligible for partial credit only (50%) and removed satisfactory satisfies C4 submission criteria; eligible for awards labels Mar 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
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
Projects
None yet
Development

No branches or pull requests

5 participants