@gooddollar/goodprotocol 1.0.8 → 1.0.11

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 (123) 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 +4 -0
  66. package/artifacts/contracts/staking/BaseShareFieldV2.sol/BaseShareFieldV2.json +200 -0
  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 +4 -0
  72. package/artifacts/contracts/staking/SimpleStakingV2.sol/SimpleStakingV2.json +958 -0
  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 +4 -0
  79. package/artifacts/contracts/staking/aave/GoodAaveStakingV2.sol/GoodAaveStakingV2.json +1149 -0
  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 +343 -0
  100. package/contracts/staking/SimpleStaking.sol +0 -7
  101. package/contracts/staking/SimpleStakingV2.sol +488 -0
  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 +263 -0
  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 +55 -47
  110. package/scripts/deployFullDAO.ts +1 -1
  111. package/scripts/upgradeToV2/upgradeToV2.ts +7 -3
  112. package/test/governance/StakersDistribution.test.ts +43 -14
  113. package/test/helpers.ts +6 -1
  114. package/test/staking/CompoundStakingFactory.test.ts +24 -21
  115. package/test/staking/DifferentStakingTokens.test.ts +3 -1
  116. package/test/staking/DonationsStaking.test.ts +3 -1
  117. package/test/staking/GoodAaveStakingFactory.test.ts +26 -23
  118. package/test/staking/SimpleDAIStaking.test.ts +3 -11
  119. package/test/staking/StakingRewards.test.ts +20 -14
  120. package/test/staking/SwapHelper.test.ts +4 -1
  121. package/test/staking/UsdcAaveStaking.test.ts +22 -3
  122. package/test/ubi/UBIScheme.e2e.test.ts +1 -1
  123. package/test/utils/ProtocolUpgrade.test.ts +1 -1
@@ -0,0 +1,488 @@
1
+ // SPDX-License-Identifier: MIT
2
+
3
+ pragma solidity >=0.8.0;
4
+
5
+ import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
6
+ import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
7
+ import "../Interfaces.sol";
8
+ import "../DAOStackInterfaces.sol";
9
+ import "../utils/NameService.sol";
10
+ import "../utils/DAOContract.sol";
11
+ import "./GoodFundManager.sol";
12
+ import "./BaseShareFieldV2.sol";
13
+ import "../governance/StakersDistribution.sol";
14
+ import "./UniswapV2SwapHelper.sol";
15
+
16
+ /**
17
+ * @title Staking contract that donates earned interest to the DAO
18
+ * allowing stakers to deposit Tokens
19
+ * or withdraw their stake in Tokens
20
+ * the FundManager can request to receive the interest
21
+ */
22
+ abstract contract SimpleStakingV2 is
23
+ ERC20Upgradeable,
24
+ DAOContract,
25
+ BaseShareFieldV2,
26
+ ReentrancyGuardUpgradeable,
27
+ IHasRouter
28
+ {
29
+ // Token address
30
+ ERC20 public token;
31
+ // Interest Token address
32
+ ERC20 public iToken;
33
+
34
+ // emergency pause
35
+ bool public isPaused;
36
+
37
+ //max percentage of token/dai pool liquidity to swap to DAI when collecting interest out of 100000
38
+ uint24 public maxLiquidityPercentageSwap = 300; //0.3%
39
+
40
+ /**
41
+ * @dev Emitted when `staker` stake `value` tokens of `token`
42
+ */
43
+ event Staked(address indexed staker, address token, uint256 value);
44
+
45
+ /**
46
+ * @dev Emitted when `staker` withdraws their stake `value` tokens and contracts balance will
47
+ * be reduced to`remainingBalance`.
48
+ */
49
+ event StakeWithdraw(address indexed staker, address token, uint256 value);
50
+
51
+ /**
52
+ * @dev Emitted when fundmanager transfers intrest collected from defi protrocol.
53
+ * `recipient` will receive `intrestTokenValue` as intrest.
54
+ */
55
+ event InterestCollected(
56
+ address recipient,
57
+ uint256 iTokenGains, // interest accrued
58
+ uint256 tokenGains, // interest worth in underlying token value
59
+ uint256 actualTokenRedeemed, //actual token redeemed in uniswap (max 0.3% of liquidity) to DAI
60
+ uint256 actualRewardTokenEarned, //actual reward token earned
61
+ uint256 interestCollectedInDAI //actual dai sent to the reserve as interest from converting token and optionally reward token in uniswap
62
+ );
63
+
64
+ /**
65
+ * @dev Constructor
66
+ * @param _token The address of Token
67
+ * @param _iToken The address of Interest Token
68
+ * @param _ns The address of the INameService contract
69
+ * @param _tokenName The name of the staking token
70
+ * @param _tokenSymbol The symbol of the staking token
71
+ * @param _maxRewardThreshold the blocks that should pass to get 1x reward multiplier
72
+
73
+ */
74
+ function initialize(
75
+ address _token,
76
+ address _iToken,
77
+ INameService _ns,
78
+ string memory _tokenName,
79
+ string memory _tokenSymbol,
80
+ uint64 _maxRewardThreshold
81
+ ) public virtual initializer {
82
+ setDAO(_ns);
83
+ token = ERC20(_token);
84
+ iToken = ERC20(_iToken);
85
+ __ERC20_init(_tokenName, _tokenSymbol);
86
+ require(token.decimals() <= 18, "decimals");
87
+ tokenDecimalDifference = 18 - token.decimals();
88
+ maxMultiplierThreshold = _maxRewardThreshold;
89
+ }
90
+
91
+ function setMaxLiquidityPercentageSwap(uint24 _maxPercentage) public virtual {
92
+ _onlyAvatar();
93
+ maxLiquidityPercentageSwap = _maxPercentage;
94
+ }
95
+
96
+ /**
97
+ * @dev Calculates worth of given amount of iToken in Token
98
+ * @param _amount Amount of iToken to calculate worth in Token
99
+ * @return Worth of given amount of iToken in Token
100
+ */
101
+ function iTokenWorthInToken(uint256 _amount)
102
+ internal
103
+ view
104
+ virtual
105
+ returns (uint256);
106
+
107
+ /**
108
+ * @dev Get gas cost for interest transfer so can be used in the calculation of collectable interest for particular gas amount
109
+ * @return returns hardcoded gas cost
110
+ */
111
+ function getGasCostForInterestTransfer()
112
+ external
113
+ view
114
+ virtual
115
+ returns (uint32);
116
+
117
+ /**
118
+ * @dev Returns decimal value for token.
119
+ */
120
+ function tokenDecimal() internal view virtual returns (uint256);
121
+
122
+ /**
123
+ * @dev Returns decimal value for intrest token.
124
+ */
125
+ function iTokenDecimal() internal view virtual returns (uint256);
126
+
127
+ /**
128
+ * @dev Redeem invested tokens from defi protocol.
129
+ * @param _amount tokens to be redeemed.
130
+ */
131
+ function redeem(uint256 _amount) internal virtual;
132
+
133
+ /**
134
+ * @dev Redeem invested underlying tokens from defi protocol and exchange into DAI
135
+ * @param _amount tokens to be redeemed
136
+ * @return amount of token swapped to dai, amount of reward token swapped to dai, total dai
137
+ */
138
+ function redeemUnderlyingToDAI(uint256 _amount, address _recipient)
139
+ internal
140
+ virtual
141
+ returns (
142
+ uint256,
143
+ uint256,
144
+ uint256
145
+ );
146
+
147
+ /**
148
+ * @dev Invests staked tokens to defi protocol.
149
+ * @param _amount tokens staked.
150
+ */
151
+ function mintInterestToken(uint256 _amount) internal virtual;
152
+
153
+ /**
154
+ * @dev Function that calculates current interest gains of this staking contract
155
+ * @param _returnTokenBalanceInUSD determine return token balance of staking contract in USD
156
+ * @param _returnTokenGainsInUSD determine return token gains of staking contract in USD
157
+ * @return return gains in itoken,Token and worth of total locked Tokens,token balance in USD (8 decimals),token Gains in USD (8 decimals)
158
+ */
159
+ function currentGains(
160
+ bool _returnTokenBalanceInUSD,
161
+ bool _returnTokenGainsInUSD
162
+ )
163
+ public
164
+ view
165
+ virtual
166
+ returns (
167
+ uint256,
168
+ uint256,
169
+ uint256,
170
+ uint256,
171
+ uint256
172
+ );
173
+
174
+ /**
175
+ * @dev Allows a staker to deposit Tokens. Notice that `approve` is
176
+ * needed to be executed before the execution of this method.
177
+ * Can be executed only when the contract is not paused.
178
+ * @param _amount The amount of Token or iToken to stake (it depends on _inInterestToken parameter)
179
+ * @param _donationPer The % of interest staker want to donate.
180
+ * @param _inInterestToken specificy if stake in iToken or Token
181
+ */
182
+ function stake(
183
+ uint256 _amount,
184
+ uint256 _donationPer,
185
+ bool _inInterestToken
186
+ ) external virtual nonReentrant {
187
+ require(isPaused == false, "Staking is paused");
188
+ require(_donationPer == 0 || _donationPer == 100, "donationPer");
189
+ require(_amount > 0, "amount");
190
+ require(
191
+ (_inInterestToken ? iToken : token).transferFrom(
192
+ _msgSender(),
193
+ address(this),
194
+ _amount
195
+ ),
196
+ "approve"
197
+ );
198
+ _amount = _inInterestToken ? iTokenWorthInToken(_amount) : _amount;
199
+ if (_inInterestToken == false) {
200
+ mintInterestToken(_amount); //mint iToken
201
+ }
202
+ _mint(_msgSender(), _amount); // mint Staking token for staker
203
+ (
204
+ uint32 rewardsPerBlock,
205
+ uint64 blockStart,
206
+ uint64 blockEnd,
207
+
208
+ ) = GoodFundManager(nameService.getAddress("FUND_MANAGER"))
209
+ .rewardsForStakingContract(address(this));
210
+ _increaseProductivity(
211
+ _msgSender(),
212
+ _amount,
213
+ rewardsPerBlock,
214
+ blockStart,
215
+ blockEnd,
216
+ _donationPer
217
+ );
218
+
219
+ //notify GDAO distrbution for stakers
220
+ StakersDistribution sd = StakersDistribution(
221
+ nameService.getAddress("GDAO_STAKERS")
222
+ );
223
+ if (address(sd) != address(0)) {
224
+ uint256 stakeAmountInEighteenDecimals = token.decimals() == 18
225
+ ? _amount
226
+ : _amount * 10**(18 - token.decimals());
227
+ sd.userStaked(_msgSender(), stakeAmountInEighteenDecimals);
228
+ }
229
+
230
+ emit Staked(_msgSender(), address(token), _amount);
231
+ }
232
+
233
+ /**
234
+ * @dev Withdraws the sender staked Token.
235
+ * @param _amount Amount to withdraw in Token or iToken
236
+ * @param _inInterestToken if true _amount is in iToken and also returned in iToken other wise use Token
237
+ */
238
+ function withdrawStake(uint256 _amount, bool _inInterestToken)
239
+ external
240
+ virtual
241
+ nonReentrant
242
+ {
243
+ uint256 tokenWithdraw;
244
+
245
+ if (_inInterestToken) {
246
+ uint256 tokenWorth = iTokenWorthInToken(_amount);
247
+ require(iToken.transfer(_msgSender(), _amount), "iWithdraw");
248
+ tokenWithdraw = _amount = tokenWorth;
249
+ } else {
250
+ tokenWithdraw = _amount;
251
+ redeem(tokenWithdraw);
252
+
253
+ //this is required for redeem precision loss
254
+ uint256 tokenActual = token.balanceOf(address(this));
255
+ if (tokenActual < tokenWithdraw) {
256
+ tokenWithdraw = tokenActual;
257
+ }
258
+ require(token.transfer(_msgSender(), tokenWithdraw), "withdraw");
259
+ }
260
+
261
+ GoodFundManager fm = GoodFundManager(
262
+ nameService.getAddress("FUND_MANAGER")
263
+ );
264
+
265
+ //this will revert in case user doesnt have enough productivity to withdraw _amount, as productivity=staking tokens amount
266
+ _burn(msg.sender, _amount); // burn their staking tokens
267
+
268
+ (uint32 rewardsPerBlock, uint64 blockStart, uint64 blockEnd, ) = fm
269
+ .rewardsForStakingContract(address(this));
270
+
271
+ _decreaseProductivity(
272
+ _msgSender(),
273
+ _amount,
274
+ rewardsPerBlock,
275
+ blockStart,
276
+ blockEnd
277
+ );
278
+ fm.mintReward(nameService.getAddress("CDAI"), _msgSender()); // send rewards to user and use cDAI address since reserve in cDAI
279
+
280
+ //notify GDAO distrbution for stakers
281
+ StakersDistribution sd = StakersDistribution(
282
+ nameService.getAddress("GDAO_STAKERS")
283
+ );
284
+ if (address(sd) != address(0)) {
285
+ uint256 withdrawAmountInEighteenDecimals = token.decimals() == 18
286
+ ? _amount
287
+ : _amount * 10**(18 - token.decimals());
288
+ sd.userWithdraw(_msgSender(), withdrawAmountInEighteenDecimals);
289
+ }
290
+
291
+ emit StakeWithdraw(msg.sender, address(token), tokenWithdraw);
292
+ }
293
+
294
+ /**
295
+ * @dev withdraw staker G$ rewards + GDAO rewards
296
+ * withdrawing rewards resets the multiplier! so if user just want GDAO he should use claimReputation()
297
+ */
298
+ function withdrawRewards() external nonReentrant {
299
+ GoodFundManager(nameService.getAddress("FUND_MANAGER")).mintReward(
300
+ nameService.getAddress("CDAI"),
301
+ _msgSender()
302
+ ); // send rewards to user and use cDAI address since reserve in cDAI
303
+ claimReputation();
304
+ }
305
+
306
+ /**
307
+ * @dev withdraw staker GDAO rewards
308
+ */
309
+ function claimReputation() public {
310
+ //claim reputation rewards
311
+ StakersDistribution sd = StakersDistribution(
312
+ nameService.getAddress("GDAO_STAKERS")
313
+ );
314
+ if (address(sd) != address(0)) {
315
+ address[] memory contracts = new address[](1);
316
+ contracts[0] = (address(this));
317
+ sd.claimReputation(_msgSender(), contracts);
318
+ }
319
+ }
320
+
321
+ /**
322
+ * @dev notify stakersdistribution when user performs transfer operation
323
+ */
324
+ function _transfer(
325
+ address _from,
326
+ address _to,
327
+ uint256 _value
328
+ ) internal override {
329
+ super._transfer(_from, _to, _value);
330
+ StakersDistribution sd = StakersDistribution(
331
+ nameService.getAddress("GDAO_STAKERS")
332
+ );
333
+ (
334
+ uint32 rewardsPerBlock,
335
+ uint64 blockStart,
336
+ uint64 blockEnd,
337
+
338
+ ) = GoodFundManager(nameService.getAddress("FUND_MANAGER"))
339
+ .rewardsForStakingContract(address(this));
340
+
341
+ _decreaseProductivity(_from, _value, rewardsPerBlock, blockStart, blockEnd);
342
+
343
+ _increaseProductivity(
344
+ _to,
345
+ _value,
346
+ rewardsPerBlock,
347
+ blockStart,
348
+ blockEnd,
349
+ 0
350
+ );
351
+
352
+ if (address(sd) != address(0)) {
353
+ sd.userWithdraw(_from, _value);
354
+ sd.userStaked(_to, _value);
355
+ }
356
+ }
357
+
358
+ // @dev To find difference in token's decimal and iToken's decimal
359
+ // @return difference in decimals.
360
+ // @return true if token's decimal is more than iToken's
361
+ function tokenDecimalPrecision() internal view returns (uint256, bool) {
362
+ uint256 _tokenDecimal = tokenDecimal();
363
+ uint256 _iTokenDecimal = iTokenDecimal();
364
+ uint256 decimalDifference = _tokenDecimal > _iTokenDecimal
365
+ ? _tokenDecimal - _iTokenDecimal
366
+ : _iTokenDecimal - _tokenDecimal;
367
+ return (decimalDifference, _tokenDecimal > _iTokenDecimal);
368
+ }
369
+
370
+ /**
371
+ * @dev Collects gained interest by fundmanager.
372
+ * @param _recipient The recipient of cDAI gains
373
+ * @return actualTokenRedeemed actualRewardTokenRedeemed actualDai collected interest from token,
374
+ * collected interest from reward token, total DAI received from swapping token+reward token
375
+ */
376
+ function collectUBIInterest(address _recipient)
377
+ public
378
+ virtual
379
+ returns (
380
+ uint256 actualTokenRedeemed,
381
+ uint256 actualRewardTokenRedeemed,
382
+ uint256 actualDai
383
+ )
384
+ {
385
+ _canMintRewards();
386
+
387
+ (uint256 iTokenGains, uint256 tokenGains, , , ) = currentGains(
388
+ false,
389
+ false
390
+ );
391
+
392
+ (
393
+ actualTokenRedeemed,
394
+ actualRewardTokenRedeemed,
395
+ actualDai
396
+ ) = redeemUnderlyingToDAI(iTokenGains, _recipient);
397
+
398
+ emit InterestCollected(
399
+ _recipient,
400
+ iTokenGains,
401
+ tokenGains,
402
+ actualTokenRedeemed,
403
+ actualRewardTokenRedeemed,
404
+ actualDai
405
+ );
406
+ }
407
+
408
+ /**
409
+ * @dev making the contract inactive
410
+ * NOTICE: this could theoretically result in future interest earned in cdai to remain locked
411
+ */
412
+ function pause(bool _isPaused) public {
413
+ _onlyAvatar();
414
+ isPaused = _isPaused;
415
+ }
416
+
417
+ /**
418
+ * @dev method to recover any stuck ERC20 tokens (ie compound COMP)
419
+ * @param _token the ERC20 token to recover
420
+ */
421
+ function recover(ERC20 _token) public {
422
+ _onlyAvatar();
423
+ uint256 toWithdraw = _token.balanceOf(address(this));
424
+
425
+ // recover left iToken(stakers token) only when all stakes have been withdrawn
426
+ if (address(_token) == address(iToken)) {
427
+ require(totalProductivity == 0 && isPaused, "recover");
428
+ }
429
+ require(_token.transfer(address(avatar), toWithdraw), "transfer");
430
+ }
431
+
432
+ /**
433
+ @dev function calculate Token price in USD
434
+ @param _oracle chainlink oracle usd/token oralce
435
+ @param _amount Amount of Token to calculate worth of it
436
+ @param _decimals decimals of Token
437
+ @return Returns worth of Tokens in USD
438
+ */
439
+ function getTokenValueInUSD(
440
+ address _oracle,
441
+ uint256 _amount,
442
+ uint256 _decimals
443
+ ) public view returns (uint256) {
444
+ AggregatorV3Interface tokenPriceOracle = AggregatorV3Interface(_oracle);
445
+ int256 tokenPriceinUSD = tokenPriceOracle.latestAnswer();
446
+ return (uint256(tokenPriceinUSD) * _amount) / (10**_decimals); // tokenPriceinUSD in 8 decimals and _amount is in Token's decimals so we divide it to Token's decimal at the end to reduce 8 decimals back
447
+ }
448
+
449
+ function _canMintRewards() internal view override {
450
+ require(_msgSender() == nameService.getAddress("FUND_MANAGER"), "fund");
451
+ }
452
+
453
+ function decimals() public view virtual override returns (uint8) {
454
+ return token.decimals();
455
+ }
456
+
457
+ /**
458
+ * @param _staker account to get rewards status for
459
+ * @return (minted, pending) in G$ 2 decimals
460
+ */
461
+ function getUserMintedAndPending(address _staker)
462
+ external
463
+ view
464
+ returns (uint256, uint256)
465
+ {
466
+ (
467
+ uint32 rewardsPerBlock,
468
+ uint64 blockStart,
469
+ uint64 blockEnd,
470
+
471
+ ) = GoodFundManager(nameService.getAddress("FUND_MANAGER"))
472
+ .rewardsForStakingContract(address(this));
473
+
474
+ uint256 pending = getUserPendingReward(
475
+ _staker,
476
+ rewardsPerBlock,
477
+ blockStart,
478
+ blockEnd
479
+ );
480
+
481
+ //divide by 1e16 to return in 2 decimals
482
+ return (users[_staker].rewardMinted / 1e16, pending / 1e16);
483
+ }
484
+
485
+ function getRouter() public view override returns (Uniswap) {
486
+ return Uniswap(nameService.getAddress("UNISWAP_ROUTER"));
487
+ }
488
+ }
@@ -2,7 +2,7 @@
2
2
 
3
3
  pragma solidity >=0.8.0;
4
4
  import "@openzeppelin/contracts-upgradeable/proxy/ClonesUpgradeable.sol";
5
- import "./GoodAaveStaking.sol";
5
+ import "./GoodAaveStakingV2.sol";
6
6
  import "../../Interfaces.sol";
7
7
 
8
8
  /**
@@ -14,19 +14,43 @@ import "../../Interfaces.sol";
14
14
  contract AaveStakingFactory {
15
15
  using ClonesUpgradeable for address;
16
16
 
17
- address impl = address(new GoodAaveStaking());
17
+ address public impl = address(new GoodAaveStakingV2());
18
18
 
19
- event Deployed(address proxy, address token);
19
+ event Deployed(address proxy, address token, address impl);
20
20
 
21
- function clone(ERC20 token, bytes32 paramsHash)
22
- public
23
- returns (GoodAaveStaking)
24
- {
25
- address deployed = address(impl).cloneDeterministic(
21
+ function clone(
22
+ address _impl,
23
+ ERC20 token,
24
+ bytes32 paramsHash
25
+ ) internal returns (GoodAaveStakingV2) {
26
+ address deployed = address(_impl).cloneDeterministic(
26
27
  keccak256(abi.encodePacked(address(token), paramsHash))
27
28
  );
28
- emit Deployed(deployed, address(token));
29
- return GoodAaveStaking(deployed);
29
+ emit Deployed(deployed, address(token), _impl);
30
+ return GoodAaveStakingV2(deployed);
31
+ }
32
+
33
+ function cloneAndInit(
34
+ ERC20 token,
35
+ address _lendingPool,
36
+ INameService _ns,
37
+ uint64 _maxRewardThreshold,
38
+ address _tokenUsdOracle,
39
+ IAaveIncentivesController _incentiveController,
40
+ address _aaveUSDOracle,
41
+ address[] memory _tokenToDaiSwapPath
42
+ ) public {
43
+ cloneAndInit(
44
+ impl,
45
+ token,
46
+ _lendingPool,
47
+ _ns,
48
+ _maxRewardThreshold,
49
+ _tokenUsdOracle,
50
+ _incentiveController,
51
+ _aaveUSDOracle,
52
+ _tokenToDaiSwapPath
53
+ );
30
54
  }
31
55
 
32
56
  /**
@@ -40,6 +64,7 @@ contract AaveStakingFactory {
40
64
  @param _aaveUSDOracle address of the AAVE/USD oracle
41
65
  */
42
66
  function cloneAndInit(
67
+ address _impl,
43
68
  ERC20 token,
44
69
  address _lendingPool,
45
70
  INameService _ns,
@@ -49,7 +74,8 @@ contract AaveStakingFactory {
49
74
  address _aaveUSDOracle,
50
75
  address[] memory _tokenToDaiSwapPath
51
76
  ) public {
52
- GoodAaveStaking deployed = clone(
77
+ GoodAaveStakingV2 deployed = clone(
78
+ _impl,
53
79
  token,
54
80
  keccak256(
55
81
  abi.encodePacked(
@@ -67,8 +93,8 @@ contract AaveStakingFactory {
67
93
  address(token),
68
94
  address(_lendingPool),
69
95
  _ns,
70
- string(abi.encodePacked("GoodAaveStaking ", token.name())),
71
- string(abi.encodePacked("g", token.symbol())),
96
+ string(abi.encodePacked("GoodAaveStakingV2 ", token.name())),
97
+ string(abi.encodePacked("ga", token.symbol())),
72
98
  _maxRewardThreshold,
73
99
  _tokenUsdOracle,
74
100
  _incentiveController,
@@ -77,13 +103,13 @@ contract AaveStakingFactory {
77
103
  );
78
104
  }
79
105
 
80
- function predictAddress(ERC20 token, bytes32 paramsHash)
81
- public
82
- view
83
- returns (address)
84
- {
106
+ function predictAddress(
107
+ address _impl,
108
+ ERC20 token,
109
+ bytes32 paramsHash
110
+ ) public view returns (address) {
85
111
  return
86
- address(impl).predictDeterministicAddress(
112
+ address(_impl).predictDeterministicAddress(
87
113
  keccak256(abi.encodePacked(address(token), paramsHash))
88
114
  );
89
115
  }
@@ -262,7 +262,7 @@ contract GoodAaveStaking is SimpleStaking {
262
262
  return _amount; // since aToken is peg to Token 1:1 return exact amount
263
263
  }
264
264
 
265
- function _approveTokens() internal override {
265
+ function _approveTokens() internal {
266
266
  address uniswapRouter = nameService.getAddress("UNISWAP_ROUTER");
267
267
  token.approve(uniswapRouter, type(uint256).max);
268
268
  token.approve(address(lendingPool), type(uint256).max); // approve the transfers to defi protocol as much as possible in order to save gas