@gooddollar/goodprotocol 1.0.8 → 1.0.9-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/artifacts/contracts/DAOStackInterfaces.sol/Avatar.dbg.json +1 -1
  2. package/artifacts/contracts/DAOStackInterfaces.sol/Controller.dbg.json +1 -1
  3. package/artifacts/contracts/DAOStackInterfaces.sol/GlobalConstraintInterface.dbg.json +1 -1
  4. package/artifacts/contracts/DAOStackInterfaces.sol/IntVoteInterface.dbg.json +1 -1
  5. package/artifacts/contracts/DAOStackInterfaces.sol/ReputationInterface.dbg.json +1 -1
  6. package/artifacts/contracts/DAOStackInterfaces.sol/SchemeRegistrar.dbg.json +1 -1
  7. package/artifacts/contracts/Interfaces.sol/AggregatorV3Interface.dbg.json +1 -1
  8. package/artifacts/contracts/Interfaces.sol/ERC20.dbg.json +1 -1
  9. package/artifacts/contracts/Interfaces.sol/IAaveIncentivesController.dbg.json +1 -1
  10. package/artifacts/contracts/Interfaces.sol/IAdminWallet.dbg.json +1 -1
  11. package/artifacts/contracts/Interfaces.sol/IDonationStaking.dbg.json +1 -1
  12. package/artifacts/contracts/Interfaces.sol/IERC2917.dbg.json +1 -1
  13. package/artifacts/contracts/Interfaces.sol/IFirstClaimPool.dbg.json +1 -1
  14. package/artifacts/contracts/Interfaces.sol/IGoodDollar.dbg.json +1 -1
  15. package/artifacts/contracts/Interfaces.sol/IGoodStaking.dbg.json +1 -1
  16. package/artifacts/contracts/Interfaces.sol/IHasRouter.dbg.json +1 -1
  17. package/artifacts/contracts/Interfaces.sol/IIdentity.dbg.json +1 -1
  18. package/artifacts/contracts/Interfaces.sol/ILendingPool.dbg.json +1 -1
  19. package/artifacts/contracts/Interfaces.sol/INameService.dbg.json +1 -1
  20. package/artifacts/contracts/Interfaces.sol/IUBIScheme.dbg.json +1 -1
  21. package/artifacts/contracts/Interfaces.sol/ProxyAdmin.dbg.json +1 -1
  22. package/artifacts/contracts/Interfaces.sol/Reserve.dbg.json +1 -1
  23. package/artifacts/contracts/Interfaces.sol/Staking.dbg.json +1 -1
  24. package/artifacts/contracts/Interfaces.sol/Uniswap.dbg.json +1 -1
  25. package/artifacts/contracts/Interfaces.sol/UniswapFactory.dbg.json +1 -1
  26. package/artifacts/contracts/Interfaces.sol/UniswapPair.dbg.json +1 -1
  27. package/artifacts/contracts/Interfaces.sol/cERC20.dbg.json +1 -1
  28. package/artifacts/contracts/governance/ClaimersDistribution.sol/ClaimersDistribution.dbg.json +1 -1
  29. package/artifacts/contracts/governance/CompoundVotingMachine.sol/CompoundVotingMachine.dbg.json +1 -1
  30. package/artifacts/contracts/governance/GReputation.sol/GReputation.dbg.json +1 -1
  31. package/artifacts/contracts/governance/GovarnanceStaking.sol/GovernanceStaking.dbg.json +1 -1
  32. package/artifacts/contracts/governance/MultiBaseGovernanceShareField.sol/MultiBaseGovernanceShareField.dbg.json +1 -1
  33. package/artifacts/contracts/governance/Reputation.sol/Reputation.dbg.json +1 -1
  34. package/artifacts/contracts/governance/StakersDistribution.sol/StakersDistribution.dbg.json +1 -1
  35. package/artifacts/contracts/mocks/AaveMock.sol/AaveMock.dbg.json +1 -1
  36. package/artifacts/contracts/mocks/DAIMock.sol/DAIMock.dbg.json +1 -1
  37. package/artifacts/contracts/mocks/DecimalsMock.sol/DecimalsMock.dbg.json +1 -1
  38. package/artifacts/contracts/mocks/GoodCompoundStakingTest.sol/GoodCompoundStakingTest.dbg.json +1 -1
  39. package/artifacts/contracts/mocks/GoodFundManagerTest.sol/GoodFundManagerTest.dbg.json +1 -1
  40. package/artifacts/contracts/mocks/IncentiveControllerMock.sol/IncentiveControllerMock.dbg.json +1 -1
  41. package/artifacts/contracts/mocks/LendingPoolMock.sol/LendingPoolMock.dbg.json +1 -1
  42. package/artifacts/contracts/mocks/OverMintTester.sol/OverMintTester.dbg.json +1 -1
  43. package/artifacts/contracts/mocks/OverMintTesterRegularStake.sol/OverMintTesterRegularStake.dbg.json +1 -1
  44. package/artifacts/contracts/mocks/SixteenDecimalsTokenMock.sol/SixteenDecimalsTokenMock.dbg.json +1 -1
  45. package/artifacts/contracts/mocks/SwapHelperTest.sol/SwapHelperTest.dbg.json +1 -1
  46. package/artifacts/contracts/mocks/TwentyDecimalsTokenMock.sol/TwentyDecimalsTokenMock.dbg.json +1 -1
  47. package/artifacts/contracts/mocks/UpgradableMocks.sol/UpgradableMock.dbg.json +1 -1
  48. package/artifacts/contracts/mocks/UpgradableMocks.sol/UpgradableMock2.dbg.json +1 -1
  49. package/artifacts/contracts/mocks/UsdcMock.sol/USDCMock.dbg.json +1 -1
  50. package/artifacts/contracts/mocks/cBATMock.sol/cBATMock.dbg.json +1 -1
  51. package/artifacts/contracts/mocks/cDAILowWorthMock.sol/cDAILowWorthMock.dbg.json +1 -1
  52. package/artifacts/contracts/mocks/cDAIMock.sol/cDAIMock.dbg.json +1 -1
  53. package/artifacts/contracts/mocks/cDAINonMintableMock.sol/cDAINonMintableMock.dbg.json +1 -1
  54. package/artifacts/contracts/mocks/cDecimalsMock.sol/cDecimalsMock.dbg.json +1 -1
  55. package/artifacts/contracts/mocks/cSDTMock.sol/cSDTMock.dbg.json +1 -1
  56. package/artifacts/contracts/mocks/cUSDCMock.sol/cUSDCMock.dbg.json +1 -1
  57. package/artifacts/contracts/reserve/ExchangeHelper.sol/ExchangeHelper.dbg.json +1 -1
  58. package/artifacts/contracts/reserve/GoodMarketMaker.sol/GoodMarketMaker.dbg.json +1 -1
  59. package/artifacts/contracts/reserve/GoodReserveCDai.sol/ContributionCalc.dbg.json +1 -1
  60. package/artifacts/contracts/reserve/GoodReserveCDai.sol/GoodReserveCDai.dbg.json +1 -1
  61. package/artifacts/contracts/staking/BaseShareField.sol/BaseShareField.dbg.json +1 -1
  62. package/artifacts/contracts/staking/BaseShareFieldV2.sol/BaseShareFieldV2.dbg.json +4 -0
  63. package/artifacts/contracts/staking/BaseShareFieldV2.sol/BaseShareFieldV2.json +256 -0
  64. package/artifacts/contracts/staking/DonationsStaking.sol/DonationsStaking.dbg.json +1 -1
  65. package/artifacts/contracts/staking/GoodFundManager.sol/GoodFundManager.dbg.json +1 -1
  66. package/artifacts/contracts/staking/SimpleStaking.sol/SimpleStaking.dbg.json +1 -1
  67. package/artifacts/contracts/staking/SimpleStakingV2.sol/SimpleStakingV2.dbg.json +4 -0
  68. package/artifacts/contracts/staking/SimpleStakingV2.sol/SimpleStakingV2.json +1033 -0
  69. package/artifacts/contracts/staking/UniswapV2SwapHelper.sol/UniswapV2SwapHelper.dbg.json +1 -1
  70. package/artifacts/contracts/staking/aave/AaveStakingFactory.sol/AaveStakingFactory.dbg.json +1 -1
  71. package/artifacts/contracts/staking/aave/AaveStakingFactoryV2.sol/AaveStakingFactoryV2.dbg.json +4 -0
  72. package/artifacts/contracts/staking/aave/AaveStakingFactoryV2.sol/AaveStakingFactoryV2.json +148 -0
  73. package/artifacts/contracts/staking/aave/GoodAaveStaking.sol/GoodAaveStaking.dbg.json +1 -1
  74. package/artifacts/contracts/staking/aave/GoodAaveStakingV2.sol/GoodAaveStakingV2.dbg.json +4 -0
  75. package/artifacts/contracts/staking/aave/GoodAaveStakingV2.sol/GoodAaveStakingV2.json +1224 -0
  76. package/artifacts/contracts/staking/compound/CompoundStakingFactory.sol/CompoundStakingFactory.dbg.json +1 -1
  77. package/artifacts/contracts/staking/compound/GoodCompoundStaking.sol/GoodCompoundStaking.dbg.json +1 -1
  78. package/artifacts/contracts/ubi/UBIScheme.sol/UBIScheme.dbg.json +1 -1
  79. package/artifacts/contracts/unaudited-foundation/FuseFaucet.sol/FuseFaucet.dbg.json +1 -1
  80. package/artifacts/contracts/unaudited-foundation/InvitesV1.sol/InvitesV1.dbg.json +1 -1
  81. package/artifacts/contracts/utils/BancorFormula.sol/BancorFormula.dbg.json +1 -1
  82. package/artifacts/contracts/utils/DAOContract.sol/DAOContract.dbg.json +1 -1
  83. package/artifacts/contracts/utils/DAOUpgradeableContract.sol/DAOUpgradeableContract.dbg.json +1 -1
  84. package/artifacts/contracts/utils/DSMath.sol/DSMath.dbg.json +1 -1
  85. package/artifacts/contracts/utils/DataTypes.sol/DataTypes.dbg.json +1 -1
  86. package/artifacts/contracts/utils/NameService.sol/NameService.dbg.json +1 -1
  87. package/artifacts/contracts/utils/ProtocolUpgrade.sol/OldMarketMaker.dbg.json +1 -1
  88. package/artifacts/contracts/utils/ProtocolUpgrade.sol/ProtocolUpgrade.dbg.json +1 -1
  89. package/artifacts/contracts/utils/ProtocolUpgradeFuse.sol/ProtocolUpgradeFuse.dbg.json +1 -1
  90. package/artifacts/contracts/utils/ReputationTestHelper.sol/ReputationTestHelper.dbg.json +1 -1
  91. package/contracts/staking/BaseShareFieldV2.sol +319 -0
  92. package/contracts/staking/SimpleStakingV2.sol +522 -0
  93. package/contracts/staking/aave/AaveStakingFactoryV2.sol +93 -0
  94. package/contracts/staking/aave/GoodAaveStakingV2.sol +263 -0
  95. package/package.json +1 -1
  96. package/test/helpers.ts +5 -1
  97. package/test/staking/GoodAaveStakingFactoryV2.test.ts +122 -0
  98. package/test/staking/UsdcAaveStaking.test.ts +5 -1
  99. package/test/staking/UsdcAaveStakingV2.test.ts +291 -0
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "_format": "hh-sol-dbg-1",
3
- "buildInfo": "../../../../build-info/82d74f20f1a2ee68fd4fbdf578e2beb6.json"
3
+ "buildInfo": "../../../../build-info/432071a069fa44ffd3a7f92eee83d72e.json"
4
4
  }
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "_format": "hh-sol-dbg-1",
3
- "buildInfo": "../../../../build-info/82d74f20f1a2ee68fd4fbdf578e2beb6.json"
3
+ "buildInfo": "../../../../build-info/432071a069fa44ffd3a7f92eee83d72e.json"
4
4
  }
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "_format": "hh-sol-dbg-1",
3
- "buildInfo": "../../../build-info/82d74f20f1a2ee68fd4fbdf578e2beb6.json"
3
+ "buildInfo": "../../../build-info/432071a069fa44ffd3a7f92eee83d72e.json"
4
4
  }
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "_format": "hh-sol-dbg-1",
3
- "buildInfo": "../../../build-info/82d74f20f1a2ee68fd4fbdf578e2beb6.json"
3
+ "buildInfo": "../../../build-info/432071a069fa44ffd3a7f92eee83d72e.json"
4
4
  }
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "_format": "hh-sol-dbg-1",
3
- "buildInfo": "../../../build-info/82d74f20f1a2ee68fd4fbdf578e2beb6.json"
3
+ "buildInfo": "../../../build-info/432071a069fa44ffd3a7f92eee83d72e.json"
4
4
  }
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "_format": "hh-sol-dbg-1",
3
- "buildInfo": "../../../build-info/82d74f20f1a2ee68fd4fbdf578e2beb6.json"
3
+ "buildInfo": "../../../build-info/432071a069fa44ffd3a7f92eee83d72e.json"
4
4
  }
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "_format": "hh-sol-dbg-1",
3
- "buildInfo": "../../../build-info/82d74f20f1a2ee68fd4fbdf578e2beb6.json"
3
+ "buildInfo": "../../../build-info/432071a069fa44ffd3a7f92eee83d72e.json"
4
4
  }
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "_format": "hh-sol-dbg-1",
3
- "buildInfo": "../../../build-info/82d74f20f1a2ee68fd4fbdf578e2beb6.json"
3
+ "buildInfo": "../../../build-info/432071a069fa44ffd3a7f92eee83d72e.json"
4
4
  }
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "_format": "hh-sol-dbg-1",
3
- "buildInfo": "../../../build-info/82d74f20f1a2ee68fd4fbdf578e2beb6.json"
3
+ "buildInfo": "../../../build-info/432071a069fa44ffd3a7f92eee83d72e.json"
4
4
  }
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "_format": "hh-sol-dbg-1",
3
- "buildInfo": "../../../build-info/82d74f20f1a2ee68fd4fbdf578e2beb6.json"
3
+ "buildInfo": "../../../build-info/432071a069fa44ffd3a7f92eee83d72e.json"
4
4
  }
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "_format": "hh-sol-dbg-1",
3
- "buildInfo": "../../../build-info/82d74f20f1a2ee68fd4fbdf578e2beb6.json"
3
+ "buildInfo": "../../../build-info/432071a069fa44ffd3a7f92eee83d72e.json"
4
4
  }
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "_format": "hh-sol-dbg-1",
3
- "buildInfo": "../../../build-info/82d74f20f1a2ee68fd4fbdf578e2beb6.json"
3
+ "buildInfo": "../../../build-info/432071a069fa44ffd3a7f92eee83d72e.json"
4
4
  }
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "_format": "hh-sol-dbg-1",
3
- "buildInfo": "../../../build-info/82d74f20f1a2ee68fd4fbdf578e2beb6.json"
3
+ "buildInfo": "../../../build-info/432071a069fa44ffd3a7f92eee83d72e.json"
4
4
  }
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "_format": "hh-sol-dbg-1",
3
- "buildInfo": "../../../build-info/82d74f20f1a2ee68fd4fbdf578e2beb6.json"
3
+ "buildInfo": "../../../build-info/432071a069fa44ffd3a7f92eee83d72e.json"
4
4
  }
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "_format": "hh-sol-dbg-1",
3
- "buildInfo": "../../../build-info/82d74f20f1a2ee68fd4fbdf578e2beb6.json"
3
+ "buildInfo": "../../../build-info/432071a069fa44ffd3a7f92eee83d72e.json"
4
4
  }
@@ -0,0 +1,319 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity >=0.8.0;
3
+ import "../Interfaces.sol";
4
+ import "openzeppelin-solidity/contracts/utils/math/Math.sol";
5
+ import "../utils/DSMath.sol";
6
+
7
+ contract BaseShareFieldV2 is DSMath {
8
+ // rewards claimed by users
9
+ uint128 public mintedRewards;
10
+ // number of blocks before reaching the max rewards multiplier (starting at 0.5 reaching 1 after maxMultiplierThreshold)
11
+ uint64 public maxMultiplierThreshold;
12
+ // Staking contracts accepts Tokens with max 18 decimals so this variable holds decimal difference between 18 and Token's decimal in order to make calculations
13
+ uint8 public tokenDecimalDifference;
14
+ // total staked for shares calculation
15
+ uint128 public totalProductivity;
16
+ // total staked that earns rewards (some stakers can donate their rewards)
17
+ uint128 public totalEffectiveStakes;
18
+ // rewards accumulated for distribution
19
+ uint128 public accumulatedRewards;
20
+ // block of last rewards accumulation
21
+ uint128 public lastRewardBlock;
22
+ // accumulated rewards per share in 27 decimals precision
23
+ uint256 public accAmountPerShare;
24
+
25
+ //status of user rewards. everything is in 18 decimals
26
+ struct UserInfo {
27
+ uint128 amount; // How many tokens the user has provided.
28
+ uint128 effectiveStakes; // stakes not including stakes that donate their rewards
29
+ uint128 rewardDebt; // Reward debt.
30
+ uint128 rewardEarn; // Reward earn and not minted
31
+ uint128 rewardMinted; //Rewards minted to user so far
32
+ uint64 lastRewardTime; // Last time that user got rewards
33
+ uint64 multiplierResetTime; // Reset time of multiplier
34
+ }
35
+ mapping(address => UserInfo) public users;
36
+
37
+ /**
38
+ * @dev Helper function to check if caller is fund manager
39
+ */
40
+ function _canMintRewards() internal view virtual {}
41
+
42
+ /**
43
+ * @dev Update reward variables of the given pool to be up-to-date.
44
+ * Calculates passed blocks and adding to the reward pool
45
+ * @param rewardsPerBlock how much rewards does this contract earns per block
46
+ * @param blockStart block from which contract starts earning rewards
47
+ * @param blockEnd block from which contract stops earning rewards
48
+ */
49
+ function _update(
50
+ uint256 rewardsPerBlock,
51
+ uint256 blockStart,
52
+ uint256 blockEnd
53
+ ) internal virtual {
54
+ if (totalEffectiveStakes == 0) {
55
+ lastRewardBlock = uint128(block.number);
56
+ return;
57
+ }
58
+ if (block.number >= blockStart && lastRewardBlock < blockStart) {
59
+ lastRewardBlock = uint128(blockStart);
60
+ }
61
+
62
+ uint256 _lastRewardBlock = lastRewardBlock < blockStart &&
63
+ block.number >= blockStart
64
+ ? blockStart
65
+ : lastRewardBlock;
66
+ uint256 curRewardBlock = block.number > blockEnd ? blockEnd : block.number;
67
+
68
+ if (curRewardBlock < blockStart || _lastRewardBlock >= blockEnd) return;
69
+
70
+ uint256 multiplier = curRewardBlock - _lastRewardBlock; // Blocks passed since last reward block
71
+ uint256 reward = multiplier * (rewardsPerBlock * 1e16); // rewardsPerBlock is in G$ which is only 2 decimals, we turn it into 18 decimals by multiplying 1e16
72
+
73
+ accAmountPerShare =
74
+ accAmountPerShare +
75
+ (reward * 1e27) /
76
+ (totalEffectiveStakes * (10**tokenDecimalDifference));
77
+ // Increase totalEffectiveStakes decimals if it is less than 18 decimals then accAmountPerShare in 27 decimals
78
+
79
+ lastRewardBlock = uint128(curRewardBlock);
80
+ }
81
+
82
+ /**
83
+ * @dev Audit user's rewards and calculate their earned rewards
84
+ * For the first month rewards calculated with 0.5x
85
+ * multiplier therefore they just gets half of the rewards which they earned in the first month
86
+ * after first month they get full amount of rewards for the part that they earned after one month
87
+ * @param user the user to audit
88
+ * @param updatedAmount the new stake of the user after deposit/withdraw
89
+ * @param donationPer percentage user is donating from his rewards. (currently just 0 or 100 in SimpleStaking)
90
+ */
91
+ function _audit(
92
+ address user,
93
+ uint256 updatedAmount,
94
+ uint256 donationPer
95
+ ) internal virtual {
96
+ UserInfo storage userInfo = users[user];
97
+ uint256 _amount = userInfo.amount;
98
+ uint256 userEffectiveStake = userInfo.effectiveStakes;
99
+ if (userEffectiveStake > 0) {
100
+ (
101
+ uint256 blocksToPay,
102
+ uint256 firstMonthBlocksToPay,
103
+ uint256 fullBlocksToPay
104
+ ) = _auditCalcs(userInfo);
105
+
106
+ if (blocksToPay != 0) {
107
+ uint256 pending = (userEffectiveStake *
108
+ (10**tokenDecimalDifference) *
109
+ accAmountPerShare) /
110
+ 1e27 -
111
+ userInfo.rewardDebt;
112
+ // Turn userInfo.amount to 18 decimals by multiplying tokenDecimalDifference if it's not and multiply with accAmountPerShare which is 27 decimals then divide it 1e27 bring it down to 18 decimals
113
+ uint256 rewardPerBlock = (pending * 1e9) / blocksToPay; // bring pending to 1e27
114
+ pending =
115
+ ((((firstMonthBlocksToPay * 1e2 * 5) / 10) + fullBlocksToPay * 1e2) * // multiply first month by 0.5x (5/10) since rewards in first month with multiplier 0.5 and multiply it with 1e2 to get it 2decimals so we could get more precision
116
+ rewardPerBlock) / // Multiply fullBlocksToPay with 1e2 to bring it to 2 decimals // rewardPerBlock is in 27decimals
117
+ 1e11; // Pending in 18 decimals so we divide 1e11 to bring it down to 18 decimals
118
+ userInfo.rewardEarn = uint128(userInfo.rewardEarn + pending); // Add user's earned rewards to user's account so it can be minted later
119
+ accumulatedRewards = uint128(accumulatedRewards + pending);
120
+ }
121
+ } else {
122
+ userInfo.multiplierResetTime = uint64(block.number); // Should set user's multiplierResetTime when they stake for the first time
123
+ }
124
+
125
+ //if withdrawing rewards/stake we reset multiplier, only in case of increasinig productivity we dont reset multiplier
126
+ if (updatedAmount <= _amount) {
127
+ userInfo.multiplierResetTime = uint64(block.number);
128
+ if (_amount > 0) {
129
+ //calculate relative part of user effective stakes
130
+ uint256 withdrawFromEffectiveStake = ((_amount - updatedAmount) *
131
+ userInfo.effectiveStakes) / _amount;
132
+ userInfo.effectiveStakes -= uint128(withdrawFromEffectiveStake);
133
+ totalEffectiveStakes -= uint128(withdrawFromEffectiveStake);
134
+ }
135
+ } else if (donationPer == 0) {
136
+ userInfo.effectiveStakes += uint128(updatedAmount - _amount);
137
+ totalEffectiveStakes += uint128(updatedAmount - _amount);
138
+ }
139
+ userInfo.lastRewardTime = uint64(block.number);
140
+ userInfo.amount = uint128(updatedAmount);
141
+ userInfo.rewardDebt = uint128(
142
+ (userInfo.effectiveStakes *
143
+ (10**tokenDecimalDifference) *
144
+ accAmountPerShare) / 1e27
145
+ ); // Divide to 1e27 to keep rewardDebt in 18 decimals since accAmountPerShare is 27 decimals
146
+ }
147
+
148
+ /**
149
+ * @dev Helper function to make calculations in audit and getUserPendingReward methods
150
+ */
151
+ function _auditCalcs(UserInfo memory _userInfo)
152
+ internal
153
+ view
154
+ returns (
155
+ uint256,
156
+ uint256,
157
+ uint256
158
+ )
159
+ {
160
+ uint256 blocksPaid = _userInfo.lastRewardTime -
161
+ _userInfo.multiplierResetTime; // lastRewardTime is always >= multiplierResetTime
162
+ uint256 blocksPassedFirstMonth = Math.min(
163
+ maxMultiplierThreshold,
164
+ block.number - _userInfo.multiplierResetTime
165
+ );
166
+ // blocks which is after first month
167
+ uint256 blocksToPay = block.number - _userInfo.lastRewardTime; // blocks passed since last payment
168
+ uint256 firstMonthBlocksToPay = blocksPaid >= maxMultiplierThreshold
169
+ ? 0
170
+ : blocksPassedFirstMonth - blocksPaid; // block which is in the first month so pays with 0.5x multiplier
171
+ uint256 fullBlocksToPay = blocksToPay - firstMonthBlocksToPay; // blocks to pay in full amount which means with 1x multiplier
172
+ return (blocksToPay, firstMonthBlocksToPay, fullBlocksToPay);
173
+ }
174
+
175
+ /**
176
+ * @dev This function increase user's productivity and updates the global productivity.
177
+ * This function increase user's productivity and updates the global productivity.
178
+ * the users' actual share percentage will calculated by:
179
+ * Formula: user_productivity / global_productivity
180
+ * @param user the user to update
181
+ * @param value the increase in user stake
182
+ * @param rewardsPerBlock how much rewards does this contract earns per block
183
+ * @param blockStart block from which contract starts earning rewards
184
+ * @param blockEnd block from which contract stops earning rewards
185
+ * @param donationPer percentage user is donating from his rewards. (currently just 0 or 100 in SimpleStaking)
186
+ */
187
+ function _increaseProductivity(
188
+ address user,
189
+ uint256 value,
190
+ uint256 rewardsPerBlock,
191
+ uint256 blockStart,
192
+ uint256 blockEnd,
193
+ uint256 donationPer
194
+ ) internal virtual returns (bool) {
195
+ _update(rewardsPerBlock, blockStart, blockEnd);
196
+ _audit(user, users[user].amount + value, donationPer);
197
+
198
+ totalProductivity = uint128(totalProductivity + value);
199
+ return true;
200
+ }
201
+
202
+ /**
203
+ * @dev This function will decreases user's productivity by value, and updates the global productivity
204
+ * it will record which block this is happenning and accumulates the area of (productivity * time)
205
+ * @param user the user to update
206
+ * @param value the increase in user stake
207
+ * @param rewardsPerBlock how much rewards does this contract earns per block
208
+ * @param blockStart block from which contract starts earning rewards
209
+ * @param blockEnd block from which contract stops earning rewards
210
+ */
211
+
212
+ function _decreaseProductivity(
213
+ address user,
214
+ uint256 value,
215
+ uint256 rewardsPerBlock,
216
+ uint256 blockStart,
217
+ uint256 blockEnd
218
+ ) internal virtual returns (bool) {
219
+ _update(rewardsPerBlock, blockStart, blockEnd);
220
+ _audit(user, users[user].amount - value, 1); // donationPer variable should be something different than zero so called with 1
221
+ totalProductivity = uint128(totalProductivity - value);
222
+
223
+ return true;
224
+ }
225
+
226
+ /**
227
+ * @dev Query user's pending reward with updated variables
228
+ * @param user the user to update
229
+ * @param rewardsPerBlock how much rewards does this contract earns per block
230
+ * @param blockStart block from which contract starts earning rewards
231
+ * @param blockEnd block from which contract stops earning rewards
232
+ * @return returns amount of user's earned but not minted rewards
233
+ */
234
+ function getUserPendingReward(
235
+ address user,
236
+ uint256 rewardsPerBlock,
237
+ uint256 blockStart,
238
+ uint256 blockEnd
239
+ ) public view returns (uint256) {
240
+ UserInfo memory userInfo = users[user];
241
+ uint256 _accAmountPerShare = accAmountPerShare;
242
+
243
+ uint256 pending = 0;
244
+ if (
245
+ totalEffectiveStakes != 0 &&
246
+ block.number >= blockStart &&
247
+ blockEnd >= block.number
248
+ ) {
249
+ uint256 multiplier = block.number - lastRewardBlock;
250
+ uint256 reward = multiplier * (rewardsPerBlock * 1e16); // turn it to 18 decimals since rewardsPerBlock in 2 decimals
251
+ (
252
+ uint256 blocksToPay,
253
+ uint256 firstMonthBlocksToPay,
254
+ uint256 fullBlocksToPay
255
+ ) = _auditCalcs(userInfo);
256
+
257
+ _accAmountPerShare =
258
+ _accAmountPerShare +
259
+ (reward * 1e27) /
260
+ (totalEffectiveStakes * 10**tokenDecimalDifference); // Increase totalEffectiveStakes decimals if it is less than 18 decimals then accAmountPerShare in 27 decimals
261
+ UserInfo memory tempUserInfo = userInfo; // to prevent stack too deep error any other recommendation?
262
+ if (blocksToPay != 0) {
263
+ pending =
264
+ (tempUserInfo.effectiveStakes *
265
+ (10**tokenDecimalDifference) *
266
+ _accAmountPerShare) /
267
+ 1e27 -
268
+ tempUserInfo.rewardDebt; // Turn userInfo.amount to 18 decimals by multiplying tokenDecimalDifference if it's not and multiply with accAmountPerShare which is 27 decimals then divide it 1e27 bring it down to 18 decimals
269
+ uint256 rewardPerBlock = (pending * 1e27) / (blocksToPay * 1e18); // bring both variable to 18 decimals and multiply pending by 1e27 so when we divide them to each other result would be in 1e27
270
+ pending =
271
+ ((((firstMonthBlocksToPay * 1e2 * 5) / 10) + fullBlocksToPay * 1e2) * // multiply first month by 0.5x (5/10) since rewards in first month with multiplier 0.5 and multiply it with 1e2 to get it 2decimals so we could get more precision
272
+ rewardPerBlock) / // Multiply fullBlocksToPay with 1e2 to bring it to 2decimals // rewardPerBlock is in 27decimals
273
+ 1e11; // Pending in 18 decimals so we divide 1e11 to bring it down to 18 decimals
274
+ }
275
+ }
276
+ return userInfo.rewardEarn + pending; // rewardEarn is in 18 decimals
277
+ }
278
+
279
+ /**
280
+ * @dev When the fundmanager calls this function it will updates the user records
281
+ * get the user rewards which they earned but not minted and mark it as minted
282
+ * @param user the user to update
283
+ * @param rewardsPerBlock how much rewards does this contract earns per block
284
+ * @param blockStart block from which contract starts earning rewards
285
+ * @param blockEnd block from which contract stops earning rewards
286
+ * @return returns amount to mint as reward to the user
287
+ */
288
+
289
+ function rewardsMinted(
290
+ address user,
291
+ uint256 rewardsPerBlock,
292
+ uint256 blockStart,
293
+ uint256 blockEnd
294
+ ) public returns (uint256) {
295
+ UserInfo storage userInfo = users[user];
296
+ _canMintRewards();
297
+ _update(rewardsPerBlock, blockStart, blockEnd);
298
+ _audit(user, userInfo.amount, 1); // donationPer variable should be something different than zero so called with 1
299
+ uint128 amount = userInfo.rewardEarn;
300
+ userInfo.rewardEarn = 0;
301
+ userInfo.rewardMinted += amount;
302
+ mintedRewards = mintedRewards + amount;
303
+ amount = amount / 1e16; // change decimal of mint amount to GD decimals
304
+ return amount;
305
+ }
306
+
307
+ /**
308
+ * @return Returns how many productivity a user has and global has.
309
+ */
310
+
311
+ function getProductivity(address user)
312
+ public
313
+ view
314
+ virtual
315
+ returns (uint256, uint256)
316
+ {
317
+ return (users[user].amount, totalProductivity);
318
+ }
319
+ }