A critical vulnerability in the ConstantProduct2 contract allows for incorrect division by zero in the roundUpDiv function, which is called by calcReserve. This flaw can cause transaction failures, leading to potential griefing attacks and unnecessary gas spending by users. The vulnerability arises due to the absence of a zero-check on the divisor, which can
potentially stop the contract from operating when the reserve is zero.
Vulnerability Details
The roundUpDiv function lacks a check to ensure that the divisor (b) is non-zero before performing the division.
Impact Details
An attacker can exploit this vulnerability to cause repeated transaction failures, disrupting users and potentially halting operations of the smart contract.
Users attempting to execute transactions that trigger this error will incur gas costs without achieving their intended outcomes.
References
function roundUpDiv(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) return 0;
@=> return (a - 1) / b + 1;
}
Proof of concept
In roundUpDiv Function
Condition Occurs:
If the value of b is zero, then (a - 1) / b will attempt to divide by zero.
Why Occurs:
There is no check to ensure that b is not zero before the division is performed.
Effect:
Will cause contract execution failure and abort the transaction.
Impact on calcReserve Function
Condition Occurs:
calcReserve calls roundUpDiv with b as reserves[j == 1 ? 0 : 1] * EXP_PRECISION.
If reserves[j == 1 ? 0 : 1] is zero, then b will be zero.
Why Occurs:
If any of the reserves in reserves is zero, then the product by EXP_PRECISION is still zero.
Result:
The calcReserve function will fail due to division by zero, causing the transaction to be aborted.
Recommendation
Introduce a require statement to ensure that the divisor is not zero before performing the division.
function roundUpDiv(uint256 a, uint256 b) internal pure returns (uint256) {
+ require(b != 0, "Division by zero");
if (a == 0) return 0;
return (a - 1) / b + 1;
}
Immunefi Response
Unfortunately, after reviewing your report, Immunefi has decided to close it as it does not meet our project requirements.
Your submission falls under one of the following categories:
Non-Vulnerability Issues: These include issues such as typos, layout issues, and other non-security-related problems that do not pose any security threat.
Spam Issues: These include reports that are intended to advertise a product or service, to mislead users or defame the company, or are irrelevant to the program.
UI/UX Issues: These include issues related to user interface and user experience that do not pose any security threat.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "forge-std/Test.sol";
import "../src/functions/ConstantProduct2.sol";
import "../src/libraries/LibMath.sol";
contract ConstantProduct2Test is Test {
ConstantProduct2 constantProduct2;
function setUp() public {
constantProduct2 = new ConstantProduct2();
}
function testRoundUpDivDivisionByZero() public {
uint256 a = 1000;
uint256 b = 0; // Set b to zero
// Expect the transaction to revert due to division by zero
vm.expectRevert(abi.encodeWithSignature("Panic(uint256)", 0x12)); // Use the panic code for division by zero
LibMath.roundUpDiv(a, b);
}
}