@harvest-finance/harvest-strategy-arbitrum 0.0.1-security → 1.0.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.

Potentially problematic release.


This version of @harvest-finance/harvest-strategy-arbitrum might be problematic. Click here for more details.

Files changed (199) hide show
  1. package/README.md +127 -5
  2. package/contracts/base/Controller.sol +358 -0
  3. package/contracts/base/Drip.sol +86 -0
  4. package/contracts/base/PotPool.sol +367 -0
  5. package/contracts/base/ProfitSharingReceiver.sol +38 -0
  6. package/contracts/base/Reader.sol +54 -0
  7. package/contracts/base/RewardForwarder.sol +109 -0
  8. package/contracts/base/VaultProxy.sol +34 -0
  9. package/contracts/base/VaultStorage.sol +205 -0
  10. package/contracts/base/VaultV1.sol +371 -0
  11. package/contracts/base/VaultV1GMX.sol +465 -0
  12. package/contracts/base/VaultV2.sol +111 -0
  13. package/contracts/base/VaultV2GMX.sol +111 -0
  14. package/contracts/base/factory/MegaFactory.sol +120 -0
  15. package/contracts/base/factory/interface/IPoolFactory.sol +6 -0
  16. package/contracts/base/factory/interface/IStrategyFactory.sol +6 -0
  17. package/contracts/base/factory/interface/IVaultFactory.sol +7 -0
  18. package/contracts/base/factory/pool/PotPoolFactory.sol +41 -0
  19. package/contracts/base/factory/strategy/UpgradableStrategyFactory.sol +19 -0
  20. package/contracts/base/factory/vault/RegularVaultFactory.sol +34 -0
  21. package/contracts/base/incentives/GlobalIncentivesExecutor.sol +85 -0
  22. package/contracts/base/incentives/GlobalIncentivesHelper.sol +174 -0
  23. package/contracts/base/incentives/NotifyHelperGeneric.sol +61 -0
  24. package/contracts/base/incentives/NotifyHelperStateful.sol +290 -0
  25. package/contracts/base/incentives/ViewerNotifyHelperStateful.sol +25 -0
  26. package/contracts/base/inheritance/Controllable.sol +25 -0
  27. package/contracts/base/inheritance/ControllableInit.sol +30 -0
  28. package/contracts/base/inheritance/Governable.sol +28 -0
  29. package/contracts/base/inheritance/GovernableInit.sol +50 -0
  30. package/contracts/base/inheritance/IUpgradeSource.sol +7 -0
  31. package/contracts/base/inheritance/OwnableWhitelist.sol +17 -0
  32. package/contracts/base/inheritance/Storage.sol +35 -0
  33. package/contracts/base/interface/IBalDex.sol +7 -0
  34. package/contracts/base/interface/IController.sol +132 -0
  35. package/contracts/base/interface/IDex.sol +9 -0
  36. package/contracts/base/interface/IERC4626.sol +261 -0
  37. package/contracts/base/interface/IGMXStrategy.sol +37 -0
  38. package/contracts/base/interface/IGlobalIncentivesHelper.sol +6 -0
  39. package/contracts/base/interface/IPotPool.sol +70 -0
  40. package/contracts/base/interface/IProfitSharingReceiver.sol +9 -0
  41. package/contracts/base/interface/IRewardForwarder.sol +57 -0
  42. package/contracts/base/interface/IStrategy.sol +37 -0
  43. package/contracts/base/interface/IUniversalLiquidator.sol +21 -0
  44. package/contracts/base/interface/IUniversalLiquidatorRegistry.sol +20 -0
  45. package/contracts/base/interface/IUpgradeSource.sol +9 -0
  46. package/contracts/base/interface/IVault.sol +58 -0
  47. package/contracts/base/interface/IVaultGMX.sol +71 -0
  48. package/contracts/base/interface/aura/IAuraBaseRewardPool.sol +25 -0
  49. package/contracts/base/interface/aura/IAuraBooster.sol +17 -0
  50. package/contracts/base/interface/aura/IAuraDepositor.sol +7 -0
  51. package/contracts/base/interface/balancer/Gauge.sol +22 -0
  52. package/contracts/base/interface/balancer/IBVault.sol +580 -0
  53. package/contracts/base/interface/balancer/IBalancerMinter.sol +114 -0
  54. package/contracts/base/interface/balancer/IGyroPool.sol +7 -0
  55. package/contracts/base/interface/balancer/linearPool/ILinearPool.sol +184 -0
  56. package/contracts/base/interface/balancer/linearPool/ILinearPoolFactory.sol +16 -0
  57. package/contracts/base/interface/balancer/linearPool/ILinearPoolRebalancer.sol +8 -0
  58. package/contracts/base/interface/balancer/linearPool/IPoolSwapStructs.sol +56 -0
  59. package/contracts/base/interface/compound/CTokenInterface.sol +29 -0
  60. package/contracts/base/interface/compound/IComptroller.sol +9 -0
  61. package/contracts/base/interface/dolomite/IDepositWithdraw.sol +13 -0
  62. package/contracts/base/interface/dolomite/IDolomiteMargin.sol +15 -0
  63. package/contracts/base/interface/dolomite/IRewardsDistributor.sol +11 -0
  64. package/contracts/base/interface/gamma/IClearing.sol +7 -0
  65. package/contracts/base/interface/gamma/IHypervisor.sol +9 -0
  66. package/contracts/base/interface/gamma/IUniProxy.sol +14 -0
  67. package/contracts/base/interface/gmx/EventUtils.sol +253 -0
  68. package/contracts/base/interface/gmx/ICallbackReceiver.sol +119 -0
  69. package/contracts/base/interface/gmx/IDataStore.sol +7 -0
  70. package/contracts/base/interface/gmx/IExchangeRouter.sol +38 -0
  71. package/contracts/base/interface/gmx/IGMXViewer.sol +7 -0
  72. package/contracts/base/interface/gmx/IHandler.sol +12 -0
  73. package/contracts/base/interface/gmx/IMarket.sol +7 -0
  74. package/contracts/base/interface/gmx/IOracle.sol +6 -0
  75. package/contracts/base/interface/gmx/IPriceFeed.sol +12 -0
  76. package/contracts/base/interface/gmx/IReader.sol +49 -0
  77. package/contracts/base/interface/gmx/IRoleStore.sol +6 -0
  78. package/contracts/base/interface/ipor/Errors.sol +20 -0
  79. package/contracts/base/interface/ipor/FuseStorageLib.sol +71 -0
  80. package/contracts/base/interface/ipor/FusesLib.sol +149 -0
  81. package/contracts/base/interface/ipor/IFuseCommon.sol +9 -0
  82. package/contracts/base/interface/ipor/IFuseInstantWithdraw.sol +14 -0
  83. package/contracts/base/interface/ipor/IMarketBalanceFuse.sol +10 -0
  84. package/contracts/base/interface/ipor/IPriceOracleMiddleware.sol +42 -0
  85. package/contracts/base/interface/ipor/IporMath.sol +110 -0
  86. package/contracts/base/interface/ipor/PlasmaVaultConfigLib.sol +106 -0
  87. package/contracts/base/interface/ipor/PlasmaVaultLib.sol +293 -0
  88. package/contracts/base/interface/ipor/PlasmaVaultStorageLib.sol +352 -0
  89. package/contracts/base/interface/merkl/IDistributor.sol +6 -0
  90. package/contracts/base/interface/notional/INProxy.sol +44 -0
  91. package/contracts/base/interface/notional/IPrimeToken.sol +6 -0
  92. package/contracts/base/interface/venus/IRewardsDistributor.sol +6 -0
  93. package/contracts/base/interface/weth/IWETH.sol +39 -0
  94. package/contracts/base/ipor/Erc4626BalanceFuse.sol +54 -0
  95. package/contracts/base/ipor/Erc4626SupplyFuse.sol +134 -0
  96. package/contracts/base/noop/NoopStrategyUpgradeable.sol +90 -0
  97. package/contracts/base/upgradability/BaseUpgradeabilityProxy.sol +60 -0
  98. package/contracts/base/upgradability/BaseUpgradeableStrategy.sol +144 -0
  99. package/contracts/base/upgradability/BaseUpgradeableStrategyStorage.sol +284 -0
  100. package/contracts/base/upgradability/IUpgradable.sol +7 -0
  101. package/contracts/base/upgradability/ReentrancyGuardUpgradeable.sol +51 -0
  102. package/contracts/base/upgradability/StrategyProxy.sol +34 -0
  103. package/contracts/strategies/aura/AuraStrategy.sol +403 -0
  104. package/contracts/strategies/aura/AuraStrategyMainnet_MORE_GYD.sol +32 -0
  105. package/contracts/strategies/aura/AuraStrategyMainnet_sUSDe_GYD.sol +31 -0
  106. package/contracts/strategies/aura/AuraStrategyMainnet_waFRAX_sFRAX.sol +31 -0
  107. package/contracts/strategies/aura/AuraStrategyMainnet_waGHO_GYD.sol +31 -0
  108. package/contracts/strategies/aura/AuraStrategyMainnet_waUSDC_GHO.sol +32 -0
  109. package/contracts/strategies/aura/AuraStrategyMainnet_waUSDC_GYD.sol +31 -0
  110. package/contracts/strategies/aura/AuraStrategyMainnet_waUSDT_GYD.sol +31 -0
  111. package/contracts/strategies/aura/AuraStrategyMainnet_wstETH_GYD.sol +31 -0
  112. package/contracts/strategies/camelot/CamelotV3Strategy.sol +304 -0
  113. package/contracts/strategies/camelot/CamelotV3StrategyMainnet_ARB_USDC.sol +28 -0
  114. package/contracts/strategies/camelot/CamelotV3StrategyMainnet_ETH_USDC.sol +28 -0
  115. package/contracts/strategies/camelot/CamelotV3StrategyMainnet_ETH_USDT.sol +28 -0
  116. package/contracts/strategies/camelot/CamelotV3StrategyMainnet_GMX_ETH.sol +28 -0
  117. package/contracts/strategies/camelot/CamelotV3StrategyMainnet_GRAIL_ETH.sol +28 -0
  118. package/contracts/strategies/camelot/CamelotV3StrategyMainnet_USDC_USDT.sol +28 -0
  119. package/contracts/strategies/camelot/CamelotV3StrategyMainnet_WBTC_ETH.sol +28 -0
  120. package/contracts/strategies/dolomite/DolomiteLendStrategy.sol +273 -0
  121. package/contracts/strategies/dolomite/DolomiteLendStrategyMainnet_DAI.sol +26 -0
  122. package/contracts/strategies/dolomite/DolomiteLendStrategyMainnet_GMX.sol +26 -0
  123. package/contracts/strategies/dolomite/DolomiteLendStrategyMainnet_USDC.sol +26 -0
  124. package/contracts/strategies/dolomite/DolomiteLendStrategyMainnet_USDCe.sol +26 -0
  125. package/contracts/strategies/dolomite/DolomiteLendStrategyMainnet_USDT.sol +26 -0
  126. package/contracts/strategies/dolomite/DolomiteLendStrategyMainnet_WBTC.sol +26 -0
  127. package/contracts/strategies/dolomite/DolomiteLendStrategyMainnet_WETH.sol +26 -0
  128. package/contracts/strategies/fluid/FluidLendStrategy.sol +241 -0
  129. package/contracts/strategies/fluid/FluidLendStrategyMainnet_ETH.sol +25 -0
  130. package/contracts/strategies/fluid/FluidLendStrategyMainnet_USDC.sol +25 -0
  131. package/contracts/strategies/fluid/FluidLendStrategyMainnet_USDT.sol +25 -0
  132. package/contracts/strategies/gmx/GMXStrategy.sol +472 -0
  133. package/contracts/strategies/gmx/GMXStrategyMainnet_WBTC.sol +25 -0
  134. package/contracts/strategies/gmx/GMXViewer.sol +110 -0
  135. package/contracts/strategies/notional/NotionalStrategy.sol +223 -0
  136. package/contracts/strategies/notional/NotionalStrategyMainnet_nETH.sol +27 -0
  137. package/contracts/strategies/notional/NotionalStrategyMainnet_nUSDC.sol +27 -0
  138. package/contracts/strategies/notional/NotionalStrategyMainnet_nUSDT.sol +27 -0
  139. package/contracts/strategies/notional/NotionalStrategyMainnet_nwstETH.sol +27 -0
  140. package/contracts/strategies/venus/VenusFoldStrategy.sol +591 -0
  141. package/contracts/strategies/venus/VenusFoldStrategyMainnet_ARB.sol +32 -0
  142. package/contracts/strategies/venus/VenusFoldStrategyMainnet_ETH_core.sol +32 -0
  143. package/contracts/strategies/venus/VenusFoldStrategyMainnet_ETH_lsd.sol +32 -0
  144. package/contracts/strategies/venus/VenusFoldStrategyMainnet_USDC.sol +32 -0
  145. package/contracts/strategies/venus/VenusFoldStrategyMainnet_USDT.sol +32 -0
  146. package/contracts/strategies/venus/VenusFoldStrategyMainnet_WBTC.sol +32 -0
  147. package/hardhat.config.js +60 -0
  148. package/index.js +42 -0
  149. package/package.json +38 -6
  150. package/scripts/01-deploy-vault-regular-with-upgradable-strategy.js +41 -0
  151. package/scripts/02-deploy-vault-regular.js +35 -0
  152. package/scripts/03-deploy-upgradable-strategy.js +40 -0
  153. package/scripts/04-deploy-new-implementation.js +24 -0
  154. package/scripts/05-deploy-GMXViewer.js +17 -0
  155. package/scripts/06-deploy-GMXVault.js +49 -0
  156. package/scripts/07-deploy-ipor-fuses.js +29 -0
  157. package/scripts/08-deploy-drip.js +20 -0
  158. package/scripts/README.md +55 -0
  159. package/scripts/utils.js +22 -0
  160. package/test/aura/more-gyd.js +140 -0
  161. package/test/aura/susde-gyd.js +140 -0
  162. package/test/aura/wafrax-sfrax.js +140 -0
  163. package/test/aura/wagho-gyd.js +140 -0
  164. package/test/aura/wausdc-gho.js +141 -0
  165. package/test/aura/wausdc-gyd.js +140 -0
  166. package/test/aura/wausdt-gyd.js +140 -0
  167. package/test/aura/wsteth-gyd.js +138 -0
  168. package/test/camelot/arb-usdc.js +125 -0
  169. package/test/camelot/eth-usdc.js +125 -0
  170. package/test/camelot/eth-usdt.js +125 -0
  171. package/test/camelot/gmx-eth.js +125 -0
  172. package/test/camelot/grail-eth.js +125 -0
  173. package/test/camelot/usdc-usdt.js +125 -0
  174. package/test/camelot/wbtc-eth.js +125 -0
  175. package/test/dolomite/dai.js +127 -0
  176. package/test/dolomite/gmx.js +134 -0
  177. package/test/dolomite/usdc.js +127 -0
  178. package/test/dolomite/usdce.js +127 -0
  179. package/test/dolomite/usdt.js +127 -0
  180. package/test/dolomite/wbtc.js +127 -0
  181. package/test/dolomite/weth.js +127 -0
  182. package/test/fluid/eth.js +127 -0
  183. package/test/fluid/usdc.js +134 -0
  184. package/test/fluid/usdt.js +134 -0
  185. package/test/gmx/wbtc.js +184 -0
  186. package/test/notional/neth.js +133 -0
  187. package/test/notional/nusdc.js +133 -0
  188. package/test/notional/nusdt.js +133 -0
  189. package/test/notional/nwsteth.js +133 -0
  190. package/test/test-config.js +28 -0
  191. package/test/utilities/Utils.js +96 -0
  192. package/test/utilities/hh-utils.js +248 -0
  193. package/test/utilities/make-vault.js +16 -0
  194. package/test/venus/arb.js +135 -0
  195. package/test/venus/eth-core.js +133 -0
  196. package/test/venus/eth-lsd.js +133 -0
  197. package/test/venus/usdc.js +133 -0
  198. package/test/venus/usdt.js +133 -0
  199. package/test/venus/wbtc.js +133 -0
package/README.md CHANGED
@@ -1,5 +1,127 @@
1
- # Security holding package
2
-
3
- This package contained malicious code and was removed from the registry by the npm security team. A placeholder was published to ensure users are not affected in the future.
4
-
5
- Please refer to www.npmjs.com/advisories?search=%40harvest-finance%2Fharvest-strategy-arbitrum for more information.
1
+ # Arbitrum Chain: Harvest Strategy Development
2
+
3
+ This [Hardhat](https://hardhat.org/) environment is configured to use Mainnet fork by default and provides templates and utilities for strategy development and testing.
4
+
5
+ ## Installation
6
+
7
+ 1. Run `npm install` to install all the dependencies.
8
+ 2. Sign up on [Alchemy](https://dashboard.alchemyapi.io/signup/). We recommend using Alchemy over Infura to allow for a reproducible
9
+ Mainnet fork testing environment as well as efficiency due to caching.
10
+ 3. Create a file `dev-keys.json`:
11
+ ```
12
+ {
13
+ "alchemyKey": "<your-alchemy-key>"
14
+ }
15
+ ```
16
+
17
+ ## Run
18
+
19
+ All tests are located under the `test` folder.
20
+
21
+ 1. Run `npx hardhat test [test file location]`: `npx hardhat test ./test/balancer/wsteth-usdc.js` (if for some reason the NodeJS heap runs out of memory, make sure to explicitly increase its size via `export NODE_OPTIONS=--max_old_space_size=4096`). This will produce the following output:
22
+ ```
23
+ Arbitrum Mainnet Balancer wstETH-USDC
24
+ Impersonating...
25
+ 0x6a74649aCFD7822ae8Fb78463a9f2192752E5Aa2
26
+ 0x0345Bc8EDdbba03E11e366cFb4E2b232b8f1b739
27
+ Fetching Underlying at: 0x178E029173417b1F9C8bC16DCeC6f697bC323746
28
+ New Vault Deployed: 0xa4B5Ad0ca0E05ea73E59046CBCb6b3641318c9d3
29
+ Strategy Deployed: 0xf47FCd7914b24676C78222Af1431f4826B368F30
30
+ Happy path
31
+ loop 0
32
+ old shareprice: 1000000000000000000
33
+ new shareprice: 1000000000000000000
34
+ growth: 1
35
+ instant APR: 0 %
36
+ instant APY: 0 %
37
+ loop 1
38
+ old shareprice: 1000000000000000000
39
+ new shareprice: 1000068403677420556
40
+ growth: 1.0000684036774206
41
+ instant APR: 26.04926042303911 %
42
+ instant APY: 29.74485660521895 %
43
+ loop 2
44
+ old shareprice: 1000068403677420556
45
+ new shareprice: 1000131319321304444
46
+ growth: 1.0000629113405168
47
+ instant APR: 23.95768699115301 %
48
+ instant APY: 27.061149684423057 %
49
+ loop 3
50
+ old shareprice: 1000131319321304444
51
+ new shareprice: 1000193897701257046
52
+ growth: 1.0000625701632813
53
+ instant APR: 23.827761013559037 %
54
+ instant APY: 26.896279294823277 %
55
+ loop 4
56
+ old shareprice: 1000193897701257046
57
+ new shareprice: 1000256321542735812
58
+ growth: 1.000062411739986
59
+ instant APR: 23.767430782293474 %
60
+ instant APY: 26.819795416465155 %
61
+ loop 5
62
+ old shareprice: 1000256321542735812
63
+ new shareprice: 1000318634555811359
64
+ growth: 1.0000622970450008
65
+ instant APR: 23.723753020397634 %
66
+ instant APY: 26.76445146036619 %
67
+ loop 6
68
+ old shareprice: 1000318634555811359
69
+ new shareprice: 1000380840931449184
70
+ growth: 1.0000621865608508
71
+ instant APR: 23.681678814655715 %
72
+ instant APY: 26.711162141078937 %
73
+ loop 7
74
+ old shareprice: 1000380840931449184
75
+ new shareprice: 1000442949039498353
76
+ growth: 1.0000620844637442
77
+ instant APR: 23.642798534864234 %
78
+ instant APY: 26.661937967659497 %
79
+ loop 8
80
+ old shareprice: 1000442949039498353
81
+ new shareprice: 1000479005035224559
82
+ growth: 1.0000360400318287
83
+ instant APR: 13.724644787553073 %
84
+ instant APY: 14.708122498585574 %
85
+ loop 9
86
+ old shareprice: 1000479005035224559
87
+ new shareprice: 1000479005035224559
88
+ growth: 1
89
+ instant APR: 0 %
90
+ instant APY: 0 %
91
+ earned!
92
+ APR: 18.24131008308575 %
93
+ APY: 20.005517445690145 %
94
+ ✔ Farmer should earn money (32947ms)
95
+
96
+
97
+ 1 passing (37s)
98
+ ```
99
+
100
+ ## Develop
101
+
102
+ Under `contracts/strategies`, there are plenty of examples to choose from in the repository already, therefore, creating a strategy is no longer a complicated task. Copy-pasting existing strategies with minor modifications is acceptable.
103
+
104
+ Under `contracts/base`, there are existing base interfaces and contracts that can speed up development.
105
+
106
+ ## Contribute
107
+
108
+ When ready, open a pull request with the following information:
109
+ 1. Instructions on how to run the test and at which block number
110
+ 2. A **mainnet fork test output** (like the one above in the README) clearly showing the increases of share price
111
+ 3. Info about the protocol, including:
112
+ - Live farm page(s)
113
+ - GitHub link(s)
114
+ - Etherscan link(s)
115
+ - Start/end dates for rewards
116
+ - Any limitations (e.g., maximum pool size)
117
+ - Current pool sizes used for liquidation (to make sure they are not too shallow)
118
+
119
+ The first few items can be omitted for well-known protocols (such as `curve.fi`).
120
+
121
+ 5. A description of **potential value** for Harvest: why should your strategy be live? High APYs, decent pool sizes, longevity of rewards, well-secured protocols, high-potential collaborations, etc.
122
+
123
+ A more extensive checklist for assessing protocols and farming opportunities can be found [here](https://www.notion.so/harvestfinance/Farm-ops-check-list-7cd2e0d9da364252ac465cb8a176f0e0)
124
+
125
+ ## Deployment
126
+
127
+ If your pull request is merged and given a green light for deployment, the Harvest team will take care of on-chain deployment.
@@ -0,0 +1,358 @@
1
+ // SPDX-License-Identifier: Unlicense
2
+ pragma solidity 0.8.26;
3
+
4
+ import "@openzeppelin/contracts/utils/Address.sol";
5
+ import "@openzeppelin/contracts/utils/math/SafeMath.sol";
6
+ import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
7
+ import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
8
+
9
+ import "./inheritance/Governable.sol";
10
+
11
+ import "./interface/IController.sol";
12
+ import "./interface/IStrategy.sol";
13
+ import "./interface/IVault.sol";
14
+
15
+ import "./RewardForwarder.sol";
16
+
17
+
18
+ contract Controller is Governable {
19
+ using SafeERC20 for IERC20;
20
+ using Address for address;
21
+ using SafeMath for uint256;
22
+
23
+ // ========================= Fields =========================
24
+
25
+ // external parties
26
+ address public targetToken;
27
+ address public protocolFeeReceiver;
28
+ address public profitSharingReceiver;
29
+ address public rewardForwarder;
30
+ address public universalLiquidator;
31
+ address public dolomiteYieldFarmingRouter;
32
+
33
+ uint256 public nextImplementationDelay;
34
+
35
+ /// 15% of fees captured go to iFARM stakers
36
+ uint256 public profitSharingNumerator = 700;
37
+ uint256 public nextProfitSharingNumerator = 0;
38
+ uint256 public nextProfitSharingNumeratorTimestamp = 0;
39
+
40
+ /// 5% of fees captured go to strategists
41
+ uint256 public strategistFeeNumerator = 0;
42
+ uint256 public nextStrategistFeeNumerator = 0;
43
+ uint256 public nextStrategistFeeNumeratorTimestamp = 0;
44
+
45
+ /// 5% of fees captured go to the devs of the platform
46
+ uint256 public platformFeeNumerator = 300;
47
+ uint256 public nextPlatformFeeNumerator = 0;
48
+ uint256 public nextPlatformFeeNumeratorTimestamp = 0;
49
+
50
+ /// used for queuing a new delay
51
+ uint256 public tempNextImplementationDelay = 0;
52
+ uint256 public tempNextImplementationDelayTimestamp = 0;
53
+
54
+ uint256 public constant MAX_TOTAL_FEE = 3000;
55
+ uint256 public constant FEE_DENOMINATOR = 10000;
56
+
57
+ /// @notice This mapping allows certain contracts to stake on a user's behalf
58
+ mapping (address => bool) public addressWhitelist;
59
+ mapping (bytes32 => bool) public codeWhitelist;
60
+
61
+ // All eligible hardWorkers that we have
62
+ mapping (address => bool) public hardWorkers;
63
+
64
+ // ========================= Events =========================
65
+
66
+ event QueueProfitSharingChange(uint profitSharingNumerator, uint validAtTimestamp);
67
+ event ConfirmProfitSharingChange(uint profitSharingNumerator);
68
+
69
+ event QueueStrategistFeeChange(uint strategistFeeNumerator, uint validAtTimestamp);
70
+ event ConfirmStrategistFeeChange(uint strategistFeeNumerator);
71
+
72
+ event QueuePlatformFeeChange(uint platformFeeNumerator, uint validAtTimestamp);
73
+ event ConfirmPlatformFeeChange(uint platformFeeNumerator);
74
+
75
+ event QueueNextImplementationDelay(uint implementationDelay, uint validAtTimestamp);
76
+ event ConfirmNextImplementationDelay(uint implementationDelay);
77
+
78
+ event AddedAddressToWhitelist(address indexed _address);
79
+ event RemovedAddressFromWhitelist(address indexed _address);
80
+
81
+ event AddedCodeToWhitelist(address indexed _address);
82
+ event RemovedCodeFromWhitelist(address indexed _address);
83
+
84
+ event SharePriceChangeLog(
85
+ address indexed vault,
86
+ address indexed strategy,
87
+ uint256 oldSharePrice,
88
+ uint256 newSharePrice,
89
+ uint256 timestamp
90
+ );
91
+
92
+ // ========================= Modifiers =========================
93
+
94
+ modifier onlyHardWorkerOrGovernance() {
95
+ require(hardWorkers[msg.sender] || (msg.sender == governance()),
96
+ "only hard worker can call this");
97
+ _;
98
+ }
99
+
100
+ constructor(
101
+ address _storage,
102
+ address _targetToken,
103
+ address _protocolFeeReceiver,
104
+ address _profitSharingReceiver,
105
+ address _rewardForwarder,
106
+ address _universalLiquidator,
107
+ uint _nextImplementationDelay
108
+ )
109
+ Governable(_storage)
110
+ {
111
+ require(_targetToken != address(0), "_targetToken should not be empty");
112
+ require(_protocolFeeReceiver != address(0), "_protocolFeeReceiver should not be empty");
113
+ require(_profitSharingReceiver != address(0), "_profitSharingReceiver should not be empty");
114
+ require(_rewardForwarder != address(0), "_rewardForwarder should not be empty");
115
+ require(_nextImplementationDelay > 0, "_nextImplementationDelay should be gt 0");
116
+
117
+ targetToken = _targetToken;
118
+ protocolFeeReceiver = _protocolFeeReceiver;
119
+ profitSharingReceiver = _profitSharingReceiver;
120
+ rewardForwarder = _rewardForwarder;
121
+ universalLiquidator = _universalLiquidator;
122
+ nextImplementationDelay = _nextImplementationDelay;
123
+ }
124
+
125
+ // [Grey list]
126
+ // An EOA can safely interact with the system no matter what.
127
+ // If you're using Metamask, you're using an EOA.
128
+ // Only smart contracts may be affected by this grey list.
129
+ //
130
+ // This contract will not be able to ban any EOA from the system
131
+ // even if an EOA is being added to the greyList, he/she will still be able
132
+ // to interact with the whole system as if nothing happened.
133
+ // Only smart contracts will be affected by being added to the greyList.
134
+ function greyList(address _addr) public view returns (bool) {
135
+ return !addressWhitelist[_addr] && !codeWhitelist[getContractHash(_addr)];
136
+ }
137
+
138
+ // Only smart contracts will be affected by the whitelist.
139
+ function addToWhitelist(address _target) public onlyGovernance {
140
+ addressWhitelist[_target] = true;
141
+ emit AddedAddressToWhitelist(_target);
142
+ }
143
+
144
+ function addMultipleToWhitelist(address[] memory _targets) public onlyGovernance {
145
+ for (uint256 i = 0; i < _targets.length; i++) {
146
+ addressWhitelist[_targets[i]] = true;
147
+ }
148
+ }
149
+
150
+ function removeFromWhitelist(address _target) public onlyGovernance {
151
+ addressWhitelist[_target] = false;
152
+ emit RemovedAddressFromWhitelist(_target);
153
+ }
154
+
155
+ function removeMultipleFromWhitelist(address[] memory _targets) public onlyGovernance {
156
+ for (uint256 i = 0; i < _targets.length; i++) {
157
+ addressWhitelist[_targets[i]] = false;
158
+ }
159
+ }
160
+
161
+ function getContractHash(address a) public view returns (bytes32 hash) {
162
+ assembly {
163
+ hash := extcodehash(a)
164
+ }
165
+ }
166
+
167
+ function addCodeToWhitelist(address _target) public onlyGovernance {
168
+ codeWhitelist[getContractHash(_target)] = true;
169
+ emit AddedCodeToWhitelist(_target);
170
+ }
171
+
172
+ function removeCodeFromWhitelist(address _target) public onlyGovernance {
173
+ codeWhitelist[getContractHash(_target)] = false;
174
+ emit RemovedCodeFromWhitelist(_target);
175
+ }
176
+
177
+ function setRewardForwarder(address _rewardForwarder) public onlyGovernance {
178
+ require(_rewardForwarder != address(0), "new reward forwarder should not be empty");
179
+ rewardForwarder = _rewardForwarder;
180
+ }
181
+
182
+ function setTargetToken(address _targetToken) public onlyGovernance {
183
+ require(_targetToken != address(0), "new target token should not be empty");
184
+ targetToken = _targetToken;
185
+ }
186
+
187
+ function setProfitSharingReceiver(address _profitSharingReceiver) public onlyGovernance {
188
+ require(_profitSharingReceiver != address(0), "new profit sharing receiver should not be empty");
189
+ profitSharingReceiver = _profitSharingReceiver;
190
+ }
191
+
192
+ function setProtocolFeeReceiver(address _protocolFeeReceiver) public onlyGovernance {
193
+ require(_protocolFeeReceiver != address(0), "new protocol fee receiver should not be empty");
194
+ protocolFeeReceiver = _protocolFeeReceiver;
195
+ }
196
+
197
+ function setUniversalLiquidator(address _universalLiquidator) public onlyGovernance {
198
+ require(_universalLiquidator != address(0), "new universal liquidator should not be empty");
199
+ universalLiquidator = _universalLiquidator;
200
+ }
201
+
202
+ function setDolomiteYieldFarmingRouter(address _dolomiteYieldFarmingRouter) public onlyGovernance {
203
+ require(_dolomiteYieldFarmingRouter != address(0), "new reward forwarder should not be empty");
204
+ dolomiteYieldFarmingRouter = _dolomiteYieldFarmingRouter;
205
+ }
206
+
207
+ function getPricePerFullShare(address _vault) public view returns (uint256) {
208
+ return IVault(_vault).getPricePerFullShare();
209
+ }
210
+
211
+ function doHardWork(address _vault) external onlyHardWorkerOrGovernance {
212
+ uint256 oldSharePrice = IVault(_vault).getPricePerFullShare();
213
+ IVault(_vault).doHardWork();
214
+ emit SharePriceChangeLog(
215
+ _vault,
216
+ IVault(_vault).strategy(),
217
+ oldSharePrice,
218
+ IVault(_vault).getPricePerFullShare(),
219
+ block.timestamp
220
+ );
221
+ }
222
+
223
+ function addHardWorker(address _worker) public onlyGovernance {
224
+ require(_worker != address(0), "_worker must be defined");
225
+ hardWorkers[_worker] = true;
226
+ }
227
+
228
+ function removeHardWorker(address _worker) public onlyGovernance {
229
+ require(_worker != address(0), "_worker must be defined");
230
+ hardWorkers[_worker] = false;
231
+ }
232
+
233
+ // transfers token in the controller contract to the governance
234
+ function salvage(address _token, uint256 _amount) external onlyGovernance {
235
+ IERC20(_token).safeTransfer(governance(), _amount);
236
+ }
237
+
238
+ function salvageStrategy(address _strategy, address _token, uint256 _amount) external onlyGovernance {
239
+ // the strategy is responsible for maintaining the list of
240
+ // salvageable tokens, to make sure that governance cannot come
241
+ // in and take away the coins
242
+ IStrategy(_strategy).salvageToken(governance(), _token, _amount);
243
+ }
244
+
245
+ function feeDenominator() public pure returns (uint) {
246
+ // keep the interface for this function as a `view` for now, in case it changes in the future
247
+ return FEE_DENOMINATOR;
248
+ }
249
+
250
+ function setProfitSharingNumerator(uint _profitSharingNumerator) public onlyGovernance {
251
+ require(
252
+ _profitSharingNumerator + strategistFeeNumerator + platformFeeNumerator <= MAX_TOTAL_FEE,
253
+ "total fee too high"
254
+ );
255
+
256
+ nextProfitSharingNumerator = _profitSharingNumerator;
257
+ nextProfitSharingNumeratorTimestamp = block.timestamp + nextImplementationDelay;
258
+ emit QueueProfitSharingChange(nextProfitSharingNumerator, nextProfitSharingNumeratorTimestamp);
259
+ }
260
+
261
+ function confirmSetProfitSharingNumerator() public onlyGovernance {
262
+ require(
263
+ nextProfitSharingNumerator != 0
264
+ && nextProfitSharingNumeratorTimestamp != 0
265
+ && block.timestamp >= nextProfitSharingNumeratorTimestamp,
266
+ "invalid timestamp or no new profit sharing numerator confirmed"
267
+ );
268
+ require(
269
+ nextProfitSharingNumerator + strategistFeeNumerator + platformFeeNumerator <= MAX_TOTAL_FEE,
270
+ "total fee too high"
271
+ );
272
+
273
+ profitSharingNumerator = nextProfitSharingNumerator;
274
+ nextProfitSharingNumerator = 0;
275
+ nextProfitSharingNumeratorTimestamp = 0;
276
+ emit ConfirmProfitSharingChange(profitSharingNumerator);
277
+ }
278
+
279
+ function setStrategistFeeNumerator(uint _strategistFeeNumerator) public onlyGovernance {
280
+ require(
281
+ _strategistFeeNumerator + platformFeeNumerator + profitSharingNumerator <= MAX_TOTAL_FEE,
282
+ "total fee too high"
283
+ );
284
+
285
+ nextStrategistFeeNumerator = _strategistFeeNumerator;
286
+ nextStrategistFeeNumeratorTimestamp = block.timestamp + nextImplementationDelay;
287
+ emit QueueStrategistFeeChange(nextStrategistFeeNumerator, nextStrategistFeeNumeratorTimestamp);
288
+ }
289
+
290
+ function confirmSetStrategistFeeNumerator() public onlyGovernance {
291
+ require(
292
+ nextStrategistFeeNumerator != 0
293
+ && nextStrategistFeeNumeratorTimestamp != 0
294
+ && block.timestamp >= nextStrategistFeeNumeratorTimestamp,
295
+ "invalid timestamp or no new strategist fee numerator confirmed"
296
+ );
297
+ require(
298
+ nextStrategistFeeNumerator + platformFeeNumerator + profitSharingNumerator <= MAX_TOTAL_FEE,
299
+ "total fee too high"
300
+ );
301
+
302
+ strategistFeeNumerator = nextStrategistFeeNumerator;
303
+ nextStrategistFeeNumerator = 0;
304
+ nextStrategistFeeNumeratorTimestamp = 0;
305
+ emit ConfirmStrategistFeeChange(strategistFeeNumerator);
306
+ }
307
+
308
+ function setPlatformFeeNumerator(uint _platformFeeNumerator) public onlyGovernance {
309
+ require(
310
+ _platformFeeNumerator + strategistFeeNumerator + profitSharingNumerator <= MAX_TOTAL_FEE,
311
+ "total fee too high"
312
+ );
313
+
314
+ nextPlatformFeeNumerator = _platformFeeNumerator;
315
+ nextPlatformFeeNumeratorTimestamp = block.timestamp + nextImplementationDelay;
316
+ emit QueuePlatformFeeChange(nextPlatformFeeNumerator, nextPlatformFeeNumeratorTimestamp);
317
+ }
318
+
319
+ function confirmSetPlatformFeeNumerator() public onlyGovernance {
320
+ require(
321
+ nextPlatformFeeNumerator != 0
322
+ && nextPlatformFeeNumeratorTimestamp != 0
323
+ && block.timestamp >= nextPlatformFeeNumeratorTimestamp,
324
+ "invalid timestamp or no new platform fee numerator confirmed"
325
+ );
326
+ require(
327
+ nextPlatformFeeNumerator + strategistFeeNumerator + profitSharingNumerator <= MAX_TOTAL_FEE,
328
+ "total fee too high"
329
+ );
330
+
331
+ platformFeeNumerator = nextPlatformFeeNumerator;
332
+ nextPlatformFeeNumerator = 0;
333
+ nextPlatformFeeNumeratorTimestamp = 0;
334
+ emit ConfirmPlatformFeeChange(platformFeeNumerator);
335
+ }
336
+
337
+ function setNextImplementationDelay(uint256 _nextImplementationDelay) public onlyGovernance {
338
+ require(
339
+ _nextImplementationDelay > 0,
340
+ "invalid _nextImplementationDelay"
341
+ );
342
+
343
+ tempNextImplementationDelay = _nextImplementationDelay;
344
+ tempNextImplementationDelayTimestamp = block.timestamp + nextImplementationDelay;
345
+ emit QueueNextImplementationDelay(tempNextImplementationDelay, tempNextImplementationDelayTimestamp);
346
+ }
347
+
348
+ function confirmNextImplementationDelay() public onlyGovernance {
349
+ require(
350
+ tempNextImplementationDelayTimestamp != 0 && block.timestamp >= tempNextImplementationDelayTimestamp,
351
+ "invalid timestamp or no new implementation delay confirmed"
352
+ );
353
+ nextImplementationDelay = tempNextImplementationDelay;
354
+ tempNextImplementationDelay = 0;
355
+ tempNextImplementationDelayTimestamp = 0;
356
+ emit ConfirmNextImplementationDelay(nextImplementationDelay);
357
+ }
358
+ }
@@ -0,0 +1,86 @@
1
+ // SPDX-License-Identifier: Unlicense
2
+ pragma solidity 0.8.26;
3
+
4
+ import "@openzeppelin/contracts/utils/Address.sol";
5
+ import "@openzeppelin/contracts/utils/math/Math.sol";
6
+ import "@openzeppelin/contracts/utils/math/SafeMath.sol";
7
+ import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
8
+ import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
9
+
10
+ import "./inheritance/Controllable.sol";
11
+ import "./interface/IERC4626.sol";
12
+
13
+ contract Drip is Controllable {
14
+ using SafeERC20 for IERC20;
15
+ using Address for address;
16
+ using SafeMath for uint256;
17
+
18
+ event DripAdded(DripMode mode, address vault, uint256 perSecond);
19
+ event DripRemoved(DripMode mode, address vault, uint256 perSecond);
20
+ event Dripped(address vault, uint256 amount);
21
+
22
+ enum DripMode { TokenAmount, FixedRate}
23
+
24
+ struct DripInfo {
25
+ DripMode mode;
26
+ address vault;
27
+ uint256 perSecond;
28
+ uint256 lastDripTime;
29
+ }
30
+
31
+ DripInfo[] public drips;
32
+
33
+ constructor(address _storage) Controllable(_storage) {}
34
+
35
+ function addDrip(DripMode _mode, address _vault, uint256 _perSecond) public onlyGovernance {
36
+ drips.push(DripInfo({
37
+ mode: _mode,
38
+ vault: _vault,
39
+ perSecond: _perSecond,
40
+ lastDripTime: block.timestamp
41
+ }));
42
+ emit DripAdded(_mode, _vault, _perSecond);
43
+ }
44
+
45
+ function removeDrip(uint256 _dripIndex) public onlyGovernance {
46
+ require(_dripIndex < drips.length, "Invalid index");
47
+ emit DripRemoved(drips[_dripIndex].mode, drips[_dripIndex].vault, drips[_dripIndex].perSecond);
48
+ drips[_dripIndex] = drips[drips.length - 1];
49
+ drips.pop();
50
+ }
51
+
52
+ function drip(uint256 _dripIndex) public {
53
+ require(_dripIndex < drips.length, "Invalid index");
54
+ DripInfo storage dripInfo = drips[_dripIndex];
55
+ uint256 timePassed = block.timestamp.sub(dripInfo.lastDripTime);
56
+ if (timePassed > 0) {
57
+ address token = IERC4626(dripInfo.vault).asset();
58
+ uint256 amount;
59
+ if (dripInfo.mode == DripMode.TokenAmount) {
60
+ amount = dripInfo.perSecond.mul(timePassed);
61
+ } else if (dripInfo.mode == DripMode.FixedRate) {
62
+ uint256 totalAssets = IERC4626(dripInfo.vault).totalAssets();
63
+ uint256 rate = dripInfo.perSecond.mul(timePassed);
64
+ amount = totalAssets.mul(rate).div(1e18);
65
+ } else {
66
+ revert("Invalid drip mode");
67
+ }
68
+ uint256 balance = IERC20(token).balanceOf(address(this));
69
+ if (Math.min(amount, balance) > 0) {
70
+ dripInfo.lastDripTime = block.timestamp;
71
+ IERC20(token).safeTransfer(dripInfo.vault, Math.min(amount, balance));
72
+ emit Dripped(dripInfo.vault, Math.min(amount, balance));
73
+ }
74
+ }
75
+ }
76
+
77
+ function dripAll() public {
78
+ for (uint256 i = 0; i < drips.length; i++) {
79
+ drip(i);
80
+ }
81
+ }
82
+
83
+ function salvage(address _token, uint256 _amount) public onlyGovernance {
84
+ IERC20(_token).safeTransfer(governance(), _amount);
85
+ }
86
+ }