-
Notifications
You must be signed in to change notification settings - Fork 0
Description
Amateur Banana Fish
Medium
Incorrect Protocol Activity-Time Calculation in Distribution Module Due to Unaccounted Pauses
### Summary:
The distribution module incorrectly computes timePassed
by simply subtracting lastOnChainDistributionTimestamp
from block.timestamp
. This calculation does not account for pauses in the contract, leading to incorrect distribution values upon resumption.
### Finding Description:
The _calculateGamma function calculates time elapsed (timePassed) since the last distribution:
uint256 timePassed = block.timestamp - $.lastOnChainDistributionTimestamp;
However, the DistributionModule
supports pausing and resuming, the time the contract spends in a paused state should not count towards timePassed
. Since the function does not account for pauses, the distribution formula treats the entire elapsed time as active distribution time, which can cause incorrect calculations.
The integrity of the distribution mechanism is then compromised.
Affected Code: here.
### Impact Explanation:
This issue directly affects financial calculations, i suppose the impact is Medium.
### Proof of Concept:
- Assume the contract is paused for 90 days:
// Last on-chain distribution was 6 months ago
$.lastOnChainDistributionTimestamp = block.timestamp - 180 days;
// Contract is paused for 90 days
pause();
wait(90 days);
unpause();
// timePassed should be 90 days, but incorrectly calculates as 180 days
uint256 timePassed = block.timestamp - $.lastOnChainDistributionTimestamp;
Expected: timePassed = 90 days
Actual: timePassed = 180 days
→ Incorrect gamma scaling
### Recommendation
Fix: Track Unpaused Time Instead of Using block.timestamp Directly
Modify timePassed to exclude paused durations:
// New variable to track cumulative unpaused time
uint256 unpausedTime;
function _updateUnpausedTime() internal {
if (!paused) {
unpausedTime += block.timestamp - $.lastUpdatedTimestamp;
}
$.lastUpdatedTimestamp = block.timestamp;
}
function _calculateGamma(DistributionModuleStorageV0 storage $)
internal
view
returns (uint256)
{
uint256 timePassed = unpausedTime - $.lastOnChainDistributionTimestamp;
require(timePassed >= 0, "Invalid timestamp: future time");
if (timePassed == 0 || timePassed <= DISTRIBUTION_FREQUENCY_SCALAR) {
return Math.mulDiv($.baseGamma, SCALAR_ONE, BPS_SCALAR, Math.Rounding.Floor);
}
uint256 denominator = Math.mulDiv(SCALAR_ONE, timePassed, DISTRIBUTION_FREQUENCY_SCALAR, Math.Rounding.Floor);
uint256 numerator = Math.mulDiv($.baseGamma, SCALAR_ONE, BPS_SCALAR, Math.Rounding.Floor);
return Math.mulDiv(numerator, SCALAR_ONE, denominator, Math.Rounding.Floor);
}