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

0xNirix - Reserve Ratio Can Become Zero Through Reward Operations #29

Open
sherlock-admin3 opened this issue Oct 31, 2024 · 1 comment
Labels
Sponsor Confirmed The sponsor acknowledged this issue is valid Will Fix The sponsor confirmed this issue will be fixed

Comments

@sherlock-admin3
Copy link

sherlock-admin3 commented Oct 31, 2024

0xNirix

Medium

Reserve Ratio Can Become Zero Through Reward Operations

Summary

Mathematical operations in updateRatioForReward function can cause the reserve ratio to become zero when processing large rewards, leading to a denial of service in the exchange as division by zero occurs in subsequent Bancor formula calculations.

Root Cause

In https://github.com/sherlock-audit/2024-10-mento-update/blob/main/mento-core/contracts/goodDollar/GoodDollarExchangeProvider.sol#L206, the mathematical formula for calculating new reserve ratio can result in zero:

// The mathematical operation sequence:
UD60x18 numerator = wrap(exchange.reserveBalance);
UD60x18 denominator = wrap(exchange.tokenSupply + rewardScaled).mul(wrap(currentPriceScaled));
uint256 newRatioScaled = unwrap(numerator.div(denominator));

// When denominator becomes very large relative to numerator:
uint32 newRatioUint = uint32(newRatioScaled / 1e10);  // Results in 0 
exchanges[exchangeId].reserveRatio = newRatioUint;     // Zero ratio stored

The core issue lies in the mathematical relationship:
newRatio = reserveBalance / ((tokenSupply + reward) * currentPrice)
When reward is significantly larger than tokenSupply, the denominator grows so large that the division result becomes less than 1e-10, which truncates to zero in the final conversion.

In contrast, this situation is avoided in other scenarios like

function mintFromExpansion(bytes32 exchangeId, uint256 reserveRatioScalar) external onlyExpansionController {
    // ...
    uint32 newRatioUint = uint32(unwrap(newRatio) / 1e10);
    require(newRatioUint > 0, "New ratio must be greater than 0");  // Protection exists here
    
    exchanges[exchangeId].reserveRatio = newRatioUint;
}

Internal pre-conditions

No response

External pre-conditions

No response

Attack Path

Initial Exchange State

reserveBalance = 100_000e18;              // 100K tokens
tokenSupply = 1_000_000e18;               // 1M tokens
initialReserveRatio = 100000;             // 10% ratio (MAX_WEIGHT = 1000000)
currentPrice = 1e18;                      // 1:1 price

Ratio calculation in updateRatioForReward:

// Step by step calculation that occurs in updateRatioForReward:
reward = 10_000_000_000e18;                            // 10B tokens
currentPriceScaled = currentPrice * 1e18             // 1e18 * 1e18 = 1e36
rewardScaled = minimumReward                         // 10B * 1e18

numerator = wrap(exchange.reserveBalance)            // 100_000e18
denominator = wrap(
    exchange.tokenSupply + rewardScaled             // 1M + 10B = 10.001B
).mul(wrap(currentPriceScaled))                     // * 1e36

newRatioScaled = unwrap(numerator.div(denominator))
                = 100_000e36 / (10_001_000_000e36)
                = 9.99e9                            // Just under 1e10

// Final conversion
newRatioUint = uint32(newRatioScaled / 1e10)       // 0.999 -> 0

Impact

When ratio becomes zero:

  1. All swap operations fail due to division by zero in Bancor formula
  2. Price calculations become impossible
  3. Exchange becomes inoperable

PoC

No response

Mitigation

No response

@sherlock-admin3 sherlock-admin3 changed the title Creamy Pecan Guppy - Reserve Ratio Can Become Zero Through Reward Operations 0xNirix - Reserve Ratio Can Become Zero Through Reward Operations Nov 5, 2024
@sherlock-admin2
Copy link
Contributor

The protocol team fixed this issue in the following PRs/commits:
mento-protocol/mento-core#544

@sherlock-admin3 sherlock-admin3 added Sponsor Confirmed The sponsor acknowledged this issue is valid Will Fix The sponsor confirmed this issue will be fixed labels Nov 28, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Sponsor Confirmed The sponsor acknowledged this issue is valid Will Fix The sponsor confirmed this issue will be fixed
Projects
None yet
Development

No branches or pull requests

2 participants