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

Division by zero error reverts transaction #45

Open
code423n4 opened this issue Dec 13, 2022 · 4 comments
Open

Division by zero error reverts transaction #45

code423n4 opened this issue Dec 13, 2022 · 4 comments
Labels
bug Something isn't working disagree with severity Sponsor confirms validity, but disagrees with warden’s risk assessment (sponsor explain in comments) downgraded by judge Judge downgraded the risk level of this issue grade-b Q-01 QA (Quality Assurance) Assets are not at risk. State handling, function incorrect as to spec, issues with clarity, syntax

Comments

@code423n4
Copy link
Contributor

Lines of code

https://github.com/code-423n4/2022-12-caviar/blob/0212f9dc3b6a418803dbfacda0e340e059b8aae2/src/Pair.sol#L391
https://github.com/code-423n4/2022-12-caviar/blob/0212f9dc3b6a418803dbfacda0e340e059b8aae2/src/Pair.sol#L422
https://github.com/code-423n4/2022-12-caviar/blob/0212f9dc3b6a418803dbfacda0e340e059b8aae2/src/Pair.sol#L421

Vulnerability details

Impact

Division by zero error revert transaction

Proof of Concept

There are a few division by zero error in the Pair smart contract

The first one is the function price()

function fractionalTokenReserves() public view returns (uint256) {
	return balanceOf[address(this)];
}

/// @notice The current price of one fractional token in base tokens with 18 decimals of precision.
/// @dev Calculated by dividing the base token reserves by the fractional token reserves.
/// @return price The price of one fractional token in base tokens * 1e18.
function price() public view returns (uint256) {
	return (_baseTokenReserves() * ONE) / fractionalTokenReserves();
}

If the fractionalTokenReserve is 0, the price() revert in division by zero error.

While the price() is not explicitly used in the code, external contract may reply on the price() function. The function should not revert in divison by zero error.

The same divison by zero eror is in addQuote:

function addQuote(uint256 baseTokenAmount, uint256 fractionalTokenAmount) public view returns (uint256) {
	uint256 lpTokenSupply = lpToken.totalSupply();
	if (lpTokenSupply > 0) {
		// calculate amount of lp tokens as a fraction of existing reserves
		uint256 baseTokenShare = (baseTokenAmount * lpTokenSupply) / baseTokenReserves();
		uint256 fractionalTokenShare = (fractionalTokenAmount * lpTokenSupply) / fractionalTokenReserves();
		return Math.min(baseTokenShare, fractionalTokenShare);
	} else {
		// if there is no liquidity then init
		return Math.sqrt(baseTokenAmount * fractionalTokenAmount);
	}
}

note the line:

uint256 fractionalTokenShare = (fractionalTokenAmount * lpTokenSupply) / fractionalTokenReserves();

and the line

uint256 baseTokenShare = (baseTokenAmount * lpTokenSupply) / baseTokenReserves();

the code precisely revert in divison by zero error.

Tools Used

Manual Review

Recommended Mitigation Steps

We recommend the project handle the division by zero error gracefully. Can return 0 and handle the 0 case when calling the related functoin instead of letting the transaction revert.

@code423n4 code423n4 added 2 (Med Risk) Assets not at direct risk, but function/availability of the protocol could be impacted or leak value bug Something isn't working labels Dec 13, 2022
code423n4 added a commit that referenced this issue Dec 13, 2022
@outdoteth
Copy link

Not sure I agree with severity because no funds are directly at risk here. It is also questionable if returning 0 is the correct default. Technically the price is not zero. If there are no reserves in the contract then it should be assumed that the price is undefined. External contracts should have their own checks on how to handle it imo.

The second section is invalid because it is unreachable. If the lpTokenSupply > 0 then baseTokenReserves and fractionalTokenReserves will return a value greater than 0.

@c4-sponsor
Copy link

outdoteth marked the issue as disagree with severity

@c4-sponsor c4-sponsor added the disagree with severity Sponsor confirms validity, but disagrees with warden’s risk assessment (sponsor explain in comments) label Jan 6, 2023
@c4-judge c4-judge added QA (Quality Assurance) Assets are not at risk. State handling, function incorrect as to spec, issues with clarity, syntax downgraded by judge Judge downgraded the risk level of this issue and removed 2 (Med Risk) Assets not at direct risk, but function/availability of the protocol could be impacted or leak value labels Jan 10, 2023
@c4-judge
Copy link
Contributor

berndartmueller changed the severity to QA (Quality Assurance)

@c4-judge
Copy link
Contributor

berndartmueller marked the issue as grade-b

@C4-Staff C4-Staff added the Q-01 label Jan 24, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working disagree with severity Sponsor confirms validity, but disagrees with warden’s risk assessment (sponsor explain in comments) downgraded by judge Judge downgraded the risk level of this issue grade-b Q-01 QA (Quality Assurance) Assets are not at risk. State handling, function incorrect as to spec, issues with clarity, syntax
Projects
None yet
Development

No branches or pull requests

5 participants