Ethena Labs - cccz's results

Enabling The Internet Bond

General Information

Platform: Code4rena

Start Date: 24/10/2023

Pot Size: $36,500 USDC

Total HM: 4

Participants: 147

Period: 6 days

Judge: 0xDjango

Id: 299

League: ETH

Ethena Labs

Findings Distribution

Researcher Performance

Rank: 114/147

Findings: 1

Award: $4.52

QA:
grade-b

🌟 Selected for report: 0

🚀 Solo Findings: 0

Lines of code

https://github.com/code-423n4/2023-10-ethena/blob/ee67d9b542642c9757a6b826c82d0cae60256509/contracts/StakedUSDe.sol#L191-L194

Vulnerability details

Impact

_checkMinShares() will require 0 or not less than 1e18 shares in the contract after user deposits and withdraws, this is mainly used to protect against donation attacks.

  /// @notice ensures a small non-zero amount of shares does not remain, exposing to donation attack
  function _checkMinShares() internal view {
    uint256 _totalSupply = totalSupply();
    if (_totalSupply > 0 && _totalSupply < MIN_SHARES) revert MinSharesViolation();
  }

But this introduces another problem, if a malicious user leaves 1 wei shares in the contract, then other users will have to lock 1e18 shares in the contract.

Consider the following scenario. Alice deposits 1e18 USDe and gets 1e18 shares, Bob deposits 1e18 USDe and gets 1e18 shares. Alice withdraws (1e18 - 1) shares, leaving 1 wei share in the contract. After that, Bob can only withdraw 1 wei share, because _checkMinShares() will require that the shares in the contract are not less than 1e18.

Proof of Concept

https://github.com/code-423n4/2023-10-ethena/blob/ee67d9b542642c9757a6b826c82d0cae60256509/contracts/StakedUSDe.sol#L191-L194

Tools Used

None

It is recommended to change _checkMinShares() from requiring the total shares of the contract to requiring the user's shares, which will both prevent donation attacks and solve this problem.

    super._deposit(caller, receiver, assets, shares);
-   _checkMinShares();
+   _checkMinShares(receiver);
...
    super._withdraw(caller, receiver, _owner, assets, shares);
-   _checkMinShares();
+   _checkMinShares(_owner);
...
- function _checkMinShares() internal view {
+ function _checkMinShares(address user) internal view {
-   uint256 _totalSupply = totalSupply();
-   if (_totalSupply > 0 && _totalSupply < MIN_SHARES) revert MinSharesViolation();
+   uint256 _shares = _balances[user];
+   if (_shares > 0 && _shares < MIN_SHARES) revert MinSharesViolation();
  }

Assessed type

Context

#0 - c4-pre-sort

2023-10-31T19:49:45Z

raymondfam marked the issue as sufficient quality report

#1 - c4-pre-sort

2023-10-31T19:49:58Z

raymondfam marked the issue as duplicate of #71

#2 - c4-judge

2023-11-13T20:24:52Z

fatherGoose1 marked the issue as satisfactory

#3 - c4-judge

2023-11-17T16:56:02Z

fatherGoose1 changed the severity to QA (Quality Assurance)

#4 - c4-judge

2023-11-27T20:49:10Z

fatherGoose1 marked the issue as grade-b

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter