|
1 | 1 | // SPDX-License-Identifier: MIT-1.0
|
2 |
| -pragma solidity ^0.8.18; |
| 2 | +pragma solidity ^0.8.26; |
3 | 3 |
|
4 | 4 | import { Math } from "@openzeppelin/contracts/utils/math/Math.sol";
|
5 | 5 |
|
6 | 6 | abstract contract MultiplierPointMath {
|
7 |
| - uint256 public constant YEAR = 365 days; |
8 |
| - uint256 public constant MP_APY = 1; |
| 7 | + /// @notice One (mean) tropical year, in seconds. |
| 8 | + uint256 public constant YEAR = 365 days + 5 hours + 48 minutes + 45 seconds; |
| 9 | + /// @notice Multiplier points annual percentage yield. |
| 10 | + uint256 public constant MP_APY = 100; |
| 11 | + /// @notice Accrued multiplier points maximum multiplier. |
9 | 12 | uint256 public constant MAX_MULTIPLIER = 4;
|
| 13 | + /// @notice The accrue rate period of time over which multiplier points are calculated. |
| 14 | + uint256 public constant ACCURE_RATE = 1 weeks; |
| 15 | + /// @notice Minimal value to generate 1 multiplier point in the accrue rate period (rounded up). |
| 16 | + uint256 public constant MIN_BALANCE = (((YEAR * 100) - 1) / (MP_APY * ACCURE_RATE)) + 1; |
| 17 | + /// @notice Multiplier points absolute maximum multiplier |
| 18 | + uint256 public constant MAX_MULTIPLIER_ABSOLUTE = 1 + (2 * (MAX_MULTIPLIER * MP_APY) / 100); |
| 19 | + /// @notice Maximum lockup period |
| 20 | + uint256 public constant MAX_LOCKUP_PERIOD = MAX_MULTIPLIER * YEAR; |
10 | 21 |
|
11 | 22 | /**
|
12 |
| - * @notice Calculates multiplier points accurred for given `_amount` and `_seconds` time passed |
13 |
| - * @param _amount quantity of tokens |
14 |
| - * @param _seconds time in seconds |
| 23 | + * @notice Calculates the accrued multiplier points (MPs) over a time period Δt, based on the account balance |
| 24 | + * @param _balance Represents the current account balance |
| 25 | + * @param _deltaTime The time difference or the duration over which the multiplier points are accrued, expressed in |
| 26 | + * seconds |
15 | 27 | * @return _accuredMP points accured for given `_amount` and `_seconds`
|
| 28 | + * 51584438 |
| 29 | + * 10000000 |
16 | 30 | */
|
17 |
| - function _calculateAccuredMP(uint256 _amount, uint256 _seconds) internal pure returns (uint256 _accuredMP) { |
18 |
| - return Math.mulDiv(_amount, _seconds, YEAR) * MP_APY; |
| 31 | + function _calculateAccuredMP(uint256 _balance, uint256 _deltaTime) public pure returns (uint256 _accuredMP) { |
| 32 | + return Math.mulDiv(_balance, _deltaTime * MP_APY, YEAR * 100); |
19 | 33 | }
|
20 | 34 |
|
21 | 35 | /**
|
22 |
| - * @notice Calculates bonus multiplier points for given `_amount` and `_lockedSeconds` |
| 36 | + * @notice Calculates the bonus multiplier points (MPs) earned when a balance Δa is locked for a specified duration |
| 37 | + * t_lock. |
| 38 | + * It is equivalent to the accrued multiplier points function but specifically applied in the context of a locked |
| 39 | + * balance. |
23 | 40 | * @param _amount quantity of tokens
|
24 | 41 | * @param _lockedSeconds time in seconds locked
|
25 | 42 | * @return _bonusMP bonus multiplier points for given `_amount` and `_lockedSeconds`
|
26 | 43 | */
|
27 |
| - function _calculateBonusMP(uint256 _amount, uint256 _lockedSeconds) internal pure returns (uint256 _bonusMP) { |
28 |
| - _bonusMP = _amount; |
29 |
| - if (_lockedSeconds > 0) { |
30 |
| - _bonusMP += _calculateAccuredMP(_amount, _lockedSeconds); |
31 |
| - } |
| 44 | + function _calculateBonusMP(uint256 _amount, uint256 _lockedSeconds) public pure returns (uint256 _bonusMP) { |
| 45 | + return _calculateAccuredMP(_amount, _lockedSeconds); |
| 46 | + } |
| 47 | + |
| 48 | + /** |
| 49 | + * @notice Calculates the initial multiplier points (MPs) based on the balance change Δa. The result is equal to |
| 50 | + * the amount of balance added. |
| 51 | + * @param _amount Represents the change in balance. |
| 52 | + */ |
| 53 | + function _calculateInitialMP(uint256 _amount) public pure returns (uint256 _initialMP) { |
| 54 | + return _amount; |
32 | 55 | }
|
33 | 56 |
|
34 | 57 | /**
|
35 |
| - * @notice Calculates minimum stake to genarate 1 multiplier points for given `_seconds` |
36 |
| - * @param _seconds time in seconds |
37 |
| - * @return _minimumStake minimum quantity of tokens |
| 58 | + * @notice Calculates the reduction in multiplier points (MPs) when a portion of the balance Δa `_reducedAmount` is |
| 59 | + * removed from the total balance a_bal `_currentBalance`. |
| 60 | + * The reduction is proportional to the ratio of the removed balance to the total balance, applied to the current |
| 61 | + * multiplier points $mp$. |
| 62 | + * @param _mp Represents the current multiplier points |
| 63 | + * @param _currentBalance The total account balance before the removal of Δa `_reducedBalance` |
| 64 | + * @param _reducedAmount reduced balance |
| 65 | + * @return _reducedMP Multiplier points to reduce from `_mp` |
38 | 66 | */
|
39 |
| - function _calculateMinimumStake(uint256 _seconds) internal pure returns (uint256 _minimumStake) { |
40 |
| - return YEAR / (_seconds * MP_APY); |
| 67 | + function _calculateReducedMP( |
| 68 | + uint256 _mp, |
| 69 | + uint256 _currentBalance, |
| 70 | + uint256 _reducedAmount |
| 71 | + ) |
| 72 | + public |
| 73 | + pure |
| 74 | + returns (uint256 _reducedMP) |
| 75 | + { |
| 76 | + return Math.mulDiv(_mp, _currentBalance, _reducedAmount); |
41 | 77 | }
|
42 | 78 |
|
43 | 79 | /**
|
44 | 80 | * @notice Calculates maximum stake a given `_amount` can be generated with `MAX_MULTIPLIER`
|
45 |
| - * @param _amount quantity of tokens |
| 81 | + * @param _balance quantity of tokens |
46 | 82 | * @return _maxMPAccured maximum quantity of muliplier points that can be generated for given `_amount`
|
47 | 83 | */
|
48 |
| - function _calculateMaxAccuredMP(uint256 _amount) internal pure returns (uint256 _maxMPAccured) { |
49 |
| - return _calculateAccuredMP(_amount, MAX_MULTIPLIER * YEAR); |
| 84 | + function _calculateMaxAccuredMP(uint256 _balance) public pure returns (uint256 _maxMPAccured) { |
| 85 | + return Math.mulDiv(_balance, MAX_MULTIPLIER * MP_APY, 100); |
| 86 | + } |
| 87 | + |
| 88 | + /** |
| 89 | + * @notice The maximum total multiplier points that can be generated for a determined amount of balance and lock |
| 90 | + * duration. |
| 91 | + * @param _balance Represents the current account balance |
| 92 | + * @param _lockTime The time duration for which the balance is locked |
| 93 | + * @return _maxMP Maximum multiplier points that can be generated for given `_balance` and `_lockTime` |
| 94 | + */ |
| 95 | + function _calculateMaxMP(uint256 _balance, uint256 _lockTime) public pure returns (uint256 _maxMP) { |
| 96 | + return _balance + Math.mulDiv(_balance * MP_APY, (MAX_MULTIPLIER * YEAR) + _lockTime, YEAR * 100); |
| 97 | + } |
| 98 | + |
| 99 | + /** |
| 100 | + * @dev Caution: This value is estimated and can be incorrect due precision loss. |
| 101 | + * @notice Estimates the time an account set as locked time. |
| 102 | + * @param _mpMax Maximum multiplier points calculated from the current balance. |
| 103 | + * @param _currentBalance Current balance used to calculate the maximum multiplier points. |
| 104 | + */ |
| 105 | + function _estimateLockTime(uint256 _mpMax, uint256 _currentBalance) public pure returns (uint256 _lockTime) { |
| 106 | + return Math.mulDiv((_mpMax - _currentBalance) * 100, YEAR, _currentBalance * MP_APY, Math.Rounding.Ceil) |
| 107 | + - MAX_LOCKUP_PERIOD; |
| 108 | + } |
| 109 | + |
| 110 | + /** |
| 111 | + * @dev Caution: This value is estimated and can be incorrect due precision loss. |
| 112 | + * @notice Calculates the remaining lock time available for a given `_mpMax` and `_currentBalance` |
| 113 | + * @param _mpMax Maximum multiplier points calculated from the current balance. |
| 114 | + * @param _currentBalance Current balance used to calculate the maximum multiplier points. |
| 115 | + */ |
| 116 | + function _remainingLockTimeAvailable( |
| 117 | + uint256 _mpMax, |
| 118 | + uint256 _currentBalance |
| 119 | + ) |
| 120 | + public |
| 121 | + pure |
| 122 | + returns (uint256 _lockTime) |
| 123 | + { |
| 124 | + return Math.mulDiv((_currentBalance * MAX_MULTIPLIER_ABSOLUTE) - _mpMax, YEAR, _currentBalance); |
| 125 | + } |
| 126 | + |
| 127 | + /** |
| 128 | + * @notice Calculates the lock time for a given bonus multiplier points and current balance. |
| 129 | + * @param _bonusMP bonus multiplier points intended to be generated |
| 130 | + * @param _currentBalance current balance |
| 131 | + */ |
| 132 | + function _calculateLockTime(uint256 _bonusMP, uint256 _currentBalance) public pure returns (uint256 _lockTime) { |
| 133 | + return Math.mulDiv(_bonusMP * 100, YEAR, _currentBalance * MP_APY); |
50 | 134 | }
|
51 | 135 | }
|
0 commit comments