@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,900 @@
1
+ import { expect } from "chai";
2
+ import { ethers, waffle } from "hardhat";
3
+ import { createDAO, advanceBlocks } from "../helpers";
4
+ import { StakingMockFixedAPY } from "../../types";
5
+ import { default as StakingABI } from "../../artifacts/contracts/mocks/StakingMockFixedAPY.sol/StakingMockFixedAPY.json";
6
+ const BN = ethers.BigNumber;
7
+
8
+ // APY=5% | Blocks per year = 12*60*24*365 = 6307200
9
+ // per block = nroot(1+0.05,numberOfBlocksPerYear) = 1000000007735630000
10
+ const BLOCKS_ONE_YEAR = 6307200;
11
+ const BLOCKS_FOUR_YEARS = 25228800;
12
+ const BLOCKS_TEN_YEARS = 63072000;
13
+ const INTEREST_RATE_5APY_X64 = BN.from("1000000007735630000"); // x64 representation of same number
14
+ const INTEREST_RATE_5APY_128 = BN.from("18446744216406738474"); // 128 representation of same number
15
+ // APY = 10% | nroot(1+0.10,numberOfBlocksPerYear) = 1000000015111330000
16
+ const INTEREST_RATE_10APY_X64 = BN.from("1000000015111330000"); // x64 representation of same number
17
+ const INTEREST_RATE_10APY_128 = BN.from("18446744352464388739"); // 128 representation of same number
18
+ // APY = 8% | nroot(1+0.08,numberOfBlocksPerYear) = 1000000012202093100
19
+ const INTEREST_RATE_8APY_X64 = BN.from("1000000012202093100"); // x64 representation of same number
20
+
21
+ describe("StakingRewardsFixedAPY - generic staking for fixed APY rewards contract", () => {
22
+ let signers,
23
+ setNSAddress,
24
+ nameService,
25
+ avatar,
26
+ genericCall,
27
+ controller,
28
+ fixedStaking: StakingMockFixedAPY,
29
+ goodDollar,
30
+ founder,
31
+ staker1,
32
+ staker2,
33
+ staker3,
34
+ staker4;
35
+
36
+ async function stake(_staker, _amount, contract = fixedStaking) {
37
+ await contract.connect(_staker).stake(_staker.address, _amount);
38
+ }
39
+
40
+ // on withdraw: _amount / sharePrice = shares redeemed
41
+ // on stake: _amount / sharePrice = shares added
42
+ async function getExpectedSharesChange(_amount, _contract = fixedStaking) {
43
+ return BN.from(_amount)
44
+ .mul(await _contract.SHARE_PRECISION())
45
+ .div(await _contract.sharePrice());
46
+ }
47
+
48
+ async function expectSavings(_staker, _amount, _contract = fixedStaking) {
49
+ const savings = await _contract.getSavings(_staker.address);
50
+ expect(savings.eq(_amount)).to.be.true;
51
+ }
52
+
53
+ before(async () => {
54
+ [founder, staker1, staker2, staker3, staker4, ...signers] =
55
+ await ethers.getSigners();
56
+
57
+ let {
58
+ controller: ctrl,
59
+ avatar: av,
60
+ genericCall: gc,
61
+ gd,
62
+ nameService: ns,
63
+ setDAOAddress
64
+ } = await createDAO();
65
+
66
+ setNSAddress = setDAOAddress;
67
+ nameService = ns;
68
+ avatar = av;
69
+ genericCall = gc;
70
+ controller = ctrl;
71
+ goodDollar = await ethers.getContractAt("IGoodDollar", gd);
72
+ });
73
+
74
+ const fixture_initOnly = async (wallets, provider) => {
75
+ const staking: StakingMockFixedAPY = (await waffle.deployContract(
76
+ provider.getWallets()[0],
77
+ StakingABI,
78
+ [INTEREST_RATE_5APY_X64]
79
+ )) as StakingMockFixedAPY;
80
+
81
+ return { staking };
82
+ };
83
+
84
+ const fixture_2 = async (wallets, provider) => {
85
+ const staking: StakingMockFixedAPY = (await waffle.deployContract(
86
+ provider.getWallets()[0],
87
+ StakingABI,
88
+ [INTEREST_RATE_5APY_X64]
89
+ )) as StakingMockFixedAPY;
90
+
91
+ return { staking };
92
+ };
93
+
94
+ const fixture_1year = async (wallets, provider) => {
95
+ const staking: StakingMockFixedAPY = (await waffle.deployContract(
96
+ provider.getWallets()[0],
97
+ StakingABI,
98
+ [INTEREST_RATE_5APY_X64]
99
+ )) as StakingMockFixedAPY;
100
+
101
+ await stake(staker1, 10000, staking);
102
+ await stake(staker2, 10000, staking);
103
+ await stake(staker3, 10000, staking);
104
+
105
+ await advanceBlocks(BLOCKS_ONE_YEAR);
106
+ return { staking };
107
+ };
108
+
109
+ const fixture_1year_single = async (wallets, provider) => {
110
+ const staking: StakingMockFixedAPY = (await waffle.deployContract(
111
+ provider.getWallets()[0],
112
+ StakingABI,
113
+ [INTEREST_RATE_5APY_X64]
114
+ )) as StakingMockFixedAPY;
115
+
116
+ await stake(staker3, 10000, staking);
117
+
118
+ await advanceBlocks(BLOCKS_ONE_YEAR);
119
+ return { staking };
120
+ };
121
+
122
+ it("should set APY successfully", async () => {
123
+ const { staking } = await waffle.loadFixture(fixture_initOnly);
124
+
125
+ const beforeSetInterestRateIn128 = await staking.interestRatePerBlockX64();
126
+
127
+ const interestRatePerBlockX64 = BN.from(INTEREST_RATE_10APY_X64); // x64 representation of same number
128
+ const interestRateInt128Format = BN.from(INTEREST_RATE_10APY_128); // 128 representation of same number
129
+ await staking.setAPY(interestRatePerBlockX64);
130
+
131
+ const afterSetInterestRateIn128 = await staking.interestRatePerBlockX64();
132
+
133
+ expect(afterSetInterestRateIn128).to.not.equal(beforeSetInterestRateIn128);
134
+ expect(afterSetInterestRateIn128).to.equal(interestRateInt128Format);
135
+ });
136
+
137
+ it("should update staker info after stake operation", async () => {
138
+ const { staking } = await waffle.loadFixture(fixture_initOnly);
139
+
140
+ await stake(staker1, 9000, staking);
141
+
142
+ let info = await staking.stakersInfo(staker1.address);
143
+ const initialShares = (await staking.SHARE_DECIMALS()).mul(9000);
144
+ expect(info.lastSharePrice)
145
+ .to.equal(
146
+ (await staking.SHARE_PRECISION()).div(await staking.SHARE_DECIMALS())
147
+ )
148
+ .to.eq(await staking.sharePrice()); // (1g$ with 2 decimals)
149
+ expect(await staking.sharesSupply())
150
+ .to.equal(initialShares)
151
+ .to.equal(await staking.totalSupply());
152
+ expect(await staking.sharesOf(staker1.address))
153
+ .eq(initialShares)
154
+ .eq(await staking.balanceOf(staker1.address));
155
+ expect(info.rewardsPaid).to.equal(0);
156
+ });
157
+
158
+ it("should handle stake/withdraw the minimal amount of 1", async () => {
159
+ const { staking } = await waffle.loadFixture(fixture_initOnly);
160
+
161
+ await stake(staker4, 1, staking);
162
+
163
+ await advanceBlocks(BLOCKS_TEN_YEARS);
164
+ await advanceBlocks(BLOCKS_FOUR_YEARS);
165
+
166
+ await expectSavings(staker4, 1, staking); // (1.01^14) = 1.979931
167
+ // await expect((await staking.sharePrice()).eq(BN.from(1979931))).to.be.true;
168
+
169
+ await advanceBlocks(BLOCKS_ONE_YEAR);
170
+
171
+ await expectSavings(staker4, 2, staking); // (1.01^15) = 2.078928
172
+ await expect((await staking.sharePrice()).eq(207892821613185)).to.be.true;
173
+
174
+ const minimalShares = await staking.amountToShares(1);
175
+ const stakerInfo = await staking.stakersInfo(staker4.address);
176
+ console.log({
177
+ sharePrice: await staking.sharePrice(),
178
+ minimalShares,
179
+ stakerInfo,
180
+ stakerShares: await staking.balanceOf(staker4.address)
181
+ });
182
+ await staking.withdraw(staker4.address, minimalShares); //this also withdraws the donated rewards
183
+
184
+ let info = await staking.stakersInfo(staker4.address);
185
+ await expectSavings(staker4, 1, staking);
186
+ expect(info.rewardsPaid).to.equal(1);
187
+ expect(await staking.balanceOf(staker4.address)).to.equal(
188
+ 10000 - minimalShares.toNumber()
189
+ );
190
+
191
+ await expect(
192
+ staking.withdraw(
193
+ staker4.address,
194
+ (await staking.amountToShares(1)).sub(1)
195
+ )
196
+ ).revertedWith("min shares");
197
+ });
198
+
199
+ it("should fail on staking 0", async () => {
200
+ const { staking } = await waffle.loadFixture(fixture_initOnly);
201
+ await expect(stake(staker4, 0, staking)).to.be.revertedWith("stake 0");
202
+ });
203
+
204
+ xit("should fail on staking with donationRatio > 100", async () => {
205
+ const { staking } = await waffle.loadFixture(fixture_initOnly);
206
+ await expect(stake(staker4, 1, 101, staking)).to.be.revertedWith(
207
+ "donation"
208
+ );
209
+ });
210
+
211
+ it("should fail on staking less than minimal amount of 1", async () => {
212
+ const { staking } = await waffle.loadFixture(fixture_initOnly);
213
+ await expect(stake(staker4, 0.99, staking)).to.be.reverted;
214
+ });
215
+
216
+ it("Should fail to withdraw exceeding amount", async () => {
217
+ const { staking } = await waffle.loadFixture(fixture_initOnly);
218
+ await stake(staker1, 1000, staking);
219
+
220
+ const shares = await staking.balanceOf(staker1.address);
221
+ await expect(staking.withdraw(staker1.address, shares.add(1))).revertedWith(
222
+ "no balance"
223
+ );
224
+ });
225
+
226
+ it("Should fail to withdraw when empty balance", async () => {
227
+ const { staking } = await waffle.loadFixture(fixture_initOnly);
228
+
229
+ await expect(staking.withdraw(staker1.address, 0)).revertedWith(
230
+ "no balance"
231
+ );
232
+ });
233
+
234
+ it("should update global stats after stake operation", async () => {
235
+ const { staking } = await waffle.loadFixture(fixture_initOnly);
236
+ const statsBefore = await staking.stats();
237
+ const PRECISION = await staking.PRECISION();
238
+
239
+ await stake(staker1, 9000, staking);
240
+
241
+ const statsAfter = await staking.stats();
242
+ expect(statsAfter.lastUpdateBlock.gt(statsBefore.lastUpdateBlock));
243
+ expect(statsAfter.totalStaked).to.equal(9000);
244
+ expect(await staking.sharesSupply()).eq(
245
+ (await staking.SHARE_DECIMALS()).mul(9000)
246
+ );
247
+ expect(statsAfter.totalRewardsPaid).to.equal(0);
248
+ expect(statsAfter.savings).to.equal(PRECISION.mul(9000));
249
+ });
250
+
251
+ it("should update staker info after withdraw operation", async () => {
252
+ const { staking } = await waffle.loadFixture(fixture_initOnly);
253
+ await stake(staker1, 9000, staking);
254
+ await advanceBlocks(BLOCKS_ONE_YEAR);
255
+
256
+ const sharesToWithdraw = await staking.amountToShares(4000);
257
+ const rewardsBalanceBefore = await staking.earned(staker1.address);
258
+ expect(rewardsBalanceBefore).eq(450);
259
+ await staking.withdraw(staker1.address, sharesToWithdraw);
260
+
261
+ let info = await staking.stakersInfo(staker1.address);
262
+
263
+ const initialShares = (await staking.SHARE_DECIMALS()).mul(9000);
264
+ const shares = await staking.sharesOf(staker1.address);
265
+ const savings = await staking.getSavings(staker1.address);
266
+ const rewardsBalance = await staking.earned(staker1.address);
267
+ const depositShareAfterWithdraw = info.lastSharePrice
268
+ .mul(shares)
269
+ .div(await staking.SHARE_PRECISION());
270
+
271
+ expect(savings).to.eq(5450); // 9000 deposit + 450 rewards - 4000 withdrawn
272
+ expect(rewardsBalance).to.eq(0); // 449 - 190
273
+ expect(shares).to.equal(initialShares.sub(sharesToWithdraw));
274
+ expect(info.rewardsPaid).to.equal(450); //relative amount of withdraw from total savings multiplied by rewards earned 4000/9450 * 450 and rounded up
275
+
276
+ await staking.withdraw(staker1.address, shares); //now withdraw everything
277
+ info = await staking.stakersInfo(staker1.address);
278
+ expect(await staking.sharesOf(staker1.address)).eq(0);
279
+ expect(info.rewardsPaid).to.equal(450);
280
+ });
281
+
282
+ it("should update global stats after withdraw operation", async () => {
283
+ const { staking } = await waffle.loadFixture(fixture_initOnly);
284
+ await stake(staker1, 9000, staking);
285
+ const statsBefore = await staking.stats();
286
+ await advanceBlocks(BLOCKS_ONE_YEAR);
287
+
288
+ const sharesToWithdraw = await staking.amountToShares(4000);
289
+ await staking.withdraw(staker1.address, sharesToWithdraw);
290
+
291
+ const statsAfter = await staking.stats();
292
+ const initialShares = (await staking.SHARE_DECIMALS()).mul(9000);
293
+ expect(statsAfter.lastUpdateBlock.gt(statsBefore.lastUpdateBlock));
294
+ expect(statsAfter.totalStaked).to.equal(9000 - 4000 + 450); // 9000 - (4000 - 190 rewards component withdrawn)
295
+ expect(await staking.sharesSupply()).to.equal(
296
+ initialShares.sub(sharesToWithdraw)
297
+ );
298
+ expect(statsAfter.totalRewardsPaid).to.equal(450);
299
+ expect(statsAfter.savings).to.equal(await staking.compoundNextBlock());
300
+ });
301
+
302
+ it("should compound savings over period", async () => {
303
+ const { staking } = await waffle.loadFixture(fixture_1year);
304
+ console.log(
305
+ "shares:",
306
+ await staking.balanceOf(staker1.address),
307
+ await staking.balanceOf(staker2.address),
308
+ await staking.balanceOf(staker3.address),
309
+ "info:",
310
+ await staking.stakersInfo(staker1.address),
311
+ await staking.stakersInfo(staker2.address),
312
+ await staking.stakersInfo(staker3.address)
313
+ );
314
+ let savings = await staking.getSavings(staker1.address);
315
+ expect(savings).to.equal(10500);
316
+ savings = await staking.getSavings(staker2.address);
317
+ expect(savings).to.equal(10500);
318
+ savings = await staking.getSavings(staker3.address);
319
+ expect(savings).to.equal(10499); //bought in 2 blocks after
320
+
321
+ let info = await staking.stakersInfo(staker1.address);
322
+ const initialShares = (await staking.SHARE_DECIMALS()).mul(10000);
323
+ expect(await staking.principle(staker1.address)).to.equal(10000);
324
+ expect(await staking.balanceOf(staker1.address)).to.equal(initialShares);
325
+
326
+ info = await staking.stakersInfo(staker2.address);
327
+ expect(await staking.principle(staker2.address)).to.equal(9999);
328
+ expect(await staking.balanceOf(staker2.address)).to.equal(99999999);
329
+ expect(info.rewardsPaid).to.equal(0);
330
+
331
+ info = await staking.stakersInfo(staker3.address);
332
+ expect(await staking.principle(staker3.address)).to.equal(9999);
333
+ expect(await staking.balanceOf(staker3.address)).to.equal(99999998);
334
+ expect(info.rewardsPaid).to.equal(0);
335
+ });
336
+
337
+ it("should compound savings over 2 years and new staker after 1 year", async () => {
338
+ const { staking } = await waffle.loadFixture(fixture_1year);
339
+
340
+ //add staker after first year
341
+ await stake(staker4, 125125, staking);
342
+ await advanceBlocks(BLOCKS_ONE_YEAR);
343
+ //check all stakes after 2nd year
344
+ let savings = await staking.getSavings(staker1.address);
345
+ expect(savings).to.equal(11025);
346
+ savings = await staking.getSavings(staker2.address);
347
+ expect(savings).to.equal(11025);
348
+ savings = await staking.getSavings(staker3.address);
349
+ expect(savings).to.equal(11025);
350
+ savings = await staking.getSavings(staker4.address);
351
+ expect(savings).to.equal(131381);
352
+ });
353
+
354
+ it("should withdraw full amount", async () => {
355
+ const { staking } = await waffle.loadFixture(fixture_1year);
356
+ const balance = await staking.sharesOf(staker1.address);
357
+ await staking.withdraw(staker1.address, balance);
358
+ const info = await staking.stakersInfo(staker1.address);
359
+
360
+ expect(await staking.getSavings(staker1.address)).to.equal(0);
361
+ expect(await staking.balanceOf(staker1.address)).to.equal(0);
362
+ expect(info.rewardsPaid).to.equal(500);
363
+ });
364
+
365
+ it("should withdraw partial amount and calculate savings correctly after 1 year", async () => {
366
+ const { staking } = await waffle.loadFixture(fixture_1year);
367
+ const sharesBefore = await staking.sharesOf(staker3.address);
368
+ //9500 withdraw / sharePrice = shares to reduce
369
+ const expectedSharesRedeemed = await staking.amountToShares(9500);
370
+ await staking.withdraw(staker3.address, expectedSharesRedeemed);
371
+
372
+ const balanceAfterWithdraw = await staking.getSavings(staker3.address);
373
+ expect(balanceAfterWithdraw).to.equal(999); //shares are not exactly 9500
374
+ expect((await staking.stakersInfo(staker3.address)).rewardsPaid).to.eq(500);
375
+ await advanceBlocks(BLOCKS_ONE_YEAR);
376
+
377
+ const info = await staking.stakersInfo(staker3.address);
378
+ const earnedRewards = await staking.earned(staker3.address);
379
+ expect(await staking.getSavings(staker3.address)).to.equal(1049); //savings after 999 + 1 year 5%
380
+ expect(earnedRewards).to.equal(50);
381
+
382
+ //check shares
383
+ expect(await staking.sharesOf(staker3.address)).to.equal(
384
+ sharesBefore.sub(expectedSharesRedeemed)
385
+ );
386
+ });
387
+
388
+ xit("should withdraw partial amount when partially donating and calculate savings correctly after 1 year", async () => {
389
+ const { staking } = await waffle.loadFixture(fixture_1year);
390
+ const infoBefore = await staking.stakersInfo(staker2.address);
391
+ const expectedSharesRedeemed = await getExpectedSharesChange(
392
+ 9500 + 125,
393
+ staking
394
+ ); //withdrawing 9500 but 125 donated rewards will be withdrawn also
395
+
396
+ await staking.withdraw(staker2.address, BN.from(9500)); // will withdraw 9500 from savings but also 125 donated rewards, 375 will be withdrawn from the rewards part.
397
+
398
+ const balanceAfterWithdraw = await staking.getSavings(staker2.address);
399
+ expect(balanceAfterWithdraw).to.equal(875); //10500 - 9500 + 125 donated
400
+
401
+ await advanceBlocks(BLOCKS_ONE_YEAR);
402
+
403
+ const info = await staking.stakersInfo(staker2.address);
404
+ const [earnedRewards, earnedRewardsAfterDonations] = await staking.earned(
405
+ staker2.address
406
+ );
407
+ expect(await staking.getSavings(staker2.address)).to.equal(
408
+ 907 //918 after 1 year. rewards part 43, donated 43*0.25=10.75 = 918-10.75
409
+ ); // 875 + 5%APY * 25%donation
410
+ expect(info.deposit).to.equal(875);
411
+ expect(info.rewardsPaid).to.equal(375);
412
+ expect(info.rewardsDonated).to.equal(125);
413
+ expect(info.avgDonationRatio).to.equal((await staking.PRECISION()).mul(25));
414
+ expect(info.shares.toNumber()).to.equal(
415
+ infoBefore.shares.sub(expectedSharesRedeemed)
416
+ );
417
+ expect(
418
+ info.shares
419
+ .mul(await staking.sharePrice())
420
+ .div(await staking.SHARE_PRECISION())
421
+ ).to.equal(info.deposit.add(earnedRewards));
422
+ expect(await staking.getSavings(staker2.address)).to.equal(
423
+ info.deposit.add(earnedRewardsAfterDonations)
424
+ );
425
+ });
426
+
427
+ xit("should withdraw partial amount when donating 100% and calculate savings correctly after 1 year", async () => {
428
+ const { staking } = await waffle.loadFixture(fixture_1year);
429
+ const infoBefore = await staking.stakersInfo(staker1.address);
430
+ const expectedSharesRedeemed = await getExpectedSharesChange(
431
+ 9500 + 500,
432
+ staking
433
+ ); //withdrawing 9500 but 500 donated rewards will be withdrawn also
434
+
435
+ await staking.withdraw(staker1.address, BN.from(9500)); // this will withdraw 9500 from deposit but also 500 donated rewards
436
+
437
+ const balanceAfterWithdraw = await staking.getSavings(staker1.address);
438
+ expect(balanceAfterWithdraw).to.equal(500);
439
+
440
+ await advanceBlocks(BLOCKS_ONE_YEAR);
441
+
442
+ const info = await staking.stakersInfo(staker1.address);
443
+ const [earnedRewards, earnedRewardsAfterDonations] = await staking.earned(
444
+ staker1.address
445
+ );
446
+ expect(await staking.getSavings(staker1.address)).to.equal(500);
447
+ expect(info.deposit).to.equal(500);
448
+ expect(info.rewardsPaid).to.equal(0);
449
+ expect(info.rewardsDonated).to.equal(500);
450
+ expect(info.avgDonationRatio).to.equal(
451
+ (await staking.PRECISION()).mul(100)
452
+ );
453
+ expect(info.shares.toNumber()).to.equal(
454
+ infoBefore.shares.sub(expectedSharesRedeemed)
455
+ );
456
+ expect(
457
+ info.shares
458
+ .mul(await staking.sharePrice())
459
+ .div(await staking.SHARE_PRECISION())
460
+ ).to.equal(info.deposit.add(earnedRewards));
461
+ expect(await staking.getSavings(staker1.address)).to.equal(
462
+ info.deposit.add(earnedRewardsAfterDonations)
463
+ );
464
+ });
465
+
466
+ xit("should withdraw rewards from rewards only", async () => {
467
+ const { staking } = await waffle.loadFixture(fixture_1year);
468
+ const infoBefore = await staking.stakersInfo(staker3.address);
469
+ const balance = await staking.getSavings(staker3.address);
470
+
471
+ const expectedSharesRedeemed = await getExpectedSharesChange(500, staking);
472
+ await staking.withdraw(staker3.address, 500);
473
+ const info = await staking.stakersInfo(staker3.address);
474
+
475
+ expect(balance).to.equal(10500); //initial stake 10000 + 5%
476
+ expect(await staking.getSavings(staker3.address)).to.equal(10000);
477
+ expect(info.deposit).to.equal(10000);
478
+ expect(info.shares.toNumber()).to.equal(
479
+ infoBefore.shares.sub(expectedSharesRedeemed)
480
+ );
481
+ expect(info.rewardsPaid).to.equal(500);
482
+ expect(info.rewardsDonated).to.equal(0);
483
+ expect(info.avgDonationRatio).to.equal(0);
484
+ });
485
+
486
+ xit("should update avgDonationRatio after second stake", async () => {
487
+ const { staking } = await waffle.loadFixture(fixture_1year);
488
+ const infoBefore = await staking.stakersInfo(staker1.address);
489
+ const statsBefore = await staking.stats();
490
+
491
+ await staking.stake(
492
+ staker1.address,
493
+ BN.from(infoBefore.shares) // staker1 buys same amount of shares he had
494
+ .mul(await staking.sharePrice())
495
+ .div(await staking.SHARE_PRECISION()),
496
+ 0
497
+ );
498
+
499
+ const infoAfter = await staking.stakersInfo(staker1.address);
500
+ const statsAfter = await staking.stats();
501
+ const PRECISION = await staking.PRECISION();
502
+
503
+ expect(infoBefore.avgDonationRatio).to.equal(PRECISION.mul(100)); // 1st stake had 100% donation
504
+ expect(infoAfter.avgDonationRatio).to.equal(PRECISION.mul(50)); // 2nd stake had 0% for same amount of shares => 50% average
505
+ expect(statsBefore.avgDonationRatio).to.equal(PRECISION.mul(125).div(3)); // total avg of 3 stakers => 0, 25, 100 each had staked 10000
506
+ expect(statsAfter.avgDonationRatio).to.equal(
507
+ BN.from("31249999999999999999")
508
+ ); // 31.25% = (2 * 0% + 1 * 25% + 1 * 100%) / 4
509
+ });
510
+
511
+ xit("should update avgDonationRatio after partial withdraw", async () => {
512
+ const { staking } = await waffle.loadFixture(fixture_1year);
513
+ const infoBeforeWithdraw = await staking.stakersInfo(staker1.address);
514
+ const statsBeforeWithdraw = await staking.stats();
515
+ const expectedSharesRedeemed = await getExpectedSharesChange(
516
+ 2000 + 500,
517
+ staking
518
+ ); //2000 + 500 that are donated
519
+ await staking.withdraw(staker1.address, 2000); //this also withdraws the donated rewards
520
+ const statsAfterWithdraw = await staking.stats();
521
+
522
+ const expectedGlobalAvgRatio = statsBeforeWithdraw.avgDonationRatio
523
+ .mul(statsBeforeWithdraw.totalShares)
524
+ .sub(expectedSharesRedeemed.mul(infoBeforeWithdraw.avgDonationRatio))
525
+ .div(statsAfterWithdraw.totalShares);
526
+
527
+ const infoAfterWithdraw = await staking.stakersInfo(staker1.address);
528
+ expect(infoBeforeWithdraw.avgDonationRatio).to.equal(
529
+ infoAfterWithdraw.avgDonationRatio
530
+ );
531
+
532
+ expect(expectedGlobalAvgRatio).to.equal(
533
+ statsAfterWithdraw.avgDonationRatio
534
+ );
535
+ });
536
+
537
+ it("should calculate correct share price after savings has grown", async () => {
538
+ const { staking } = await waffle.loadFixture(fixture_1year);
539
+ const SHARE_PRECISION = await staking.SHARE_PRECISION();
540
+
541
+ const savingsBefore = await staking.compound();
542
+ const expectedSharePriceBefore = BN.from(savingsBefore)
543
+ .mul(SHARE_PRECISION)
544
+ .div(await staking.PRECISION())
545
+ .div(await staking.sharesSupply());
546
+ const actualSharePriceBefore = await staking.sharePrice();
547
+ expect(actualSharePriceBefore).to.equal(expectedSharePriceBefore);
548
+
549
+ await advanceBlocks(BLOCKS_ONE_YEAR);
550
+
551
+ const savingsAfter = savingsBefore.mul(105).div(100); //estimate
552
+ const expectedSharePriceAfter = BN.from(savingsAfter)
553
+ .mul(SHARE_PRECISION)
554
+ .div(await staking.PRECISION())
555
+ .div(await staking.sharesSupply());
556
+ const actualSharePriceAfter = await staking.sharePrice();
557
+ expect(actualSharePriceAfter.div(1e8)).to.eq(
558
+ expectedSharePriceAfter.div(1e8)
559
+ ); //compare rough estimate so we reduce precision by 1e8
560
+ });
561
+
562
+ it("should check compound function compounds savings correctly", async () => {
563
+ const { staking } = await waffle.loadFixture(fixture_1year);
564
+ const PRECISION = await staking.PRECISION();
565
+
566
+ const expectedCompoundBefore = 3 * 10000 * 1.05; // 3 stakers of 10000 with 5 APY, after one year
567
+ const actualCompoundBefore = (await staking.compound()).div(PRECISION);
568
+ expect(actualCompoundBefore).to.equal(expectedCompoundBefore);
569
+
570
+ await advanceBlocks(BLOCKS_ONE_YEAR);
571
+
572
+ const expectedCompoundAfter = expectedCompoundBefore * 1.05;
573
+ const actualCompoundAfter = (await staking.compound()).div(PRECISION);
574
+ expect(actualCompoundAfter).to.equal(expectedCompoundAfter);
575
+ expect(actualCompoundAfter.gt(actualCompoundBefore)).to.be.true;
576
+ });
577
+
578
+ it("should calculate earned rewards in period", async () => {
579
+ const { staking } = await waffle.loadFixture(fixture_1year);
580
+ let earnedRewards1 = await staking.earned(staker1.address);
581
+ let earnedRewards2 = await staking.earned(staker2.address);
582
+ let earnedRewards3 = await staking.earned(staker3.address);
583
+
584
+ expect(earnedRewards1).equal(earnedRewards2).equal(500);
585
+ expect(earnedRewards3).eq(499);
586
+
587
+ await advanceBlocks(BLOCKS_ONE_YEAR);
588
+ earnedRewards1 = await staking.earned(staker1.address);
589
+ earnedRewards2 = await staking.earned(staker2.address);
590
+ earnedRewards3 = await staking.earned(staker3.address);
591
+
592
+ expect(earnedRewards1)
593
+ .equal(earnedRewards2)
594
+ .equal(earnedRewards3)
595
+ .equal(1025);
596
+ });
597
+
598
+ it("Should undo reward part and update staker info", async () => {
599
+ const { staking } = await waffle.loadFixture(fixture_1year);
600
+
601
+ const initialInfo = await staking.stakersInfo(staker3.address);
602
+ const sharesToWithdraw = await staking.amountToShares(500);
603
+ const initialRewards = await staking.earned(staker3.address);
604
+ await staking.withdrawAndUndo(staker3.address, sharesToWithdraw);
605
+
606
+ const infoAfterUndo = await staking.stakersInfo(staker3.address);
607
+
608
+ expect(await staking.getSavings(staker3.address)).to.equal(10499);
609
+
610
+ expect(await staking.earned(staker3.address)).to.eq(500);
611
+ expect(infoAfterUndo.rewardsPaid).to.equal(initialInfo.rewardsPaid);
612
+ });
613
+
614
+ it("Should undo reward and keep global stats the same", async () => {
615
+ const { staking } = await waffle.loadFixture(fixture_1year);
616
+
617
+ const initialStats = await staking.stats();
618
+
619
+ const initialSavings = await staking.compoundNextBlock(); //withdrawAndUndo will calculate savings of next block
620
+ const sharesToWithdraw = await staking.amountToShares(500);
621
+ const initialShares = await staking.sharesSupply();
622
+ await staking.withdrawAndUndo(staker3.address, sharesToWithdraw);
623
+ const statsAfterUndo = await staking.stats();
624
+
625
+ expect(statsAfterUndo.savings.div(ethers.constants.WeiPerEther)).to.equal(
626
+ 31500
627
+ );
628
+
629
+ expect(initialStats.totalRewardsPaid).to.equal(
630
+ statsAfterUndo.totalRewardsPaid
631
+ );
632
+
633
+ expect(await staking.sharesSupply()).to.lt(initialShares);
634
+ expect(initialStats.totalStaked).to.equal(statsAfterUndo.totalStaked);
635
+ });
636
+
637
+ xit("Should undo reward when part of them is donated and keep info and global stats the same", async () => {
638
+ const { staking } = await waffle.loadFixture(fixture_1year);
639
+
640
+ const initialStats = await staking.stats();
641
+ const initialInfo = await staking.stakersInfo(staker2.address);
642
+ const initialSavings = await staking.getSavings(staker2.address);
643
+ const latestSavings = await staking.compoundNextBlock(); //withdrawAndUndo will calculate savings of next block
644
+
645
+ await staking.withdrawAndUndo(staker2.address, 375); //375 rewards 125 donated
646
+
647
+ const infoAfterUndo = await staking.stakersInfo(staker2.address);
648
+ expect(await staking.getSavings(staker2.address)).to.equal(initialSavings);
649
+ expect(infoAfterUndo.rewardsPaid).to.equal(0);
650
+ expect(infoAfterUndo.rewardsDonated).to.equal(0);
651
+
652
+ expect(infoAfterUndo.avgDonationRatio).to.equal(
653
+ initialInfo.avgDonationRatio
654
+ );
655
+ expect(initialInfo.shares).to.eq(infoAfterUndo.shares);
656
+
657
+ //check global stats
658
+ const statsAfterUndo = await staking.stats();
659
+
660
+ expect(statsAfterUndo.savings).to.equal(latestSavings);
661
+
662
+ expect(initialStats.totalRewardsDonated).to.equal(
663
+ statsAfterUndo.totalRewardsDonated
664
+ );
665
+ expect(initialStats.totalRewardsPaid).to.equal(
666
+ statsAfterUndo.totalRewardsPaid
667
+ );
668
+ expect(initialStats.totalShares).to.equal(statsAfterUndo.totalShares);
669
+ expect(initialStats.totalStaked).to.equal(statsAfterUndo.totalStaked);
670
+ expect(initialStats.avgDonationRatio).to.equal(
671
+ statsAfterUndo.avgDonationRatio.add(1) //precision loss during withdraw avgDonationRatio calculation
672
+ );
673
+ });
674
+
675
+ it("Should undo reward when withdrawing partial rewards keep info and global stats the same", async () => {
676
+ const { staking } = await waffle.loadFixture(fixture_1year);
677
+
678
+ const initialInfo = await staking.stakersInfo(staker2.address);
679
+ const initialSavings = await staking.getSavings(staker2.address);
680
+ const initialStats = await staking.stats();
681
+ const initialTotalSavings = await staking.compoundNextBlock(); //withdrawAndUndo will calculate savings of next block
682
+ const initialSharesSupply = await staking.sharesSupply();
683
+ //current rewards are 500 so 250 is only partial withdraw of rewards
684
+ const sharesToWithdraw = await staking.amountToShares(250);
685
+ await staking.withdrawAndUndo(staker2.address, sharesToWithdraw);
686
+
687
+ const infoAfterUndo = await staking.stakersInfo(staker2.address);
688
+ expect(await staking.getSavings(staker2.address)).to.equal(initialSavings);
689
+ expect(infoAfterUndo.rewardsPaid).to.equal(initialInfo.rewardsPaid);
690
+
691
+ //check global stats
692
+ const statsAfterUndo = await staking.stats();
693
+
694
+ expect(statsAfterUndo.savings).to.equal(initialTotalSavings);
695
+
696
+ expect(initialStats.totalRewardsDonated).to.equal(
697
+ statsAfterUndo.totalRewardsDonated
698
+ );
699
+ expect(initialStats.totalRewardsPaid).to.equal(
700
+ statsAfterUndo.totalRewardsPaid
701
+ );
702
+ expect(initialSharesSupply).to.equal((await staking.sharesSupply()).add(1)); //precision loss when converting back from rewards amount to shares
703
+ expect(initialStats.totalStaked).to.equal(statsAfterUndo.totalStaked);
704
+ });
705
+
706
+ //helper test
707
+ // it.only("Should not suffer from endless precission loss", async () => {
708
+ // const { staking } = await waffle.loadFixture(fixture_1year_single);
709
+
710
+ // const initialShares = await staking.sharesOf(staker3.address);
711
+ // const maxLoss = await staking.amountToShares(1);
712
+ // for (let i = 0; i < 500; i++) {
713
+ // expect(await staking.getSavings(staker3.address)).eq(10500);
714
+ // expect(await staking.sharesOf(staker3.address)).gte(
715
+ // initialShares.sub(maxLoss)
716
+ // );
717
+ // expect(await staking.earned(staker3.address)).eq(500);
718
+ // const sharesToWithdraw = await staking.amountToShares(500);
719
+ // await staking.withdrawAndUndo(staker3.address, sharesToWithdraw);
720
+ // }
721
+ // });
722
+
723
+ xit("Should undo reward when withdrawing rewards + deposit and update deposit info and stats correctly", async () => {});
724
+
725
+ it("Should be able to withdraw right after staking", async () => {
726
+ const { staking } = await waffle.loadFixture(fixture_1year);
727
+ await stake(staker4, 10000, staking);
728
+ await expect(
729
+ staking.withdraw(
730
+ staker4.address,
731
+ await staking.balanceOf(staker4.address)
732
+ )
733
+ ).not.reverted;
734
+
735
+ const info = await staking.stakersInfo(staker4.address);
736
+ expect(await staking.getSavings(staker4.address)).to.equal(0);
737
+ expect(info.rewardsPaid).to.equal(0);
738
+ expect(info.lastSharePrice.div(1e8)).to.equal(
739
+ (await staking.sharePrice()).div(1e8)
740
+ );
741
+ });
742
+
743
+ it("should calculate savings correctly after set APY ", async () => {
744
+ const { staking } = await waffle.loadFixture(fixture_1year);
745
+ await stake(staker4, 125125, staking);
746
+
747
+ // before set, APY is 5%
748
+ const beforeSetInterestRateIn128 = await staking.interestRatePerBlockX64();
749
+ expect(beforeSetInterestRateIn128).to.equal(INTEREST_RATE_5APY_128);
750
+
751
+ // set APY to 10%
752
+ await staking.setAPY(INTEREST_RATE_10APY_X64);
753
+ await advanceBlocks(BLOCKS_ONE_YEAR);
754
+
755
+ await expectSavings(staker1, 11550, staking);
756
+ await expectSavings(staker2, 11550, staking);
757
+ await expectSavings(staker3, 11550, staking); // 10000 + 10000((1.05APY1 * 1.10APY2) - 1)
758
+ await expectSavings(staker4, 137637, staking); // 125125((1.10APY2) - 1)
759
+
760
+ // set APY to 8%
761
+ await staking.setAPY(INTEREST_RATE_8APY_X64);
762
+ await advanceBlocks(BLOCKS_ONE_YEAR);
763
+
764
+ await expectSavings(staker1, 12474, staking);
765
+ await expectSavings(staker2, 12474, staking);
766
+ await expectSavings(staker3, 12474, staking);
767
+ await expectSavings(staker4, 148648, staking); // 125125((1.10APY2 * 1.08APY3) - 1)
768
+ });
769
+
770
+ it("should handle first stake big, followed by smaller actions", async () => {
771
+ const { staking } = await waffle.loadFixture(fixture_2);
772
+
773
+ await stake(staker4, 10000000, staking);
774
+
775
+ const savingsAfterBigStake = await staking.getSavings(staker4.address);
776
+ const infoAfterBigStake = await staking.stakersInfo(staker4.address);
777
+ await stake(signers[0], 5, staking);
778
+
779
+ const savingsAfterSmallStake = await staking.getSavings(staker4.address);
780
+ const smallStakeSavings = await staking.getSavings(signers[0].address);
781
+ expect(smallStakeSavings).gt(0);
782
+ const sharesAfterBigStake = await staking.balanceOf(staker4.address);
783
+
784
+ const sharesAfterSmallStake = await staking.balanceOf(signers[0].address);
785
+ expect(savingsAfterSmallStake.eq(savingsAfterBigStake)).to.be.true;
786
+ expect(sharesAfterSmallStake).gt(0);
787
+
788
+ const onegdShares = await staking.amountToShares(1);
789
+ await expect(staking.withdraw(staker4.address, 1000)).revertedWith("min");
790
+
791
+ await expect(staking.withdraw(staker4.address, onegdShares)).not.reverted;
792
+ await expect(
793
+ staking.withdraw(
794
+ signers[0].address,
795
+ await staking.balanceOf(signers[0].address)
796
+ )
797
+ ).not.reverted;
798
+
799
+ const sharesAfterWithdraw = await staking.balanceOf(staker4.address);
800
+ const sharesAfterWithdraw2 = await staking.balanceOf(signers[0].address);
801
+
802
+ expect(sharesAfterWithdraw).to.equal(sharesAfterBigStake.sub(onegdShares));
803
+ expect(sharesAfterWithdraw2).to.equal(0);
804
+ });
805
+
806
+ it("should handle first stake small, followed by 100 Billion stake", async () => {
807
+ const { staking } = await waffle.loadFixture(fixture_2);
808
+
809
+ await stake(signers[0], 5, staking);
810
+ await stake(staker4, 1e13, staking);
811
+
812
+ const onegdShares = await staking.amountToShares(1);
813
+ await staking.withdraw(staker4.address, onegdShares);
814
+
815
+ await expect(
816
+ staking.withdraw(
817
+ signers[0].address,
818
+ await staking.balanceOf(signers[0].address)
819
+ )
820
+ ).not.reverted;
821
+ });
822
+
823
+ it("should handle first 100 Billion stake, followed by a small", async () => {
824
+ const { staking } = await waffle.loadFixture(fixture_2);
825
+
826
+ await stake(staker4, 1e13, staking);
827
+ await stake(signers[0], 5, staking);
828
+
829
+ const onegdShares = await staking.amountToShares(1);
830
+ await expect(
831
+ staking.withdraw(
832
+ signers[0].address,
833
+ await staking.balanceOf(signers[0].address)
834
+ )
835
+ ).not.reverted;
836
+ await expect(staking.withdraw(staker4.address, onegdShares)).not.reverted;
837
+ });
838
+
839
+ xit("should withdraw all when amount=max uint", async () => {
840
+ const { staking } = await waffle.loadFixture(fixture_1year);
841
+ await expect(staking.withdraw(staker3.address, 0)).revertedWith("balance");
842
+ await staking.withdraw(staker3.address, ethers.constants.MaxUint256);
843
+ const info = await staking.stakersInfo(staker3.address);
844
+
845
+ expect(info.rewardsPaid).to.equal(499);
846
+ expect(await staking.sharesOf(staker3.address)).to.equal(0);
847
+ expect(await staking.getSavings(staker3.address)).to.equal(0);
848
+ });
849
+
850
+ it("should be able to get rewards debt (ie savings - deposits - donated rewards)", async () => {
851
+ const { staking } = await waffle.loadFixture(fixture_1year);
852
+ const debt = (await staking.getRewardsDebt()).div(
853
+ ethers.utils.parseEther("1")
854
+ ); //debt is in 1e18 precision
855
+ expect(debt).to.equal(1500); //30000*1.05 - 300000
856
+ });
857
+
858
+ it("should not be able to stake less than share price", async () => {
859
+ const { staking } = await waffle.loadFixture(fixture_1year);
860
+ await advanceBlocks(BLOCKS_TEN_YEARS * 20);
861
+
862
+ await expect(stake(staker1, 1, staking)).to.revertedWith("share");
863
+ await expect(stake(staker1, 2, staking)).to.not.reverted;
864
+ });
865
+
866
+ it("should not be able to withdraw less than share price", async () => {
867
+ const { staking } = await waffle.loadFixture(fixture_1year);
868
+ await advanceBlocks(BLOCKS_TEN_YEARS * 10);
869
+
870
+ const sharePrice = await staking.sharePrice();
871
+ await expect(staking.withdraw(staker3.address, 1)).to.revertedWith("share");
872
+ });
873
+
874
+ it("should handle stake/withdraw for 1 Trillion staked for 50 years", async () => {
875
+ const { staking } = await waffle.loadFixture(fixture_1year);
876
+ await stake(staker3, 100000000000000, staking);
877
+ await advanceBlocks(BLOCKS_TEN_YEARS * 5);
878
+
879
+ await expect(
880
+ staking.withdraw(
881
+ staker3.address,
882
+ await staking.balanceOf(staker3.address)
883
+ )
884
+ ).to.not.reverted;
885
+ });
886
+
887
+ it("should have undo reward handle invalid input", async () => {
888
+ const staking: StakingMockFixedAPY = (await (
889
+ await ethers.getContractFactory("StakingMockFixedAPY")
890
+ ).deploy(INTEREST_RATE_5APY_X64)) as StakingMockFixedAPY;
891
+
892
+ //undo 0 rewards
893
+ await stake(staker4, 10000, staking);
894
+ await staking.withdraw(
895
+ staker4.address,
896
+ await staking.balanceOf(staker4.address)
897
+ );
898
+ await expect(staking.undoReward(staker4.address, 0)).to.not.reverted;
899
+ });
900
+ });