From fe5cd4b517d43e610df449224beb26ce1392ae5e Mon Sep 17 00:00:00 2001 From: Martin Strobl <20109376+mart1n-xyz@users.noreply.github.com> Date: Tue, 11 Jul 2023 11:56:34 +0200 Subject: [PATCH 1/3] Initial MP mint repaired - Now, MPs are minted on the newly staked amount only (previously was entire stake). - The bonus MPs are calculated correctly such that there is a 1x bonus per year of lock. - Still TBD: MPs are not minted for existing stake if current lock extended (or newly introduced), there is no check for max boost MP ceiling --- contracts/StakeManager.sol | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/contracts/StakeManager.sol b/contracts/StakeManager.sol index 9a58659..2929d28 100644 --- a/contracts/StakeManager.sol +++ b/contracts/StakeManager.sol @@ -24,9 +24,10 @@ contract StakeManager is Ownable { } uint256 public constant EPOCH_SIZE = 1 weeks; + uint256 public constant YEAR = 365 days; uint256 public constant MP_APY = 1; uint256 public constant STAKE_APY = 1; - uint256 public constant MAX_BOOST = 1; + uint256 public constant MAX_BOOST = 4; uint256 public constant MAX_MP = 1; mapping (address => Account) accounts; @@ -62,7 +63,7 @@ contract StakeManager is Ownable { processAccount(account, currentEpoch); account.balance += _amount; account.rewardAddress = StakeVault(msg.sender).owner(); - mintIntialMultiplier(account, _time); + mintIntialMultiplier(account, _time, _amount); stakeSupply += _amount; } @@ -199,11 +200,11 @@ contract StakeManager is Ownable { multiplierSupply += increasedMultiplier; } - function mintIntialMultiplier(Account storage account, uint256 lockTime) private { + function mintIntialMultiplier(Account storage account, uint256 lockTime, uint256 amount) private { //if balance still locked, multipliers must be minted from difference of time. uint256 dT = account.lockUntil > block.timestamp ? block.timestamp + lockTime - account.lockUntil : lockTime; account.lockUntil = block.timestamp + lockTime; - uint256 increasedMultiplier = account.balance * (dT+1); //dT+1 could be replaced by requiring that dT is > 0, as it wouldnt matter 1 second locked. + uint256 increasedMultiplier = amount * ((dT/YEAR)+1); account.lastMint = block.timestamp; account.multiplier += increasedMultiplier; multiplierSupply += increasedMultiplier; From a731962d324a0d2eca7d2bee228950c60439064a Mon Sep 17 00:00:00 2001 From: Martin Strobl <20109376+mart1n-xyz@users.noreply.github.com> Date: Tue, 11 Jul 2023 12:08:30 +0200 Subject: [PATCH 2/3] Repair minting MPs with lock - The "free MPs" in the amount of 100% of stake that are minted on deposit are now not minted anymore duplicitely in the lock function --- contracts/StakeManager.sol | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/contracts/StakeManager.sol b/contracts/StakeManager.sol index 2929d28..2c71ff7 100644 --- a/contracts/StakeManager.sol +++ b/contracts/StakeManager.sol @@ -63,7 +63,7 @@ contract StakeManager is Ownable { processAccount(account, currentEpoch); account.balance += _amount; account.rewardAddress = StakeVault(msg.sender).owner(); - mintIntialMultiplier(account, _time, _amount); + mintIntialMultiplier(account, _time, _amount, 1); stakeSupply += _amount; } @@ -90,7 +90,7 @@ contract StakeManager is Ownable { Account storage account = accounts[msg.sender]; processAccount(account, currentEpoch); require(block.timestamp + _time > account.lockUntil, "Cannot decrease lock time"); - mintIntialMultiplier(account, _time); + mintIntialMultiplier(account, _time, account.balance, 0); } /** @@ -200,11 +200,11 @@ contract StakeManager is Ownable { multiplierSupply += increasedMultiplier; } - function mintIntialMultiplier(Account storage account, uint256 lockTime, uint256 amount) private { + function mintIntialMultiplier(Account storage account, uint256 lockTime, uint256 amount, uint256 initMint) private { //if balance still locked, multipliers must be minted from difference of time. uint256 dT = account.lockUntil > block.timestamp ? block.timestamp + lockTime - account.lockUntil : lockTime; account.lockUntil = block.timestamp + lockTime; - uint256 increasedMultiplier = amount * ((dT/YEAR)+1); + uint256 increasedMultiplier = amount * ((dT/YEAR)+initMint); account.lastMint = block.timestamp; account.multiplier += increasedMultiplier; multiplierSupply += increasedMultiplier; From 56f007e3b7b87d201709158b47ae4aef57a973b1 Mon Sep 17 00:00:00 2001 From: Martin Strobl <20109376+mart1n-xyz@users.noreply.github.com> Date: Tue, 11 Jul 2023 15:47:55 +0200 Subject: [PATCH 3/3] added MP boost limit check - limit checked when locking incl. the increased limit due to bonus - limit checked when processing only for accounts that are not locked --- contracts/StakeManager.sol | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/contracts/StakeManager.sol b/contracts/StakeManager.sol index 2c71ff7..dd8ea55 100644 --- a/contracts/StakeManager.sol +++ b/contracts/StakeManager.sol @@ -26,9 +26,8 @@ contract StakeManager is Ownable { uint256 public constant EPOCH_SIZE = 1 weeks; uint256 public constant YEAR = 365 days; uint256 public constant MP_APY = 1; - uint256 public constant STAKE_APY = 1; uint256 public constant MAX_BOOST = 4; - uint256 public constant MAX_MP = 1; + mapping (address => Account) accounts; mapping (uint256 => Epoch) epochs; @@ -151,9 +150,16 @@ contract StakeManager is Ownable { accounts[_vault] = _account; } - function calcMaxMultiplierIncrease(uint256 _increasedMultiplier, uint256 _currentMp) private pure returns(uint256 _maxToIncrease) { + function calcMaxMultiplierIncrease(uint256 _increasedMultiplier, uint256 _currentMp, uint256 _lockUntil, uint256 _stake) private pure returns(uint256 _maxToIncrease) { uint256 newMp = _increasedMultiplier + _currentMp; - return newMp > MAX_MP ? MAX_MP - newMp : _increasedMultiplier; + if(block.timestamp > _lockUntil){ + //not locked, limit to max_boost + return newMp > _stake*MAX_BOOST ? _stake*MAX_BOOST - _currentMp : _increasedMultiplier; + } else { + // locked, ignore cap + return _increasedMultiplier; + } + } function processEpoch() private { @@ -194,8 +200,8 @@ contract StakeManager is Ownable { uint256 deltaTime = processTime - account.lastMint; account.lastMint = processTime; uint256 increasedMultiplier = calcMaxMultiplierIncrease( - account.balance * (MP_APY * deltaTime), - account.multiplier); + account.balance * (MP_APY/YEAR * deltaTime), + account.multiplier, account.lockUntil, account.balance); account.multiplier += increasedMultiplier; multiplierSupply += increasedMultiplier; } @@ -206,8 +212,9 @@ contract StakeManager is Ownable { account.lockUntil = block.timestamp + lockTime; uint256 increasedMultiplier = amount * ((dT/YEAR)+initMint); account.lastMint = block.timestamp; - account.multiplier += increasedMultiplier; + increasedMultiplier = account.multiplier+increasedMultiplier > (account.balance*(MAX_BOOST+(dT/YEAR))) ? account.balance*(MAX_BOOST+(dT/YEAR))-account.multiplier : increasedMultiplier; // checks if MPs are within (lock_time_in_years+MAX_BOOST)*stake multiplierSupply += increasedMultiplier; + account.multiplier += increasedMultiplier; } function totalSupply() public view returns (uint256) {