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

Inaccurate Interest Accrual Due to block.number Usage

Closed this issue · 0 comments

Lines of code

https://github.com/code-423n4/2024-07-loopfi/blob/57871f64bdea450c1f04c9a53dc1a78223719164/src/CDPVault.sol#L305

Vulnerability details

Vulnerability Details

In the ICDPVault interface, the lastDebtUpdate field is used to store the timestamp of the last update to a user's debt. This timestamp is crucial for calculating accrued interest over time. The system relies on lastDebtUpdate to accurately compute the time elapsed since the last debt update for interest accrual. However, the function _modifyPosition currently uses block.number instead of block.timestamp to update lastDebtUpdate.

The use of block.number introduces inaccuracies in calculating time-based operations such as interest accrual. Since block numbers do not correspond to a consistent passage of real-world time, relying on them can lead to incorrect interest calculations, which could either undercharge or overcharge users.

Code Snippet

function _modifyPosition(
    address owner,
    Position memory position,
    uint256 newDebt,
    uint256 newCumulativeIndex,
    int256 deltaCollateral,
    uint256 totalDebt_
) internal returns (Position memory) {
    uint256 currentDebt = position.debt;
    // update collateral and debt amounts by the deltas
    position.collateral = add(position.collateral, deltaCollateral);
    position.debt = newDebt;
    position.cumulativeIndexLastUpdate = newCumulativeIndex;
    position.lastDebtUpdate = uint64(block.number); // Issue: Incorrect time tracking
}

Impact

  • Using block.number instead of block.timestamp may result in inaccurate interest charges because the system incorrectly estimates the time elapsed.
  • Users could be unfairly charged more or less interest than they should be, leading to a loss of trust in the system.

Scenario

When a user's debt position is updated, the system calculates interest based on the difference between the current time and lastDebtUpdate. If this difference is based on block.number, which varies in time consistency, the system may incorrectly calculate the interest. For instance, during periods of network congestion or unusually fast block times, the interest accrued may be significantly off from what it should be.

Fix

Replace block.number with block.timestamp to ensure the lastDebtUpdate reflects the actual time:

position.lastDebtUpdate = uint64(block.timestamp);

Example Usage:

function calculateAccruedInterest(address owner) public view returns (uint256) {
    (, uint256 debt, uint256 lastDebtUpdate, , , ) = positions(owner);
    uint256 timeElapsed = block.timestamp - lastDebtUpdate;
    uint256 interestRate = annualInterestRate / 365 days; // Simplified daily interest rate calculation
    return (debt * interestRate * timeElapsed) / 365 days;
}

Assessed type

Context