sherlock-audit / 2024-06-magicsea-judging

2 stars 0 forks source link

chitranshu - Audit Report: Integration of Dynamic Month Duration Calculation in `Booster` Smart Contract #286

Closed sherlock-admin3 closed 1 month ago

sherlock-admin3 commented 2 months ago

chitranshu

Medium

Audit Report: Integration of Dynamic Month Duration Calculation in Booster Smart Contract

Summary

The proposed integration of the NextMonthDays library into the Booster smart contract aims to replace the static definition of month duration (SEC_PER_MONTH) with a dynamic calculation based on the actual number of days in the next calendar month. This enhancement provides users with accurate information regarding the end time of reward periods, aligning with business model requirements for clarity and precision.

Vulnerability Detail

The current implementation of SEC_PER_MONTH in the Booster smart contract uses a fixed value of 2,628,000 seconds, equating to approximately 30 days. However, this static definition does not account for variations in the number of days per month due to leap years and calendar irregularities. This could lead to discrepancies between the expected and actual end times of reward periods, potentially confusing users and affecting the accuracy of financial projections. https://github.com/sherlock-audit/2024-06-magicsea/blob/main/magicsea-staking/src/booster/Booster.sol#L111 By integrating the NextMonthDays library, the contract dynamically calculates the duration of the next month based on the current timestamp. This approach mitigates the risk of inaccuracies stemming from static month duration assumptions, ensuring that reward end times are reliably aligned with calendar months.

Impact

Medium: The impact of inaccuracies in reward period calculations can lead to user confusion and misaligned expectations regarding the availability of rewards. In financial applications such as staking contracts, where timing precision is crucial, discrepancies in reward period end times could undermine user trust and satisfaction.

Code Snippet

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

import "./NextMonthDays.sol";

contract Booster {
-    uint256 public constant SEC_PER_MONTH = 2628000; // Financial month ~ 30 days
+    uint256 public constant SEC_PER_MONTH = 2628000; // Financial month ~ 30 days

    // Other contract code...

+    function getDynamicSecPerMonth() external view returns (uint256) {
+       return NextMonthDays.getNextMonthDays() * 1 days; // Convert days to seconds
    }

    // Other contract functions...
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

library NextMonthDays {
    function getNextMonthDays() public view returns (uint8) {
        uint256 currentTimestamp = block.timestamp;
        uint8[12] memory daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];

        // Extract the current year and month from the timestamp
        (uint16 currentYear, uint8 currentMonth,) = _timestampToDate(currentTimestamp);

        // Determine the next month and year
        uint8 nextMonth = currentMonth == 12 ? 1 : currentMonth + 1;
        uint16 nextYear = currentMonth == 12 ? currentYear + 1 : currentYear;

        // Check for leap year if February is the next month
        if (nextMonth == 2 && _isLeapYear(nextYear)) {
            return 29;
        } else {
            return daysInMonth[nextMonth - 1];
        }
    }

    function _timestampToDate(uint256 timestamp) private pure returns (uint16 year, uint8 month, uint8 day) {
        uint256 z = timestamp / 86400 + 719468;
        uint256 era = (z >= 0 ? z : z - 146096) / 146097;
        uint256 doe = z - era * 146097;
        uint256 yoe = (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365;
        uint256 y = yoe + era * 400;
        uint256 doy = doe - (365 * yoe + yoe / 4 - yoe / 100);
        uint256 mp = (5 * doy + 2) / 153;
        uint256 d = doy - (153 * mp + 2) / 5 + 1;
        uint256 m = mp < 10 ? mp + 3 : mp - 9;

        year = uint16(y + (m <= 2 ? 1 : 0));
        month = uint8(m);
        day = uint8(d);
    }

    function _isLeapYear(uint16 year) private pure returns (bool) {
        if (year % 4 == 0) {
            if (year % 100 == 0) {
                return year % 400 == 0;
            } else {
                return true;
            }
        } else {
            return false;
        }
    }
}

}

Tool used

Manual Review

Recommendation

To enhance the robustness and usability of the Booster smart contract, consider integrating the NextMonthDays library as proposed. This integration ensures that reward period end times accurately reflect the actual number of days in the next calendar month, thereby providing users with transparent and predictable reward scheduling. Additionally, document the integration thoroughly to facilitate understanding and maintenance by future developers.

0xSmartContract commented 1 month ago

This issue does not indicate a security vulnerability or critical flaw. The change to dynamic month duration calculation is more of a design improvement rather than a necessity for security or functionality.

Additionally, static month duration has been commonly used in financial contracts without significant issues.

The recommended change addresses user convenience and precision but does not mitigate any direct threat to the contract’s integrity or operation. Thus, the reported issue is considered invalid from a security standpoint.

Also Booster.sol is out of scope

https://github.com/sherlock-audit/2024-06-magicsea/tree/main?tab=readme-ov-file#audit-scope