Skip to content

Latest commit

 

History

History
93 lines (68 loc) · 3.88 KB

034.md

File metadata and controls

93 lines (68 loc) · 3.88 KB

Kind Aqua Ostrich

Medium

Potential division by zero in _calculateCollateralAmountRequired cause the transaction to revert in PredictDotLoan.sol

Summary

Potential division by zero in _calculateCollateralAmountRequired in PredictDotLoan.sol cause the transaction to revert.

Root Cause

The function _calculateCollateralAmountRequired is responsible for calculating the required collateral for a loan offer based on the proposal, the fulfillment so far, and the amount being fulfilled. https://github.com/sherlock-audit/2024-09-predict-fun/blob/main/predict-dot-loan/contracts/PredictDotLoan.sol#L1161-L1171 The line 1169 performs a division by proposal.loanAmount. If proposal.loanAmount is zero, this will lead to a division by zero error, causing the transaction to revert. Also. there's no check in place to ensure that proposal.loanAmount is non-zero, which makes this function vulnerable.

We can create a test case (PoC below) to exploit this vulnerability by providing a Proposal struct where proposal.loanAmount == 0. This will result in a transaction revert due to the division by zero.

  1. In the testDivisionByZero() function, we create a Proposal with loanAmount == 0.
  2. The function _calculateCollateralAmountRequired will attempt to perform the division (proposal.collateralAmount * fulfillAmount) / proposal.loanAmount, which will result in a division by zero and cause the transaction to revert.

Internal pre-conditions

No response

External pre-conditions

No response

Attack Path

No response

Impact

  1. The division by zero will revert transactions, leading to disruption of contract operations. Users attempting to execute the function in legitimate contexts could encounter reverts, resulting in poor user experience and protocol inefficiency.
  2. An attacker could intentionally trigger division by zero by crafting a proposal with loanAmount == 0, leading to denial of service (DoS) attacks. By creating proposals with zero loanAmount, an attacker could prevent legitimate users from interacting with the contract, disrupting the entire loan issuance process.

PoC

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

contract CollateralCalculation {
    struct Proposal {
        uint256 collateralAmount;
        uint256 loanAmount; // This could be zero, causing a division by zero
    }

    struct Fulfillment {
        uint256 collateralAmount;
        uint256 loanAmount;
    }

    function calculateCollateralAmountRequired(
        Proposal calldata proposal,
        Fulfillment storage fulfillment,
        uint256 fulfillAmount
    ) external view returns (uint256 collateralAmountRequired) {
        // Vulnerable division by zero
        if (fulfillment.loanAmount + fulfillAmount == proposal.loanAmount) {
            collateralAmountRequired = proposal.collateralAmount - fulfillment.collateralAmount;
        } else {
            collateralAmountRequired = (proposal.collateralAmount * fulfillAmount) / proposal.loanAmount;
        }
    }

    // Simple function to test the vulnerability
    function testDivisionByZero() external view returns (uint256) {
        Proposal memory proposal = Proposal({collateralAmount: 1000, loanAmount: 0}); // loanAmount is zero
        Fulfillment storage fulfillment;
        uint256 fulfillAmount = 100;

        return calculateCollateralAmountRequired(proposal, fulfillment, fulfillAmount);
    }
}

Mitigation

  1. Before performing the division, ensure proposal.loanAmount is non-zero:
require(proposal.loanAmount > 0, "Loan amount cannot be zero");
  1. If a loanAmount == 0 scenario is valid (in specific cases), introduce logic to handle it gracefully without dividing by zero:
if (proposal.loanAmount == 0) {
    collateralAmountRequired = 0;
} else {
    collateralAmountRequired = (proposal.collateralAmount * fulfillAmount) / proposal.loanAmount;
}