code-423n4 / 2024-07-basin-validation

0 stars 0 forks source link

Decimal Handling Flaw in decodeWellData Function Leads to Potential Miscalculations #87

Closed c4-bot-8 closed 3 months ago

c4-bot-8 commented 3 months ago

Lines of code

https://github.com/code-423n4/2024-07-basin/blob/7d5aacbb144d0ba0bc358dfde6e0cc913d25310e/src/functions/Stable2.sol#L310-L327

Vulnerability details

Impact

A critical bug has been identified in the decodeWellData function that compromises the handling of token decimals, particularly for the second token in a pair. This function is intended to standardize decimal place representation, but it fails to correct the second token's decimals when set to zero. The consequences of this error cascade through several key functions:

  1. calcRate: It would give the wrong exchange rates between tokens.

  2. calcLpTokenSupply: It could give wrong information about how much liquidity is in the pool.

  3. getScaledReserves: It might make token amounts look way bigger than they really are.

scaledReserves[1] = reserves[1] * 10 ** (18 - 0) = reserves[1] * 1e18

  1. calcReserve: It might calculate token reserves incorrectly and could even cause math errors.

These mistakes could lead to big problems with how tokens are valued and how the whole system works.

Proof of Concept

The problem is in this part of the code:

function decodeWellData(bytes memory data) public view virtual returns (uint256[] memory decimals) {
        (uint256 decimal0, uint256 decimal1) = abi.decode(data, (uint256, uint256));

        // if well data returns 0, assume 18 decimals.
        if (decimal0 == 0) {
            decimal0 = 18;
        }
        if (decimal0 == 0) {
            decimal1 = 18;
        }
        if (decimal0 > 18 || decimal1 > 18) revert InvalidTokenDecimals();

        decimals = new uint256[](2);
        decimals[0] = decimal0;
        decimals[1] = decimal1;
    }

The second if statement checks decimal0 again instead of checking decimal1. This means it never fixes decimal1 when it's zero.

Tools Used

Manual review

Recommended Mitigation Steps

To fix this, change the code to:

function decodeWellData(bytes memory data) public view virtual returns (uint256[] memory decimals) {
    (uint256 decimal0, uint256 decimal1) = abi.decode(data, (uint256, uint256));

    // if well data returns 0, assume 18 decimals.
    if (decimal0 == 0) {
        decimal0 = 18;
    }
-   if (decimal0 == 0) {
+   if (decimal1 == 0) {
        decimal1 = 18;
    }
    if (decimal0 > 18 || decimal1 > 18) revert InvalidTokenDecimals();

    decimals = new uint256[](2);
    decimals[0] = decimal0;
    decimals[1] = decimal1;
}

This change makes sure both tokens are handled correctly, which will keep all the calculations in the system accurate.

Assessed type

Decimal