@gooddollar/goodprotocol 1.0.23 → 1.0.26-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/artifacts/abis/FuseFaucet.min.json +1 -0
  2. package/artifacts/abis/FuseStakingV3.min.json +1 -0
  3. package/artifacts/abis/IConsensus.min.json +1 -0
  4. package/artifacts/abis/InvitesV1.min.json +1 -0
  5. package/artifacts/abis/PegSwap.min.json +1 -0
  6. package/artifacts/contracts/DAOStackInterfaces.sol/Avatar.dbg.json +1 -1
  7. package/artifacts/contracts/DAOStackInterfaces.sol/Controller.dbg.json +1 -1
  8. package/artifacts/contracts/DAOStackInterfaces.sol/GlobalConstraintInterface.dbg.json +1 -1
  9. package/artifacts/contracts/DAOStackInterfaces.sol/IntVoteInterface.dbg.json +1 -1
  10. package/artifacts/contracts/DAOStackInterfaces.sol/ReputationInterface.dbg.json +1 -1
  11. package/artifacts/contracts/DAOStackInterfaces.sol/SchemeRegistrar.dbg.json +1 -1
  12. package/artifacts/contracts/Interfaces.sol/AggregatorV3Interface.dbg.json +1 -1
  13. package/artifacts/contracts/Interfaces.sol/ERC20.dbg.json +1 -1
  14. package/artifacts/contracts/Interfaces.sol/IAaveIncentivesController.dbg.json +1 -1
  15. package/artifacts/contracts/Interfaces.sol/IAdminWallet.dbg.json +1 -1
  16. package/artifacts/contracts/Interfaces.sol/IDonationStaking.dbg.json +1 -1
  17. package/artifacts/contracts/Interfaces.sol/IERC2917.dbg.json +1 -1
  18. package/artifacts/contracts/Interfaces.sol/IFirstClaimPool.dbg.json +1 -1
  19. package/artifacts/contracts/Interfaces.sol/IGoodDollar.dbg.json +1 -1
  20. package/artifacts/contracts/Interfaces.sol/IGoodStaking.dbg.json +1 -1
  21. package/artifacts/contracts/Interfaces.sol/IHasRouter.dbg.json +1 -1
  22. package/artifacts/contracts/Interfaces.sol/IIdentity.dbg.json +1 -1
  23. package/artifacts/contracts/Interfaces.sol/ILendingPool.dbg.json +1 -1
  24. package/artifacts/contracts/Interfaces.sol/INameService.dbg.json +1 -1
  25. package/artifacts/contracts/Interfaces.sol/IUBIScheme.dbg.json +1 -1
  26. package/artifacts/contracts/Interfaces.sol/ProxyAdmin.dbg.json +1 -1
  27. package/artifacts/contracts/Interfaces.sol/Reserve.dbg.json +1 -1
  28. package/artifacts/contracts/Interfaces.sol/Staking.dbg.json +1 -1
  29. package/artifacts/contracts/Interfaces.sol/Uniswap.dbg.json +1 -1
  30. package/artifacts/contracts/Interfaces.sol/UniswapFactory.dbg.json +1 -1
  31. package/artifacts/contracts/Interfaces.sol/UniswapPair.dbg.json +1 -1
  32. package/artifacts/contracts/Interfaces.sol/cERC20.dbg.json +1 -1
  33. package/artifacts/contracts/fuseFaucet/FuseFaucet.sol/FuseFaucet.dbg.json +4 -0
  34. package/artifacts/contracts/fuseFaucet/FuseFaucet.sol/FuseFaucet.json +325 -0
  35. package/artifacts/contracts/governance/ClaimersDistribution.sol/ClaimersDistribution.dbg.json +1 -1
  36. package/artifacts/contracts/governance/CompoundVotingMachine.sol/CompoundVotingMachine.dbg.json +1 -1
  37. package/artifacts/contracts/governance/GReputation.sol/GReputation.dbg.json +1 -1
  38. package/artifacts/contracts/governance/GovernanceStaking.sol/GovernanceStaking.dbg.json +1 -1
  39. package/artifacts/contracts/governance/MultiBaseGovernanceShareField.sol/MultiBaseGovernanceShareField.dbg.json +1 -1
  40. package/artifacts/contracts/governance/Reputation.sol/Reputation.dbg.json +1 -1
  41. package/artifacts/contracts/governance/StakersDistribution.sol/StakersDistribution.dbg.json +1 -1
  42. package/artifacts/contracts/invite/InvitesV1.sol/InvitesV1.dbg.json +4 -0
  43. package/artifacts/contracts/invite/InvitesV1.sol/InvitesV1.json +492 -0
  44. package/artifacts/contracts/mocks/AaveMock.sol/AaveMock.dbg.json +1 -1
  45. package/artifacts/contracts/mocks/DAIMock.sol/DAIMock.dbg.json +1 -1
  46. package/artifacts/contracts/mocks/DecimalsMock.sol/DecimalsMock.dbg.json +1 -1
  47. package/artifacts/contracts/mocks/GoodCompoundStakingTest.sol/GoodCompoundStakingTest.dbg.json +1 -1
  48. package/artifacts/contracts/mocks/GoodFundManagerTest.sol/GoodFundManagerTest.dbg.json +1 -1
  49. package/artifacts/contracts/mocks/IncentiveControllerMock.sol/IncentiveControllerMock.dbg.json +1 -1
  50. package/artifacts/contracts/mocks/LendingPoolMock.sol/LendingPoolMock.dbg.json +1 -1
  51. package/artifacts/contracts/mocks/OverMintTester.sol/OverMintTester.dbg.json +1 -1
  52. package/artifacts/contracts/mocks/OverMintTesterRegularStake.sol/OverMintTesterRegularStake.dbg.json +1 -1
  53. package/artifacts/contracts/mocks/SixteenDecimalsTokenMock.sol/SixteenDecimalsTokenMock.dbg.json +1 -1
  54. package/artifacts/contracts/mocks/SwapHelperTest.sol/SwapHelperTest.dbg.json +1 -1
  55. package/artifacts/contracts/mocks/TwentyDecimalsTokenMock.sol/TwentyDecimalsTokenMock.dbg.json +1 -1
  56. package/artifacts/contracts/mocks/UpgradableMocks.sol/UpgradableMock.dbg.json +1 -1
  57. package/artifacts/contracts/mocks/UpgradableMocks.sol/UpgradableMock2.dbg.json +1 -1
  58. package/artifacts/contracts/mocks/UpgradableMocks.sol/UpgradableMock3.dbg.json +1 -1
  59. package/artifacts/contracts/mocks/UpgradableMocks.sol/UpgradableMock4.dbg.json +1 -1
  60. package/artifacts/contracts/mocks/UsdcMock.sol/USDCMock.dbg.json +1 -1
  61. package/artifacts/contracts/mocks/cBATMock.sol/cBATMock.dbg.json +1 -1
  62. package/artifacts/contracts/mocks/cDAILowWorthMock.sol/cDAILowWorthMock.dbg.json +1 -1
  63. package/artifacts/contracts/mocks/cDAIMock.sol/cDAIMock.dbg.json +1 -1
  64. package/artifacts/contracts/mocks/cDAINonMintableMock.sol/cDAINonMintableMock.dbg.json +1 -1
  65. package/artifacts/contracts/mocks/cDecimalsMock.sol/cDecimalsMock.dbg.json +1 -1
  66. package/artifacts/contracts/mocks/cSDTMock.sol/cSDTMock.dbg.json +1 -1
  67. package/artifacts/contracts/mocks/cUSDCMock.sol/cUSDCMock.dbg.json +1 -1
  68. package/artifacts/contracts/reserve/ExchangeHelper.sol/ExchangeHelper.dbg.json +1 -1
  69. package/artifacts/contracts/reserve/GoodMarketMaker.sol/GoodMarketMaker.dbg.json +1 -1
  70. package/artifacts/contracts/reserve/GoodReserveCDai.sol/ContributionCalc.dbg.json +1 -1
  71. package/artifacts/contracts/reserve/GoodReserveCDai.sol/GoodReserveCDai.dbg.json +1 -1
  72. package/artifacts/contracts/staking/BaseShareField.sol/BaseShareField.dbg.json +1 -1
  73. package/artifacts/contracts/staking/BaseShareFieldV2.sol/BaseShareFieldV2.dbg.json +1 -1
  74. package/artifacts/contracts/staking/DonationsStaking.sol/DonationsStaking.dbg.json +1 -1
  75. package/artifacts/contracts/staking/FuseStakingV3.sol/FuseStakingV3.dbg.json +4 -0
  76. package/artifacts/contracts/staking/FuseStakingV3.sol/FuseStakingV3.json +733 -0
  77. package/artifacts/contracts/staking/FuseStakingV3.sol/IConsensus.dbg.json +4 -0
  78. package/artifacts/contracts/staking/FuseStakingV3.sol/IConsensus.json +104 -0
  79. package/artifacts/contracts/staking/FuseStakingV3.sol/PegSwap.dbg.json +4 -0
  80. package/artifacts/contracts/staking/FuseStakingV3.sol/PegSwap.json +34 -0
  81. package/artifacts/contracts/staking/GoodFundManager.sol/GoodFundManager.dbg.json +1 -1
  82. package/artifacts/contracts/staking/SimpleStaking.sol/SimpleStaking.dbg.json +1 -1
  83. package/artifacts/contracts/staking/SimpleStakingV2.sol/SimpleStakingV2.dbg.json +1 -1
  84. package/artifacts/contracts/staking/UniswapV2SwapHelper.sol/UniswapV2SwapHelper.dbg.json +1 -1
  85. package/artifacts/contracts/staking/aave/AaveStakingFactory.sol/AaveStakingFactory.dbg.json +1 -1
  86. package/artifacts/contracts/staking/aave/GoodAaveStaking.sol/GoodAaveStaking.dbg.json +1 -1
  87. package/artifacts/contracts/staking/aave/GoodAaveStakingV2.sol/GoodAaveStakingV2.dbg.json +1 -1
  88. package/artifacts/contracts/staking/compound/CompoundStakingFactory.sol/CompoundStakingFactory.dbg.json +1 -1
  89. package/artifacts/contracts/staking/compound/GoodCompoundStaking.sol/GoodCompoundStaking.dbg.json +1 -1
  90. package/artifacts/contracts/staking/compound/GoodCompoundStakingV2.sol/GoodCompoundStakingV2.dbg.json +1 -1
  91. package/artifacts/contracts/ubi/UBIScheme.sol/UBIScheme.dbg.json +1 -1
  92. package/artifacts/contracts/utils/BancorFormula.sol/BancorFormula.dbg.json +1 -1
  93. package/artifacts/contracts/utils/BulkProof.sol/BulkProof.dbg.json +1 -1
  94. package/artifacts/contracts/utils/DAOContract.sol/DAOContract.dbg.json +1 -1
  95. package/artifacts/contracts/utils/DAOUpgradeableContract.sol/DAOUpgradeableContract.dbg.json +1 -1
  96. package/artifacts/contracts/utils/DSMath.sol/DSMath.dbg.json +1 -1
  97. package/artifacts/contracts/utils/DataTypes.sol/DataTypes.dbg.json +1 -1
  98. package/artifacts/contracts/utils/NameService.sol/NameService.dbg.json +1 -1
  99. package/artifacts/contracts/utils/ProtocolUpgrade.sol/OldMarketMaker.dbg.json +1 -1
  100. package/artifacts/contracts/utils/ProtocolUpgrade.sol/ProtocolUpgrade.dbg.json +1 -1
  101. package/artifacts/contracts/utils/ProtocolUpgradeFuse.sol/ProtocolUpgradeFuse.dbg.json +1 -1
  102. package/artifacts/contracts/utils/ProtocolUpgradeFuseRecover.sol/ProtocolUpgradeFuseRecover.dbg.json +1 -1
  103. package/artifacts/contracts/utils/ProtocolUpgradeRecover.sol/ProtocolUpgradeRecover.dbg.json +1 -1
  104. package/artifacts/contracts/utils/ReputationTestHelper.sol/ReputationTestHelper.dbg.json +1 -1
  105. package/contracts/fuseFaucet/FuseFaucet.sol +172 -0
  106. package/contracts/invite/InvitesV1.sol +316 -0
  107. package/contracts/staking/FuseStakingV3.sol +641 -0
  108. package/hardhat.config.ts +7 -0
  109. package/package.json +7 -6
  110. package/patches/@nomiclabs+hardhat-etherscan+3.0.3.patch +41 -0
  111. package/patches/@openzeppelin+hardhat-upgrades+1.7.0.patch +67 -0
  112. package/patches/@openzeppelin+upgrades-core+1.4.2.patch +21 -0
  113. package/scripts/misc/faucetStats.ts +103 -0
  114. package/scripts/upgradeToV2/upgradeToV2.ts +22 -7
  115. package/test/FuseFaucet.test.ts +168 -0
  116. package/test/InvitesV1.test.ts +354 -0
  117. package/test/staking/FuseStaking.test.ts +152 -0
  118. package/types/FuseFaucet.ts +498 -0
  119. package/types/FuseStakingV3.ts +1234 -0
  120. package/types/IConsensus.ts +225 -0
  121. package/types/InvitesV1.ts +797 -0
  122. package/types/OwnableUpgradeable.ts +166 -0
  123. package/types/PegSwap.ts +112 -0
  124. package/types/factories/FuseFaucet__factory.ts +373 -0
  125. package/types/factories/FuseStakingV3__factory.ts +781 -0
  126. package/types/factories/IConsensus__factory.ts +116 -0
  127. package/types/factories/InvitesV1__factory.ts +540 -0
  128. package/types/factories/OwnableUpgradeable__factory.ts +78 -0
  129. package/types/factories/PegSwap__factory.ts +46 -0
  130. package/types/hardhat.d.ts +54 -0
  131. package/types/index.ts +12 -0
@@ -0,0 +1,641 @@
1
+ // SPDX-License-Identifier: MIT
2
+
3
+ pragma solidity >=0.8;
4
+ import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
5
+ import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
6
+ import "@openzeppelin/contracts-upgradeable/utils/math/SafeMathUpgradeable.sol";
7
+
8
+ import "../Interfaces.sol";
9
+ import "../ubi/UBIScheme.sol";
10
+
11
+ // import "hardhat/console.sol";
12
+
13
+ interface IConsensus {
14
+ /**
15
+ * @dev delegate to a validator
16
+ * @param _validator the address of the validator msg.sender is delegating to
17
+ */
18
+ function delegate(address _validator) external payable;
19
+
20
+ /**
21
+ * @dev Function to be called when a delegator whishes to withdraw some of his staked funds for a validator
22
+ * @param _validator the address of the validator msg.sender has delegating to
23
+ * @param _amount the amount msg.sender wishes to withdraw from the contract
24
+ */
25
+ function withdraw(address _validator, uint256 _amount) external;
26
+
27
+ function delegatedAmount(address _address, address _validator)
28
+ external
29
+ view
30
+ returns (uint256);
31
+
32
+ function stakeAmount(address _address) external view returns (uint256);
33
+
34
+ function delegators(address _validator)
35
+ external
36
+ view
37
+ returns (address[] memory);
38
+ }
39
+
40
+ interface PegSwap {
41
+ /**
42
+ * @notice exchanges the source token for target token
43
+ * @param sourceAmount count of tokens being swapped
44
+ * @param source the token that is being given
45
+ * @param target the token that is being taken
46
+ */
47
+ function swap(
48
+ uint256 sourceAmount,
49
+ address source,
50
+ address target
51
+ ) external;
52
+ }
53
+
54
+ contract FuseStakingV3 is Initializable, OwnableUpgradeable {
55
+ using SafeMathUpgradeable for uint256;
56
+
57
+ mapping(address => uint256) public stakers;
58
+ address[] public validators;
59
+
60
+ IConsensus public consensus;
61
+
62
+ Uniswap public uniswap;
63
+ IGoodDollar public GD;
64
+ UBIScheme public ubischeme;
65
+ UniswapFactory public uniswapFactory;
66
+ UniswapPair public uniswapPair;
67
+
68
+ uint256 public lastDayCollected; //ubi day from ubischeme
69
+
70
+ uint256 public stakeBackRatio;
71
+ uint256 public maxSlippageRatio; //actually its max price impact ratio
72
+ uint256 public keeperFeeRatio;
73
+ uint256 public RATIO_BASE;
74
+ uint256 public communityPoolRatio; //out of G$ bought how much should goto pool
75
+
76
+ uint256 public communityPoolBalance;
77
+ uint256 public pendingFuseEarnings; //earnings not used because of slippage
78
+
79
+ address public USDC;
80
+ address public fUSD;
81
+
82
+ bool public paused;
83
+ address public guardian;
84
+
85
+ PegSwap pegSwap;
86
+
87
+ event UBICollected(
88
+ uint256 indexed currentDay,
89
+ uint256 ubi, //G$ sent to ubischeme
90
+ uint256 communityPool, //G$ added to pool
91
+ uint256 gdBought, //actual G$ we got out of swapping stakingRewards + pendingFuseEarnings
92
+ uint256 stakingRewards, //rewards earned since previous collection,
93
+ uint256 pendingFuseEarnings, //new balance of fuse pending to be swapped for G$
94
+ address keeper,
95
+ uint256 keeperGDFee
96
+ );
97
+
98
+ /**
99
+ * @dev initialize
100
+ */
101
+ function initialize() public initializer {
102
+ __Ownable_init_unchained();
103
+ consensus = IConsensus(
104
+ address(0x3014ca10b91cb3D0AD85fEf7A3Cb95BCAc9c0f79)
105
+ );
106
+ validators.push(address(0xcb876A393F05a6677a8a029f1C6D7603B416C0A6));
107
+ }
108
+
109
+ modifier notPaused() {
110
+ require(paused == false, "ubi collection is pauased");
111
+ _;
112
+ }
113
+
114
+ modifier onlyGuardian() {
115
+ require(msg.sender == guardian, "not guardian");
116
+ _;
117
+ }
118
+
119
+ function upgrade0() external {
120
+ if (RATIO_BASE == 0) {
121
+ stakeBackRatio = 33333; //%33
122
+ communityPoolRatio = 33333; //%33
123
+ maxSlippageRatio = 3000; //3%
124
+ keeperFeeRatio = 30; //0.03%
125
+ RATIO_BASE = 100000; //100%
126
+ }
127
+ }
128
+
129
+ function upgrade1(
130
+ address _gd,
131
+ address _ubischeme,
132
+ address _uniswap
133
+ ) external {
134
+ if (address(uniswapPair) == address(0)) {
135
+ uniswap = Uniswap(
136
+ _uniswap == address(0)
137
+ ? 0xFB76e9E7d88E308aB530330eD90e84a952570319
138
+ : _uniswap
139
+ );
140
+ GD = IGoodDollar(_gd);
141
+ ubischeme = UBIScheme(_ubischeme);
142
+
143
+ uniswapFactory = UniswapFactory(uniswap.factory());
144
+ uniswapPair = UniswapPair(
145
+ uniswapFactory.getPair(uniswap.WETH(), _gd)
146
+ );
147
+ }
148
+ }
149
+
150
+ function upgrade2() external {
151
+ if (USDC == address(0)) {
152
+ USDC = address(0x620fd5fa44BE6af63715Ef4E65DDFA0387aD13F5);
153
+ fUSD = address(0x249BE57637D8B013Ad64785404b24aeBaE9B098B);
154
+ }
155
+ }
156
+
157
+ function upgrade3() external {
158
+ if (guardian == address(0)) {
159
+ paused = true;
160
+ guardian = address(0x5128E3C1f8846724cc1007Af9b4189713922E4BB);
161
+ }
162
+ }
163
+
164
+ function upgrade4() external {
165
+ if (address(pegSwap) == address(0)) {
166
+ pegSwap = PegSwap(0xdfE016328E7BcD6FA06614fE3AF3877E931F7e0a);
167
+ paused = false;
168
+ }
169
+ }
170
+
171
+ function upgrade5() external {
172
+ cERC20(fUSD).approve(address(pegSwap), type(uint256).max);
173
+ cERC20(USDC).approve(address(uniswap), type(uint256).max);
174
+ }
175
+
176
+ function upgrade6() external {
177
+ //switch to voltage
178
+ uniswap = Uniswap(0xE3F85aAd0c8DD7337427B9dF5d0fB741d65EEEB5);
179
+ uniswapFactory = UniswapFactory(uniswap.factory());
180
+ uniswapPair = UniswapPair(
181
+ uniswapFactory.getPair(uniswap.WETH(), address(GD))
182
+ );
183
+ }
184
+
185
+ function setContracts(address _gd, address _ubischeme) public onlyOwner {
186
+ if (_gd != address(0)) {
187
+ GD = IGoodDollar(_gd);
188
+ }
189
+ if (_ubischeme != address(0)) {
190
+ ubischeme = UBIScheme(_ubischeme);
191
+ }
192
+ }
193
+
194
+ function stake() public payable returns (bool) {
195
+ return stake(address(0));
196
+ }
197
+
198
+ function stake(address _validator)
199
+ public
200
+ payable
201
+ onlyGuardian
202
+ returns (bool)
203
+ {
204
+ require(msg.value > 0, "stake must be > 0");
205
+ require(validators.length > 0, "no approved validators");
206
+ bool found;
207
+ for (
208
+ uint256 i = 0;
209
+ _validator != address(0) && i < validators.length;
210
+ i++
211
+ ) {
212
+ if (validators[i] != _validator) {
213
+ found = true;
214
+ break;
215
+ }
216
+ }
217
+ require(
218
+ _validator == address(0) || found,
219
+ "validator not in approved list"
220
+ );
221
+
222
+ bool staked = stakeNextValidator(msg.value, _validator);
223
+ stakers[msg.sender] += msg.value;
224
+ return staked;
225
+ }
226
+
227
+ function balanceOf(address _owner) public view returns (uint256) {
228
+ return stakers[_owner];
229
+ }
230
+
231
+ function withdrawAll() public onlyGuardian {
232
+ for (uint256 i = 0; i < validators.length; i++) {
233
+ uint256 cur = consensus.delegatedAmount(
234
+ address(this),
235
+ validators[i]
236
+ );
237
+ if (cur == 0) continue;
238
+ undelegateWithCatch(validators[i], cur);
239
+ }
240
+ uint256 effectiveBalance = balance(); //use only undelegated funds
241
+ pendingFuseEarnings = 0;
242
+ if (effectiveBalance > 0) {
243
+ msg.sender.call{ value: effectiveBalance }("");
244
+ }
245
+ }
246
+
247
+ function withdraw(uint256 _value) public returns (uint256) {
248
+ uint256 effectiveBalance = balance(); //use only undelegated funds
249
+ uint256 toWithdraw = _value == 0 ? stakers[msg.sender] : _value;
250
+ uint256 toCollect = toWithdraw;
251
+ require(
252
+ toWithdraw > 0 && toWithdraw <= stakers[msg.sender],
253
+ "invalid withdraw amount"
254
+ );
255
+ uint256 perValidator = _value.div(validators.length);
256
+ for (uint256 i = 0; i < validators.length; i++) {
257
+ uint256 cur = consensus.delegatedAmount(
258
+ address(this),
259
+ validators[i]
260
+ );
261
+ if (cur == 0) continue;
262
+ if (cur <= perValidator) {
263
+ undelegateWithCatch(validators[i], cur);
264
+ toCollect = toCollect.sub(cur);
265
+ } else {
266
+ undelegateWithCatch(validators[i], perValidator);
267
+ toCollect = toCollect.sub(perValidator);
268
+ }
269
+ if (toCollect == 0) break;
270
+ }
271
+
272
+ effectiveBalance = balance().sub(effectiveBalance); //use only undelegated funds
273
+
274
+ // in case some funds where not withdrawn
275
+ if (toWithdraw > effectiveBalance) {
276
+ toWithdraw = effectiveBalance;
277
+ }
278
+
279
+ stakers[msg.sender] = stakers[msg.sender].sub(toWithdraw);
280
+ if (toWithdraw > 0) {
281
+ msg.sender.call{ value: toWithdraw }("");
282
+ }
283
+ return toWithdraw;
284
+ }
285
+
286
+ function stakeNextValidator(uint256 _value, address _validator)
287
+ internal
288
+ returns (bool)
289
+ {
290
+ if (validators.length == 0) return false;
291
+ if (_validator != address(0)) {
292
+ consensus.delegate{ value: _value }(_validator);
293
+ return true;
294
+ }
295
+
296
+ uint256 perValidator = (totalDelegated() + _value) / validators.length;
297
+ uint256 left = _value;
298
+ for (uint256 i = 0; i < validators.length && left > 0; i++) {
299
+ uint256 cur = consensus.delegatedAmount(
300
+ address(this),
301
+ validators[i]
302
+ );
303
+
304
+ if (cur < perValidator) {
305
+ uint256 toDelegate = perValidator.sub(cur);
306
+ toDelegate = toDelegate < left ? toDelegate : left;
307
+ consensus.delegate{ value: toDelegate }(validators[i]);
308
+ left = left.sub(toDelegate);
309
+ }
310
+ }
311
+
312
+ return true;
313
+ }
314
+
315
+ function addValidator(address _v) public onlyOwner {
316
+ validators.push(_v);
317
+ }
318
+
319
+ function totalDelegated() public view returns (uint256) {
320
+ uint256 total = 0;
321
+ for (uint256 i = 0; i < validators.length; i++) {
322
+ uint256 cur = consensus.delegatedAmount(
323
+ address(this),
324
+ validators[i]
325
+ );
326
+ total += cur;
327
+ }
328
+ return total;
329
+ }
330
+
331
+ function removeValidator(address _validator) public onlyOwner {
332
+ uint256 delegated = consensus.delegatedAmount(
333
+ address(this),
334
+ _validator
335
+ );
336
+ if (delegated > 0) {
337
+ uint256 prevBalance = balance();
338
+ undelegateWithCatch(_validator, delegated);
339
+
340
+ // wasnt withdrawn because validator needs to be taken of active validators
341
+ if (balance() == prevBalance) {
342
+ // pendingValidators.push(_validator);
343
+ return;
344
+ }
345
+ }
346
+
347
+ for (uint256 i = 0; i < validators.length; i++) {
348
+ if (validators[i] == _validator) {
349
+ if (i < validators.length - 1)
350
+ validators[i] = validators[validators.length - 1];
351
+ validators.pop();
352
+ break;
353
+ }
354
+ }
355
+ }
356
+
357
+ function collectUBIInterest() public notPaused {
358
+ uint256 curDay = ubischeme.currentDay();
359
+ require(
360
+ curDay != lastDayCollected,
361
+ "can collect only once in a ubi cycle"
362
+ );
363
+
364
+ uint256 earnings = balance() - pendingFuseEarnings;
365
+ require(pendingFuseEarnings + earnings > 0, "no earnings to collect");
366
+
367
+ lastDayCollected = curDay;
368
+ uint256 fuseUBI = earnings.mul(RATIO_BASE - stakeBackRatio).div(
369
+ RATIO_BASE
370
+ );
371
+ uint256 stakeBack = earnings - fuseUBI;
372
+
373
+ uint256[] memory fuseswapResult = _buyGD(fuseUBI + pendingFuseEarnings); //buy GD with X% of earnings
374
+ pendingFuseEarnings = fuseUBI + pendingFuseEarnings - fuseswapResult[0];
375
+ stakeNextValidator(stakeBack, address(0)); //stake back the rest of the earnings
376
+
377
+ uint256 gdBought = fuseswapResult[fuseswapResult.length - 1];
378
+ uint256 keeperFee = gdBought.mul(keeperFeeRatio).div(RATIO_BASE);
379
+ if (keeperFee > 0) GD.transfer(msg.sender, keeperFee);
380
+ gdBought -= keeperFee;
381
+ uint256 communityPoolContribution = gdBought
382
+ .mul(communityPoolRatio)
383
+ .div(RATIO_BASE); //subtract fee // * ommunityPoolRatio // = G$ after fee * communityPoolRatio%
384
+
385
+ uint256 ubiAfterFeeAndPool = gdBought.sub(communityPoolContribution);
386
+
387
+ GD.transfer(address(ubischeme), ubiAfterFeeAndPool); //transfer to ubischeme
388
+ communityPoolBalance += communityPoolContribution;
389
+
390
+ emit UBICollected(
391
+ curDay,
392
+ ubiAfterFeeAndPool,
393
+ communityPoolContribution,
394
+ gdBought,
395
+ earnings,
396
+ pendingFuseEarnings,
397
+ msg.sender,
398
+ keeperFee
399
+ );
400
+ }
401
+
402
+ /**
403
+ * @dev internal method to buy GD from fuseswap
404
+ * @param _value fuse to be sold
405
+ * @return uniswap coversion results uint256[2]
406
+ */
407
+ function _buyGD(uint256 _value) internal returns (uint256[] memory) {
408
+ //buy from uniwasp
409
+ require(_value > 0, "buy value should be > 0");
410
+ (uint256 maxFuse, uint256 fuseGDOut) = calcMaxFuseWithPriceImpact(
411
+ _value
412
+ );
413
+ (
414
+ uint256 maxFuseUSDC,
415
+ uint256 usdcGDOut
416
+ ) = calcMaxFuseUSDCWithPriceImpact(_value);
417
+ address[] memory path;
418
+ if (maxFuse >= maxFuseUSDC) {
419
+ path = new address[](2);
420
+ path[1] = address(GD);
421
+ path[0] = uniswap.WETH();
422
+ return
423
+ uniswap.swapExactETHForTokens{ value: maxFuse }(
424
+ (fuseGDOut * 95) / 100,
425
+ path,
426
+ address(this),
427
+ block.timestamp
428
+ );
429
+ } else {
430
+ (uint256 usdcAmount, uint256 usedFuse) = _buyUSDC(maxFuseUSDC);
431
+ path = new address[](2);
432
+ path[1] = address(GD);
433
+ path[0] = USDC;
434
+
435
+ uint256[] memory result = uniswap.swapExactTokensForTokens(
436
+ usdcAmount,
437
+ (usdcGDOut * 95) / 100,
438
+ path,
439
+ address(this),
440
+ block.timestamp
441
+ );
442
+ //buyGD should return how much fuse was used in [0] and how much G$ we got in [1]
443
+ result[0] = usedFuse;
444
+ return result;
445
+ }
446
+ }
447
+
448
+ /**
449
+ * @dev internal method to buy USDC via fuse->fusd
450
+ * @param _fuseIn fuse to be sold
451
+ * @return usdcAmount and usedFuse how much usdc we got and how much fuse was used
452
+ */
453
+
454
+ function _buyUSDC(uint256 _fuseIn)
455
+ internal
456
+ returns (uint256 usdcAmount, uint256 usedFuse)
457
+ {
458
+ //buy from uniwasp
459
+ require(_fuseIn > 0, "buy value should be > 0");
460
+ UniswapPair uniswapFUSEfUSDPair = UniswapPair(
461
+ uniswapFactory.getPair(uniswap.WETH(), fUSD)
462
+ ); //fusd is pegged 1:1 to usdc
463
+ (uint256 r_fuse, uint256 r_fusd, ) = uniswapFUSEfUSDPair.getReserves();
464
+
465
+ (uint256 maxFuse, uint256 tokenOut) = calcMaxTokenWithPriceImpact(
466
+ r_fuse,
467
+ r_fusd,
468
+ _fuseIn
469
+ ); //expect r_token to be in 18 decimals
470
+
471
+ address[] memory path = new address[](2);
472
+ path[1] = fUSD;
473
+ path[0] = uniswap.WETH();
474
+ uint256[] memory result = uniswap.swapExactETHForTokens{
475
+ value: maxFuse
476
+ }((tokenOut * 95) / 100, path, address(this), block.timestamp);
477
+
478
+ pegSwap.swap(result[1], fUSD, USDC);
479
+ usedFuse = result[0];
480
+ usdcAmount = result[1] / 1e12; //convert fusd from 1e18 to usdc 1e6
481
+ }
482
+
483
+ function calcMaxFuseWithPriceImpact(uint256 _value)
484
+ public
485
+ view
486
+ returns (uint256 fuseAmount, uint256 tokenOut)
487
+ {
488
+ (uint256 r_fuse, uint256 r_gd, ) = UniswapPair(
489
+ uniswapFactory.getPair(uniswap.WETH(), address(GD))
490
+ ).getReserves();
491
+
492
+ return calcMaxTokenWithPriceImpact(r_fuse, r_gd, _value);
493
+ }
494
+
495
+ function calcMaxFuseUSDCWithPriceImpact(uint256 _value)
496
+ public
497
+ view
498
+ returns (uint256 maxFuse, uint256 gdOut)
499
+ {
500
+ UniswapPair uniswapFUSEfUSDPair = UniswapPair(
501
+ uniswapFactory.getPair(uniswap.WETH(), fUSD)
502
+ ); //fusd is pegged 1:1 to usdc
503
+ UniswapPair uniswapGDUSDCPair = UniswapPair(
504
+ uniswapFactory.getPair(address(GD), USDC)
505
+ );
506
+ (uint256 rg_gd, uint256 rg_usdc, ) = uniswapGDUSDCPair.getReserves();
507
+ (uint256 r_fuse, uint256 r_fusd, ) = uniswapFUSEfUSDPair.getReserves();
508
+ //fusd is 1e18 so to keep in original 1e18 precision we first multiply by 1e18
509
+ uint256 fusdPriceInFuse = r_fuse.mul(1e18).div(r_fusd);
510
+ // console.log(
511
+ // "rgd: %s rusdc:%s usdcPriceInFuse: %s",
512
+ // rg_gd,
513
+ // rg_usdc,
514
+ // fusdPriceInFuse
515
+ // );
516
+ // console.log("rfuse: %s rusdc:%s", r_fuse, r_fusd);
517
+
518
+ //how many fusd we can get for fuse
519
+ //value and usdPriceInFuse are in 1e18, we mul by 1e18 to keep 18 decimals precision
520
+ uint256 fuseValueInfUSD = _value.mul(1e18).div(fusdPriceInFuse);
521
+ // console.log("fuse fusd value: %s", fuseValueInfUSD);
522
+
523
+ (uint256 maxUSDC, uint256 tokenOut) = calcMaxTokenWithPriceImpact(
524
+ rg_usdc * 1e12,
525
+ rg_gd,
526
+ fuseValueInfUSD
527
+ ); //expect r_token to be in 18 decimals
528
+ // console.log("max USDC: %s", maxUSDC);
529
+ gdOut = tokenOut;
530
+ maxFuse = maxUSDC.mul(fusdPriceInFuse).div(1e18); //both are in 1e18 precision, div by 1e18 to keep precision
531
+ }
532
+
533
+ /**
534
+ * uniswap amountOut helper
535
+ */
536
+ function getAmountOut(
537
+ uint256 _amountIn,
538
+ uint256 _reserveIn,
539
+ uint256 _reserveOut
540
+ ) internal pure returns (uint256 amountOut) {
541
+ uint256 amountInWithFee = _amountIn * 997;
542
+ uint256 numerator = amountInWithFee * _reserveOut;
543
+ uint256 denominator = _reserveIn * 1000 + amountInWithFee;
544
+ amountOut = numerator / denominator;
545
+ }
546
+
547
+ /**
548
+ * @dev use binary search to find quantity that will result with price impact < maxPriceImpactRatio
549
+ */
550
+ function calcMaxTokenWithPriceImpact(
551
+ uint256 r_token,
552
+ uint256 r_gd,
553
+ uint256 _value
554
+ ) public view returns (uint256 maxToken, uint256 tokenOut) {
555
+ maxToken = (r_token * maxSlippageRatio) / RATIO_BASE;
556
+ maxToken = maxToken < _value ? maxToken : _value;
557
+ tokenOut = getAmountOut(maxToken, r_token, r_gd);
558
+ // uint256 start = 0;
559
+ // uint256 end = _value.div(1e18); //save iterations by moving precision to whole Fuse quantity
560
+ // // uint256 curPriceWei = uint256(1e18).mul(r_gd) / r_token; //uniswap quote formula UniswapV2Library.sol
561
+ // uint256 gdForQuantity = getAmountOut(1e18, r_token, r_gd);
562
+ // uint256 priceForQuantityWei = rdiv(1e18, gdForQuantity.mul(1e16)).div(
563
+ // 1e9
564
+ // );
565
+ // uint256 maxPriceWei = priceForQuantityWei
566
+ // .mul(RATIO_BASE.add(maxSlippageRatio))
567
+ // .div(RATIO_BASE);
568
+ // // console.log(
569
+ // // "curPrice: %s, maxPrice %s",
570
+ // // priceForQuantityWei,
571
+ // // maxPriceWei
572
+ // // );
573
+ // fuseAmount = _value;
574
+ // tokenOut;
575
+ // //Iterate while start not meets end
576
+ // while (start <= end) {
577
+ // // Find the mid index
578
+ // uint256 midQuantityWei = start.add(end).mul(1e18).div(2); //restore quantity precision
579
+ // if (midQuantityWei == 0) break;
580
+ // gdForQuantity = getAmountOut(midQuantityWei, r_token, r_gd);
581
+ // priceForQuantityWei = rdiv(midQuantityWei, gdForQuantity.mul(1e16))
582
+ // .div(1e9);
583
+ // // console.log(
584
+ // // "gdForQuantity: %s, priceForQuantity: %s, midQuantity: %s",
585
+ // // gdForQuantity,
586
+ // // priceForQuantityWei,
587
+ // // midQuantityWei
588
+ // // );
589
+ // if (priceForQuantityWei <= maxPriceWei) {
590
+ // start = midQuantityWei.div(1e18) + 1; //reduce precision to whole quantity div 1e18
591
+ // fuseAmount = midQuantityWei;
592
+ // tokenOut = gdForQuantity;
593
+ // } else end = midQuantityWei.div(1e18) - 1; //reduce precision to whole quantity div 1e18
594
+ // }
595
+ }
596
+
597
+ function undelegateWithCatch(address _validator, uint256 _amount)
598
+ internal
599
+ returns (bool)
600
+ {
601
+ try consensus.withdraw(_validator, _amount) {
602
+ return true;
603
+ } catch Error(
604
+ string memory /*reason*/
605
+ ) {
606
+ // This is executed in case
607
+ // revert was called inside getData
608
+ // and a reason string was provided.
609
+ return false;
610
+ } catch (
611
+ bytes memory /*lowLevelData*/
612
+ ) {
613
+ // This is executed in case revert() was used
614
+ // or there was a failing assertion, division
615
+ // by zero, etc. inside getData.
616
+ return false;
617
+ }
618
+ }
619
+
620
+ function balance() internal view returns (uint256) {
621
+ return payable(address(this)).balance;
622
+ }
623
+
624
+ function setPaused(bool _paused) external onlyGuardian {
625
+ paused = _paused;
626
+ }
627
+
628
+ function setGuardian(address _guardian) external onlyGuardian {
629
+ guardian = _guardian;
630
+ }
631
+
632
+ function collectCommunityPool(address _to, uint256 amount)
633
+ external
634
+ onlyGuardian
635
+ {
636
+ communityPoolBalance -= amount;
637
+ GD.transfer(_to, amount);
638
+ }
639
+
640
+ receive() external payable {}
641
+ }
package/hardhat.config.ts CHANGED
@@ -121,6 +121,13 @@ const hhconfig: HardhatUserConfig = {
121
121
  gas: 6000000,
122
122
  gasPrice: 1000000000
123
123
  },
124
+ fuseexplorer: {
125
+ accounts: { mnemonic },
126
+ url: "https://explorer-node.fuse.io/",
127
+ chainId: 122,
128
+ gas: 6000000,
129
+ gasPrice: 1000000000
130
+ },
124
131
  fusespark: {
125
132
  accounts: { mnemonic },
126
133
  url: "https://rpc.fusespark.io/",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gooddollar/goodprotocol",
3
- "version": "1.0.23",
3
+ "version": "1.0.26-beta.0",
4
4
  "description": "GoodDollar Protocol",
5
5
  "scripts": {
6
6
  "build": "scripts/build.sh deploy",
@@ -14,10 +14,10 @@
14
14
  "daoUpgrade": "hardhat run scripts/upgradeToV2/upgradeToV2.ts",
15
15
  "deployOldDAO": "hardhat run scripts/test/localOldDaoDeploy.ts",
16
16
  "runNode": "hardhat node &",
17
- "testDAOUpgrade": "yarn runNode && yarn compile && yarn deployOldDAO --network develop-mainnet && yarn daoUpgrade --network develop-mainnet",
18
- "testDAOUpgradeFuse": "yarn runNode && yarn compile && yarn deployOldDAO --network develop && yarn daoUpgrade --network develop",
19
- "deployTestOld": "yarn runNode && yarn compile && hardhat run scripts/test/singleOldDaoDeploy.ts --network dapptest && yarn daoUpgrade --network dapptest && yarn daoUpgrade --network dapptest-mainnet && hardhat run scripts/test/simulateInterest.ts --network dapptest",
20
- "deployTest": "yarn runNode && yarn compile && hardhat run scripts/deployFullDAO.ts --network dapptest && hardhat run scripts/deployFullDAO.ts --network dapptest-mainnet && hardhat run scripts/test/simulateInterest.ts --network dapptest"
17
+ "testDAOUpgrade": "yarn runNode & yarn compile && yarn deployOldDAO --network develop-mainnet && yarn daoUpgrade --network develop-mainnet",
18
+ "testDAOUpgradeFuse": "yarn runNode & yarn compile && yarn deployOldDAO --network develop && yarn daoUpgrade --network develop",
19
+ "deployTestOld": "yarn runNode & yarn compile && hardhat run scripts/test/singleOldDaoDeploy.ts --network dapptest && yarn daoUpgrade --network dapptest && yarn daoUpgrade --network dapptest-mainnet && hardhat run scripts/test/simulateInterest.ts --network dapptest",
20
+ "deployTest": "yarn runNode & yarn compile && hardhat run scripts/deployFullDAO.ts --network dapptest && hardhat run scripts/deployFullDAO.ts --network dapptest-mainnet && hardhat run scripts/test/simulateInterest.ts --network dapptest"
21
21
  },
22
22
  "files": [
23
23
  "artifacts/contracts",
@@ -32,7 +32,8 @@
32
32
  "truffle-config.js",
33
33
  "tsconfig.json",
34
34
  "test",
35
- "types"
35
+ "types",
36
+ "patches"
36
37
  ],
37
38
  "repository": {
38
39
  "type": "git",