Beanstalk Notion
Beanstalk Notion
/
🪲
Bug Reports
/
BIC Notes
/
📄
Report #34660
📄

Report #34660

Report Date
August 19, 2024
Status
Closed
Payout

Griefing(Incorrect Handling of Zero Ratios)

‣
Report Info

Report ID

#34660

Report type

Smart Contract

Has PoC?

Yes

Target

https://etherscan.io/address/0xBA150C2ae0f8450D4B832beeFa3338d4b5982d26

Impacts

Griefing (e.g. no profit motive for an attacker, but damage to the users or the protocol)

Description

The provided test below results indicate a vulnerability in the calcReserveAtRatioSwap function of the ConstantProduct2 contract. The function fails to handle incorrect ratios, specifically a ratio of zero, resulting in unexpected behavior instead of a revert.

Test Case: Initializes two arrays: reserves and incorrectRatios with specific values. Calls calcReserveAtRatioSwap twice with different parameters. Asserts that the first call's result is greater than zero. Expects the second call to revert but it doesn't. Failure Analysis:

The test fails because the second call to calcReserveAtRatioSwap with incorrect ratios (specifically, a ratio of 0) does not revert as expected. This suggests that the ConstantProduct2 contract's logic might not be handling incorrect ratios correctly. Impact: The failure to handle incorrect ratios can lead to several negative consequences:

Incorrect Calculations: The function might return incorrect reserve values, leading to incorrect pricing and trading decisions. Exploitability: Malicious actors could potentially manipulate the contract's state by providing invalid inputs, leading to financial losses or other adverse effects. If this behavior is exploited, it could cause disruptions in any protocol relying on the ConstantProduct2 contract for liquidity or price calculations. Specifically: Liquidity Calculations: Inaccurate liquidity calculations could lead to mispriced trades. Protocol Integrity: The absence of error handling may allow malicious actors to pass zero ratios, leading to unintended outcomes and potential loss of funds.

Proof of concept

POC:

// SPDX-License-Identifier: MIT pragma solidity ^0.8.20;

import "forge-std/Test.sol"; import "../src/functions/ConstantProduct2.sol"; // Adjust the path as necessary

contract ConstantProduct2Test is Test { ConstantProduct2 constantProduct2;

}

Root Cause Analysis The calcReserveAtRatioSwap function calculates reserves based on the input ratios. When one of the ratios is zero, the function performs a multiplication that results in a zero value, which it returns instead of reverting. This lack of validation for zero ratios could lead to unexpected and incorrect behavior in other parts of the contract or dependent systems.

Immunefi Response

We have reviewed your submission, but unfortunately, we are closing the report for the following reasons:
  • The submission contains the output of an automated scanner without demonstrating that it is a valid issue.
  • The submission lacks the required information regarding the vulnerability's impact on the reported asset.

Please note that the project will receive a report of the closed submission and may choose to re-open it, but they are not obligated to do so.

function setUp() public {
    // Deploy the ConstantProduct2 contract
    constantProduct2 = new ConstantProduct2();
}

function testIncorrectRatios() public {
    // Define some test reserves and incorrect ratios
    uint256[] memory reserves = new uint256[](2);
    uint256[] memory incorrectRatios = new uint256[](2);

    // Set initial reserves (e.g., 1000 and 2000 tokens)
    reserves[0] = 1000 * 1e18;
    reserves[1] = 2000 * 1e18;

    // Set incorrect ratios
    // e.g., ratio[0] is much larger than ratio[1], which may lead to precision issues
    incorrectRatios[0] = 1000000 * 1e18; // Very large ratio for token 0
    incorrectRatios[1] = 1;

    // Call the calcReserveAtRatioSwap with the incorrect ratios and expect it to either revert or return a safe value
    try constantProduct2.calcReserveAtRatioSwap(reserves, 0, incorrectRatios, "") {
        // If it doesn't revert, check if the result is within expected bounds
        uint256 reserve = constantProduct2.calcReserveAtRatioSwap(reserves, 0, incorrectRatios, "");
        assertGt(reserve, 0, "Reserve should be greater than 0 even with incorrect ratios");
    } catch {
        // If the function reverts, it should revert for a good reason
        assertTrue(true, "Function correctly reverted with incorrect ratios");
    }

    // Another scenario where the ratio is zero, which should cause a revert or safe handling
    incorrectRatios[1] = 0;

    // Expect the function to revert due to division by zero or invalid ratio
    vm.expectRevert(); // Expect any revert
    constantProduct2.calcReserveAtRatioSwap(reserves, 1, incorrectRatios, "");
}