@gooddollar/goodprotocol 1.0.10 → 1.0.13-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 (127) hide show
  1. package/artifacts/contracts/DAOStackInterfaces.sol/Avatar.dbg.json +1 -1
  2. package/artifacts/contracts/DAOStackInterfaces.sol/Controller.dbg.json +1 -1
  3. package/artifacts/contracts/DAOStackInterfaces.sol/GlobalConstraintInterface.dbg.json +1 -1
  4. package/artifacts/contracts/DAOStackInterfaces.sol/IntVoteInterface.dbg.json +1 -1
  5. package/artifacts/contracts/DAOStackInterfaces.sol/ReputationInterface.dbg.json +1 -1
  6. package/artifacts/contracts/DAOStackInterfaces.sol/SchemeRegistrar.dbg.json +1 -1
  7. package/artifacts/contracts/Interfaces.sol/AggregatorV3Interface.dbg.json +1 -1
  8. package/artifacts/contracts/Interfaces.sol/ERC20.dbg.json +1 -1
  9. package/artifacts/contracts/Interfaces.sol/IAaveIncentivesController.dbg.json +1 -1
  10. package/artifacts/contracts/Interfaces.sol/IAdminWallet.dbg.json +1 -1
  11. package/artifacts/contracts/Interfaces.sol/IDonationStaking.dbg.json +1 -1
  12. package/artifacts/contracts/Interfaces.sol/IERC2917.dbg.json +1 -1
  13. package/artifacts/contracts/Interfaces.sol/IFirstClaimPool.dbg.json +1 -1
  14. package/artifacts/contracts/Interfaces.sol/IGoodDollar.dbg.json +1 -1
  15. package/artifacts/contracts/Interfaces.sol/IGoodStaking.dbg.json +1 -1
  16. package/artifacts/contracts/Interfaces.sol/IHasRouter.dbg.json +1 -1
  17. package/artifacts/contracts/Interfaces.sol/IIdentity.dbg.json +1 -1
  18. package/artifacts/contracts/Interfaces.sol/ILendingPool.dbg.json +1 -1
  19. package/artifacts/contracts/Interfaces.sol/INameService.dbg.json +1 -1
  20. package/artifacts/contracts/Interfaces.sol/IUBIScheme.dbg.json +1 -1
  21. package/artifacts/contracts/Interfaces.sol/ProxyAdmin.dbg.json +1 -1
  22. package/artifacts/contracts/Interfaces.sol/Reserve.dbg.json +1 -1
  23. package/artifacts/contracts/Interfaces.sol/Staking.dbg.json +1 -1
  24. package/artifacts/contracts/Interfaces.sol/Uniswap.dbg.json +1 -1
  25. package/artifacts/contracts/Interfaces.sol/UniswapFactory.dbg.json +1 -1
  26. package/artifacts/contracts/Interfaces.sol/UniswapPair.dbg.json +1 -1
  27. package/artifacts/contracts/Interfaces.sol/cERC20.dbg.json +1 -1
  28. package/artifacts/contracts/governance/ClaimersDistribution.sol/ClaimersDistribution.dbg.json +1 -1
  29. package/artifacts/contracts/governance/CompoundVotingMachine.sol/CompoundVotingMachine.dbg.json +1 -1
  30. package/artifacts/contracts/governance/GReputation.sol/GReputation.dbg.json +1 -1
  31. package/artifacts/contracts/governance/GovarnanceStaking.sol/GovernanceStaking.dbg.json +1 -1
  32. package/artifacts/contracts/governance/MultiBaseGovernanceShareField.sol/MultiBaseGovernanceShareField.dbg.json +1 -1
  33. package/artifacts/contracts/governance/Reputation.sol/Reputation.dbg.json +1 -1
  34. package/artifacts/contracts/governance/StakersDistribution.sol/StakersDistribution.dbg.json +1 -1
  35. package/artifacts/contracts/governance/StakersDistribution.sol/StakersDistribution.json +2 -2
  36. package/artifacts/contracts/mocks/AaveMock.sol/AaveMock.dbg.json +1 -1
  37. package/artifacts/contracts/mocks/DAIMock.sol/DAIMock.dbg.json +1 -1
  38. package/artifacts/contracts/mocks/DecimalsMock.sol/DecimalsMock.dbg.json +1 -1
  39. package/artifacts/contracts/mocks/GoodCompoundStakingTest.sol/GoodCompoundStakingTest.dbg.json +1 -1
  40. package/artifacts/contracts/mocks/GoodCompoundStakingTest.sol/GoodCompoundStakingTest.json +6 -6
  41. package/artifacts/contracts/mocks/GoodFundManagerTest.sol/GoodFundManagerTest.dbg.json +1 -1
  42. package/artifacts/contracts/mocks/IncentiveControllerMock.sol/IncentiveControllerMock.dbg.json +1 -1
  43. package/artifacts/contracts/mocks/LendingPoolMock.sol/LendingPoolMock.dbg.json +1 -1
  44. package/artifacts/contracts/mocks/OverMintTester.sol/OverMintTester.dbg.json +1 -1
  45. package/artifacts/contracts/mocks/OverMintTesterRegularStake.sol/OverMintTesterRegularStake.dbg.json +1 -1
  46. package/artifacts/contracts/mocks/OverMintTesterRegularStake.sol/OverMintTesterRegularStake.json +2 -2
  47. package/artifacts/contracts/mocks/SixteenDecimalsTokenMock.sol/SixteenDecimalsTokenMock.dbg.json +1 -1
  48. package/artifacts/contracts/mocks/SwapHelperTest.sol/SwapHelperTest.dbg.json +1 -1
  49. package/artifacts/contracts/mocks/TwentyDecimalsTokenMock.sol/TwentyDecimalsTokenMock.dbg.json +1 -1
  50. package/artifacts/contracts/mocks/UpgradableMocks.sol/UpgradableMock.dbg.json +1 -1
  51. package/artifacts/contracts/mocks/UpgradableMocks.sol/UpgradableMock2.dbg.json +1 -1
  52. package/artifacts/contracts/mocks/UsdcMock.sol/USDCMock.dbg.json +1 -1
  53. package/artifacts/contracts/mocks/cBATMock.sol/cBATMock.dbg.json +1 -1
  54. package/artifacts/contracts/mocks/cDAILowWorthMock.sol/cDAILowWorthMock.dbg.json +1 -1
  55. package/artifacts/contracts/mocks/cDAIMock.sol/cDAIMock.dbg.json +1 -1
  56. package/artifacts/contracts/mocks/cDAINonMintableMock.sol/cDAINonMintableMock.dbg.json +1 -1
  57. package/artifacts/contracts/mocks/cDecimalsMock.sol/cDecimalsMock.dbg.json +1 -1
  58. package/artifacts/contracts/mocks/cSDTMock.sol/cSDTMock.dbg.json +1 -1
  59. package/artifacts/contracts/mocks/cUSDCMock.sol/cUSDCMock.dbg.json +1 -1
  60. package/artifacts/contracts/reserve/ExchangeHelper.sol/ExchangeHelper.dbg.json +1 -1
  61. package/artifacts/contracts/reserve/GoodMarketMaker.sol/GoodMarketMaker.dbg.json +1 -1
  62. package/artifacts/contracts/reserve/GoodReserveCDai.sol/ContributionCalc.dbg.json +1 -1
  63. package/artifacts/contracts/reserve/GoodReserveCDai.sol/GoodReserveCDai.dbg.json +1 -1
  64. package/artifacts/contracts/staking/BaseShareField.sol/BaseShareField.dbg.json +1 -1
  65. package/artifacts/contracts/staking/BaseShareFieldV2.sol/BaseShareFieldV2.dbg.json +1 -1
  66. package/artifacts/contracts/staking/BaseShareFieldV2.sol/BaseShareFieldV2.json +48 -104
  67. package/artifacts/contracts/staking/DonationsStaking.sol/DonationsStaking.dbg.json +1 -1
  68. package/artifacts/contracts/staking/DonationsStaking.sol/DonationsStaking.json +2 -2
  69. package/artifacts/contracts/staking/GoodFundManager.sol/GoodFundManager.dbg.json +1 -1
  70. package/artifacts/contracts/staking/SimpleStaking.sol/SimpleStaking.dbg.json +1 -1
  71. package/artifacts/contracts/staking/SimpleStakingV2.sol/SimpleStakingV2.dbg.json +1 -1
  72. package/artifacts/contracts/staking/SimpleStakingV2.sol/SimpleStakingV2.json +48 -123
  73. package/artifacts/contracts/staking/UniswapV2SwapHelper.sol/UniswapV2SwapHelper.dbg.json +1 -1
  74. package/artifacts/contracts/staking/aave/AaveStakingFactory.sol/AaveStakingFactory.dbg.json +1 -1
  75. package/artifacts/contracts/staking/aave/AaveStakingFactory.sol/AaveStakingFactory.json +65 -12
  76. package/artifacts/contracts/staking/aave/GoodAaveStaking.sol/GoodAaveStaking.dbg.json +1 -1
  77. package/artifacts/contracts/staking/aave/GoodAaveStaking.sol/GoodAaveStaking.json +4 -4
  78. package/artifacts/contracts/staking/aave/GoodAaveStakingV2.sol/GoodAaveStakingV2.dbg.json +1 -1
  79. package/artifacts/contracts/staking/aave/GoodAaveStakingV2.sol/GoodAaveStakingV2.json +52 -127
  80. package/artifacts/contracts/staking/compound/CompoundStakingFactory.sol/CompoundStakingFactory.dbg.json +1 -1
  81. package/artifacts/contracts/staking/compound/CompoundStakingFactory.sol/CompoundStakingFactory.json +57 -14
  82. package/artifacts/contracts/staking/compound/GoodCompoundStaking.sol/GoodCompoundStaking.dbg.json +1 -1
  83. package/artifacts/contracts/staking/compound/GoodCompoundStaking.sol/GoodCompoundStaking.json +6 -6
  84. package/artifacts/contracts/staking/compound/GoodCompoundStakingV2.sol/GoodCompoundStakingV2.dbg.json +4 -0
  85. package/artifacts/contracts/staking/compound/GoodCompoundStakingV2.sol/GoodCompoundStakingV2.json +1092 -0
  86. package/artifacts/contracts/ubi/UBIScheme.sol/UBIScheme.dbg.json +1 -1
  87. package/artifacts/contracts/unaudited-foundation/FuseFaucet.sol/FuseFaucet.dbg.json +1 -1
  88. package/artifacts/contracts/unaudited-foundation/InvitesV1.sol/InvitesV1.dbg.json +1 -1
  89. package/artifacts/contracts/utils/BancorFormula.sol/BancorFormula.dbg.json +1 -1
  90. package/artifacts/contracts/utils/DAOContract.sol/DAOContract.dbg.json +1 -1
  91. package/artifacts/contracts/utils/DAOUpgradeableContract.sol/DAOUpgradeableContract.dbg.json +1 -1
  92. package/artifacts/contracts/utils/DSMath.sol/DSMath.dbg.json +1 -1
  93. package/artifacts/contracts/utils/DataTypes.sol/DataTypes.dbg.json +1 -1
  94. package/artifacts/contracts/utils/NameService.sol/NameService.dbg.json +1 -1
  95. package/artifacts/contracts/utils/ProtocolUpgrade.sol/OldMarketMaker.dbg.json +1 -1
  96. package/artifacts/contracts/utils/ProtocolUpgrade.sol/ProtocolUpgrade.dbg.json +1 -1
  97. package/artifacts/contracts/utils/ProtocolUpgradeFuse.sol/ProtocolUpgradeFuse.dbg.json +1 -1
  98. package/artifacts/contracts/utils/ReputationTestHelper.sol/ReputationTestHelper.dbg.json +1 -1
  99. package/contracts/staking/BaseShareFieldV2.sol +45 -21
  100. package/contracts/staking/SimpleStaking.sol +0 -7
  101. package/contracts/staking/SimpleStakingV2.sol +10 -44
  102. package/contracts/staking/aave/AaveStakingFactory.sol +45 -19
  103. package/contracts/staking/aave/GoodAaveStaking.sol +1 -1
  104. package/contracts/staking/aave/GoodAaveStakingV2.sol +2 -2
  105. package/contracts/staking/compound/CompoundStakingFactory.sol +41 -18
  106. package/contracts/staking/compound/GoodCompoundStaking.sol +1 -1
  107. package/contracts/staking/compound/GoodCompoundStakingV2.sol +315 -0
  108. package/package.json +1 -1
  109. package/releases/deployment.json +57 -47
  110. package/scripts/upgradeToV2/upgradeToV2.ts +7 -3
  111. package/test/governance/StakersDistribution.test.ts +30 -1
  112. package/test/helpers.ts +1 -0
  113. package/test/staking/CompoundStakingFactory.test.ts +24 -21
  114. package/test/staking/DifferentStakingTokens.test.ts +3 -1
  115. package/test/staking/DonationsStaking.test.ts +21 -16
  116. package/test/staking/GoodAaveStakingFactory.test.ts +26 -23
  117. package/test/staking/SimpleDAIStaking.test.ts +3 -11
  118. package/test/staking/StakingRewards.test.ts +20 -14
  119. package/test/staking/SwapHelper.test.ts +4 -1
  120. package/test/staking/UsdcAaveStaking.test.ts +23 -8
  121. package/test/ubi/UBIScheme.e2e.test.ts +1 -1
  122. package/test/utils/ProtocolUpgrade.test.ts +1 -1
  123. package/artifacts/contracts/staking/aave/AaveStakingFactoryV2.sol/AaveStakingFactoryV2.dbg.json +0 -4
  124. package/artifacts/contracts/staking/aave/AaveStakingFactoryV2.sol/AaveStakingFactoryV2.json +0 -148
  125. package/contracts/staking/aave/AaveStakingFactoryV2.sol +0 -93
  126. package/test/staking/GoodAaveStakingFactoryV2.test.ts +0 -122
  127. package/test/staking/UsdcAaveStakingV2.test.ts +0 -291
@@ -0,0 +1,315 @@
1
+ // SPDX-License-Identifier: MIT
2
+
3
+ pragma solidity >=0.8.0;
4
+ import "../SimpleStakingV2.sol";
5
+ import "../../Interfaces.sol";
6
+ import "../UniswapV2SwapHelper.sol";
7
+
8
+ /**
9
+ * @title Staking contract that donates earned interest to the DAO
10
+ * allowing stakers to deposit Token
11
+ * or withdraw their stake in Token
12
+ * the contracts buy cToken and can transfer the daily interest to the DAO
13
+ */
14
+ contract GoodCompoundStakingV2 is SimpleStakingV2 {
15
+ using UniswapV2SwapHelper for IHasRouter;
16
+
17
+ // Address of the TOKEN/USD oracle from chainlink
18
+ address tokenUsdOracle;
19
+ //Address of the COMP/USD oracle from chianlink
20
+ address compUsdOracle;
21
+
22
+ // Gas cost to collect interest from this staking contract
23
+ uint32 collectInterestGasCost;
24
+ // Gas cost to collect COMP rewards
25
+ uint32 compCollectGasCost;
26
+
27
+ address[] tokenToDaiSwapPath;
28
+
29
+ ERC20 comp;
30
+
31
+ Uniswap uniswapContract;
32
+
33
+ function getSettings()
34
+ external
35
+ view
36
+ returns (uint32 _collectInterestGasCost, uint32 _compCollectGasCost)
37
+ {
38
+ return (collectInterestGasCost, compCollectGasCost);
39
+ }
40
+
41
+ /**
42
+ * @param _token Token to swap DEFI token
43
+ * @param _iToken DEFI token address
44
+ * @param _ns Address of the NameService
45
+ * @param _tokenName Name of the staking token which will be provided to staker for their staking share
46
+ * @param _tokenSymbol Symbol of the staking token which will be provided to staker for their staking share
47
+ * @param _maxRewardThreshold Determines blocks to pass for 1x Multiplier
48
+ * @param _tokenUsdOracle address of the TOKEN/USD oracle
49
+ * @param _compUsdOracle address of the COMP/USD oracle
50
+ * @param _tokenToDaiSwapPath the uniswap path to swap token to DAI, should be empty if token is DAI
51
+ */
52
+ function init(
53
+ address _token,
54
+ address _iToken,
55
+ INameService _ns,
56
+ string memory _tokenName,
57
+ string memory _tokenSymbol,
58
+ uint64 _maxRewardThreshold,
59
+ address _tokenUsdOracle,
60
+ address _compUsdOracle,
61
+ address[] memory _tokenToDaiSwapPath
62
+ ) public {
63
+ initialize(
64
+ _token,
65
+ _iToken,
66
+ _ns,
67
+ _tokenName,
68
+ _tokenSymbol,
69
+ _maxRewardThreshold
70
+ );
71
+
72
+ address dai = nameService.getAddress("DAI");
73
+ require(
74
+ _token == dai ||
75
+ (_tokenToDaiSwapPath[0] == _token &&
76
+ _tokenToDaiSwapPath[_tokenToDaiSwapPath.length - 1] == dai),
77
+ "path"
78
+ );
79
+
80
+ //above initialize going to revert on second call, so this is safe
81
+ compUsdOracle = _compUsdOracle;
82
+ tokenUsdOracle = _tokenUsdOracle;
83
+ tokenToDaiSwapPath = _tokenToDaiSwapPath;
84
+ comp = ERC20(nameService.getAddress("COMP"));
85
+ uniswapContract = Uniswap(nameService.getAddress("UNISWAP_ROUTER"));
86
+ collectInterestGasCost = 250000;
87
+ compCollectGasCost = 150000;
88
+ comp.approve(address(uniswapContract), type(uint256).max);
89
+ token.approve(address(uniswapContract), type(uint256).max);
90
+ token.approve(address(iToken), type(uint256).max); // approve the transfers to defi protocol as much as possible in order to save gas
91
+ }
92
+
93
+ /**
94
+ * @dev stake some Token
95
+ * @param _amount of Token to stake
96
+ */
97
+ function mintInterestToken(uint256 _amount) internal override {
98
+ require(cERC20(address(iToken)).mint(_amount) == 0, "minting");
99
+ }
100
+
101
+ /**
102
+ * @dev redeem Token from compound
103
+ * @param _amount of token to redeem in Token
104
+ */
105
+ function redeem(uint256 _amount) internal override {
106
+ require(cERC20(address(iToken)).redeemUnderlying(_amount) == 0, "redeem");
107
+ }
108
+
109
+ /**
110
+ * @dev Function to redeem cToken + reward COMP for DAI, so reserve knows how to handle it. (reserve can handle dai or cdai)
111
+ * @dev _amount of token in iToken
112
+ * @dev _recipient recipient of the DAI
113
+ * @return actualTokenGains amount of token redeemed for dai,
114
+ actualRewardTokenGains amount of reward token redeemed for dai,
115
+ daiAmount total dai received
116
+ */
117
+ function redeemUnderlyingToDAI(uint256 _amount, address _recipient)
118
+ internal
119
+ override
120
+ returns (
121
+ uint256 actualTokenGains,
122
+ uint256 actualRewardTokenGains,
123
+ uint256 daiAmount
124
+ )
125
+ {
126
+ uint256 compBalance = comp.balanceOf(address(this));
127
+
128
+ uint256 redeemedDAI;
129
+
130
+ if (compBalance > 0) {
131
+ address[] memory compToDaiSwapPath = new address[](3);
132
+ compToDaiSwapPath[0] = address(comp);
133
+ compToDaiSwapPath[1] = uniswapContract.WETH();
134
+ compToDaiSwapPath[2] = nameService.getAddress("DAI");
135
+ actualRewardTokenGains = IHasRouter(this).maxSafeTokenAmount(
136
+ address(comp),
137
+ uniswapContract.WETH(),
138
+ compBalance,
139
+ maxLiquidityPercentageSwap
140
+ );
141
+
142
+ redeemedDAI = IHasRouter(this).swap(
143
+ compToDaiSwapPath,
144
+ actualRewardTokenGains,
145
+ 0,
146
+ _recipient
147
+ );
148
+ }
149
+ //in case of cdai there's no need to swap to DAI, we send cdai to reserve directly
150
+ actualTokenGains = iTokenWorthInToken(_amount);
151
+ if (address(iToken) == nameService.getAddress("CDAI")) {
152
+ require(iToken.transfer(_recipient, _amount), "collect");
153
+ return (
154
+ actualTokenGains,
155
+ actualRewardTokenGains,
156
+ actualTokenGains + redeemedDAI
157
+ ); // If iToken is cDAI then just return cDAI
158
+ }
159
+
160
+ //out of requested interests to withdraw how much is it safe to swap
161
+ uint256 safeAmount = IHasRouter(this).maxSafeTokenAmount(
162
+ address(token),
163
+ tokenToDaiSwapPath[1],
164
+ actualTokenGains,
165
+ maxLiquidityPercentageSwap
166
+ );
167
+
168
+ if (actualTokenGains > safeAmount) {
169
+ actualTokenGains = safeAmount;
170
+ //recalculate how much iToken to redeem
171
+ _amount = tokenWorthIniToken(actualTokenGains);
172
+ }
173
+
174
+ require(cERC20(address(iToken)).redeem(_amount) == 0, "iredeem");
175
+
176
+ actualTokenGains = token.balanceOf(address(this));
177
+
178
+ if (actualTokenGains > 0) {
179
+ redeemedDAI += IHasRouter(this).swap(
180
+ tokenToDaiSwapPath,
181
+ actualTokenGains,
182
+ 0,
183
+ _recipient
184
+ );
185
+ }
186
+
187
+ return (actualTokenGains, actualRewardTokenGains, redeemedDAI);
188
+ }
189
+
190
+ /**
191
+ * @dev returns decimals of token.
192
+ */
193
+ function tokenDecimal() internal view override returns (uint256) {
194
+ return uint256(ERC20(address(token)).decimals());
195
+ }
196
+
197
+ /**
198
+ * @dev returns decimals of interest token.
199
+ */
200
+ function iTokenDecimal() internal view override returns (uint256) {
201
+ return uint256(ERC20(address(iToken)).decimals());
202
+ }
203
+
204
+ /**
205
+ * @dev Function that calculates current interest gains of this staking contract
206
+ * @param _returnTokenBalanceInUSD determine return token balance of staking contract in USD
207
+ * @param _returnTokenGainsInUSD determine return token gains of staking contract in USD
208
+ * @return iTokenGains gains in itoken, tokenGains gains in token, tokenBalance total locked Tokens, balanceInUsd locked tokens worth in USD, tokenGainsInUSD token Gains in USD
209
+ */
210
+ function currentGains(
211
+ bool _returnTokenBalanceInUSD,
212
+ bool _returnTokenGainsInUSD
213
+ )
214
+ public
215
+ view
216
+ override
217
+ returns (
218
+ uint256 iTokenGains,
219
+ uint256 tokenGains,
220
+ uint256 tokenBalance,
221
+ uint256 balanceInUSD,
222
+ uint256 tokenGainsInUSD
223
+ )
224
+ {
225
+ tokenBalance = iTokenWorthInToken(iToken.balanceOf(address(this)));
226
+ balanceInUSD = _returnTokenBalanceInUSD
227
+ ? getTokenValueInUSD(tokenUsdOracle, tokenBalance, token.decimals())
228
+ : 0;
229
+ uint256 compValueInUSD = _returnTokenGainsInUSD
230
+ ? getTokenValueInUSD(
231
+ compUsdOracle,
232
+ comp.balanceOf(address(this)),
233
+ 18 // COMP is in 18 decimal
234
+ )
235
+ : 0;
236
+ if (tokenBalance <= totalProductivity) {
237
+ return (0, 0, tokenBalance, balanceInUSD, compValueInUSD);
238
+ }
239
+
240
+ tokenGains = tokenBalance - totalProductivity;
241
+ tokenGainsInUSD = _returnTokenGainsInUSD
242
+ ? getTokenValueInUSD(tokenUsdOracle, tokenGains, token.decimals()) +
243
+ compValueInUSD
244
+ : 0;
245
+
246
+ iTokenGains = tokenWorthIniToken(tokenGains);
247
+ }
248
+
249
+ /**
250
+ * @dev Function to get interest transfer cost for this particular staking contract
251
+ */
252
+ function getGasCostForInterestTransfer()
253
+ external
254
+ view
255
+ override
256
+ returns (uint32)
257
+ {
258
+ uint256 compBalance = comp.balanceOf(address(this));
259
+ if (compBalance > 0) return collectInterestGasCost + 200000; // need to make more check for this value
260
+
261
+ return collectInterestGasCost;
262
+ }
263
+
264
+ /**
265
+ * @dev Calculates worth of given amount of iToken in Token
266
+ * @param _amount Amount of token to calculate worth in Token
267
+ * @return Worth of given amount of token in Token
268
+ */
269
+ function iTokenWorthInToken(uint256 _amount)
270
+ internal
271
+ view
272
+ override
273
+ returns (uint256)
274
+ {
275
+ uint256 er = cERC20(address(iToken)).exchangeRateStored();
276
+ (uint256 decimalDifference, bool caseType) = tokenDecimalPrecision();
277
+ uint256 mantissa = 18 + tokenDecimal() - iTokenDecimal();
278
+ uint256 tokenWorth = caseType == true
279
+ ? (_amount * (10**decimalDifference) * er) / 10**mantissa
280
+ : ((_amount / (10**decimalDifference)) * er) / 10**mantissa; // calculation based on https://compound.finance/docs#protocol-math
281
+ return tokenWorth;
282
+ }
283
+
284
+ /**
285
+ * @dev Calculates worth of given amount of token in iToken
286
+ * @param _amount Amount of iToken to calculate worth in token
287
+ * @return tokenWorth Worth of given amount of token in iToken
288
+ */
289
+ function tokenWorthIniToken(uint256 _amount)
290
+ public
291
+ view
292
+ returns (uint256 tokenWorth)
293
+ {
294
+ uint256 er = cERC20(address(iToken)).exchangeRateStored();
295
+ (uint256 decimalDifference, bool caseType) = tokenDecimalPrecision();
296
+ uint256 mantissa = 18 + tokenDecimal() - iTokenDecimal();
297
+ tokenWorth = caseType == true
298
+ ? ((_amount / (10**decimalDifference)) * 10**mantissa) / er
299
+ : ((_amount * (10**decimalDifference)) * 10**mantissa) / er; // calculation based on https://compound.finance/docs#protocol-math
300
+ }
301
+
302
+ /**
303
+ * @dev Set Gas cost to interest collection for this contract
304
+ * @param _collectInterestGasCost Gas cost to collect interest
305
+ * @param _rewardTokenCollectCost gas cost to collect reward tokens
306
+ */
307
+ function setcollectInterestGasCostParams(
308
+ uint32 _collectInterestGasCost,
309
+ uint32 _rewardTokenCollectCost
310
+ ) external {
311
+ _onlyAvatar();
312
+ collectInterestGasCost = _collectInterestGasCost;
313
+ compCollectGasCost = _rewardTokenCollectCost;
314
+ }
315
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gooddollar/goodprotocol",
3
- "version": "1.0.10",
3
+ "version": "1.0.13-beta.1",
4
4
  "description": "GoodDollar Protocol",
5
5
  "scripts": {
6
6
  "build": "scripts/build.sh deploy",
@@ -321,62 +321,66 @@
321
321
  },
322
322
  "test": {
323
323
  "ProxyFactory": "0x36dE29DB57062A583436Ae071e141404dFE2311C",
324
- "NameService": "0xAd8C024cE4E90D0bf00eD29f441581F6FDE54C34",
325
- "GReputation": "0x80073051B408D4011221634c7fe464d16Eef4eb5",
326
- "CompoundVotingMachine": "0xFA18ab3DD023DAFB2cEB6cb0507557b26362180E",
327
- "ClaimersDistribution": "0x065A4F59bEE2Eaca8a73Ca4eD84CA0aB288b5BdD",
328
- "GovernanceStaking": "0xcFa693a6B5d8399b771582afF07B5a8f55D75d40",
329
- "UBIScheme": "0x4dd4301DB4461EbD0ac859fFFCc90531EBaC5D75",
330
- "ProtocolUpgradeFuse": "0xAf49e224e71AF966D5367E6c8DED0CF7FcD110d0",
324
+ "NameService": "0x105678e10c32a29543902067fEd1BB2e5E0B3CEe",
325
+ "GReputation": "0xFf73F4DEeFFe4f7E53E20d757b99d82D465c93b9",
326
+ "CompoundVotingMachine": "0x1dfBd51e464E45A9Dfe33B79222D6B3f0bedC1f0",
327
+ "ClaimersDistribution": "0xB3375A6f09CFFF8591577d03133eeaF39cA76a84",
328
+ "GovernanceStaking": "0xFD6F7A6a5c21A3f503EBaE7a473639974379c351",
329
+ "UBIScheme": "0x137dbc6fd877D802c567B74741D9B2526685718A",
330
+ "ProtocolUpgradeFuse": "0x0ed64d01D0B4B655E410EF1441dD677B695639E7",
331
331
  "network": "test",
332
332
  "networkId": 4447,
333
- "HomeBridge": "0xc90C13734D20e27904dF248FB850f50C81CE3642",
334
- "OneTimePayments": "0x4D5D3FaE9b08a4FA2aEB9Bc0d86E3dB3b3126438",
335
- "AdminWallet": "0x65E001B67f1aD28FF337C4F6e1cA52F31F5Eb9Fd",
336
- "Identity": "0x473A31861aB89d5D7a78E7efc57ad31d84ED5343",
337
- "GoodDollar": "0x040F0292f908c83BdEcCAE7600344503F2a20691",
338
- "Controller": "0x75B282FdEaEce36C6E9363F30010058c284D9199",
339
- "Avatar": "0xB3cbA81d4ce278661E26E2107936A014efc31343",
340
- "FirstClaimPool": "0xd3aF095DE5D1419ADabE47a48d6110e37236A97F",
341
- "BancorFormula": "0x0d6e43d4d7944408d9a5A10BC57B4348d61cD764",
342
- "DAI": "0xB3a1e45D60f9394bC4327f5Dc46dB56D8a3c3688",
343
- "cDAI": "0x1f720E7952650ED8Ca142feBD52aCBe8b7A21741",
344
- "COMP": "0xD83C9f1B0DaFb1992eF92ac62D6509e54AD4eD48"
333
+ "HomeBridge": "0xDC11f7E700A4c898AE5CAddB1082cFfa76512aDD",
334
+ "OneTimePayments": "0x86A2EE8FAf9A840F7a2c64CA3d51209F9A02081D",
335
+ "AdminWallet": "0x34B40BA116d5Dec75548a9e9A8f15411461E8c70",
336
+ "Identity": "0x36b58F5C1969B7b6591D752ea6F5486D069010AB",
337
+ "GoodDollar": "0x5971B98C0066517Bae7D44021f42e50B77cfe1F9",
338
+ "Controller": "0xF380bC8b4e595dECa3A55A4C98A6C4fA1c96f537",
339
+ "Avatar": "0x724dbC61127E39A610Be416b455deb800d51A3B2",
340
+ "FirstClaimPool": "0x720472c8ce72c2A2D711333e064ABD3E6BbEAdd3",
341
+ "BancorFormula": "0xD8a5a9b31c3C0232E196d518E89Fd8bF83AcAd43",
342
+ "DAI": "0x4C4a2f8c81640e47606d3fd77B353E87Ba015584",
343
+ "cDAI": "0x2E2Ed0Cfd3AD2f1d34481277b3204d807Ca2F8c2",
344
+ "COMP": "0x21dF544947ba3E8b3c32561399E88B52Dc8b2823"
345
345
  },
346
346
  "test-mainnet": {
347
347
  "ProxyFactory": "0xce17442a9e26bcFDFAb2e9028e3A655d046f1654",
348
- "NameService": "0x55125Ed5fa29594A8DbD7D0fB186888537B9c140",
349
- "GReputation": "0x7235eC3c7b450eE36De0141b205d89D08C5de5fE",
350
- "CompoundVotingMachine": "0xE8A10EA2E8764EB25684A2974913dDAbFefA4494",
351
- "GoodMarketMaker": "0xF4eD16cBD64f07230C5bc9667357cE1D161DF894",
352
- "GoodReserveCDai": "0x1bEA43626e0b6Afe157FBD1398093359261bB53e",
353
- "ExchangeHelper": "0x6fad49b578CbF1d8F21b6dF17ccBB5d409Fb6BC8",
354
- "GoodFundManager": "0x7963849A738719BE64c669c8Ce5613A6331C8caC",
355
- "StakersDistribution": "0x5c73Ed454acB4467C0a35264D7a455C607FcE1bA",
356
- "ProtocolUpgrade": "0x9c15162c1f7f01C64c0e068f2E48D39Cd7b18f86",
357
- "UniswapV2SwapHelper": "0x39683C5c01B4a875FA7d4f5766D2Df521Fc0b4AD",
358
- "CompoundStakingFactory": "0x712e1b726F6149C768fff8572CeA0Bdba23a561B",
359
- "AaveStakingFactory": "0x36c7b0946e701EA6cE8e101B4C959FF15D0DeE15",
348
+ "NameService": "0xE88Cd74511b17f10363b557c2E9632CAab353b39",
349
+ "GReputation": "0x3B7bF1232414Bc52E3C233D0aF8524f259463034",
350
+ "CompoundVotingMachine": "0xA6F88E890518adAB4517f95c74b0aF4370b7e0be",
351
+ "GoodMarketMaker": "0xa3b0167657e47ABa3b541C1b21448B449f2CE3bc",
352
+ "GoodReserveCDai": "0xFE67C7f6d6A9eDA3adE28d8d1bdf1B764491E823",
353
+ "ExchangeHelper": "0x9bDB9d2aD7Aaf2763e49aa518A3b3CC4798210c6",
354
+ "GoodFundManager": "0xfE16B3e38B6eEb8f4eA0C820cB4547ec03edFE0e",
355
+ "StakersDistribution": "0xab06522CFF9ec6302a32b9db057293E80e1BC43a",
356
+ "ProtocolUpgrade": "0x5D42EBdBBa61412295D7b0302d6F50aC449Ddb4F",
357
+ "UniswapV2SwapHelper": "0xddE78e6202518FF4936b5302cC2891ec180E8bFf",
358
+ "CompoundStakingFactory": "0xB06c856C8eaBd1d8321b687E188204C1018BC4E5",
359
+ "AaveStakingFactory": "0xaB7B4c595d3cE8C85e16DA86630f2fc223B05057",
360
360
  "network": "test-mainnet",
361
361
  "networkId": 4447,
362
- "ForeignBridge": "0x9F95c870a4104603630CBEDBbbd56c6465Cc8A58",
363
- "Contribution": "0x770ace66dd84B035F71FfC977448032EE688604d",
362
+ "ForeignBridge": "0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9",
363
+ "Contribution": "0xA51c1fc2f0D1a1b8494Ed1FE312d7C3a78Ed91C0",
364
364
  "StakingContracts": [
365
365
  [
366
- "0xb440419193c65B52e68a819BBe11Bd770Bf93B33",
366
+ "0x8f19E89ed457Ca4a3cb0dF96653d1952F465ca4A",
367
367
  13888
368
+ ],
369
+ [
370
+ "0x810D8eB0BC99Faebc340EcA183e0110Cf0635A89",
371
+ "6944"
368
372
  ]
369
373
  ],
370
- "DonationsStaking": "0x4e21A8F1d5C27C3A99b2781E1aB215f6a75A0122",
371
- "Identity": "0x66a2BECe75FCE45ddFe2C06216CE9350a4c46498",
372
- "GoodDollar": "0x53DE0F59992D932020ad00CF4ABEe89051F8961d",
373
- "Controller": "0x86851c91c15A49Ba4a9Cc9859f2d84C47b7aD91d",
374
- "Avatar": "0xB8FC6cFAb3E190e648aac2d7aB69d466f3674bDB",
375
- "FirstClaimPool": "0x59E0b0C67a8f14BE8C5855C95CdD2ba95a7f2BbB",
376
- "BancorFormula": "0x1aaaD333A7d363a8576779B71BF589580cC9D82E",
377
- "DAI": "0x63766F0efAa46a86E9055bB46e41ff7bc64CBEA2",
378
- "cDAI": "0x24ef01de6baE76eE73Da210940A296F739d87952",
379
- "COMP": "0x3C3297C2Be0F0C51b604dC0A798cF610d7406De2"
374
+ "DonationsStaking": "0x0B92eE05ABeeeEdef0a0e861468A4317d6E2AC93",
375
+ "Identity": "0x0165878A594ca255338adfa4d48449f69242Eb8F",
376
+ "GoodDollar": "0x9bd03768a7DCc129555dE410FF8E85528A4F88b5",
377
+ "Controller": "0x23dB4a08f2272df049a4932a4Cc3A6Dc1002B33E",
378
+ "Avatar": "0x61c36a8d610163660E21a8b7359e1Cac0C9133e1",
379
+ "FirstClaimPool": "0xE6E340D132b5f46d1e472DebcD681B2aBc16e57E",
380
+ "BancorFormula": "0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9",
381
+ "DAI": "0x5FbDB2315678afecb367f032d93F642f64180aa3",
382
+ "cDAI": "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0",
383
+ "COMP": "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512"
380
384
  },
381
385
  "production": {
382
386
  "ProxyFactory": "0x4659176E962763e7C8A4eF965ecfD0fdf9f52057",
@@ -415,8 +419,8 @@
415
419
  "StakersDistribution": "0x12D15EfC3c9661AD68209CD197D416BFd9B145f5",
416
420
  "ProtocolUpgrade": "0xfc918F32D89b7592Fbda5a0FbC7Eaa0c9a0d5d4a",
417
421
  "UniswapV2SwapHelper": "0x62305662fA7c4BC442803b940d9192DbDC92D710",
418
- "CompoundStakingFactory": "0x2C89e77d53C31ED6b331a19207799B3C11Db07eA",
419
- "AaveStakingFactory": "0xc6a6bdAD97248f92096f9D62a2EE413D438B97f4",
422
+ "CompoundStakingFactory": "0x5f6f25143cd580e2e285210d7cfcb26e59cf9566",
423
+ "AaveStakingFactory": "0xa99ba154223052b8c5fd92b3f5df9eb08b72d5fc",
420
424
  "network": "production-mainnet",
421
425
  "networkId": 1,
422
426
  "ForeignBridge": "0xD5D11eE582c8931F336fbcd135e98CEE4DB8CCB0",
@@ -424,10 +428,16 @@
424
428
  "StakingContracts": [
425
429
  [
426
430
  "0xD33bA17C8A644C585089145e86E282fada6F3bfd",
431
+ 310
432
+ ]
433
+ ],
434
+ "StakingContractsV2": [
435
+ [
436
+ "0x02416eb83cff1f19163f21010149c3867f3261e1",
427
437
  13888
428
438
  ],
429
439
  [
430
- "0x3bF213f102928A0E7F07a8c5086322a028D7ee14",
440
+ "0xf4c34bed7dd779485692bb1857acf9c561b45010",
431
441
  6944
432
442
  ]
433
443
  ],
@@ -819,7 +819,9 @@ export const main = async (
819
819
  ]
820
820
  });
821
821
  const tx = await (
822
- await compfactory.cloneAndInit(
822
+ await compfactory[
823
+ "cloneAndInit(address,address,uint64,address,address,address[])"
824
+ ](
823
825
  token.address,
824
826
  release.NameService,
825
827
  protocolSettings.staking.fullRewardsThreshold, //blocks before switching for 0.5x rewards to 1x multiplier
@@ -841,7 +843,7 @@ export const main = async (
841
843
  // Promise.resolve(["0x9999c40c8b88c740076b15d2e708db6a7a071b53", 13888])
842
844
  // ];
843
845
  let deployed;
844
- if (!isRopsten && !isDevelop) {
846
+ if (!isRopsten || isTest) {
845
847
  const aaveps = aaveTokens.map(async token => {
846
848
  let rewardsPerBlock = (protocolSettings.staking.rewardsPerBlock / 2) //aave gets half of the rewards
847
849
  .toFixed(0);
@@ -851,7 +853,9 @@ export const main = async (
851
853
  rewardsPerBlock
852
854
  });
853
855
  const tx = await (
854
- await aavefactory.cloneAndInit(
856
+ await aavefactory[
857
+ "cloneAndInit(address,address,address,uint64,address,address,address,address[])"
858
+ ](
855
859
  token.address,
856
860
  get(protocolSettings, "aave.lendingPool", dao.AaveLendingPool),
857
861
  release.NameService,
@@ -149,7 +149,7 @@ describe("StakersDistribution - staking with GD and get Rewards in GDAO", () =>
149
149
  const router = uniswap.router;
150
150
  await setDAOAddress("UNISWAP_ROUTER", router.address);
151
151
 
152
- let simpleStakingFactory = await getStakingFactory("GoodCompoundStaking");
152
+ let simpleStakingFactory = await getStakingFactory("GoodCompoundStakingV2");
153
153
 
154
154
  simpleUsdcStaking = await simpleStakingFactory
155
155
  .deploy()
@@ -774,4 +774,33 @@ describe("StakersDistribution - staking with GD and get Rewards in GDAO", () =>
774
774
  expect(usdcStakingProductivity[1]).to.be.equal(daiStakingProductivity[1]);
775
775
  expect(usdcStakingRewardsPerBlock).to.be.equal(daiStakingRewardsPerBlock);
776
776
  });
777
+
778
+ it("should be able to transfer staking token when using stakersdistribution", async () => {
779
+ const stakingAmountDai = ethers.utils.parseEther("10000");
780
+ const stakingAmountUsdc = ethers.utils.parseUnits("10000", 6);
781
+ await dai["mint(address,uint256)"](staker.address, stakingAmountDai);
782
+ await dai.connect(staker).approve(simpleStaking.address, stakingAmountDai);
783
+ await usdc["mint(address,uint256)"](staker.address, stakingAmountUsdc);
784
+ await usdc
785
+ .connect(staker)
786
+ .approve(simpleUsdcStaking.address, stakingAmountUsdc);
787
+ await simpleStaking.connect(staker).stake(stakingAmountDai, 0, false);
788
+ await increaseTime(86700 * 30); // Increase one month
789
+ await simpleUsdcStaking.connect(staker).stake(stakingAmountUsdc, 0, false);
790
+ await advanceBlocks(10);
791
+
792
+ await simpleUsdcStaking
793
+ .connect(staker)
794
+ .transfer(signers[1].address, stakingAmountUsdc);
795
+
796
+ expect(await simpleUsdcStaking.balanceOf(signers[1].address)).to.eq(
797
+ stakingAmountUsdc
798
+ );
799
+ expect(await simpleUsdcStaking.balanceOf(staker.address)).to.eq(0);
800
+ // await expect(
801
+ // simpleStaking
802
+ // .connect(staker)
803
+ // .transfer(signers[1].address, ethers.utils.parseEther("10000"))
804
+ // ).to.not.reverted;
805
+ });
777
806
  });
package/test/helpers.ts CHANGED
@@ -23,6 +23,7 @@ export const getStakingFactory = async (
23
23
  | "GoodAaveStaking"
24
24
  | "GoodCompoundStakingTest"
25
25
  | "GoodAaveStakingV2"
26
+ | "GoodCompoundStakingV2"
26
27
  ) => {
27
28
  let swapHelper = await ethers
28
29
  .getContractFactory("UniswapV2SwapHelper")
@@ -4,7 +4,7 @@ import { expect } from "chai";
4
4
  import {
5
5
  CERC20,
6
6
  GoodCompoundStaking,
7
- CompoundStakingFactory,
7
+ CompoundStakingFactory
8
8
  } from "../../types";
9
9
  import { createDAO, deployUniswap } from "../helpers";
10
10
  import { Contract } from "ethers";
@@ -46,33 +46,35 @@ describe("CompoundStakingFactory", () => {
46
46
  await dao.setDAOAddress("UNISWAP_ROUTER", router.address);
47
47
  let swapHelper = await ethers
48
48
  .getContractFactory("UniswapV2SwapHelper")
49
- .then((_) => _.deploy());
49
+ .then(_ => _.deploy());
50
50
 
51
51
  stakingFactory = (await ethers
52
52
  .getContractFactory("CompoundStakingFactory", {
53
- libraries: { UniswapV2SwapHelper: swapHelper.address },
53
+ libraries: { UniswapV2SwapHelper: swapHelper.address }
54
54
  })
55
- .then((_) => _.deploy())) as CompoundStakingFactory;
55
+ .then(_ => _.deploy())) as CompoundStakingFactory;
56
56
  });
57
57
 
58
- it("should create proxy clone", async () => {
59
- const res = await (
60
- await stakingFactory.clone(cdai, ethers.constants.HashZero)
61
- ).wait();
62
- const log = res.events.find((_) => _.event === "Deployed");
63
- const detAddress = await stakingFactory.predictAddress(
64
- cdai,
65
- ethers.constants.HashZero
66
- );
67
- expect(log).to.not.empty;
68
- expect(log.args.proxy).to.equal(detAddress);
69
- expect(log.args.cToken).to.equal(cdai);
70
- });
58
+ // it("should create proxy clone", async () => {
59
+ // const res = await (
60
+ // await stakingFactory.clone(cdai, ethers.constants.HashZero)
61
+ // ).wait();
62
+ // const log = res.events.find(_ => _.event === "Deployed");
63
+ // const detAddress = await stakingFactory.predictAddress(
64
+ // cdai,
65
+ // ethers.constants.HashZero
66
+ // );
67
+ // expect(log).to.not.empty;
68
+ // expect(log.args.proxy).to.equal(detAddress);
69
+ // expect(log.args.cToken).to.equal(cdai);
70
+ // });
71
71
 
72
72
  it("should create and initialize clone", async () => {
73
73
  console.log(await dao.nameService.getAddress("UNISWAP_ROUTER"));
74
74
  const res = await (
75
- await stakingFactory.cloneAndInit(
75
+ await stakingFactory[
76
+ "cloneAndInit(address,address,uint64,address,address,address[])"
77
+ ](
76
78
  cdai,
77
79
  dao.nameService.address,
78
80
  5760,
@@ -81,8 +83,9 @@ describe("CompoundStakingFactory", () => {
81
83
  []
82
84
  )
83
85
  ).wait();
84
- const log = res.events.find((_) => _.event === "Deployed");
86
+ const log = res.events.find(_ => _.event === "Deployed");
85
87
  const detAddress = await stakingFactory.predictAddress(
88
+ await stakingFactory.impl(),
86
89
  cdai,
87
90
  ethers.utils.solidityKeccak256(
88
91
  ["address", "uint64", "address", "address[]"],
@@ -95,12 +98,12 @@ describe("CompoundStakingFactory", () => {
95
98
 
96
99
  //check initialization
97
100
  const staking: GoodCompoundStaking = (await ethers.getContractAt(
98
- "GoodCompoundStaking",
101
+ "GoodCompoundStakingV2",
99
102
  detAddress
100
103
  )) as GoodCompoundStaking;
101
104
  expect(await staking.iToken()).to.equal(cdai);
102
105
  expect(await staking.token()).to.equal(dai);
103
- expect(await staking.name()).to.equal("GoodCompoundStaking Compound DAI");
106
+ expect(await staking.name()).to.equal("GoodCompoundStakingV2 Compound DAI");
104
107
  expect(await staking.symbol()).to.equal("gcDAI");
105
108
  });
106
109
  });
@@ -90,7 +90,9 @@ describe("Different decimals staking token", () => {
90
90
  goodDollar = await ethers.getContractAt("IGoodDollar", gd);
91
91
 
92
92
  tokenUsdOracleFactory = await ethers.getContractFactory("BatUSDMockOracle");
93
- goodCompoundStakingFactory = await getStakingFactory("GoodCompoundStaking");
93
+ goodCompoundStakingFactory = await getStakingFactory(
94
+ "GoodCompoundStakingV2"
95
+ );
94
96
 
95
97
  tokenFactory = await ethers.getContractFactory("DecimalsMock");
96
98
  cTokenFactory = await ethers.getContractFactory("cDecimalsMock");