@gooddollar/goodprotocol 1.0.18 → 1.0.19-beta.2

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 (164) hide show
  1. package/artifacts/abis/GReputation.min.json +1 -1
  2. package/artifacts/abis/GoodAaveStaking.min.json +1 -1
  3. package/artifacts/abis/GoodAaveStakingV2.min.json +1 -1
  4. package/artifacts/abis/GoodCompoundStaking.min.json +1 -1
  5. package/artifacts/abis/GoodCompoundStakingTest.min.json +1 -1
  6. package/artifacts/abis/GoodCompoundStakingV2.min.json +1 -1
  7. package/artifacts/abis/UpgradableMock3.min.json +1 -0
  8. package/artifacts/abis/UpgradableMock4.min.json +1 -0
  9. package/artifacts/contracts/DAOStackInterfaces.sol/Avatar.dbg.json +1 -1
  10. package/artifacts/contracts/DAOStackInterfaces.sol/Controller.dbg.json +1 -1
  11. package/artifacts/contracts/DAOStackInterfaces.sol/GlobalConstraintInterface.dbg.json +1 -1
  12. package/artifacts/contracts/DAOStackInterfaces.sol/IntVoteInterface.dbg.json +1 -1
  13. package/artifacts/contracts/DAOStackInterfaces.sol/ReputationInterface.dbg.json +1 -1
  14. package/artifacts/contracts/DAOStackInterfaces.sol/SchemeRegistrar.dbg.json +1 -1
  15. package/artifacts/contracts/Interfaces.sol/AggregatorV3Interface.dbg.json +1 -1
  16. package/artifacts/contracts/Interfaces.sol/ERC20.dbg.json +1 -1
  17. package/artifacts/contracts/Interfaces.sol/IAaveIncentivesController.dbg.json +1 -1
  18. package/artifacts/contracts/Interfaces.sol/IAdminWallet.dbg.json +1 -1
  19. package/artifacts/contracts/Interfaces.sol/IDonationStaking.dbg.json +1 -1
  20. package/artifacts/contracts/Interfaces.sol/IERC2917.dbg.json +1 -1
  21. package/artifacts/contracts/Interfaces.sol/IFirstClaimPool.dbg.json +1 -1
  22. package/artifacts/contracts/Interfaces.sol/IGoodDollar.dbg.json +1 -1
  23. package/artifacts/contracts/Interfaces.sol/IGoodStaking.dbg.json +1 -1
  24. package/artifacts/contracts/Interfaces.sol/IHasRouter.dbg.json +1 -1
  25. package/artifacts/contracts/Interfaces.sol/IIdentity.dbg.json +1 -1
  26. package/artifacts/contracts/Interfaces.sol/ILendingPool.dbg.json +1 -1
  27. package/artifacts/contracts/Interfaces.sol/INameService.dbg.json +1 -1
  28. package/artifacts/contracts/Interfaces.sol/IUBIScheme.dbg.json +1 -1
  29. package/artifacts/contracts/Interfaces.sol/ProxyAdmin.dbg.json +1 -1
  30. package/artifacts/contracts/Interfaces.sol/Reserve.dbg.json +1 -1
  31. package/artifacts/contracts/Interfaces.sol/Staking.dbg.json +1 -1
  32. package/artifacts/contracts/Interfaces.sol/Uniswap.dbg.json +1 -1
  33. package/artifacts/contracts/Interfaces.sol/UniswapFactory.dbg.json +1 -1
  34. package/artifacts/contracts/Interfaces.sol/UniswapPair.dbg.json +1 -1
  35. package/artifacts/contracts/Interfaces.sol/cERC20.dbg.json +1 -1
  36. package/artifacts/contracts/governance/ClaimersDistribution.sol/ClaimersDistribution.dbg.json +1 -1
  37. package/artifacts/contracts/governance/ClaimersDistribution.sol/ClaimersDistribution.json +2 -2
  38. package/artifacts/contracts/governance/CompoundVotingMachine.sol/CompoundVotingMachine.dbg.json +1 -1
  39. package/artifacts/contracts/governance/GReputation.sol/GReputation.dbg.json +1 -1
  40. package/artifacts/contracts/governance/GReputation.sol/GReputation.json +15 -2
  41. package/artifacts/contracts/governance/GovernanceStaking.sol/GovernanceStaking.dbg.json +1 -1
  42. package/artifacts/contracts/governance/MultiBaseGovernanceShareField.sol/MultiBaseGovernanceShareField.dbg.json +1 -1
  43. package/artifacts/contracts/governance/Reputation.sol/Reputation.dbg.json +1 -1
  44. package/artifacts/contracts/governance/Reputation.sol/Reputation.json +2 -2
  45. package/artifacts/contracts/governance/StakersDistribution.sol/StakersDistribution.dbg.json +1 -1
  46. package/artifacts/contracts/governance/StakersDistribution.sol/StakersDistribution.json +2 -2
  47. package/artifacts/contracts/mocks/AaveMock.sol/AaveMock.dbg.json +1 -1
  48. package/artifacts/contracts/mocks/AaveUSDMockOracle.sol/AaveUSDMockOracle.dbg.json +1 -1
  49. package/artifacts/contracts/mocks/BatUSDMockOracle.sol/BatUSDMockOracle.dbg.json +1 -1
  50. package/artifacts/contracts/mocks/CompUsdMockOracle.sol/CompUSDMockOracle.dbg.json +1 -1
  51. package/artifacts/contracts/mocks/DAIMock.sol/DAIMock.dbg.json +1 -1
  52. package/artifacts/contracts/mocks/DaiEthPriceMockOracle.sol/DaiEthPriceMockOracle.dbg.json +1 -1
  53. package/artifacts/contracts/mocks/DecimalsMock.sol/DecimalsMock.dbg.json +1 -1
  54. package/artifacts/contracts/mocks/EthUSDMockOracle.sol/EthUSDMockOracle.dbg.json +1 -1
  55. package/artifacts/contracts/mocks/GasPriceMockOracle.sol/GasPriceMockOracle.dbg.json +1 -1
  56. package/artifacts/contracts/mocks/GoodCompoundStakingTest.sol/GoodCompoundStakingTest.dbg.json +1 -1
  57. package/artifacts/contracts/mocks/GoodCompoundStakingTest.sol/GoodCompoundStakingTest.json +6 -6
  58. package/artifacts/contracts/mocks/GoodFundManagerTest.sol/GoodFundManagerTest.dbg.json +1 -1
  59. package/artifacts/contracts/mocks/IncentiveControllerMock.sol/IncentiveControllerMock.dbg.json +1 -1
  60. package/artifacts/contracts/mocks/LendingPoolMock.sol/LendingPoolMock.dbg.json +1 -1
  61. package/artifacts/contracts/mocks/OverMintTester.sol/OverMintTester.dbg.json +1 -1
  62. package/artifacts/contracts/mocks/OverMintTesterRegularStake.sol/OverMintTesterRegularStake.dbg.json +1 -1
  63. package/artifacts/contracts/mocks/OverMintTesterRegularStake.sol/OverMintTesterRegularStake.json +2 -2
  64. package/artifacts/contracts/mocks/SixteenDecimalsTokenMock.sol/SixteenDecimalsTokenMock.dbg.json +1 -1
  65. package/artifacts/contracts/mocks/SwapHelperTest.sol/SwapHelperTest.dbg.json +1 -1
  66. package/artifacts/contracts/mocks/TwentyDecimalsTokenMock.sol/TwentyDecimalsTokenMock.dbg.json +1 -1
  67. package/artifacts/contracts/mocks/UpgradableMocks.sol/UpgradableMock.dbg.json +1 -1
  68. package/artifacts/contracts/mocks/UpgradableMocks.sol/UpgradableMock.json +2 -2
  69. package/artifacts/contracts/mocks/UpgradableMocks.sol/UpgradableMock2.dbg.json +1 -1
  70. package/artifacts/contracts/mocks/UpgradableMocks.sol/UpgradableMock2.json +2 -2
  71. package/artifacts/contracts/mocks/UpgradableMocks.sol/UpgradableMock3.dbg.json +4 -0
  72. package/artifacts/contracts/mocks/UpgradableMocks.sol/UpgradableMock3.json +172 -0
  73. package/artifacts/contracts/mocks/UpgradableMocks.sol/UpgradableMock4.dbg.json +4 -0
  74. package/artifacts/contracts/mocks/UpgradableMocks.sol/UpgradableMock4.json +172 -0
  75. package/artifacts/contracts/mocks/UsdcMock.sol/USDCMock.dbg.json +1 -1
  76. package/artifacts/contracts/mocks/cBATMock.sol/cBATMock.dbg.json +1 -1
  77. package/artifacts/contracts/mocks/cDAILowWorthMock.sol/cDAILowWorthMock.dbg.json +1 -1
  78. package/artifacts/contracts/mocks/cDAIMock.sol/cDAIMock.dbg.json +1 -1
  79. package/artifacts/contracts/mocks/cDAINonMintableMock.sol/cDAINonMintableMock.dbg.json +1 -1
  80. package/artifacts/contracts/mocks/cDecimalsMock.sol/cDecimalsMock.dbg.json +1 -1
  81. package/artifacts/contracts/mocks/cSDTMock.sol/cSDTMock.dbg.json +1 -1
  82. package/artifacts/contracts/mocks/cUSDCMock.sol/cUSDCMock.dbg.json +1 -1
  83. package/artifacts/contracts/reserve/ExchangeHelper.sol/ExchangeHelper.dbg.json +1 -1
  84. package/artifacts/contracts/reserve/GoodMarketMaker.sol/GoodMarketMaker.dbg.json +1 -1
  85. package/artifacts/contracts/reserve/GoodReserveCDai.sol/ContributionCalc.dbg.json +1 -1
  86. package/artifacts/contracts/reserve/GoodReserveCDai.sol/GoodReserveCDai.dbg.json +1 -1
  87. package/artifacts/contracts/staking/BaseShareField.sol/BaseShareField.dbg.json +1 -1
  88. package/artifacts/contracts/staking/BaseShareFieldV2.sol/BaseShareFieldV2.dbg.json +1 -1
  89. package/artifacts/contracts/staking/DonationsStaking.sol/DonationsStaking.dbg.json +1 -1
  90. package/artifacts/contracts/staking/DonationsStaking.sol/DonationsStaking.json +2 -2
  91. package/artifacts/contracts/staking/GoodFundManager.sol/GoodFundManager.dbg.json +1 -1
  92. package/artifacts/contracts/staking/SimpleStaking.sol/SimpleStaking.dbg.json +1 -1
  93. package/artifacts/contracts/staking/SimpleStakingV2.sol/SimpleStakingV2.dbg.json +1 -1
  94. package/artifacts/contracts/staking/UniswapV2SwapHelper.sol/UniswapV2SwapHelper.dbg.json +1 -1
  95. package/artifacts/contracts/staking/aave/AaveStakingFactory.sol/AaveStakingFactory.dbg.json +1 -1
  96. package/artifacts/contracts/staking/aave/AaveStakingFactory.sol/AaveStakingFactory.json +2 -2
  97. package/artifacts/contracts/staking/aave/GoodAaveStaking.sol/GoodAaveStaking.dbg.json +1 -1
  98. package/artifacts/contracts/staking/aave/GoodAaveStaking.sol/GoodAaveStaking.json +3 -3
  99. package/artifacts/contracts/staking/aave/GoodAaveStakingV2.sol/GoodAaveStakingV2.dbg.json +1 -1
  100. package/artifacts/contracts/staking/aave/GoodAaveStakingV2.sol/GoodAaveStakingV2.json +3 -3
  101. package/artifacts/contracts/staking/compound/CompoundStakingFactory.sol/CompoundStakingFactory.dbg.json +1 -1
  102. package/artifacts/contracts/staking/compound/CompoundStakingFactory.sol/CompoundStakingFactory.json +2 -2
  103. package/artifacts/contracts/staking/compound/GoodCompoundStaking.sol/GoodCompoundStaking.dbg.json +1 -1
  104. package/artifacts/contracts/staking/compound/GoodCompoundStaking.sol/GoodCompoundStaking.json +4 -4
  105. package/artifacts/contracts/staking/compound/GoodCompoundStakingV2.sol/GoodCompoundStakingV2.dbg.json +1 -1
  106. package/artifacts/contracts/staking/compound/GoodCompoundStakingV2.sol/GoodCompoundStakingV2.json +4 -4
  107. package/artifacts/contracts/ubi/UBIScheme.sol/UBIScheme.dbg.json +1 -1
  108. package/artifacts/contracts/ubi/UBIScheme.sol/UBIScheme.json +2 -2
  109. package/artifacts/contracts/utils/BancorFormula.sol/BancorFormula.dbg.json +1 -1
  110. package/artifacts/contracts/utils/BulkProof.sol/BulkProof.dbg.json +1 -1
  111. package/artifacts/contracts/utils/BulkProof.sol/BulkProof.json +2 -2
  112. package/artifacts/contracts/utils/DAOContract.sol/DAOContract.dbg.json +1 -1
  113. package/artifacts/contracts/utils/DAOUpgradeableContract.sol/DAOUpgradeableContract.dbg.json +1 -1
  114. package/artifacts/contracts/utils/DSMath.sol/DSMath.dbg.json +1 -1
  115. package/artifacts/contracts/utils/DataTypes.sol/DataTypes.dbg.json +1 -1
  116. package/artifacts/contracts/utils/MultiCall.sol/Multicall.dbg.json +1 -1
  117. package/artifacts/contracts/utils/NameService.sol/NameService.dbg.json +1 -1
  118. package/artifacts/contracts/utils/ProtocolUpgrade.sol/OldMarketMaker.dbg.json +1 -1
  119. package/artifacts/contracts/utils/ProtocolUpgrade.sol/ProtocolUpgrade.dbg.json +1 -1
  120. package/artifacts/contracts/utils/ProtocolUpgradeFuse.sol/ProtocolUpgradeFuse.dbg.json +1 -1
  121. package/artifacts/contracts/utils/ProtocolUpgradeFuseRecover.sol/ProtocolUpgradeFuseRecover.dbg.json +1 -1
  122. package/artifacts/contracts/utils/ProtocolUpgradeRecover.sol/ProtocolUpgradeRecover.dbg.json +1 -1
  123. package/artifacts/contracts/utils/ProxyFactory1967.sol/ERC1967Proxy.dbg.json +1 -1
  124. package/artifacts/contracts/utils/ProxyFactory1967.sol/ProxyFactory1967.dbg.json +1 -1
  125. package/artifacts/contracts/utils/ReputationTestHelper.sol/ReputationTestHelper.dbg.json +1 -1
  126. package/artifacts/contracts/utils/ReputationTestHelper.sol/ReputationTestHelper.json +2 -2
  127. package/contracts/governance/GReputation.sol +8 -0
  128. package/contracts/governance/Reputation.sol +5 -3
  129. package/contracts/mocks/UpgradableMocks.sol +18 -0
  130. package/contracts/staking/SimpleStaking.sol +2 -1
  131. package/contracts/staking/SimpleStakingV2.sol +2 -1
  132. package/hardhat.config.ts +63 -8
  133. package/package.json +7 -5
  134. package/releases/deployment.json +11 -0
  135. package/scripts/multichain-deploy/basicdao-deploy.ts +256 -0
  136. package/scripts/multichain-deploy/helpers.ts +96 -0
  137. package/test/governance/ClaimersDistribution.test.ts +6 -6
  138. package/test/governance/CompoundVotingMachine.daoscheme.ts +14 -1
  139. package/test/governance/CompoundVotingMachine.guardian.test.ts +11 -1
  140. package/test/governance/GReputation.test.ts +32 -1
  141. package/test/governance/StakersDistribution.test.ts +62 -1
  142. package/test/helpers.ts +15 -0
  143. package/test/reserve/GoodMarketMaker.test.ts +11 -0
  144. package/test/reserve/GoodReserveCDai.gdx.test.ts +23 -8
  145. package/test/reserve/GoodReserveCDai.test.ts +37 -2
  146. package/test/staking/CompoundStakingFactory.test.ts +31 -0
  147. package/test/staking/DonationsStaking.test.ts +99 -2
  148. package/test/staking/GoodAaveStakingFactory.test.ts +36 -1
  149. package/test/staking/SimpleDAIStaking.test.ts +52 -2
  150. package/test/staking/StakingRewards.test.ts +38 -0
  151. package/test/staking/UsdcAaveStaking.test.ts +45 -19
  152. package/test/ubi/UBIScheme.test.ts +68 -0
  153. package/test/utils/DAOUpgradeableContract.test.ts +47 -0
  154. package/test/utils/NameService.test.ts +50 -55
  155. package/test/utils/ProxyFactory.test.ts +17 -0
  156. package/yarn.lock +607 -119
  157. package/artifacts/abis/FuseFaucet.min.json +0 -1
  158. package/artifacts/abis/InvitesV1.min.json +0 -1
  159. package/artifacts/contracts/unaudited-foundation/FuseFaucet.sol/FuseFaucet.dbg.json +0 -4
  160. package/artifacts/contracts/unaudited-foundation/FuseFaucet.sol/FuseFaucet.json +0 -200
  161. package/artifacts/contracts/unaudited-foundation/InvitesV1.sol/InvitesV1.dbg.json +0 -4
  162. package/artifacts/contracts/unaudited-foundation/InvitesV1.sol/InvitesV1.json +0 -486
  163. package/contracts/unaudited-foundation/FuseFaucet.sol +0 -120
  164. package/contracts/unaudited-foundation/InvitesV1.sol +0 -304
@@ -8,6 +8,8 @@ import { createDAO, increaseTime, advanceBlocks } from "../helpers";
8
8
  import ContributionCalculation from "@gooddollar/goodcontracts/stakingModel/build/contracts/ContributionCalculation.json";
9
9
 
10
10
  const BN = ethers.BigNumber;
11
+ const RANDOM_GDX_MERKLEROOT1 =
12
+ "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
11
13
  export const NULL_ADDRESS = ethers.constants.AddressZero;
12
14
  export const BLOCK_INTERVAL = 1;
13
15
 
@@ -25,7 +27,9 @@ describe("GDX Token", () => {
25
27
  staker,
26
28
  schemeMock,
27
29
  signers,
28
- setDAOAddress;
30
+ genericCall,
31
+ setDAOAddress,
32
+ runAsAvatarOnly;
29
33
 
30
34
  before(async () => {
31
35
  [founder, staker, ...signers] = await ethers.getSigners();
@@ -44,6 +48,8 @@ describe("GDX Token", () => {
44
48
  marketMaker: mm,
45
49
  daiAddress,
46
50
  cdaiAddress,
51
+ genericCall: gn,
52
+ runAsAvatarOnly: raao
47
53
  } = await createDAO();
48
54
 
49
55
  dai = await ethers.getContractAt("DAIMock", daiAddress);
@@ -53,7 +59,9 @@ describe("GDX Token", () => {
53
59
  controller = ctrl;
54
60
  setDAOAddress = sda;
55
61
  goodReserve = reserve as GoodReserveCDai;
56
-
62
+ genericCall = gn;
63
+ runAsAvatarOnly = raao;
64
+
57
65
  console.log("deployed dao", {
58
66
  founder: founder.address,
59
67
  gd,
@@ -93,13 +101,8 @@ describe("GDX Token", () => {
93
101
  "setContributionRatio",
94
102
  [nom, denom]
95
103
  );
96
- const ictrl = await ethers.getContractAt(
97
- "Controller",
98
- controller,
99
- schemeMock
100
- );
101
104
 
102
- await ictrl.genericCall(contribution.address, encodedCall, avatar, 0);
105
+ await genericCall(contribution.address, encodedCall);
103
106
  });
104
107
 
105
108
  it("should have only role of admin assigned to avatar", async () => {
@@ -253,6 +256,18 @@ describe("GDX Token", () => {
253
256
  );
254
257
  });
255
258
 
259
+ it("should set GDX airdrop by avatar", async () => {
260
+ await runAsAvatarOnly(goodReserve,"setGDXAirdrop(bytes32)", RANDOM_GDX_MERKLEROOT1);
261
+ expect(await goodReserve.gdxAirdrop()).to.equal(RANDOM_GDX_MERKLEROOT1);
262
+
263
+ const originalGDXAirdrop = "0x26ef809f3f845395c0bc66ce1eea85146516cb99afd030e2085b13e79514e94c";
264
+ const encodedCall = goodReserve.interface.encodeFunctionData(
265
+ "setGDXAirdrop",
266
+ [originalGDXAirdrop]
267
+ );
268
+ await genericCall(goodReserve.address, encodedCall);
269
+ });
270
+
256
271
  //check sample proof generated by gdxAirdropCalculation.ts script
257
272
  it("should be able to claim gdx", async () => {
258
273
  await goodReserve.claimGDX(
@@ -28,7 +28,8 @@ describe("GoodReserve - staking with cDAI mocks", () => {
28
28
  signers,
29
29
  exchangeHelper: Contract,
30
30
  setDAOAddress,
31
- nameService;
31
+ nameService,
32
+ runAsAvatarOnly;
32
33
 
33
34
  before(async () => {
34
35
  [founder, staker, ...signers] = await ethers.getSigners();
@@ -46,7 +47,8 @@ describe("GoodReserve - staking with cDAI mocks", () => {
46
47
  marketMaker: mm,
47
48
  daiAddress,
48
49
  cdaiAddress,
49
- reserve
50
+ reserve,
51
+ runAsAvatarOnly: raao,
50
52
  } = await createDAO();
51
53
 
52
54
  dai = await ethers.getContractAt("DAIMock", daiAddress);
@@ -56,6 +58,7 @@ describe("GoodReserve - staking with cDAI mocks", () => {
56
58
  controller = ctrl;
57
59
  setDAOAddress = sda;
58
60
  nameService = ns;
61
+ runAsAvatarOnly = raao;
59
62
  await setDAOAddress("UNISWAP_ROUTER", signers[0].address);
60
63
  const exchangeHelperFactory = await ethers.getContractFactory(
61
64
  "ExchangeHelper"
@@ -1128,4 +1131,36 @@ describe("GoodReserve - staking with cDAI mocks", () => {
1128
1131
  expect(await goodDollar.isMinter(goodReserve.address)).to.be.false;
1129
1132
  expect(await goodDollar.isMinter(avatar)).to.be.true;
1130
1133
  });
1134
+
1135
+ it("should set reserve ratio daily expansion by avatar", async () => {
1136
+ let currentReserveRatioDailyExpansion =
1137
+ await marketMaker.reserveRatioDailyExpansion();
1138
+ console.log(currentReserveRatioDailyExpansion.toString());
1139
+
1140
+ await runAsAvatarOnly(
1141
+ goodReserve,
1142
+ "setReserveRatioDailyExpansion(uint256,uint256)",
1143
+ 1,
1144
+ 1e15
1145
+ );
1146
+
1147
+ let newReserveRatioDailyExpansion =
1148
+ await marketMaker.reserveRatioDailyExpansion();
1149
+ console.log(newReserveRatioDailyExpansion.toString());
1150
+
1151
+ expect(newReserveRatioDailyExpansion).to.not.equal(currentReserveRatioDailyExpansion);
1152
+ expect(newReserveRatioDailyExpansion).to.be.equal(BN.from("1000000000000"));
1153
+
1154
+ const encodedCall = goodReserve.interface.encodeFunctionData(
1155
+ "setReserveRatioDailyExpansion",
1156
+ [BN.from(currentReserveRatioDailyExpansion).div(1e12),
1157
+ 1e15]
1158
+ );
1159
+ const ctrl = await ethers.getContractAt(
1160
+ "Controller",
1161
+ controller,
1162
+ schemeMock
1163
+ );
1164
+ await ctrl.genericCall(goodReserve.address, encodedCall, avatar, 0);
1165
+ });
1131
1166
  });
@@ -4,6 +4,7 @@ import { expect } from "chai";
4
4
  import {
5
5
  CERC20,
6
6
  GoodCompoundStaking,
7
+ GoodCompoundStakingV2,
7
8
  CompoundStakingFactory
8
9
  } from "../../types";
9
10
  import { createDAO, deployUniswap } from "../helpers";
@@ -106,4 +107,34 @@ describe("CompoundStakingFactory", () => {
106
107
  expect(await staking.name()).to.equal("GoodCompoundStakingV2 Compound DAI");
107
108
  expect(await staking.symbol()).to.equal("gcDAI");
108
109
  });
110
+
111
+ it("should get correct gas cost settings", async () => {
112
+ const goodCompoundStakingV2 = (await ethers.getContractAt(
113
+ "GoodCompoundStakingV2",
114
+ await stakingFactory.impl()
115
+ )) as GoodCompoundStakingV2;
116
+
117
+ await goodCompoundStakingV2.init(
118
+ dai,
119
+ cdai,
120
+ dao.nameService.address,
121
+ "DAI",
122
+ "DAI",
123
+ 5760,
124
+ stakingFactory.address,
125
+ compUsdOracle.address,
126
+ []
127
+ );
128
+
129
+ const INITIAL_COLLECT_INTEREST_GAS_COST = 250000;
130
+ const INITIAL_COLLECT_COMP_GAS_COST = 150000;
131
+ const gasCostForInterestTransfer = await goodCompoundStakingV2.getGasCostForInterestTransfer();
132
+ expect(gasCostForInterestTransfer).to.equal(INITIAL_COLLECT_INTEREST_GAS_COST);
133
+
134
+ const settings = await goodCompoundStakingV2.getSettings();
135
+ const collectInteresetGasCost = settings[0];
136
+ const compCollectGasCost = settings[1];
137
+ expect(collectInteresetGasCost).to.equal(INITIAL_COLLECT_INTEREST_GAS_COST);
138
+ expect(compCollectGasCost).to.equal(INITIAL_COLLECT_COMP_GAS_COST);
139
+ });
109
140
  });
@@ -235,7 +235,7 @@ describe("DonationsStaking - DonationStaking contract that receives funds in ETH
235
235
  "no stakingToken to stake"
236
236
  );
237
237
  });
238
-
238
+
239
239
  it("it should stake donations with ETH according to 0.3% of pool", async () => {
240
240
  let stakeAmount = ethers.utils.parseEther("20");
241
241
  const pairContract = await ethers.getContractAt(
@@ -315,6 +315,82 @@ describe("DonationsStaking - DonationStaking contract that receives funds in ETH
315
315
 
316
316
  expect(totalStakedAfterEnd).to.be.equal(0);
317
317
  });
318
+
319
+ it("should not allow to stake donations when not active", async () => {
320
+ let isActive = await donationsStaking.active();
321
+ expect(isActive).to.be.equal(true);
322
+ let stakeAmount = ethers.utils.parseEther("10");
323
+ await dai["mint(address,uint256)"](donationsStaking.address, stakeAmount);
324
+
325
+ expect(donationsStaking.stakeDonations()).to.not.be.reverted;
326
+
327
+ let encodedData = donationsStaking.interface.encodeFunctionData(
328
+ "setActive",
329
+ [false]
330
+ );
331
+ await genericCall(donationsStaking.address, encodedData);
332
+
333
+ isActive = await donationsStaking.active();
334
+ expect(isActive).to.be.equal(false);
335
+ await dai["mint(address,uint256)"](donationsStaking.address, stakeAmount);
336
+ await expect(donationsStaking.stakeDonations()).to.be.reverted;
337
+ // revent to original state
338
+ encodedData = donationsStaking.interface.encodeFunctionData(
339
+ "setActive",
340
+ [true]
341
+ );
342
+ await genericCall(donationsStaking.address, encodedData);
343
+ });
344
+
345
+ it("should not allow to set swap path on invalid path", async () => {
346
+ //Valid scenario check: from ETH to staking token
347
+ let pathToSet = [NULL_ADDRESS, bat.address, cDAI.address, dai.address];
348
+ let encodedData = donationsStaking.interface.encodeFunctionData(
349
+ "setSwapPaths",
350
+ [pathToSet]
351
+ );
352
+ await genericCall(donationsStaking.address, encodedData);
353
+ expect(await isEthToStakingTokenPathEqualTo(pathToSet)).to.be.true;
354
+
355
+ // Invalid scenarios checks
356
+ const invalidPaths = [
357
+ [NULL_ADDRESS], // less than minimum 2 length
358
+ [bat.address, dai.address], // first is not ETH null address
359
+ [NULL_ADDRESS, bat.address] // last is not the staking token
360
+ ];
361
+
362
+ for (const invalidPath of invalidPaths) {
363
+ encodedData = donationsStaking.interface.encodeFunctionData(
364
+ "setSwapPaths",
365
+ [invalidPath]
366
+ );
367
+ await genericCall(donationsStaking.address, encodedData);
368
+ expect(await isEthToStakingTokenPathEqualTo(invalidPath)).to.be.false;
369
+ }
370
+
371
+ encodedData = donationsStaking.interface.encodeFunctionData(
372
+ "setSwapPaths",
373
+ [[NULL_ADDRESS, dai.address]]
374
+ );
375
+ await genericCall(donationsStaking.address, encodedData);
376
+ });
377
+
378
+ async function isEthToStakingTokenPathEqualTo(path) {
379
+ for (let index = 0; index < path.length; index++) {
380
+ let expectedValue = path[index];
381
+ let valueAtIndex = await donationsStaking.ethToStakingTokenSwapPath(index).catch(e=>e);
382
+ if (expectedValue != valueAtIndex) {
383
+ return false;
384
+ }
385
+ }
386
+
387
+ const outOfArray = await donationsStaking.ethToStakingTokenSwapPath(path.length).catch(e=>e);
388
+ if (!outOfArray.message) {
389
+ return false;
390
+ }
391
+
392
+ return true;
393
+ }
318
394
 
319
395
  it("it should set stakingContract when avatar call it ", async () => {
320
396
  let stakeAmount = ethers.utils.parseEther("6000"); // Max swap amount is around 5964 with current liquidity level so we should set it to higher number in order to test functionality
@@ -397,10 +473,31 @@ describe("DonationsStaking - DonationStaking contract that receives funds in ETH
397
473
  avatarDaiBalanceBeforeSet.add(stakingAmountBeforeSet.sub(safeAmount))
398
474
  ); // It should send leftover stakingToken to avatar after swap to ETH in safeAmount
399
475
  expect(stakingAmountBeforeSet).to.be.gt(safeAmount); // maxSafeAmount must be smaller than actualstaking amount so we can verify that we hit the limit for transaction amount at once
476
+ });
477
+
478
+ it("should set max liquidity percentage swap when avatar", async () => {
479
+ const originalPercentage = await donationsStaking.maxLiquidityPercentageSwap();
480
+ //fail when not avatar
481
+ const percentageToSet = 21;
482
+ expect(donationsStaking.connect(staker)["setMaxLiquidityPercentageSwap(uint24)"](percentageToSet)).
483
+ to.be.revertedWith("only avatar can call this method");
484
+ //succeed when avatar
485
+ let encodedData = donationsStaking.interface.encodeFunctionData(
486
+ "setMaxLiquidityPercentageSwap",
487
+ [percentageToSet]
488
+ );
489
+ await genericCall(donationsStaking.address, encodedData);
490
+ const actualPercentage = await donationsStaking.maxLiquidityPercentageSwap();
491
+ expect(actualPercentage).to.be.equal(percentageToSet);
492
+ //revent to original state
493
+ encodedData = donationsStaking.interface.encodeFunctionData(
494
+ "setMaxLiquidityPercentageSwap",
495
+ [originalPercentage]
496
+ );
400
497
  });
401
498
 
402
499
  it("it should return version of DonationsStaking properly", async () => {
403
500
  const version = await donationsStaking.getVersion();
404
501
  expect(version).to.be.equal("2.0.0");
405
502
  });
406
- });
503
+ });
@@ -1,7 +1,7 @@
1
1
  import { default as hre, ethers, upgrades } from "hardhat";
2
2
  import { deployMockContract, MockContract } from "ethereum-waffle";
3
3
  import { expect } from "chai";
4
- import { CERC20, GoodAaveStaking, AaveStakingFactory } from "../../types";
4
+ import { CERC20, GoodAaveStaking, GoodAaveStakingV2, AaveStakingFactory } from "../../types";
5
5
  import { createDAO, deployUniswap } from "../helpers";
6
6
  import { Contract } from "ethers";
7
7
 
@@ -122,4 +122,39 @@ describe("AaveStakingFactory", () => {
122
122
  expect(await staking.name()).to.equal("GoodAaveStakingV2 USDC");
123
123
  expect(await staking.symbol()).to.equal("gaUSDC");
124
124
  });
125
+
126
+ it("should revert implementation on invalid initialization", async () => {
127
+ const goodAaveStakingV2 = (await ethers.getContractAt(
128
+ "GoodAaveStakingV2",
129
+ await stakingFactory.impl()
130
+ )) as GoodAaveStakingV2;
131
+ await expect(goodAaveStakingV2.init(
132
+ usdc.address,
133
+ lendingPool.address,
134
+ dao.nameService.address,
135
+ "USDC",
136
+ "USDC",
137
+ 5760,
138
+ stakingFactory.address,
139
+ incentiveController.address,
140
+ aaveUsdOracle.address,
141
+ [cdai, dai] // violates tokenToDaiSwapPath[0] == _token (cdai != usdc)
142
+ )).to.be.revertedWith(
143
+ "invalid _tokenToDaiSwapPath"
144
+ );
145
+ await expect(goodAaveStakingV2.init(
146
+ usdc.address,
147
+ lendingPool.address,
148
+ dao.nameService.address,
149
+ "USDC",
150
+ "USDC",
151
+ 5760,
152
+ stakingFactory.address,
153
+ incentiveController.address,
154
+ aaveUsdOracle.address,
155
+ [usdc.address, cdai] // violates _tokenToDaiSwapPath[] path leading to dai
156
+ )).to.be.revertedWith(
157
+ "invalid _tokenToDaiSwapPath"
158
+ );
159
+ });
125
160
  });
@@ -32,7 +32,8 @@ describe("SimpleDAISTAking - staking with cDAI mocks", () => {
32
32
  setDAOAddress,
33
33
  initializeToken,
34
34
  goodCompoundStakingFactory,
35
- deployStaking;
35
+ deployStaking,
36
+ runAsAvatarOnly;
36
37
 
37
38
  before(async () => {
38
39
  [founder, staker, ...signers] = await ethers.getSigners();
@@ -55,7 +56,8 @@ describe("SimpleDAISTAking - staking with cDAI mocks", () => {
55
56
  daiAddress,
56
57
  cdaiAddress,
57
58
  reserve,
58
- setReserveToken
59
+ setReserveToken,
60
+ runAsAvatarOnly: raao,
59
61
  } = await createDAO();
60
62
  dai = await ethers.getContractAt("DAIMock", daiAddress);
61
63
  cDAI = await ethers.getContractAt("cDAIMock", cdaiAddress);
@@ -63,6 +65,7 @@ describe("SimpleDAISTAking - staking with cDAI mocks", () => {
63
65
  controller = ctrl;
64
66
  setDAOAddress = sda;
65
67
  nameService = ns;
68
+ runAsAvatarOnly = raao;
66
69
  initializeToken = setReserveToken;
67
70
  goodReserve = reserve as GoodReserveCDai;
68
71
 
@@ -1258,6 +1261,33 @@ describe("SimpleDAISTAking - staking with cDAI mocks", () => {
1258
1261
  );
1259
1262
  });
1260
1263
 
1264
+ it("should not be able to withdraw stake when the withdrawn amount is higher than the staked amount", async () => {
1265
+ const stakeAmount = ethers.utils.parseEther("100");
1266
+ const higherThanStakeAmount = ethers.utils.parseEther("101");
1267
+ await cDAI["mint(address,uint256)"](
1268
+ staker.address,
1269
+ stakeAmount
1270
+ );
1271
+ await cDAI
1272
+ .connect(staker)
1273
+ .approve(goodCompoundStaking.address, higherThanStakeAmount);
1274
+
1275
+ await goodCompoundStaking
1276
+ .connect(staker)
1277
+ .stake(stakeAmount, "100", true);
1278
+
1279
+ const tx = await goodCompoundStaking
1280
+ .connect(staker)
1281
+ .withdrawStake(higherThanStakeAmount, true)
1282
+ .catch(e => e);
1283
+
1284
+ expect(tx.message).to.be.not.empty;
1285
+ // revent to original state
1286
+ await goodCompoundStaking
1287
+ .connect(staker)
1288
+ .withdrawStake(stakeAmount, true);
1289
+ });
1290
+
1261
1291
  it("should pause the contract", async () => {
1262
1292
  let encodedCall = goodCompoundStakingFactory.interface.encodeFunctionData(
1263
1293
  "pause",
@@ -1423,4 +1453,24 @@ describe("SimpleDAISTAking - staking with cDAI mocks", () => {
1423
1453
  ).catch(e => e);
1424
1454
  expect(simpleStaking.message).to.be.not.empty;
1425
1455
  });
1456
+
1457
+ it("should set max liquidity percentage swap when avatar", async () => {
1458
+ goodCompoundStaking = await deployStaking();
1459
+ const percentageBeforeSet = await goodCompoundStaking.maxLiquidityPercentageSwap();
1460
+ const percentageToSet = 21;
1461
+ await runAsAvatarOnly(
1462
+ goodCompoundStaking,
1463
+ "setMaxLiquidityPercentageSwap(uint24)",
1464
+ percentageToSet
1465
+ )
1466
+ const percentageAfterSet = await goodCompoundStaking.maxLiquidityPercentageSwap();
1467
+ expect(percentageAfterSet).to.be.equal(percentageToSet);
1468
+ expect(percentageAfterSet).to.not.equal(percentageBeforeSet);
1469
+ });
1470
+
1471
+ it("should get decimals equal to token demials", async () => {
1472
+ goodCompoundStaking = await deployStaking();
1473
+ expect(await goodCompoundStaking.decimals()).to.equal(await dai.decimals());
1474
+ expect(await goodCompoundStaking.decimals()).to.equal(18);
1475
+ });
1426
1476
  });
@@ -614,6 +614,44 @@ describe("StakingRewards - staking with cDAI mocks and get Rewards in GoodDollar
614
614
  .withdrawStake(stakingAmount, false);
615
615
  });
616
616
 
617
+ it("should get user minted and pending rewards", async () => {
618
+ const goodFundManagerFactory = await ethers.getContractFactory(
619
+ "GoodFundManager"
620
+ );
621
+ const currentBlockNumber = await ethers.provider.getBlockNumber();
622
+ const encodedData = goodFundManagerFactory.interface.encodeFunctionData(
623
+ "setStakingReward",
624
+ [
625
+ "1000",
626
+ goodCompoundStaking.address,
627
+ currentBlockNumber,
628
+ currentBlockNumber + 5000,
629
+ false
630
+ ] // set 10 gd per block
631
+ );
632
+ await genericCall(goodFundManager.address, encodedData, avatar, 0);
633
+
634
+ const stakingAmount = ethers.utils.parseEther("100");
635
+
636
+ await dai["mint(address,uint256)"](staker.address, stakingAmount);
637
+ await dai
638
+ .connect(staker)
639
+ .approve(goodCompoundStaking.address, stakingAmount);
640
+ await goodCompoundStaking.connect(staker).stake(stakingAmount, 0, false);
641
+
642
+ await advanceBlocks(4);
643
+
644
+ const userMintedAndPending = await goodCompoundStaking.getUserMintedAndPending(staker.address);
645
+ const userMintedReward = userMintedAndPending[0].toString();
646
+ const userPendingReward = userMintedAndPending[1].toString();
647
+ expect(userMintedReward).to.equal("5000");
648
+ expect(userPendingReward).to.equal("2000");
649
+
650
+ await goodCompoundStaking
651
+ .connect(staker)
652
+ .withdrawStake(stakingAmount, false);
653
+ });
654
+
617
655
  it("it should get rewards with 1x multiplier for after threshold pass", async () => {
618
656
  const goodFundManagerFactory = await ethers.getContractFactory(
619
657
  "GoodFundManager"
@@ -29,7 +29,10 @@ describe("UsdcAaveStakingV2 - staking with USDC mocks to AAVE interface", () =>
29
29
  lendingPool,
30
30
  setDAOAddress,
31
31
  genericCall,
32
- goodAaveStakingFactory;
32
+ goodAaveStakingFactory,
33
+ runAsAvatarOnly,
34
+ deployStaking;
35
+
33
36
  before(async () => {
34
37
  [founder, staker, ...signers] = await ethers.getSigners();
35
38
  schemeMock = signers.pop();
@@ -55,7 +58,8 @@ describe("UsdcAaveStakingV2 - staking with USDC mocks to AAVE interface", () =>
55
58
  marketMaker: mm,
56
59
  daiAddress,
57
60
  genericCall: gc,
58
- COMP
61
+ COMP,
62
+ runAsAvatarOnly: raao
59
63
  } = await createDAO();
60
64
  dai = await ethers.getContractAt("DAIMock", daiAddress);
61
65
  avatar = av;
@@ -63,6 +67,7 @@ describe("UsdcAaveStakingV2 - staking with USDC mocks to AAVE interface", () =>
63
67
  setDAOAddress = sda;
64
68
  nameService = ns;
65
69
  genericCall = gc;
70
+ runAsAvatarOnly = raao;
66
71
  console.log("deployed dao", {
67
72
  founder: founder.address,
68
73
  gd,
@@ -133,23 +138,26 @@ describe("UsdcAaveStakingV2 - staking with USDC mocks to AAVE interface", () =>
133
138
  await ethers.getContractFactory("AaveUSDMockOracle")
134
139
  ).deploy();
135
140
  await setDAOAddress("AAVE", aave.address);
136
- goodAaveStaking = await goodAaveStakingFactory
137
- .deploy()
138
- .then(async contract => {
139
- await contract.init(
140
- usdc.address,
141
- lendingPool.address,
142
- nameService.address,
143
- "Good USDC",
144
- "gUSDC",
145
- "172800",
146
- daiUsdOracle.address,
147
- incentiveController.address,
148
- aaveUsdOracle.address,
149
- [usdc.address, dai.address]
150
- );
151
- return contract;
152
- });
141
+ deployStaking = async () => {
142
+ return await goodAaveStakingFactory
143
+ .deploy()
144
+ .then(async contract => {
145
+ await contract.init(
146
+ usdc.address,
147
+ lendingPool.address,
148
+ nameService.address,
149
+ "Good USDC",
150
+ "gUSDC",
151
+ "172800",
152
+ daiUsdOracle.address,
153
+ incentiveController.address,
154
+ aaveUsdOracle.address,
155
+ [usdc.address, dai.address]
156
+ );
157
+ return contract;
158
+ });
159
+ };
160
+ goodAaveStaking = await deployStaking();
153
161
  await usdc["mint(address,uint256)"](
154
162
  founder.address,
155
163
  ethers.utils.parseUnits("500000000000000", 6)
@@ -306,4 +314,22 @@ describe("UsdcAaveStakingV2 - staking with USDC mocks to AAVE interface", () =>
306
314
  await token1.transfer(pair.address, token1Amount);
307
315
  await pair.mint(founder.address);
308
316
  }
317
+
318
+ it("should set gas cost to interest collection parameters", async () => {
319
+ const stakingContract = await deployStaking();
320
+ const collectGasCostBefore = await stakingContract.collectInterestGasCost();
321
+ const claimStakeGasCostBefore = await stakingContract.collectInterestGasCost();
322
+ await runAsAvatarOnly(
323
+ stakingContract,
324
+ "setcollectInterestGasCostParams(uint32,uint32)",
325
+ 999,
326
+ 999
327
+ )
328
+ const collectGasCostAfter = await stakingContract.collectInterestGasCost();
329
+ const claimStakeGasCostAfter = await stakingContract.collectInterestGasCost();
330
+ expect(collectGasCostAfter).to.not.equal(collectGasCostBefore);
331
+ expect(collectGasCostAfter).to.equal(999);
332
+ expect(claimStakeGasCostAfter).to.not.equal(claimStakeGasCostBefore);
333
+ expect(claimStakeGasCostAfter).to.equal(999);
334
+ });
309
335
  });