@gooddollar/goodprotocol 1.0.28 → 1.0.29-beta.1

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 (352) hide show
  1. package/artifacts/abis/BulkProof.min.json +1 -1
  2. package/artifacts/abis/DistributionBridgeMock.min.json +1 -0
  3. package/artifacts/abis/DistributionHelper.min.json +1 -0
  4. package/artifacts/abis/DistributionHelperTest.min.json +1 -0
  5. package/artifacts/abis/DistributionHelperTestHelper.min.json +1 -0
  6. package/artifacts/abis/ERC20.min.json +1 -1
  7. package/artifacts/abis/GoodDollarMintBurnWrapper.min.json +1 -0
  8. package/artifacts/abis/GoodDollarStaking.min.json +1 -0
  9. package/artifacts/abis/GoodDollarStakingMock.min.json +1 -0
  10. package/artifacts/abis/GoodReserveCDai.min.json +1 -1
  11. package/artifacts/abis/IERC2917.min.json +1 -1
  12. package/artifacts/abis/IGoodDollarStakingTest.min.json +1 -0
  13. package/artifacts/abis/IMultichainRouter.min.json +1 -0
  14. package/artifacts/abis/IRouter.min.json +1 -0
  15. package/artifacts/abis/IWrapper.min.json +1 -0
  16. package/artifacts/abis/Math64x64.min.json +1 -0
  17. package/artifacts/abis/MultichainBridgeHelper.min.json +1 -0
  18. package/artifacts/abis/MultichainRouterMock.min.json +1 -0
  19. package/artifacts/abis/OverMintTester.min.json +1 -1
  20. package/artifacts/abis/PausableControl.min.json +1 -0
  21. package/artifacts/abis/RewardsMinter.min.json +1 -0
  22. package/artifacts/abis/StakingMockFixedAPY.min.json +1 -0
  23. package/artifacts/abis/StakingRewardsFixedAPY.min.json +1 -0
  24. package/artifacts/abis/TokenOperation.min.json +1 -0
  25. package/artifacts/abis/cERC20.min.json +1 -1
  26. package/artifacts/contracts/DAOStackInterfaces.sol/Avatar.dbg.json +1 -1
  27. package/artifacts/contracts/DAOStackInterfaces.sol/Controller.dbg.json +1 -1
  28. package/artifacts/contracts/DAOStackInterfaces.sol/GlobalConstraintInterface.dbg.json +1 -1
  29. package/artifacts/contracts/DAOStackInterfaces.sol/IntVoteInterface.dbg.json +1 -1
  30. package/artifacts/contracts/DAOStackInterfaces.sol/ReputationInterface.dbg.json +1 -1
  31. package/artifacts/contracts/DAOStackInterfaces.sol/SchemeRegistrar.dbg.json +1 -1
  32. package/artifacts/contracts/Interfaces.sol/AggregatorV3Interface.dbg.json +1 -1
  33. package/artifacts/contracts/Interfaces.sol/ERC20.dbg.json +1 -1
  34. package/artifacts/contracts/Interfaces.sol/ERC20.json +13 -0
  35. package/artifacts/contracts/Interfaces.sol/IAaveIncentivesController.dbg.json +1 -1
  36. package/artifacts/contracts/Interfaces.sol/IAdminWallet.dbg.json +1 -1
  37. package/artifacts/contracts/Interfaces.sol/IDonationStaking.dbg.json +1 -1
  38. package/artifacts/contracts/Interfaces.sol/IERC2917.dbg.json +1 -1
  39. package/artifacts/contracts/Interfaces.sol/IERC2917.json +13 -0
  40. package/artifacts/contracts/Interfaces.sol/IFirstClaimPool.dbg.json +1 -1
  41. package/artifacts/contracts/Interfaces.sol/IGoodDollar.dbg.json +1 -1
  42. package/artifacts/contracts/Interfaces.sol/IGoodStaking.dbg.json +1 -1
  43. package/artifacts/contracts/Interfaces.sol/IHasRouter.dbg.json +1 -1
  44. package/artifacts/contracts/Interfaces.sol/IIdentity.dbg.json +1 -1
  45. package/artifacts/contracts/Interfaces.sol/ILendingPool.dbg.json +1 -1
  46. package/artifacts/contracts/Interfaces.sol/IMultichainRouter.dbg.json +4 -0
  47. package/artifacts/contracts/Interfaces.sol/IMultichainRouter.json +67 -0
  48. package/artifacts/contracts/Interfaces.sol/INameService.dbg.json +1 -1
  49. package/artifacts/contracts/Interfaces.sol/IUBIScheme.dbg.json +1 -1
  50. package/artifacts/contracts/Interfaces.sol/ProxyAdmin.dbg.json +1 -1
  51. package/artifacts/contracts/Interfaces.sol/Reserve.dbg.json +1 -1
  52. package/artifacts/contracts/Interfaces.sol/Staking.dbg.json +1 -1
  53. package/artifacts/contracts/Interfaces.sol/Uniswap.dbg.json +1 -1
  54. package/artifacts/contracts/Interfaces.sol/UniswapFactory.dbg.json +1 -1
  55. package/artifacts/contracts/Interfaces.sol/UniswapPair.dbg.json +1 -1
  56. package/artifacts/contracts/Interfaces.sol/cERC20.dbg.json +1 -1
  57. package/artifacts/contracts/Interfaces.sol/cERC20.json +13 -0
  58. package/artifacts/contracts/fuseFaucet/FuseFaucet.sol/FuseFaucet.dbg.json +1 -1
  59. package/artifacts/contracts/fuseFaucet/FuseFaucet.sol/FuseFaucet.json +2 -2
  60. package/artifacts/contracts/governance/ClaimersDistribution.sol/ClaimersDistribution.dbg.json +1 -1
  61. package/artifacts/contracts/governance/ClaimersDistribution.sol/ClaimersDistribution.json +2 -2
  62. package/artifacts/contracts/governance/CompoundVotingMachine.sol/CompoundVotingMachine.dbg.json +1 -1
  63. package/artifacts/contracts/governance/CompoundVotingMachine.sol/CompoundVotingMachine.json +2 -2
  64. package/artifacts/contracts/governance/GReputation.sol/GReputation.dbg.json +1 -1
  65. package/artifacts/contracts/governance/GReputation.sol/GReputation.json +2 -2
  66. package/artifacts/contracts/governance/GoodDollarStaking.sol/GoodDollarStaking.dbg.json +4 -0
  67. package/artifacts/contracts/governance/GoodDollarStaking.sol/GoodDollarStaking.json +1322 -0
  68. package/artifacts/contracts/governance/GoodDollarStaking.sol/RewardsMinter.dbg.json +4 -0
  69. package/artifacts/contracts/governance/GoodDollarStaking.sol/RewardsMinter.json +35 -0
  70. package/artifacts/contracts/governance/GovernanceStaking.sol/GovernanceStaking.dbg.json +1 -1
  71. package/artifacts/contracts/governance/GovernanceStaking.sol/GovernanceStaking.json +2 -2
  72. package/artifacts/contracts/governance/MultiBaseGovernanceShareField.sol/MultiBaseGovernanceShareField.dbg.json +1 -1
  73. package/artifacts/contracts/governance/Reputation.sol/Reputation.dbg.json +1 -1
  74. package/artifacts/contracts/governance/Reputation.sol/Reputation.json +2 -2
  75. package/artifacts/contracts/governance/StakersDistribution.sol/StakersDistribution.dbg.json +1 -1
  76. package/artifacts/contracts/governance/StakersDistribution.sol/StakersDistribution.json +2 -2
  77. package/artifacts/contracts/invite/InvitesV1.sol/InvitesV1.dbg.json +1 -1
  78. package/artifacts/contracts/invite/InvitesV1.sol/InvitesV1.json +2 -2
  79. package/artifacts/contracts/mocks/AaveMock.sol/AaveMock.dbg.json +1 -1
  80. package/artifacts/contracts/mocks/DAIMock.sol/DAIMock.dbg.json +1 -1
  81. package/artifacts/contracts/mocks/DecimalsMock.sol/DecimalsMock.dbg.json +1 -1
  82. package/artifacts/contracts/mocks/DistributionBridgeMock.sol/DistributionBridgeMock.dbg.json +4 -0
  83. package/artifacts/contracts/mocks/DistributionBridgeMock.sol/DistributionBridgeMock.json +152 -0
  84. package/artifacts/contracts/mocks/DistributionHelperTest.sol/DistributionHelperTest.dbg.json +4 -0
  85. package/artifacts/contracts/mocks/DistributionHelperTest.sol/DistributionHelperTest.json +662 -0
  86. package/artifacts/contracts/mocks/DistributionHelperTest.sol/DistributionHelperTestHelper.dbg.json +4 -0
  87. package/artifacts/contracts/mocks/DistributionHelperTest.sol/DistributionHelperTestHelper.json +680 -0
  88. package/artifacts/contracts/mocks/GoodCompoundStakingTest.sol/GoodCompoundStakingTest.dbg.json +1 -1
  89. package/artifacts/contracts/mocks/GoodCompoundStakingTest.sol/GoodCompoundStakingTest.json +2 -2
  90. package/artifacts/contracts/mocks/GoodDollarStakingMock.sol/GoodDollarStakingMock.dbg.json +4 -0
  91. package/artifacts/contracts/mocks/GoodDollarStakingMock.sol/GoodDollarStakingMock.json +1322 -0
  92. package/artifacts/contracts/mocks/GoodFundManagerTest.sol/GoodFundManagerTest.dbg.json +1 -1
  93. package/artifacts/contracts/mocks/GoodFundManagerTest.sol/GoodFundManagerTest.json +2 -2
  94. package/artifacts/contracts/mocks/IncentiveControllerMock.sol/IncentiveControllerMock.dbg.json +1 -1
  95. package/artifacts/contracts/mocks/LendingPoolMock.sol/LendingPoolMock.dbg.json +1 -1
  96. package/artifacts/contracts/mocks/MultichainRouterMock.sol/IWrapper.dbg.json +4 -0
  97. package/artifacts/contracts/mocks/MultichainRouterMock.sol/IWrapper.json +59 -0
  98. package/artifacts/contracts/mocks/MultichainRouterMock.sol/MultichainRouterMock.dbg.json +4 -0
  99. package/artifacts/contracts/mocks/MultichainRouterMock.sol/MultichainRouterMock.json +81 -0
  100. package/artifacts/contracts/mocks/OverMintTester.sol/IGoodDollarStakingTest.dbg.json +4 -0
  101. package/artifacts/contracts/mocks/OverMintTester.sol/IGoodDollarStakingTest.json +49 -0
  102. package/artifacts/contracts/mocks/OverMintTester.sol/OverMintTester.dbg.json +1 -1
  103. package/artifacts/contracts/mocks/OverMintTester.sol/OverMintTester.json +4 -4
  104. package/artifacts/contracts/mocks/OverMintTesterRegularStake.sol/OverMintTesterRegularStake.dbg.json +1 -1
  105. package/artifacts/contracts/mocks/OverMintTesterRegularStake.sol/OverMintTesterRegularStake.json +2 -2
  106. package/artifacts/contracts/mocks/SixteenDecimalsTokenMock.sol/SixteenDecimalsTokenMock.dbg.json +1 -1
  107. package/artifacts/contracts/mocks/StakingMockFixedAPY.sol/StakingMockFixedAPY.dbg.json +4 -0
  108. package/artifacts/contracts/mocks/StakingMockFixedAPY.sol/StakingMockFixedAPY.json +682 -0
  109. package/artifacts/contracts/mocks/SwapHelperTest.sol/SwapHelperTest.dbg.json +1 -1
  110. package/artifacts/contracts/mocks/SwapHelperTest.sol/SwapHelperTest.json +2 -2
  111. package/artifacts/contracts/mocks/TwentyDecimalsTokenMock.sol/TwentyDecimalsTokenMock.dbg.json +1 -1
  112. package/artifacts/contracts/mocks/UpgradableMocks.sol/UpgradableMock.dbg.json +1 -1
  113. package/artifacts/contracts/mocks/UpgradableMocks.sol/UpgradableMock.json +2 -2
  114. package/artifacts/contracts/mocks/UpgradableMocks.sol/UpgradableMock2.dbg.json +1 -1
  115. package/artifacts/contracts/mocks/UpgradableMocks.sol/UpgradableMock2.json +2 -2
  116. package/artifacts/contracts/mocks/UpgradableMocks.sol/UpgradableMock3.dbg.json +1 -1
  117. package/artifacts/contracts/mocks/UpgradableMocks.sol/UpgradableMock3.json +2 -2
  118. package/artifacts/contracts/mocks/UpgradableMocks.sol/UpgradableMock4.dbg.json +1 -1
  119. package/artifacts/contracts/mocks/UpgradableMocks.sol/UpgradableMock4.json +2 -2
  120. package/artifacts/contracts/mocks/UsdcMock.sol/USDCMock.dbg.json +1 -1
  121. package/artifacts/contracts/mocks/cBATMock.sol/cBATMock.dbg.json +1 -1
  122. package/artifacts/contracts/mocks/cDAILowWorthMock.sol/cDAILowWorthMock.dbg.json +1 -1
  123. package/artifacts/contracts/mocks/cDAIMock.sol/cDAIMock.dbg.json +1 -1
  124. package/artifacts/contracts/mocks/cDAINonMintableMock.sol/cDAINonMintableMock.dbg.json +1 -1
  125. package/artifacts/contracts/mocks/cDecimalsMock.sol/cDecimalsMock.dbg.json +1 -1
  126. package/artifacts/contracts/mocks/cSDTMock.sol/cSDTMock.dbg.json +1 -1
  127. package/artifacts/contracts/mocks/cUSDCMock.sol/cUSDCMock.dbg.json +1 -1
  128. package/artifacts/contracts/reserve/DistributionHelper.sol/DistributionHelper.dbg.json +4 -0
  129. package/artifacts/contracts/reserve/DistributionHelper.sol/DistributionHelper.json +662 -0
  130. package/artifacts/contracts/reserve/ExchangeHelper.sol/ExchangeHelper.dbg.json +1 -1
  131. package/artifacts/contracts/reserve/ExchangeHelper.sol/ExchangeHelper.json +2 -2
  132. package/artifacts/contracts/reserve/GoodMarketMaker.sol/GoodMarketMaker.dbg.json +1 -1
  133. package/artifacts/contracts/reserve/GoodMarketMaker.sol/GoodMarketMaker.json +2 -2
  134. package/artifacts/contracts/reserve/GoodReserveCDai.sol/ContributionCalc.dbg.json +1 -1
  135. package/artifacts/contracts/reserve/GoodReserveCDai.sol/GoodReserveCDai.dbg.json +1 -1
  136. package/artifacts/contracts/reserve/GoodReserveCDai.sol/GoodReserveCDai.json +75 -35
  137. package/artifacts/contracts/staking/BaseShareField.sol/BaseShareField.dbg.json +1 -1
  138. package/artifacts/contracts/staking/BaseShareField.sol/BaseShareField.json +2 -2
  139. package/artifacts/contracts/staking/BaseShareFieldV2.sol/BaseShareFieldV2.dbg.json +1 -1
  140. package/artifacts/contracts/staking/BaseShareFieldV2.sol/BaseShareFieldV2.json +2 -2
  141. package/artifacts/contracts/staking/DonationsStaking.sol/DonationsStaking.dbg.json +1 -1
  142. package/artifacts/contracts/staking/DonationsStaking.sol/DonationsStaking.json +2 -2
  143. package/artifacts/contracts/staking/FuseStakingV3.sol/FuseStakingV3.dbg.json +1 -1
  144. package/artifacts/contracts/staking/FuseStakingV3.sol/FuseStakingV3.json +2 -2
  145. package/artifacts/contracts/staking/FuseStakingV3.sol/IConsensus.dbg.json +1 -1
  146. package/artifacts/contracts/staking/FuseStakingV3.sol/PegSwap.dbg.json +1 -1
  147. package/artifacts/contracts/staking/GoodFundManager.sol/GoodFundManager.dbg.json +1 -1
  148. package/artifacts/contracts/staking/GoodFundManager.sol/GoodFundManager.json +2 -2
  149. package/artifacts/contracts/staking/SimpleStaking.sol/SimpleStaking.dbg.json +1 -1
  150. package/artifacts/contracts/staking/SimpleStakingV2.sol/SimpleStakingV2.dbg.json +1 -1
  151. package/artifacts/contracts/staking/UniswapV2SwapHelper.sol/UniswapV2SwapHelper.dbg.json +1 -1
  152. package/artifacts/contracts/staking/UniswapV2SwapHelper.sol/UniswapV2SwapHelper.json +2 -2
  153. package/artifacts/contracts/staking/aave/AaveStakingFactory.sol/AaveStakingFactory.dbg.json +1 -1
  154. package/artifacts/contracts/staking/aave/AaveStakingFactory.sol/AaveStakingFactory.json +2 -2
  155. package/artifacts/contracts/staking/aave/GoodAaveStaking.sol/GoodAaveStaking.dbg.json +1 -1
  156. package/artifacts/contracts/staking/aave/GoodAaveStaking.sol/GoodAaveStaking.json +2 -2
  157. package/artifacts/contracts/staking/aave/GoodAaveStakingV2.sol/GoodAaveStakingV2.dbg.json +1 -1
  158. package/artifacts/contracts/staking/aave/GoodAaveStakingV2.sol/GoodAaveStakingV2.json +2 -2
  159. package/artifacts/contracts/staking/compound/CompoundStakingFactory.sol/CompoundStakingFactory.dbg.json +1 -1
  160. package/artifacts/contracts/staking/compound/CompoundStakingFactory.sol/CompoundStakingFactory.json +2 -2
  161. package/artifacts/contracts/staking/compound/GoodCompoundStaking.sol/GoodCompoundStaking.dbg.json +1 -1
  162. package/artifacts/contracts/staking/compound/GoodCompoundStaking.sol/GoodCompoundStaking.json +2 -2
  163. package/artifacts/contracts/staking/compound/GoodCompoundStakingV2.sol/GoodCompoundStakingV2.dbg.json +1 -1
  164. package/artifacts/contracts/staking/compound/GoodCompoundStakingV2.sol/GoodCompoundStakingV2.json +2 -2
  165. package/artifacts/contracts/staking/utils/Math64X64.sol/Math64x64.dbg.json +4 -0
  166. package/artifacts/contracts/staking/utils/Math64X64.sol/Math64x64.json +10 -0
  167. package/artifacts/contracts/staking/utils/StakingRewardsFixedAPY.sol/StakingRewardsFixedAPY.dbg.json +4 -0
  168. package/artifacts/contracts/staking/utils/StakingRewardsFixedAPY.sol/StakingRewardsFixedAPY.json +268 -0
  169. package/artifacts/contracts/ubi/UBIScheme.sol/UBIScheme.dbg.json +1 -1
  170. package/artifacts/contracts/ubi/UBIScheme.sol/UBIScheme.json +2 -2
  171. package/artifacts/contracts/utils/AdminWallet.sol/AdminWallet.dbg.json +1 -1
  172. package/artifacts/contracts/utils/AdminWallet.sol/AdminWallet.json +2 -2
  173. package/artifacts/contracts/utils/BancorFormula.sol/BancorFormula.dbg.json +1 -1
  174. package/artifacts/contracts/utils/BulkProof.sol/BulkProof.dbg.json +1 -1
  175. package/artifacts/contracts/utils/BulkProof.sol/BulkProof.json +3 -34
  176. package/artifacts/contracts/utils/DAOContract.sol/DAOContract.dbg.json +1 -1
  177. package/artifacts/contracts/utils/DAOContract.sol/DAOContract.json +2 -2
  178. package/artifacts/contracts/utils/DAOUpgradeableContract.sol/DAOUpgradeableContract.dbg.json +1 -1
  179. package/artifacts/contracts/utils/DAOUpgradeableContract.sol/DAOUpgradeableContract.json +2 -2
  180. package/artifacts/contracts/utils/DSMath.sol/DSMath.dbg.json +1 -1
  181. package/artifacts/contracts/utils/DataTypes.sol/DataTypes.dbg.json +1 -1
  182. package/artifacts/contracts/utils/GoodDollarMintBurnWrapper.sol/GoodDollarMintBurnWrapper.dbg.json +4 -0
  183. package/artifacts/contracts/utils/GoodDollarMintBurnWrapper.sol/GoodDollarMintBurnWrapper.json +1263 -0
  184. package/artifacts/contracts/utils/GoodDollarMintBurnWrapper.sol/IRouter.dbg.json +4 -0
  185. package/artifacts/contracts/utils/GoodDollarMintBurnWrapper.sol/IRouter.json +59 -0
  186. package/artifacts/contracts/utils/GoodDollarMintBurnWrapper.sol/PausableControl.dbg.json +4 -0
  187. package/artifacts/contracts/utils/GoodDollarMintBurnWrapper.sol/PausableControl.json +69 -0
  188. package/artifacts/contracts/utils/GoodDollarMintBurnWrapper.sol/TokenOperation.dbg.json +4 -0
  189. package/artifacts/contracts/utils/GoodDollarMintBurnWrapper.sol/TokenOperation.json +10 -0
  190. package/artifacts/contracts/utils/MultichainBridgeHelper.sol/MultichainBridgeHelper.dbg.json +4 -0
  191. package/artifacts/contracts/utils/MultichainBridgeHelper.sol/MultichainBridgeHelper.json +79 -0
  192. package/artifacts/contracts/utils/NameService.sol/NameService.dbg.json +1 -1
  193. package/artifacts/contracts/utils/ProtocolUpgrade.sol/OldMarketMaker.dbg.json +1 -1
  194. package/artifacts/contracts/utils/ProtocolUpgrade.sol/ProtocolUpgrade.dbg.json +1 -1
  195. package/artifacts/contracts/utils/ProtocolUpgrade.sol/ProtocolUpgrade.json +2 -2
  196. package/artifacts/contracts/utils/ProtocolUpgradeFuse.sol/ProtocolUpgradeFuse.dbg.json +1 -1
  197. package/artifacts/contracts/utils/ProtocolUpgradeFuse.sol/ProtocolUpgradeFuse.json +2 -2
  198. package/artifacts/contracts/utils/ProtocolUpgradeFuseRecover.sol/ProtocolUpgradeFuseRecover.dbg.json +1 -1
  199. package/artifacts/contracts/utils/ProtocolUpgradeFuseRecover.sol/ProtocolUpgradeFuseRecover.json +2 -2
  200. package/artifacts/contracts/utils/ProtocolUpgradeRecover.sol/ProtocolUpgradeRecover.dbg.json +1 -1
  201. package/artifacts/contracts/utils/ProtocolUpgradeRecover.sol/ProtocolUpgradeRecover.json +2 -2
  202. package/artifacts/contracts/utils/ProxyFactory1967.sol/ERC1967Proxy.dbg.json +1 -1
  203. package/artifacts/contracts/utils/ProxyFactory1967.sol/ProxyFactory1967.dbg.json +1 -1
  204. package/artifacts/contracts/utils/ReputationTestHelper.sol/ReputationTestHelper.dbg.json +1 -1
  205. package/artifacts/contracts/utils/ReputationTestHelper.sol/ReputationTestHelper.json +2 -2
  206. package/contracts/Interfaces.sol +20 -0
  207. package/contracts/governance/GoodDollarStaking.sol +510 -0
  208. package/contracts/governance/MultiBaseGovernanceShareField.sol +1 -0
  209. package/contracts/mocks/DistributionBridgeMock.sol +50 -0
  210. package/contracts/mocks/DistributionHelperTest.sol +22 -0
  211. package/contracts/mocks/GoodDollarStakingMock.sol +24 -0
  212. package/contracts/mocks/MultichainRouterMock.sol +38 -0
  213. package/contracts/mocks/OverMintTester.sol +39 -25
  214. package/contracts/mocks/StakingMockFixedAPY.sol +78 -0
  215. package/contracts/reserve/DistributionHelper.sol +142 -0
  216. package/contracts/reserve/GoodReserveCDai.sol +95 -41
  217. package/contracts/staking/utils/Math64X64.sol +268 -0
  218. package/contracts/staking/utils/StakingRewardsFixedAPY.sol +336 -0
  219. package/contracts/utils/BulkProof.sol +10 -10
  220. package/contracts/utils/GoodDollarMintBurnWrapper.sol +638 -0
  221. package/contracts/utils/MultichainBridgeHelper.sol +39 -0
  222. package/hardhat.config.ts +5 -3
  223. package/package.json +7 -4
  224. package/patches/@openzeppelin+hardhat-upgrades+1.7.0.patch.depracate +67 -0
  225. package/releases/deployment.json +10 -3
  226. package/releases/olddao.json +1 -1
  227. package/scripts/analytics/activeUsersCount.ts +65 -0
  228. package/scripts/analytics/activeWalletsStats.ts +150 -0
  229. package/scripts/analytics/claimIncidentStats.ts +117 -0
  230. package/scripts/analytics/faucetStats.ts +103 -0
  231. package/scripts/analytics/goodHolders.ts +50 -0
  232. package/scripts/{misc → analytics}/goodgiveback.ts +0 -0
  233. package/scripts/governance/airdropCalculation.ts +1 -0
  234. package/scripts/multichain-deploy/basicdao-deploy.ts +20 -5
  235. package/scripts/multichain-deploy/gdSavings-deploy.ts +232 -0
  236. package/scripts/multichain-deploy/helpers.ts +73 -8
  237. package/scripts/multichain-deploy/multichainWrapper-deploy.ts +56 -0
  238. package/scripts/multichain-deploy/nonubiDistribution-deploy.ts +170 -0
  239. package/scripts/voltageswaps.ts +47 -0
  240. package/test/governance/ClaimersDistribution.test.ts +1 -1
  241. package/test/governance/GoodDollarStaking.gd.test.ts +559 -0
  242. package/test/governance/GoodDollarStaking.good.test.ts +998 -0
  243. package/test/governance/GovernanceStaking.test.ts +43 -0
  244. package/test/helpers.ts +9 -12
  245. package/test/reserve/DistributionHelper.test.ts +394 -0
  246. package/test/reserve/GoodReserveCDai.distribution.test.ts +296 -0
  247. package/test/reserve/GoodReserveCDai.gdx.test.ts +21 -16
  248. package/test/reserve/GoodReserveCDai.pause.test.ts +116 -0
  249. package/test/staking/StakingRewardsFixedAPY.test.ts +900 -0
  250. package/test/utils/AdminWallet.test.ts +35 -6
  251. package/test/utils/GoodDollarMintBurnWrapper.test.ts +796 -0
  252. package/tsconfig.json +4 -9
  253. package/types/AccessControl.ts +361 -0
  254. package/types/CERC20.ts +25 -0
  255. package/types/DistributionBridgeMock.ts +251 -0
  256. package/types/DistributionHelper.ts +908 -0
  257. package/types/DistributionHelperTest.ts +909 -0
  258. package/types/DistributionHelperTestHelper.ts +945 -0
  259. package/types/ERC165.ts +104 -0
  260. package/types/ERC20.ts +101 -49
  261. package/types/GoodDollarMintBurnWrapper.ts +1806 -0
  262. package/types/GoodDollarStaking.ts +1855 -0
  263. package/types/GoodDollarStakingMock.ts +1855 -0
  264. package/types/GoodReserveCDai.ts +90 -55
  265. package/types/IAccessControl.ts +306 -0
  266. package/types/IERC165.ts +104 -0
  267. package/types/IERC20.ts +300 -0
  268. package/types/IERC20Metadata.ts +339 -0
  269. package/types/IERC2917.ts +25 -0
  270. package/types/IGoodDollarStakingTest.ts +160 -0
  271. package/types/IMultichainRouter.ts +166 -0
  272. package/types/IRouter.ts +143 -0
  273. package/types/IWrapper.ts +143 -0
  274. package/types/MultichainBridgeHelper.ts +170 -0
  275. package/types/MultichainRouterMock.ts +141 -0
  276. package/types/Pausable.ts +103 -0
  277. package/types/PausableControl.ts +125 -0
  278. package/types/{BulkProof.ts → RewardsMinter.ts} +24 -28
  279. package/types/StakingMockFixedAPY.ts +995 -0
  280. package/types/StakingRewardsFixedAPY.ts +428 -0
  281. package/types/factories/AaveStakingFactory__factory.ts +1 -1
  282. package/types/factories/AccessControl__factory.ts +227 -0
  283. package/types/factories/AdminWallet__factory.ts +1 -1
  284. package/types/factories/BaseShareFieldV2__factory.ts +1 -1
  285. package/types/factories/BaseShareField__factory.ts +1 -1
  286. package/types/factories/CERC20__factory.ts +13 -0
  287. package/types/factories/ClaimersDistribution__factory.ts +1 -1
  288. package/types/factories/CompoundStakingFactory__factory.ts +1 -1
  289. package/types/factories/CompoundVotingMachine__factory.ts +1 -1
  290. package/types/factories/DAOContract__factory.ts +1 -1
  291. package/types/factories/DAOUpgradeableContract__factory.ts +1 -1
  292. package/types/factories/DistributionBridgeMock__factory.ts +207 -0
  293. package/types/factories/DistributionHelperTestHelper__factory.ts +737 -0
  294. package/types/factories/DistributionHelperTest__factory.ts +717 -0
  295. package/types/factories/DistributionHelper__factory.ts +713 -0
  296. package/types/factories/DonationsStaking__factory.ts +1 -1
  297. package/types/factories/ERC165__factory.ts +39 -0
  298. package/types/factories/ERC20__factory.ts +13 -0
  299. package/types/factories/ExchangeHelper__factory.ts +1 -1
  300. package/types/factories/FuseFaucet__factory.ts +1 -1
  301. package/types/factories/FuseStakingV3__factory.ts +1 -1
  302. package/types/factories/GReputation__factory.ts +1 -1
  303. package/types/factories/GoodAaveStakingV2__factory.ts +1 -1
  304. package/types/factories/GoodAaveStaking__factory.ts +1 -1
  305. package/types/factories/GoodCompoundStakingTest__factory.ts +1 -1
  306. package/types/factories/GoodCompoundStakingV2__factory.ts +1 -1
  307. package/types/factories/GoodCompoundStaking__factory.ts +1 -1
  308. package/types/factories/GoodDollarMintBurnWrapper__factory.ts +1318 -0
  309. package/types/factories/GoodDollarStakingMock__factory.ts +1404 -0
  310. package/types/factories/GoodDollarStaking__factory.ts +1400 -0
  311. package/types/factories/GoodFundManagerTest__factory.ts +1 -1
  312. package/types/factories/GoodFundManager__factory.ts +1 -1
  313. package/types/factories/GoodMarketMaker__factory.ts +1 -1
  314. package/types/factories/GoodReserveCDai__factory.ts +74 -34
  315. package/types/factories/GovernanceStaking__factory.ts +1 -1
  316. package/types/factories/IAccessControl__factory.ts +198 -0
  317. package/types/factories/IERC165__factory.ts +42 -0
  318. package/types/factories/IERC20Metadata__factory.ts +248 -0
  319. package/types/factories/IERC20__factory.ts +203 -0
  320. package/types/factories/IERC2917__factory.ts +13 -0
  321. package/types/factories/IGoodDollarStakingTest__factory.ts +68 -0
  322. package/types/factories/IMultichainRouter__factory.ts +82 -0
  323. package/types/factories/IRouter__factory.ts +71 -0
  324. package/types/factories/IWrapper__factory.ts +71 -0
  325. package/types/factories/InvitesV1__factory.ts +1 -1
  326. package/types/factories/MultichainBridgeHelper__factory.ts +134 -0
  327. package/types/factories/MultichainRouterMock__factory.ts +141 -0
  328. package/types/factories/OverMintTesterRegularStake__factory.ts +1 -1
  329. package/types/factories/OverMintTester__factory.ts +3 -3
  330. package/types/factories/PausableControl__factory.ts +84 -0
  331. package/types/factories/Pausable__factory.ts +62 -0
  332. package/types/factories/ProtocolUpgradeFuseRecover__factory.ts +1 -1
  333. package/types/factories/ProtocolUpgradeFuse__factory.ts +1 -1
  334. package/types/factories/ProtocolUpgradeRecover__factory.ts +1 -1
  335. package/types/factories/ProtocolUpgrade__factory.ts +1 -1
  336. package/types/factories/ReputationTestHelper__factory.ts +1 -1
  337. package/types/factories/Reputation__factory.ts +1 -1
  338. package/types/factories/RewardsMinter__factory.ts +47 -0
  339. package/types/factories/StakersDistribution__factory.ts +1 -1
  340. package/types/factories/StakingMockFixedAPY__factory.ts +745 -0
  341. package/types/factories/StakingRewardsFixedAPY__factory.ts +287 -0
  342. package/types/factories/SwapHelperTest__factory.ts +1 -1
  343. package/types/factories/UBIScheme__factory.ts +1 -1
  344. package/types/factories/UniswapV2SwapHelper__factory.ts +1 -1
  345. package/types/factories/UpgradableMock2__factory.ts +1 -1
  346. package/types/factories/UpgradableMock3__factory.ts +1 -1
  347. package/types/factories/UpgradableMock4__factory.ts +1 -1
  348. package/types/factories/UpgradableMock__factory.ts +1 -1
  349. package/types/hardhat.d.ts +225 -9
  350. package/types/index.ts +50 -4
  351. package/yarn.lock +180 -104
  352. package/types/factories/BulkProof__factory.ts +0 -89
@@ -0,0 +1,998 @@
1
+ import { default as hre, ethers, waffle } from "hardhat";
2
+ import { BigNumber, Contract, Signer } from "ethers";
3
+ import { expect } from "chai";
4
+ import { GoodReserveCDai, GReputation, GoodDollarStaking } from "../../types";
5
+ import { createDAO, advanceBlocks } from "../helpers";
6
+ import { FormatTypes } from "ethers/lib/utils";
7
+ import { getFounders } from "../../scripts/getFounders";
8
+
9
+ const BN = ethers.BigNumber;
10
+ export const NULL_ADDRESS = ethers.constants.AddressZero;
11
+ export const BLOCK_INTERVAL = 30;
12
+
13
+ describe("GoodDollarStaking - check GOOD rewards based on GovernanceStaking.test.js", () => {
14
+ let dai: Contract;
15
+ let cDAI: Contract;
16
+ let goodReserve: GoodReserveCDai;
17
+ let grep: GReputation;
18
+ let avatar,
19
+ goodDollar,
20
+ controller,
21
+ founder,
22
+ staker,
23
+ staker2,
24
+ staker3,
25
+ schemeMock,
26
+ signers,
27
+ nameService,
28
+ setDAOAddress;
29
+
30
+ before(async () => {
31
+ [founder, staker, staker2, staker3, ...signers] = await ethers.getSigners();
32
+ schemeMock = signers.pop();
33
+ const cdaiFactory = await ethers.getContractFactory("cDAIMock");
34
+
35
+ let {
36
+ controller: ctrl,
37
+ avatar: av,
38
+ gd,
39
+ identity,
40
+ nameService: ns,
41
+ setDAOAddress: sda,
42
+ daiAddress,
43
+ cdaiAddress,
44
+ reserve,
45
+ reputation
46
+ } = await createDAO();
47
+ dai = await ethers.getContractAt("DAIMock", daiAddress);
48
+ cDAI = await ethers.getContractAt("cDAIMock", cdaiAddress);
49
+ avatar = av;
50
+ controller = ctrl;
51
+ setDAOAddress = sda;
52
+ nameService = ns;
53
+ goodReserve = reserve as GoodReserveCDai;
54
+ console.log("deployed dao", {
55
+ founder: founder.address,
56
+ gd,
57
+ identity,
58
+ controller,
59
+ avatar
60
+ });
61
+
62
+ grep = (await ethers.getContractAt(
63
+ "GReputation",
64
+ reputation
65
+ )) as GReputation;
66
+ goodDollar = await ethers.getContractAt("IGoodDollar", gd);
67
+
68
+ //This set addresses should be another function because when we put this initialization of addresses in initializer then nameservice is not ready yet so no proper addresses
69
+ // await goodReserve.setAddresses();
70
+ });
71
+
72
+ const fixture = async (wallets, provider) => {
73
+ const f = await ethers.getContractFactory("GoodDollarStakingMock");
74
+
75
+ wallets = provider.getWallets();
76
+ const staking = (await waffle.deployContract(
77
+ wallets[0],
78
+ {
79
+ abi: JSON.parse(
80
+ f.interface.format(FormatTypes.json) as string
81
+ ) as any[],
82
+ bytecode: f.bytecode
83
+ },
84
+ [nameService.address, BN.from("1000000007735630000"), 518400 * 12, 30]
85
+ )) as GoodDollarStaking;
86
+
87
+ await staking.upgrade();
88
+
89
+ return { staking };
90
+ };
91
+
92
+ const fixture_ready = async (wallets, provider) => {
93
+ const f = await ethers.getContractFactory("GoodDollarStakingMock");
94
+
95
+ wallets = provider.getWallets();
96
+ const staking = (await waffle.deployContract(
97
+ wallets[0],
98
+ {
99
+ abi: JSON.parse(
100
+ f.interface.format(FormatTypes.json) as string
101
+ ) as any[],
102
+ bytecode: f.bytecode
103
+ },
104
+ [nameService.address, BN.from("1000000007735630000"), 518400 * 12, 30]
105
+ )) as GoodDollarStaking;
106
+
107
+ await staking.upgrade();
108
+
109
+ await setDAOAddress("GDAO_STAKING", staking.address);
110
+
111
+ return { staking };
112
+ };
113
+
114
+ const fixture_upgradeTest = async (wallets, provider) => {
115
+ const f = await ethers.getContractFactory("GoodDollarStaking");
116
+
117
+ wallets = provider.getWallets();
118
+ const staking = (await waffle.deployContract(
119
+ wallets[0],
120
+ {
121
+ abi: JSON.parse(
122
+ f.interface.format(FormatTypes.json) as string
123
+ ) as any[],
124
+ bytecode: f.bytecode
125
+ },
126
+ [nameService.address, BN.from("1000000007735630000"), 518400 * 12, 30]
127
+ )) as GoodDollarStaking;
128
+
129
+ //TODO: register as scheme here
130
+
131
+ return { staking };
132
+ };
133
+
134
+ it("Should not revert withdraw but also not mint GOOD reward when staking contract is not minter", async () => {
135
+ const { staking } = await waffle.loadFixture(fixture);
136
+ await goodDollar.mint(founder.address, "100");
137
+ await goodDollar.approve(staking.address, "100");
138
+ await staking.stake("100");
139
+ await advanceBlocks(5);
140
+ await expect(
141
+ staking.withdrawStake(await staking.balanceOf(founder.address))
142
+ ).to.not.reverted;
143
+ expect(await grep.balanceOfLocal(founder.address)).to.eq(0);
144
+ });
145
+
146
+ it("Should be able to mint rewards after set GDAO staking contract", async () => {
147
+ const { staking } = await waffle.loadFixture(fixture_ready);
148
+
149
+ await goodDollar.mint(founder.address, "100");
150
+ await goodDollar.approve(staking.address, "100");
151
+ await staking.stake("100");
152
+ await advanceBlocks(5);
153
+
154
+ const GDAOBalanceBeforeWithdraw = await grep.balanceOfLocal(
155
+ founder.address
156
+ );
157
+ await staking.withdrawStake(await staking.amountToShares("100"));
158
+ const GDAOBalanceAfterWithdraw = await grep.balanceOfLocal(founder.address);
159
+
160
+ expect(GDAOBalanceAfterWithdraw).to.gt(GDAOBalanceBeforeWithdraw);
161
+ });
162
+
163
+ it("Avatar should be able to change rewards per block", async () => {
164
+ const { staking } = await waffle.loadFixture(fixture_ready);
165
+
166
+ const ictrl = await ethers.getContractAt(
167
+ "Controller",
168
+ controller,
169
+ schemeMock
170
+ );
171
+
172
+ let encodedCall = staking.interface.encodeFunctionData(
173
+ "setMonthlyGOODRewards",
174
+ [ethers.utils.parseEther("1728000")]
175
+ );
176
+ await ictrl.genericCall(staking.address, encodedCall, avatar, 0);
177
+ const rewardsPerBlock = (await staking.getRewardsPerBlock())[0];
178
+ expect(rewardsPerBlock).to.equal(
179
+ ethers.utils.parseEther("1728000").div(BN.from("518400")) // 1728000 is montlhy reward amount and 518400 is monthly blocks for FUSE chain
180
+ );
181
+ await goodDollar.mint(founder.address, "100");
182
+ await goodDollar.approve(staking.address, "100");
183
+ const stakeBlockNumber = (await ethers.provider.getBlockNumber()) + 1;
184
+ await staking.stake("100");
185
+ await advanceBlocks(4);
186
+ const GDAOBalanceBeforeWithdraw = await grep.balanceOfLocal(
187
+ founder.address
188
+ );
189
+ await staking.withdrawStake(await staking.balanceOf(founder.address));
190
+ const withdrawBlockNumber = await ethers.provider.getBlockNumber();
191
+ const GDAOBalanceAfterWithdraw = await grep.balanceOfLocal(founder.address);
192
+ const multiplier = withdrawBlockNumber - stakeBlockNumber;
193
+ const calculatedReward = rewardsPerBlock.mul(multiplier); // We calculate user rewards since it's the only staker so gets whole rewards so rewardsPerBlock * multipler(block that passed between stake and withdraw)
194
+ expect(GDAOBalanceAfterWithdraw).to.be.equal(
195
+ GDAOBalanceBeforeWithdraw.add(calculatedReward)
196
+ );
197
+ });
198
+
199
+ it("Should be able to withdraw rewards without withdraw stake", async () => {
200
+ const { staking } = await waffle.loadFixture(fixture_ready);
201
+ const rewardsPerBlock = (await staking.getRewardsPerBlock())[0];
202
+ await goodDollar.mint(founder.address, "100");
203
+ await goodDollar.approve(staking.address, "100");
204
+ const stakeBlockNumber = (await ethers.provider.getBlockNumber()) + 1;
205
+ await staking.stake("100");
206
+ await advanceBlocks(4);
207
+ const GDAOBalanceBeforeWithdraw = await grep.balanceOfLocal(
208
+ founder.address
209
+ );
210
+ const transaction = await (await staking.withdrawRewards()).wait();
211
+ const withdrawBlockNumber = await ethers.provider.getBlockNumber();
212
+ const GDAOBalanceAfterWithdraw = await grep.balanceOfLocal(founder.address);
213
+ const multiplier = withdrawBlockNumber - stakeBlockNumber;
214
+ const calculatedReward = rewardsPerBlock.mul(multiplier); // We calculate user rewards since it's the only staker so gets whole rewards so rewardsPerBlock * multipler(block that passed between stake and withdraw)
215
+ expect(GDAOBalanceAfterWithdraw).to.be.equal(
216
+ GDAOBalanceBeforeWithdraw.add(calculatedReward)
217
+ );
218
+ expect(transaction.events.find(_ => _.event === "ReputationEarned")).to.be
219
+ .not.empty;
220
+ });
221
+
222
+ it("Should be able to withdraw transferred stakes", async () => {
223
+ const { staking } = await waffle.loadFixture(fixture_ready);
224
+
225
+ await goodDollar.mint(staker.address, "100");
226
+ await goodDollar.connect(staker).approve(staking.address, "100");
227
+ await staking.connect(staker).stake("100");
228
+ await advanceBlocks(4);
229
+ await staking
230
+ .connect(staker)
231
+ .transfer(founder.address, await staking.balanceOf(staker.address));
232
+ await staking.connect(staker).withdrawRewards();
233
+ const gdaoBalanceBeforeWithdraw = await grep.balanceOfLocal(
234
+ founder.address
235
+ );
236
+ await staking.withdrawStake(await staking.balanceOf(founder.address));
237
+ const gdaoBalanceAfterWithdraw = await grep.balanceOfLocal(founder.address);
238
+ expect(gdaoBalanceAfterWithdraw).to.gt(gdaoBalanceBeforeWithdraw);
239
+ });
240
+
241
+ it("should not be able to withdraw after they send their stake to somebody else", async () => {
242
+ const { staking } = await waffle.loadFixture(fixture_ready);
243
+
244
+ await goodDollar.mint(staker.address, "100");
245
+ await goodDollar.connect(staker).approve(staking.address, "100");
246
+ await staking.connect(staker).stake("100");
247
+ await advanceBlocks(4);
248
+ await staking
249
+ .connect(staker)
250
+ .transfer(founder.address, await staking.balanceOf(staker.address));
251
+
252
+ await expect(staking.connect(staker).withdrawStake(1)).revertedWith(
253
+ "no balance"
254
+ );
255
+ });
256
+
257
+ it("it should distribute reward with correct precision", async () => {
258
+ const { staking } = await waffle.loadFixture(fixture_ready);
259
+
260
+ const ictrl = await ethers.getContractAt(
261
+ "Controller",
262
+ controller,
263
+ schemeMock
264
+ );
265
+
266
+ let encodedCall = staking.interface.encodeFunctionData(
267
+ "setMonthlyGOODRewards",
268
+ ["17280000000000000000"] // Give 0.0001 GDAO per block so 17.28 GDAO per month
269
+ );
270
+ await ictrl.genericCall(staking.address, encodedCall, avatar, 0);
271
+ const rewardsPerBlock = (await staking.getRewardsPerBlock())[0];
272
+ await goodDollar.mint(founder.address, "100");
273
+ await goodDollar.approve(staking.address, "100");
274
+ const stakeBlockNumber = (await ethers.provider.getBlockNumber()) + 1;
275
+ await staking.stake("100");
276
+ await advanceBlocks(4);
277
+ const GDAOBalanceBeforeWithdraw = await grep.balanceOfLocal(
278
+ founder.address
279
+ );
280
+ await staking.withdrawStake(await staking.balanceOf(founder.address));
281
+ const withdrawBlockNumber = await ethers.provider.getBlockNumber();
282
+ const GDAOBalanceAfterWithdraw = await grep.balanceOfLocal(founder.address);
283
+ const multiplier = withdrawBlockNumber - stakeBlockNumber;
284
+ const calculatedReward = rewardsPerBlock.mul(multiplier); // We calculate user rewards since it's the only staker so gets whole rewards so rewardsPerBlock * multipler(block that passed between stake and withdraw)
285
+ expect(calculatedReward).gt(0);
286
+ expect(GDAOBalanceAfterWithdraw).to.be.equal(
287
+ GDAOBalanceBeforeWithdraw.add(calculatedReward)
288
+ );
289
+ });
290
+
291
+ it("it should not generate rewards when rewards per block set to 0", async () => {
292
+ const { staking } = await waffle.loadFixture(fixture_ready);
293
+
294
+ const ictrl = await ethers.getContractAt(
295
+ "Controller",
296
+ controller,
297
+ schemeMock
298
+ );
299
+
300
+ let encodedCall = staking.interface.encodeFunctionData(
301
+ "setMonthlyGOODRewards",
302
+ ["0"] // Give 0 GDAO per block
303
+ );
304
+ await ictrl.genericCall(staking.address, encodedCall, avatar, 0);
305
+
306
+ await goodDollar.mint(founder.address, "100");
307
+ await goodDollar.approve(staking.address, "100");
308
+ await staking.stake("100");
309
+ const userProductivity = await staking["getStaked(address)"](
310
+ founder.address
311
+ );
312
+ expect(userProductivity[0]).to.be.equal("1000000");
313
+ await advanceBlocks(4);
314
+ const GDAOBalanceBeforeWithdraw = await grep.balanceOfLocal(
315
+ founder.address
316
+ );
317
+ await staking.withdrawStake(await staking.balanceOf(founder.address));
318
+ const GDAOBalanceAfterWithdraw = await grep.balanceOfLocal(founder.address);
319
+ expect(GDAOBalanceAfterWithdraw.sub(GDAOBalanceBeforeWithdraw)).to.equal(0);
320
+ });
321
+
322
+ it("it should return productivity values correctly", async () => {
323
+ const { staking } = await waffle.loadFixture(fixture_ready);
324
+ await goodDollar.mint(founder.address, "100");
325
+ await goodDollar.approve(staking.address, "100");
326
+ await staking.stake("100");
327
+ const productivityValue = await staking["getStaked(address)"](
328
+ founder.address
329
+ );
330
+
331
+ expect(productivityValue[0].toString())
332
+ .eq(productivityValue[1].toString())
333
+ .to.equal(await staking.sharesOf(founder.address));
334
+ await staking.withdrawStake(await staking.balanceOf(founder.address));
335
+ });
336
+
337
+ it("it should return earned rewards with pending ones properly for a short period", async () => {
338
+ const { staking } = await waffle.loadFixture(fixture_ready);
339
+ const rewardsPerBlock = (await staking.getRewardsPerBlock())[0];
340
+ await goodDollar.mint(founder.address, "100");
341
+ await goodDollar.approve(staking.address, "100");
342
+ const stakeBlockNumber = (await ethers.provider.getBlockNumber()) + 1;
343
+ await staking.stake("100");
344
+ await advanceBlocks(5);
345
+ const [totalEarnedGOOD] = await staking["getUserPendingReward(address)"](
346
+ founder.address
347
+ );
348
+ const pendingRewardBlockNumber = await ethers.provider.getBlockNumber();
349
+ const multiplier = pendingRewardBlockNumber - stakeBlockNumber;
350
+ const calculatedPendingReward = rewardsPerBlock.mul(multiplier); // We calculate user rewards since it's the only staker so gets whole rewards so rewardsPerBlock * multipler(block that passed between stake and withdraw)
351
+ expect(totalEarnedGOOD).to.be.equal(calculatedPendingReward);
352
+ await staking.withdrawStake(await staking.balanceOf(founder.address));
353
+ });
354
+
355
+ it("Accumulated per share has enough precision when reward << totalproductivity", async () => {
356
+ const { staking } = await waffle.loadFixture(fixture_ready);
357
+
358
+ const rewardsPerBlock = (await staking.getRewardsPerBlock())[0];
359
+ await goodDollar.mint(founder.address, "100000000000000"); // 1 trillion gd stake
360
+ await goodDollar.approve(staking.address, "1000000000000");
361
+ const stakeBlockNumber = (await ethers.provider.getBlockNumber()) + 1;
362
+ await staking.stake("1000000000000");
363
+ await advanceBlocks(4);
364
+ const GDAOBalanceBeforeWithdraw = await grep.balanceOfLocal(
365
+ founder.address
366
+ );
367
+ await staking.withdrawStake(await staking.sharesOf(founder.address));
368
+ const withdrawBlockNumber = await ethers.provider.getBlockNumber();
369
+ const GDAOBalanceAfterWithdraw = await grep.balanceOfLocal(founder.address);
370
+ const multiplier = withdrawBlockNumber - stakeBlockNumber;
371
+ const calculatedReward = rewardsPerBlock.mul(multiplier); // We calculate user rewards since it's the only staker so gets whole rewards so rewardsPerBlock * multipler(block that passed between stake and withdraw)
372
+ expect(GDAOBalanceAfterWithdraw).to.be.equal(
373
+ GDAOBalanceBeforeWithdraw.add(calculatedReward)
374
+ );
375
+ });
376
+
377
+ it("user receive fractional gdao properly when his stake << totalProductivity", async () => {
378
+ const { staking } = await waffle.loadFixture(fixture_ready);
379
+
380
+ const rewardsPerBlock = (await staking.getRewardsPerBlock())[0];
381
+ await goodDollar.mint(founder.address, "800"); // 8gd
382
+ await goodDollar.mint(staker.address, "200"); // 2gd
383
+ await goodDollar.approve(staking.address, "800");
384
+ await goodDollar.connect(staker).approve(staking.address, "200");
385
+ await staking.stake("800");
386
+ const secondStakerStakeBlockNumber =
387
+ (await ethers.provider.getBlockNumber()) + 1;
388
+ await staking.connect(staker).stake("200");
389
+ await advanceBlocks(4);
390
+ const GDAOBalanceBeforeWithdraw = await grep.balanceOfLocal(staker.address);
391
+ const FounderGDAOBalanceBeforeWithdraw = await grep.balanceOfLocal(
392
+ founder.address
393
+ );
394
+ const founderShares = await staking.sharesOf(founder.address);
395
+ const stakerShares = await staking.sharesOf(staker.address);
396
+
397
+ const totalShares = await staking.sharesSupply();
398
+ await staking.withdrawStake(founderShares);
399
+
400
+ const founderWithdrawBlockNumber = await ethers.provider.getBlockNumber();
401
+ await staking.connect(staker).withdrawStake(stakerShares);
402
+ const GDAOBalanceAfterWithdraw = await grep.balanceOfLocal(staker.address);
403
+ const FounderGDAOBalanceAfterWithdraw = await grep.balanceOfLocal(
404
+ founder.address
405
+ );
406
+
407
+ const founderCalculatedRewards = rewardsPerBlock.add(
408
+ rewardsPerBlock
409
+ .mul(founderShares)
410
+ .mul(founderWithdrawBlockNumber - secondStakerStakeBlockNumber)
411
+ .div(totalShares)
412
+ ); // Founder should get full rewards for one block plus his relative share of the rewards
413
+ const stakerCalculatedRewards = rewardsPerBlock
414
+ .mul(stakerShares)
415
+ .mul(founderWithdrawBlockNumber - secondStakerStakeBlockNumber)
416
+ .div(totalShares)
417
+ .add(rewardsPerBlock)
418
+ .add(1); // Staker should get his relative share of rewards initially then when Founder withdraw their stake Staker would own %100 of rewards and would get full amount
419
+ expect(FounderGDAOBalanceAfterWithdraw).to.be.equal(
420
+ FounderGDAOBalanceBeforeWithdraw.add(founderCalculatedRewards)
421
+ );
422
+ expect(GDAOBalanceAfterWithdraw).to.be.equal(
423
+ GDAOBalanceBeforeWithdraw.add(stakerCalculatedRewards)
424
+ );
425
+ });
426
+
427
+ it("it should be able to tranfer tokens when user approve", async () => {
428
+ const { staking } = await waffle.loadFixture(fixture_ready);
429
+
430
+ await goodDollar.mint(founder.address, "100");
431
+ await goodDollar.approve(staking.address, "100");
432
+ await staking.stake("100");
433
+ const sharesBalance = await staking.balanceOf(founder.address);
434
+ await staking.approve(staker.address, sharesBalance);
435
+ const stakerProductivityBeforeTransfer = await staking.getStaked(
436
+ staker.address
437
+ );
438
+
439
+ await staking
440
+ .connect(staker)
441
+ .transferFrom(founder.address, staker.address, sharesBalance);
442
+ const stakerProductivity = await staking.getStaked(staker.address);
443
+
444
+ expect(await staking.balanceOf(founder.address)).to.equal(0);
445
+ expect(await staking.balanceOf(staker.address)).to.equal(sharesBalance);
446
+
447
+ expect((await staking.goodStakerInfo(staker.address)).amount).to.equal(
448
+ sharesBalance
449
+ );
450
+ expect(stakerProductivityBeforeTransfer[0]).to.be.equal(0);
451
+ expect(stakerProductivity[0]).to.be.equal(sharesBalance);
452
+ });
453
+
454
+ it("it should return staker data", async () => {
455
+ const { staking } = await waffle.loadFixture(fixture_ready);
456
+
457
+ await goodDollar.mint(staker2.address, "200");
458
+ await goodDollar.connect(staker2).approve(staking.address, "200");
459
+ await staking.connect(staker2).stake("100");
460
+
461
+ await advanceBlocks(10);
462
+ await staking.connect(staker2).stake("100"); //perform some action so GOOD rewardDebt is updated
463
+
464
+ expect((await staking.goodStakerInfo(staker2.address)).rewardDebt).to.gt(0); //debt should start according to accumulated rewards in contract. debt is the user stake starting point.
465
+
466
+ const sharesToWithdraw = await staking.amountToShares(1);
467
+ const sharesBalance = await staking.balanceOf(staker2.address);
468
+ await staking.connect(staker2).withdrawStake(sharesToWithdraw);
469
+
470
+ expect(await staking.balanceOf(staker2.address)).to.equal(
471
+ sharesBalance.sub(sharesToWithdraw)
472
+ );
473
+
474
+ expect((await staking.goodStakerInfo(staker2.address)).amount).to.equal(
475
+ sharesBalance.sub(sharesToWithdraw)
476
+ );
477
+ expect((await staking.goodStakerInfo(staker2.address)).rewardDebt).to.gt(0); //should have withdrawn rewards after withdraw stake
478
+ expect((await staking.goodStakerInfo(staker2.address)).rewardEarn).to.equal(
479
+ 0
480
+ ); //should have 0 pending rewards after withdraw stake
481
+
482
+ await advanceBlocks(10);
483
+ await goodDollar.connect(staker2).approve(staking.address, "200");
484
+
485
+ await staking.connect(staker2).stake("1"); //should calculate user pending rewards
486
+
487
+ expect(
488
+ (await staking.goodStakerInfo(staker2.address)).rewardEarn
489
+ ).to.be.equal(
490
+ 0 //should have 0 rewardEarned because every action, like the above stake withdraws gdao rewards
491
+ );
492
+ await advanceBlocks(2); // pass some blocks
493
+ const [userPendingGoodReward] = await staking[
494
+ "getUserPendingReward(address)"
495
+ ](staker2.address);
496
+ expect(userPendingGoodReward).to.be.gt(0);
497
+ });
498
+
499
+ it("it should return pendingRewards equal zero after withdraw", async () => {
500
+ const { staking } = await waffle.loadFixture(fixture_ready);
501
+
502
+ await goodDollar.mint(staker.address, "200");
503
+ await goodDollar.connect(staker).approve(staking.address, "200");
504
+ await staking.connect(staker).stake("100");
505
+ await advanceBlocks(10);
506
+
507
+ let [userPendingGoodRewards] = await staking[
508
+ "getUserPendingReward(address)"
509
+ ](staker.address);
510
+ expect(userPendingGoodRewards).to.be.gt(0);
511
+ await staking.connect(staker).withdrawRewards();
512
+ [userPendingGoodRewards] = await staking["getUserPendingReward(address)"](
513
+ staker.address
514
+ );
515
+ expect(userPendingGoodRewards).to.equal(0);
516
+ await advanceBlocks(1);
517
+ [userPendingGoodRewards] = await staking["getUserPendingReward(address)"](
518
+ staker.address
519
+ );
520
+ expect(userPendingGoodRewards).to.gt(0); //one block passed
521
+
522
+ await staking
523
+ .connect(staker)
524
+ .withdrawStake(await staking.sharesOf(staker.address));
525
+ [userPendingGoodRewards] = await staking["getUserPendingReward(address)"](
526
+ staker.address
527
+ );
528
+ expect(userPendingGoodRewards).to.be.equal(0);
529
+ });
530
+
531
+ it("it should calculate accumulated rewards per share correctly", async () => {
532
+ const { staking } = await waffle.loadFixture(fixture_ready);
533
+
534
+ await goodDollar.mint(founder.address, "200");
535
+ await goodDollar.mint(staker.address, "200");
536
+
537
+ await goodDollar.approve(staking.address, "200");
538
+ await goodDollar.connect(staker).approve(staking.address, "200");
539
+
540
+ await staking.stake("100");
541
+ let accumulatedRewardsPerShare = (
542
+ await staking["totalRewardsPerShare()"]()
543
+ )[0];
544
+ expect(accumulatedRewardsPerShare).to.equal(0); //first has no accumulated rewards yet, since no blocks have passed since staking
545
+
546
+ let totalProductiviy = await staking.sharesSupply();
547
+
548
+ await staking.stake("100");
549
+ accumulatedRewardsPerShare = (await staking["totalRewardsPerShare()"]())[0];
550
+ const rewardsPerBlock = (await staking.getRewardsPerBlock())[0];
551
+ expect(rewardsPerBlock).to.equal(
552
+ ethers.utils
553
+ .parseEther("2000000") //2M reputation
554
+ .div(await staking.getChainBlocksPerMonth())
555
+ );
556
+ console.log({ rewardsPerBlock, totalProductiviy });
557
+
558
+ //totalRewardsPerShare is in 1e27 , divid by 1e9 to get 1e18 decimals
559
+ expect(accumulatedRewardsPerShare.div(BN.from(1e9))).to.not.equal(
560
+ ethers.utils
561
+ .parseEther("2000000")
562
+ .mul(BN.from(1e2)) //G$ is 2 decimals, dividing reduces decimals by 2, so we first increase to 1e20 decimals
563
+ .div(await staking.getChainBlocksPerMonth())
564
+ .div(totalProductiviy)
565
+ .mul(BN.from("1"))
566
+ .mul(BN.from("10000000000000000")), //increase precision to 1e18 from totalProductivity G$ 2 decimals;
567
+
568
+ "1 blocks"
569
+ ); //2 blocks passed but now we have 200 total productivity before 3rd stake
570
+
571
+ totalProductiviy = await staking.sharesSupply();
572
+ await staking.connect(staker).stake("100");
573
+ let accumulatedRewardsPerShare2 = (
574
+ await staking["totalRewardsPerShare()"]()
575
+ )[0];
576
+
577
+ //shouldnt be naive accumlattion of 2 blocks, since total productivity has changed between blocks
578
+ expect(accumulatedRewardsPerShare2.div(BN.from(1e9))).to.not.equal(
579
+ ethers.utils
580
+ .parseEther("2000000")
581
+ .mul(BN.from(1e2)) //G$ is 2 decimals, dividing reduces decimals by 2, so we first increase to 1e20 decimals
582
+ .div(await staking.getChainBlocksPerMonth())
583
+ .div(totalProductiviy)
584
+ .mul(BN.from("2"))
585
+ .mul(BN.from("10000000000000000")), //increase precision to 1e18 from totalProductivity G$ 2 decimals;
586
+
587
+ "2 blocks"
588
+ ); //2 blocks passed but now we have 200 total productivity before 3rd stake
589
+
590
+ const calculatedAccRewards = rdiv(
591
+ ethers.utils
592
+ .parseEther("2000000")
593
+ .div(await staking.getChainBlocksPerMonth()),
594
+ totalProductiviy
595
+ );
596
+ //accumulated so far plus block accumulation
597
+ expect(accumulatedRewardsPerShare2).to.equal(
598
+ calculatedAccRewards.add(accumulatedRewardsPerShare).sub(1), //add rewards from previous block
599
+ "2 blocks correct"
600
+ );
601
+ });
602
+
603
+ it("Staking tokens should be 18 decimals", async () => {
604
+ const { staking } = await waffle.loadFixture(fixture_ready);
605
+
606
+ const decimals = await staking.decimals();
607
+ expect(decimals.toString()).to.be.equal("18");
608
+ });
609
+
610
+ it("Stake amount should be positive", async () => {
611
+ const { staking } = await waffle.loadFixture(fixture_ready);
612
+
613
+ await expect(staking.stake("0")).revertedWith("Cannot stake 0");
614
+ });
615
+
616
+ it("It should approve stake amount in order to stake", async () => {
617
+ const { staking } = await waffle.loadFixture(fixture_ready);
618
+
619
+ await expect(staking.stake(ethers.utils.parseEther("10000000"))).to
620
+ .reverted;
621
+ });
622
+
623
+ it("Withdraw 0 should succeed", async () => {
624
+ const { staking } = await waffle.loadFixture(fixture_ready);
625
+
626
+ await expect(staking.withdrawStake("0")).to.not.reverted;
627
+ });
628
+
629
+ it("Withdraw uint max should withdraw everything", async () => {
630
+ const { staking } = await waffle.loadFixture(fixture_ready);
631
+
632
+ await goodDollar.mint(staker2.address, "200");
633
+ await goodDollar.connect(staker2).approve(staking.address, "200");
634
+ await staking.connect(staker2).stake("200");
635
+ await advanceBlocks(1000);
636
+ await staking
637
+ .connect(staker2)
638
+ .withdrawStake(await staking.sharesOf(staker2.address));
639
+ expect(await staking.getSavings(staker2.address)).to.equal(0);
640
+ const staked = await staking.getStaked(staker2.address);
641
+ staked.map(stake => {
642
+ expect(stake).to.equal(0);
643
+ });
644
+ });
645
+
646
+ it("Should use overriden _transfer that handles productivity when using transferFrom which is defined in super erc20 contract", async () => {
647
+ const { staking } = await waffle.loadFixture(fixture_ready);
648
+ await expect(
649
+ staking.transferFrom(
650
+ founder.address,
651
+ staker.address,
652
+ ethers.utils.parseEther("10000000")
653
+ )
654
+ ).to.reverted;
655
+ });
656
+
657
+ it("it should get rewards for previous stakes when stake new amount of tokens", async () => {
658
+ const { staking } = await waffle.loadFixture(fixture_ready);
659
+
660
+ const rewardsPerBlock = (await staking.getRewardsPerBlock())[0];
661
+ await goodDollar.mint(founder.address, "200");
662
+ await goodDollar.approve(staking.address, "200");
663
+ const stakeBlockNumber = (await ethers.provider.getBlockNumber()) + 1;
664
+ await staking.stake("100");
665
+ await advanceBlocks(5);
666
+ const gdaoBalanceBeforeGetRewards = await grep.balanceOfLocal(
667
+ founder.address
668
+ );
669
+ await staking.stake("100");
670
+ const getRewardsBlockNumber = await ethers.provider.getBlockNumber();
671
+ const gdaoBalanceAfterGetRewards = await grep.balanceOfLocal(
672
+ founder.address
673
+ );
674
+ const multiplier = getRewardsBlockNumber - stakeBlockNumber;
675
+ const calculatedReward = rewardsPerBlock.mul(multiplier); // We calculate user rewards since it's the only staker so gets whole rewards so rewardsPerBlock * multipler(block that passed between stake and withdraw)
676
+ await staking.withdrawStake(await staking.sharesOf(founder.address));
677
+ expect(gdaoBalanceAfterGetRewards).to.be.equal(
678
+ gdaoBalanceBeforeGetRewards.add(calculatedReward)
679
+ );
680
+ });
681
+
682
+ it("it should distribute rewards properly when there are multiple stakers", async () => {
683
+ const { staking } = await waffle.loadFixture(fixture_ready);
684
+
685
+ const rewardsPerBlock = (await staking.getRewardsPerBlock())[0];
686
+ const stakingAmount = BN.from("100");
687
+ await goodDollar.mint(founder.address, stakingAmount);
688
+ await goodDollar.mint(staker.address, stakingAmount);
689
+ await goodDollar.mint(signers[0].address, stakingAmount);
690
+ await goodDollar.mint(signers[1].address, stakingAmount);
691
+
692
+ await goodDollar.approve(staking.address, stakingAmount);
693
+ await goodDollar.connect(staker).approve(staking.address, stakingAmount);
694
+ await goodDollar
695
+ .connect(signers[0])
696
+ .approve(staking.address, stakingAmount);
697
+ await goodDollar
698
+ .connect(signers[1])
699
+ .approve(staking.address, stakingAmount);
700
+ await staking.stake(stakingAmount);
701
+ const stakerOneGDAOBalanceAfterStake = await grep.balanceOfLocal(
702
+ founder.address
703
+ );
704
+ await staking.connect(staker).stake(stakingAmount.div(10));
705
+ const stakerTwoGDAOBalanceAfterStake = await grep.balanceOfLocal(
706
+ staker.address
707
+ );
708
+ await staking.connect(signers[0]).stake(stakingAmount.div(4));
709
+
710
+ const stakerThreeGDAOBalanceAfterStake = await grep.balanceOfLocal(
711
+ signers[0].address
712
+ );
713
+ const stakerFourStakeBlockNumber =
714
+ (await ethers.provider.getBlockNumber()) + 1;
715
+ await staking.connect(signers[1]).stake(stakingAmount.div(5));
716
+
717
+ const stakerFourGDAOBalanceAfterStake = await grep.balanceOfLocal(
718
+ signers[1].address
719
+ );
720
+ await advanceBlocks(10);
721
+
722
+ const totalShares = await staking.sharesSupply();
723
+ const founderShares = await staking.sharesOf(founder.address);
724
+ await staking.withdrawStake(founderShares);
725
+ const stakerOneWithdrawBlockNumber = await ethers.provider.getBlockNumber();
726
+ const stakerOneGDAOBalanceAfterWithdraw = await grep.balanceOfLocal(
727
+ founder.address
728
+ );
729
+
730
+ const stakerShares = await staking.sharesOf(staker.address);
731
+ await staking.connect(staker).withdrawStake(stakerShares);
732
+ const stakerTwoGDAOBalanceAfterWithdraw = await grep.balanceOfLocal(
733
+ staker.address
734
+ );
735
+
736
+ const signer0Shares = await staking.sharesOf(signers[0].address);
737
+ await staking.connect(signers[0]).withdrawStake(signer0Shares);
738
+ const stakerThreeGDAOBalanceAfterWithdraw = await grep.balanceOfLocal(
739
+ signers[0].address
740
+ );
741
+
742
+ const signer1Shares = await staking.sharesOf(signers[1].address);
743
+
744
+ await staking.connect(signers[1]).withdrawStake(signer1Shares);
745
+ const stakerFourGDAOBalanceAfterWithdraw = await grep.balanceOfLocal(
746
+ signers[1].address
747
+ );
748
+ const stakerOneRewardsCalculated = rewardsPerBlock
749
+ .add(
750
+ rewardsPerBlock.mul(founderShares).div(founderShares.add(stakerShares))
751
+ )
752
+ .add(
753
+ rewardsPerBlock
754
+ .mul(founderShares)
755
+ .div(founderShares.add(stakerShares).add(signer0Shares))
756
+ )
757
+ .add(
758
+ rewardsPerBlock
759
+ .mul(founderShares)
760
+ .mul(stakerOneWithdrawBlockNumber - stakerFourStakeBlockNumber)
761
+ .div(totalShares)
762
+ )
763
+ .add(BN.from("2"));
764
+
765
+ const stakerTwoRewardsCalculated = rewardsPerBlock
766
+ .mul(stakerShares)
767
+ .div(founderShares.add(stakerShares))
768
+ .add(
769
+ rewardsPerBlock
770
+ .mul(stakerShares)
771
+ .div(founderShares.add(stakerShares).add(signer0Shares))
772
+ )
773
+ .add(
774
+ rewardsPerBlock
775
+ .mul(stakerShares)
776
+ .mul(stakerOneWithdrawBlockNumber - stakerFourStakeBlockNumber)
777
+ .div(totalShares)
778
+ )
779
+ .add(
780
+ rewardsPerBlock
781
+ .mul(stakerShares)
782
+ .div(stakerShares.add(signer0Shares).add(signer1Shares))
783
+ )
784
+ .add(BN.from("1"));
785
+
786
+ const stakerThreeRewardsCalculated = rewardsPerBlock
787
+ .mul(signer0Shares)
788
+ .div(founderShares.add(stakerShares).add(signer0Shares))
789
+ .add(
790
+ rewardsPerBlock
791
+ .mul(signer0Shares)
792
+ .mul(stakerOneWithdrawBlockNumber - stakerFourStakeBlockNumber)
793
+ .div(totalShares)
794
+ )
795
+ .add(
796
+ rewardsPerBlock
797
+ .mul(signer0Shares)
798
+ .div(stakerShares.add(signer0Shares).add(signer1Shares))
799
+ )
800
+ .add(
801
+ rewardsPerBlock.mul(signer0Shares).div(signer0Shares.add(signer1Shares))
802
+ )
803
+ .add(BN.from("2"));
804
+
805
+ const stakerFourRewardsCalculated = rewardsPerBlock
806
+ .mul(signer1Shares)
807
+ .mul(stakerOneWithdrawBlockNumber - stakerFourStakeBlockNumber)
808
+ .div(totalShares)
809
+ .add(
810
+ rewardsPerBlock
811
+ .mul(signer1Shares)
812
+ .div(stakerShares.add(signer0Shares).add(signer1Shares))
813
+ )
814
+ .add(
815
+ rewardsPerBlock.mul(signer1Shares).div(signer0Shares.add(signer1Shares))
816
+ )
817
+ .add(rewardsPerBlock)
818
+ .add(BN.from("1"));
819
+ expect(stakerOneGDAOBalanceAfterWithdraw).to.be.equal(
820
+ stakerOneGDAOBalanceAfterStake.add(stakerOneRewardsCalculated)
821
+ );
822
+ expect(stakerTwoGDAOBalanceAfterWithdraw).to.be.equal(
823
+ stakerTwoGDAOBalanceAfterStake.add(stakerTwoRewardsCalculated)
824
+ );
825
+ expect(stakerThreeGDAOBalanceAfterWithdraw).to.be.equal(
826
+ stakerThreeGDAOBalanceAfterStake.add(stakerThreeRewardsCalculated)
827
+ );
828
+ expect(stakerFourGDAOBalanceAfterWithdraw).to.be.equal(
829
+ stakerFourGDAOBalanceAfterStake.add(stakerFourRewardsCalculated)
830
+ );
831
+ });
832
+
833
+ it("it should get staking reward even when stake amount is low", async () => {
834
+ const { staking } = await waffle.loadFixture(fixture_ready);
835
+
836
+ const rewardsPerBlock = (await staking.getRewardsPerBlock())[0];
837
+ const stakingAmount = BN.from("10000");
838
+ await goodDollar.mint(founder.address, stakingAmount);
839
+ await goodDollar.mint(staker.address, stakingAmount);
840
+ await goodDollar.approve(staking.address, stakingAmount);
841
+ await goodDollar.connect(staker).approve(staking.address, stakingAmount);
842
+ await staking.stake(stakingAmount);
843
+ const stakerOneGDAOBalanceAfterStake = await grep.balanceOfLocal(
844
+ founder.address
845
+ );
846
+ const stakerTwoStakeBlockNumber =
847
+ (await ethers.provider.getBlockNumber()) + 1;
848
+ await staking.connect(staker).stake(2);
849
+ const stakerTwoGDAOBalanceAfterStake = await grep.balanceOfLocal(
850
+ staker.address
851
+ );
852
+ await advanceBlocks(10);
853
+
854
+ const staker1Shares = await staking.sharesOf(founder.address);
855
+ const staker2Shares = await staking.sharesOf(staker.address);
856
+ await staking
857
+ .connect(staker)
858
+ .withdrawStake(await staking.sharesOf(staker.address));
859
+ const stakerTwoWithdrawBlockNumber = await ethers.provider.getBlockNumber();
860
+
861
+ await staking.withdrawStake(await staking.sharesOf(founder.address));
862
+
863
+ const stakerOneGDAOBalanceAfterWithdraw = await grep.balanceOfLocal(
864
+ founder.address
865
+ );
866
+ const stakerTwoGDAOBalanceAfterWithdraw = await grep.balanceOfLocal(
867
+ staker.address
868
+ );
869
+ const calculatedRewardsStakerOne = rewardsPerBlock
870
+ .add(
871
+ rewardsPerBlock
872
+ .mul(staker1Shares)
873
+ .mul(stakerTwoWithdrawBlockNumber - stakerTwoStakeBlockNumber)
874
+ .div(staker1Shares.add(staker2Shares))
875
+ )
876
+ .add(rewardsPerBlock);
877
+
878
+ const calculatedRewardsStakerTwo = rewardsPerBlock
879
+ .mul(staker2Shares)
880
+ .mul(stakerTwoWithdrawBlockNumber - stakerTwoStakeBlockNumber)
881
+ .div(staker1Shares.add(staker2Shares))
882
+ .add(BN.from("1"));
883
+
884
+ expect(stakerOneGDAOBalanceAfterWithdraw).to.be.equal(
885
+ stakerOneGDAOBalanceAfterStake.add(calculatedRewardsStakerOne)
886
+ );
887
+ expect(stakerTwoGDAOBalanceAfterWithdraw).to.be.equal(
888
+ stakerTwoGDAOBalanceAfterStake.add(calculatedRewardsStakerTwo).sub(1)
889
+ );
890
+ });
891
+
892
+ it("it should mint rewards properly when withdrawRewards", async () => {
893
+ const { staking } = await waffle.loadFixture(fixture_ready);
894
+ await goodDollar.mint(founder.address, "200");
895
+ const rewardsPerBlock = (await staking.getRewardsPerBlock())[0];
896
+ await goodDollar.approve(staking.address, "200");
897
+
898
+ const stakeBlockNumber = (await ethers.provider.getBlockNumber()) + 1;
899
+ await staking.stake("200");
900
+ const GDAOBalanceAfterStake = await grep.balanceOfLocal(founder.address);
901
+ await advanceBlocks(100);
902
+ await staking.withdrawRewards();
903
+ const withdrawRewardsBlockNumber = await ethers.provider.getBlockNumber();
904
+ const GDAOBalanceAfterWithdraw = await grep.balanceOfLocal(founder.address);
905
+
906
+ expect(GDAOBalanceAfterWithdraw).to.be.equal(
907
+ GDAOBalanceAfterStake.add(
908
+ rewardsPerBlock.mul(withdrawRewardsBlockNumber - stakeBlockNumber)
909
+ )
910
+ );
911
+ });
912
+
913
+ it("it should not overmint rewards when staker withdraw their rewards", async () => {
914
+ const { staking } = await waffle.loadFixture(fixture_ready);
915
+
916
+ const overmintTesterFactory = await ethers.getContractFactory(
917
+ "OverMintTester"
918
+ );
919
+ const overMintTester = await overmintTesterFactory.deploy(
920
+ goodDollar.address,
921
+ staking.address,
922
+ grep.address
923
+ );
924
+ await goodDollar.mint(overMintTester.address, "100");
925
+ const rewardsPerBlock = (await staking.getRewardsPerBlock())[0];
926
+ const stakeBlockNumber = (await ethers.provider.getBlockNumber()) + 1;
927
+ await overMintTester.stake();
928
+ const GDAOBalanceAfterStake = await grep.balanceOfLocal(
929
+ overMintTester.address
930
+ );
931
+ await advanceBlocks(100);
932
+ await overMintTester.overMintTest();
933
+ const withdrawRewardsBlockNumber = await ethers.provider.getBlockNumber();
934
+ const GDAOBalanceAfterWithdrawReward = await grep.balanceOfLocal(
935
+ overMintTester.address
936
+ );
937
+ await advanceBlocks(20);
938
+ await overMintTester.overMintTest();
939
+ const secondWithdrawRewardsBlockNumber =
940
+ await ethers.provider.getBlockNumber();
941
+ const GDAOBalanceAfterSecondWithdrawReward = await grep.balanceOfLocal(
942
+ overMintTester.address
943
+ );
944
+
945
+ expect(GDAOBalanceAfterWithdrawReward).to.be.gt(GDAOBalanceAfterStake);
946
+ expect(
947
+ GDAOBalanceAfterWithdrawReward.sub(GDAOBalanceAfterStake)
948
+ ).to.be.equal(
949
+ rewardsPerBlock.mul(withdrawRewardsBlockNumber - stakeBlockNumber)
950
+ );
951
+ expect(GDAOBalanceAfterSecondWithdrawReward).to.be.gt(
952
+ GDAOBalanceAfterWithdrawReward
953
+ );
954
+ expect(
955
+ GDAOBalanceAfterSecondWithdrawReward.sub(GDAOBalanceAfterWithdrawReward)
956
+ ).to.be.equal(
957
+ rewardsPerBlock.mul(
958
+ secondWithdrawRewardsBlockNumber - withdrawRewardsBlockNumber
959
+ )
960
+ );
961
+ });
962
+
963
+ it("it should accrue previous rewards based on previous monthly rate on monthly rewards rate change to 0", async () => {
964
+ const { staking } = await waffle.loadFixture(fixture_ready);
965
+
966
+ const ictrl = await ethers.getContractAt(
967
+ "Controller",
968
+ controller,
969
+ schemeMock
970
+ );
971
+
972
+ const rewardsPerBlock = (await staking.getRewardsPerBlock())[0];
973
+ await goodDollar.mint(founder.address, "100");
974
+ await goodDollar.approve(staking.address, "100");
975
+ const stakeBlockNumber = (await ethers.provider.getBlockNumber()) + 1;
976
+ await staking.stake("100");
977
+ await advanceBlocks(4);
978
+
979
+ let encodedCall = staking.interface.encodeFunctionData(
980
+ "setMonthlyGOODRewards",
981
+ ["0"] // Give 0.0001 GDAO per block so 17.28 GDAO per month
982
+ );
983
+ await ictrl.genericCall(staking.address, encodedCall, avatar, 0);
984
+
985
+ const withdrawBlockNumber = await ethers.provider.getBlockNumber();
986
+ const multiplier = withdrawBlockNumber - stakeBlockNumber;
987
+ const calculatedReward = rewardsPerBlock.mul(multiplier);
988
+ const [pendingReward] = await staking["getUserPendingReward(address)"](
989
+ founder.address
990
+ );
991
+ expect(pendingReward).to.equal(calculatedReward);
992
+ await advanceBlocks(4);
993
+ });
994
+
995
+ function rdiv(x: BigNumber, y: BigNumber) {
996
+ return x.mul(BN.from("10").pow(27)).add(y.div(2)).div(y);
997
+ }
998
+ });