code-423n4 / 2024-06-panoptic-validation

0 stars 0 forks source link

Math.sol library uses the bitwise-xor operator instead of the exponentiation operator #8

Open c4-bot-4 opened 5 months ago

c4-bot-4 commented 5 months ago

Lines of code

https://github.com/code-423n4/2024-06-panoptic/blob/153f0d82440b7e63075d55b0659706531431145f/contracts/libraries/Math.sol#L340-L433 https://github.com/code-423n4/2024-06-panoptic/blob/153f0d82440b7e63075d55b0659706531431145f/contracts/libraries/Math.sol#L414

Vulnerability details

Impact

Detailed description of the impact of this finding.

File: Math.sol

Function: mulDiv(uint256,uint256,uint256)

Location: Line 340-433

The function mulDiv in the Math.sol library uses the bitwise-xor operator ^ instead of the exponentiation operator **. This occurs at line 414 in the expression inv = (3 * denominator) ^ 2. This misuse of operators can lead to incorrect calculations and potentially severe arithmetic errors in smart contracts that rely on this function for mathematical operations.

Proof of Concept

Provide direct links to all referenced code in GitHub. Add screenshots, logs, or any other relevant proof that illustrates the concept.

The incorrect operator is used in the following line:

// Incorrect exponentiation
inv = (3 * denominator) ^ 2; // Line 414

The correct implementation should use the exponentiation operator ** to raise the result of (3 * denominator) to the power of 2.

File Name: test/foundry/libraries/Maths.t.sol
Prerequisites:
1. Copy the solidity code below into the file and path: test/foundry/libraries/Maths.t.sol
2. Save the file.
3. Within terminal, in the panoptic root folder run forge test -vvvvv --match-contract MathsTest  --fork-url "https://eth-mainnet.g.alchemy.com/v2/{Token}"
Please see POC below.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "ds-test/test.sol";
import "../../../contracts/libraries/Math.sol";

contract MathsTest is DSTest {

    function testMulDivWithFailure() public {
        // Values that typically cause failure due to incorrect operator
        uint256 a = 123456789;
        uint256 b = 987654321;
        uint256 c = 2;

        // Expected value with correct exponentiation
        uint256 expected = (a * b) ** c;

        // Actual value using the incorrect operator
        uint256 actual = Math.mulDiv(a, b, c);

        // Assert that the actual value does not match the expected value
        assertEq(expected, actual, "The mulDiv function returned the incorrect value.");
    }
}
forge test -vvvvv --match-contract MathsTest  --fork-url "https://eth-mainnet.g.alchemy.com/v2/{Token}"
[⠊] Compiling...
No files changed, compilation skipped

Ran 1 test for test/foundry/libraries/Maths.t.sol:MathsTest
[FAIL. Reason: assertion failed] testMulDivWithFailure() (gas: 18701)
Logs:
  Error: The mulDiv function returned the incorrect value.
  Error: a == b not satisfied [uint]
        Left: 14867566530049990397812181822702361
       Right: 60966315556317634

Traces:
  [18701] MathsTest::testMulDivWithFailure()
    ├─ emit log_named_string(key: "Error", val: "The mulDiv function returned the incorrect value.")
    ├─ emit log(val: "Error: a == b not satisfied [uint]")
    ├─ emit log_named_uint(key: "      Left", val: 14867566530049990397812181822702361 [1.486e34])
    ├─ emit log_named_uint(key: "     Right", val: 60966315556317634 [6.096e16])
    ├─ [0] VM::store(VM: [0x7109709ECfa91a80626fF3989D68f67F5b1DD12D], 0x6661696c65640000000000000000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000000000000000000000000001)
    │   └─ ← [Return] 
    └─ ← [Stop] 

Suite result: FAILED. 0 passed; 1 failed; 0 skipped; finished in 1.04s (155.00ms CPU time)

Ran 1 test suite in 2.18s (1.04s CPU time): 0 tests passed, 1 failed, 0 skipped (1 total tests)

Failing tests:
Encountered 1 failing test in test/foundry/libraries/Maths.t.sol:MathsTest
[FAIL. Reason: assertion failed] testMulDivWithFailure() (gas: 18701)

Encountered a total of 1 failing tests, 0 tests succeeded

This test will import the Math.sol library and the DSTest contract from the Dappsys test library, which is commonly used in smart contract testing. The testMulDivWithFailure function calculates the expected value using the correct exponentiation operator ** and compares it to the actual value returned by the mulDiv function using the incorrect operator ^. If the values do not match, the test will fail, indicating that the mulDiv function needs to be corrected. And the test did indeed fail with incorrect matching values as depicted in the bash log above this.

Tools Used

Manual review, Slither and Foundry POC.

Recommended Mitigation Steps

Replace the bitwise-xor operator ^ with the exponentiation operator ** to correctly perform the power operation:

// Corrected exponentiation
inv = (3 * denominator) ** 2; // Line 414

Assessed type

Math