@harvest-finance/harvest-strategy-arbitrum 0.0.1-security → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

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 +39 -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
@@ -0,0 +1,205 @@
1
+ // SPDX-License-Identifier: Unlicense
2
+ pragma solidity 0.8.26;
3
+
4
+ import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
5
+
6
+ contract VaultStorage is Initializable {
7
+
8
+ bytes32 internal constant _STRATEGY_SLOT = 0xf1a169aa0f736c2813818fdfbdc5755c31e0839c8f49831a16543496b28574ea;
9
+ bytes32 internal constant _UNDERLYING_SLOT = 0x1994607607e11d53306ef62e45e3bd85762c58d9bf38b5578bc4a258a26a7371;
10
+ bytes32 internal constant _UNDERLYING_UNIT_SLOT = 0xa66bc57d4b4eed7c7687876ca77997588987307cb13ecc23f5e52725192e5fff;
11
+ bytes32 internal constant _VAULT_FRACTION_TO_INVEST_NUMERATOR_SLOT = 0x39122c9adfb653455d0c05043bd52fcfbc2be864e832efd3abc72ce5a3d7ed5a;
12
+ bytes32 internal constant _VAULT_FRACTION_TO_INVEST_DENOMINATOR_SLOT = 0x469a3bad2fab7b936c45eecd1f5da52af89cead3e2ed7f732b6f3fc92ed32308;
13
+ bytes32 internal constant _NEXT_IMPLEMENTATION_SLOT = 0xb1acf527cd7cd1668b30e5a9a1c0d845714604de29ce560150922c9d8c0937df;
14
+ bytes32 internal constant _NEXT_IMPLEMENTATION_TIMESTAMP_SLOT = 0x3bc747f4b148b37be485de3223c90b4468252967d2ea7f9fcbd8b6e653f434c9;
15
+ bytes32 internal constant _NEXT_STRATEGY_SLOT = 0xcd7bd9250b0e02f3b13eccf8c73ef5543cb618e0004628f9ca53b65fbdbde2d0;
16
+ bytes32 internal constant _NEXT_STRATEGY_TIMESTAMP_SLOT = 0x5d2b24811886ad126f78c499d71a932a5435795e4f2f6552f0900f12d663cdcf;
17
+ bytes32 internal constant _INVEST_ON_DEPOSIT_SLOT = 0xf7bd21df2fc19bd074b391db8b42bdc473ae2e1b3067fdb7b05f39bd9eda16ea;
18
+ bytes32 internal constant _COMPOUND_ON_WITHDRAW_SLOT = 0x724ff40d01b658bcc822d9ceb05c9e2f446998b3033585f9bcac7fd7929aaca7;
19
+ bytes32 internal constant _PAUSED_SLOT = 0xf1cf856d03630b74791fc293cfafd739932a5a075b02d357fb7a726a38777930;
20
+ bytes32 internal constant _DECIMALS_SLOT = 0x246bc3666321037fcc8ce5afddcaab1759373f2b839e69dcb1f4c90cffa41f37;
21
+
22
+ /**
23
+ * @dev Storage slot with the address of the current implementation.
24
+ * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
25
+ * validated in the constructor.
26
+ */
27
+ bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
28
+
29
+ constructor() {
30
+ assert(_STRATEGY_SLOT == bytes32(uint256(keccak256("eip1967.vaultStorage.strategy")) - 1));
31
+ assert(_UNDERLYING_SLOT == bytes32(uint256(keccak256("eip1967.vaultStorage.underlying")) - 1));
32
+ assert(_UNDERLYING_UNIT_SLOT == bytes32(uint256(keccak256("eip1967.vaultStorage.underlyingUnit")) - 1));
33
+ assert(_VAULT_FRACTION_TO_INVEST_NUMERATOR_SLOT == bytes32(uint256(keccak256("eip1967.vaultStorage.vaultFractionToInvestNumerator")) - 1));
34
+ assert(_VAULT_FRACTION_TO_INVEST_DENOMINATOR_SLOT == bytes32(uint256(keccak256("eip1967.vaultStorage.vaultFractionToInvestDenominator")) - 1));
35
+ assert(_NEXT_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256("eip1967.vaultStorage.nextImplementation")) - 1));
36
+ assert(_NEXT_IMPLEMENTATION_TIMESTAMP_SLOT == bytes32(uint256(keccak256("eip1967.vaultStorage.nextImplementationTimestamp")) - 1));
37
+ assert(_NEXT_STRATEGY_SLOT == bytes32(uint256(keccak256("eip1967.vaultStorage.nextStrategy")) - 1));
38
+ assert(_NEXT_STRATEGY_TIMESTAMP_SLOT == bytes32(uint256(keccak256("eip1967.vaultStorage.nextStrategyTimestamp")) - 1));
39
+ assert(_INVEST_ON_DEPOSIT_SLOT == bytes32(uint256(keccak256("eip1967.vaultStorage.investOnDeposit")) - 1));
40
+ assert(_COMPOUND_ON_WITHDRAW_SLOT == bytes32(uint256(keccak256("eip1967.vaultStorage.compoundOnWithdraw")) - 1));
41
+ assert(_PAUSED_SLOT == bytes32(uint256(keccak256("eip1967.vaultStorage.paused")) - 1));
42
+ assert(_DECIMALS_SLOT == bytes32(uint256(keccak256("eip1967.vaultStorage.decimals")) - 1));
43
+ }
44
+
45
+ function initialize(
46
+ address _underlying,
47
+ uint256 _toInvestNumerator,
48
+ uint256 _toInvestDenominator,
49
+ uint256 _underlyingUnit
50
+ ) public initializer {
51
+ _setUnderlying(_underlying);
52
+ _setVaultFractionToInvestNumerator(_toInvestNumerator);
53
+ _setVaultFractionToInvestDenominator(_toInvestDenominator);
54
+ _setUnderlyingUnit(_underlyingUnit);
55
+ _setNextStrategyTimestamp(0);
56
+ _setNextStrategy(address(0));
57
+ _setInvestOnDeposit(true);
58
+ }
59
+
60
+ function _setDecimals(uint256 _value) internal {
61
+ setUint256(_DECIMALS_SLOT, _value);
62
+ }
63
+
64
+ function _decimals() internal view returns (uint256) {
65
+ return getUint256(_DECIMALS_SLOT);
66
+ }
67
+
68
+ function _setStrategy(address _address) internal {
69
+ setAddress(_STRATEGY_SLOT, _address);
70
+ }
71
+
72
+ function _strategy() internal view returns (address) {
73
+ return getAddress(_STRATEGY_SLOT);
74
+ }
75
+
76
+ function _setUnderlying(address _address) internal {
77
+ setAddress(_UNDERLYING_SLOT, _address);
78
+ }
79
+
80
+ function _underlying() internal view returns (address) {
81
+ return getAddress(_UNDERLYING_SLOT);
82
+ }
83
+
84
+ function _setUnderlyingUnit(uint256 _value) internal {
85
+ setUint256(_UNDERLYING_UNIT_SLOT, _value);
86
+ }
87
+
88
+ function _underlyingUnit() internal view returns (uint256) {
89
+ return getUint256(_UNDERLYING_UNIT_SLOT);
90
+ }
91
+
92
+ function _setVaultFractionToInvestNumerator(uint256 _value) internal {
93
+ setUint256(_VAULT_FRACTION_TO_INVEST_NUMERATOR_SLOT, _value);
94
+ }
95
+
96
+ function _vaultFractionToInvestNumerator() internal view returns (uint256) {
97
+ return getUint256(_VAULT_FRACTION_TO_INVEST_NUMERATOR_SLOT);
98
+ }
99
+
100
+ function _setVaultFractionToInvestDenominator(uint256 _value) internal {
101
+ setUint256(_VAULT_FRACTION_TO_INVEST_DENOMINATOR_SLOT, _value);
102
+ }
103
+
104
+ function _vaultFractionToInvestDenominator() internal view returns (uint256) {
105
+ return getUint256(_VAULT_FRACTION_TO_INVEST_DENOMINATOR_SLOT);
106
+ }
107
+
108
+ function _setInvestOnDeposit(bool _value) internal {
109
+ setBoolean(_INVEST_ON_DEPOSIT_SLOT, _value);
110
+ }
111
+
112
+ function _investOnDeposit() internal view returns (bool) {
113
+ return getBoolean(_INVEST_ON_DEPOSIT_SLOT);
114
+ }
115
+
116
+ function _setCompoundOnWithdraw(bool _value) internal {
117
+ setBoolean(_COMPOUND_ON_WITHDRAW_SLOT, _value);
118
+ }
119
+
120
+ function _compoundOnWithdraw() internal view returns (bool) {
121
+ return getBoolean(_COMPOUND_ON_WITHDRAW_SLOT);
122
+ }
123
+
124
+ function _setNextImplementation(address _address) internal {
125
+ setAddress(_NEXT_IMPLEMENTATION_SLOT, _address);
126
+ }
127
+
128
+ function _nextImplementation() internal view returns (address) {
129
+ return getAddress(_NEXT_IMPLEMENTATION_SLOT);
130
+ }
131
+
132
+ function _setNextImplementationTimestamp(uint256 _value) internal {
133
+ setUint256(_NEXT_IMPLEMENTATION_TIMESTAMP_SLOT, _value);
134
+ }
135
+
136
+ function _nextImplementationTimestamp() internal view returns (uint256) {
137
+ return getUint256(_NEXT_IMPLEMENTATION_TIMESTAMP_SLOT);
138
+ }
139
+
140
+ function _setNextStrategy(address _value) internal {
141
+ setAddress(_NEXT_STRATEGY_SLOT, _value);
142
+ }
143
+
144
+ function _nextStrategy() internal view returns (address) {
145
+ return getAddress(_NEXT_STRATEGY_SLOT);
146
+ }
147
+
148
+ function _setNextStrategyTimestamp(uint256 _value) internal {
149
+ setUint256(_NEXT_STRATEGY_TIMESTAMP_SLOT, _value);
150
+ }
151
+
152
+ function _nextStrategyTimestamp() internal view returns (uint256) {
153
+ return getUint256(_NEXT_STRATEGY_TIMESTAMP_SLOT);
154
+ }
155
+
156
+ function _implementation() internal view returns (address) {
157
+ return getAddress(_IMPLEMENTATION_SLOT);
158
+ }
159
+
160
+ function _paused() internal view returns (bool) {
161
+ return getBoolean(_PAUSED_SLOT);
162
+ }
163
+
164
+ function _setPaused(bool _value) internal {
165
+ setBoolean(_PAUSED_SLOT, _value);
166
+ }
167
+
168
+ function setBoolean(bytes32 slot, bool _value) internal {
169
+ setUint256(slot, _value ? 1 : 0);
170
+ }
171
+
172
+ function getBoolean(bytes32 slot) internal view returns (bool) {
173
+ return (getUint256(slot) == 1);
174
+ }
175
+
176
+ function setAddress(bytes32 slot, address _address) internal {
177
+ // solhint-disable-next-line no-inline-assembly
178
+ assembly {
179
+ sstore(slot, _address)
180
+ }
181
+ }
182
+
183
+ function setUint256(bytes32 slot, uint256 _value) internal {
184
+ // solhint-disable-next-line no-inline-assembly
185
+ assembly {
186
+ sstore(slot, _value)
187
+ }
188
+ }
189
+
190
+ function getAddress(bytes32 slot) internal view returns (address str) {
191
+ // solhint-disable-next-line no-inline-assembly
192
+ assembly {
193
+ str := sload(slot)
194
+ }
195
+ }
196
+
197
+ function getUint256(bytes32 slot) internal view returns (uint256 str) {
198
+ // solhint-disable-next-line no-inline-assembly
199
+ assembly {
200
+ str := sload(slot)
201
+ }
202
+ }
203
+
204
+ uint256[50] private ______gap;
205
+ }
@@ -0,0 +1,371 @@
1
+ // SPDX-License-Identifier: Unlicense
2
+ pragma solidity 0.8.26;
3
+
4
+ import "@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol";
5
+ import "@openzeppelin/contracts-upgradeable/utils/math/SafeMathUpgradeable.sol";
6
+ import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
7
+ import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
8
+ import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
9
+ import "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol";
10
+ import "./interface/IStrategy.sol";
11
+ import "./interface/IVault.sol";
12
+ import "./interface/IController.sol";
13
+ import "./interface/IUpgradeSource.sol";
14
+ import "./inheritance/ControllableInit.sol";
15
+ import "./VaultStorage.sol";
16
+ import "./interface/IERC4626.sol";
17
+
18
+ contract VaultV1 is ERC20Upgradeable, IUpgradeSource, ControllableInit, VaultStorage {
19
+ using SafeERC20Upgradeable for IERC20Upgradeable;
20
+ using AddressUpgradeable for address;
21
+ using SafeMathUpgradeable for uint256;
22
+
23
+ event Invest(uint256 amount);
24
+ event StrategyAnnounced(address newStrategy, uint256 time);
25
+ event StrategyChanged(address newStrategy, address oldStrategy);
26
+
27
+ constructor() {
28
+ }
29
+
30
+ // the function is name differently to not cause inheritance clash in truffle and allows tests
31
+ function initializeVault(
32
+ address _storage,
33
+ address _underlying,
34
+ uint256 _toInvestNumerator,
35
+ uint256 _toInvestDenominator
36
+ ) public initializer {
37
+ require(_toInvestNumerator <= _toInvestDenominator, "cannot invest more than 100%");
38
+ require(_toInvestDenominator != 0, "cannot divide by 0");
39
+
40
+ __ERC20_init(
41
+ string(abi.encodePacked("FARM_", ERC20Upgradeable(_underlying).symbol())),
42
+ string(abi.encodePacked("f", ERC20Upgradeable(_underlying).symbol()))
43
+ );
44
+ _setDecimals(ERC20Upgradeable(_underlying).decimals());
45
+
46
+ ControllableInit.initialize(
47
+ _storage
48
+ );
49
+
50
+ uint256 underlyingUnit = 10 ** uint256(ERC20Upgradeable(address(_underlying)).decimals());
51
+ VaultStorage.initialize(
52
+ _underlying,
53
+ _toInvestNumerator,
54
+ _toInvestDenominator,
55
+ underlyingUnit
56
+ );
57
+ }
58
+
59
+ function decimals() public view override returns(uint8) {
60
+ return uint8(_decimals());
61
+ }
62
+
63
+ function strategy() public view returns(address) {
64
+ return _strategy();
65
+ }
66
+
67
+ function underlying() public view returns(address) {
68
+ return _underlying();
69
+ }
70
+
71
+ function underlyingUnit() public view returns(uint256) {
72
+ return _underlyingUnit();
73
+ }
74
+
75
+ function vaultFractionToInvestNumerator() public view returns(uint256) {
76
+ return _vaultFractionToInvestNumerator();
77
+ }
78
+
79
+ function vaultFractionToInvestDenominator() public view returns(uint256) {
80
+ return _vaultFractionToInvestDenominator();
81
+ }
82
+
83
+ function nextImplementation() public view returns(address) {
84
+ return _nextImplementation();
85
+ }
86
+
87
+ function nextImplementationTimestamp() public view returns(uint256) {
88
+ return _nextImplementationTimestamp();
89
+ }
90
+
91
+ function nextImplementationDelay() public view returns (uint256) {
92
+ return IController(controller()).nextImplementationDelay();
93
+ }
94
+
95
+ function setInvestOnDeposit(bool value) external onlyGovernance {
96
+ _setInvestOnDeposit(value);
97
+ }
98
+
99
+ function investOnDeposit() public view returns (bool) {
100
+ return _investOnDeposit();
101
+ }
102
+
103
+ function setCompoundOnWithdraw(bool value) external onlyGovernance {
104
+ _setCompoundOnWithdraw(value);
105
+ }
106
+
107
+ function compoundOnWithdraw() public view returns (bool) {
108
+ return _compoundOnWithdraw();
109
+ }
110
+
111
+ modifier whenStrategyDefined() {
112
+ require(address(strategy()) != address(0), "Strategy must be defined");
113
+ _;
114
+ }
115
+
116
+ // Only smart contracts will be affected by this modifier
117
+ modifier defense() {
118
+ require(
119
+ (msg.sender == tx.origin) || // If it is a normal user and not smart contract,
120
+ // then the requirement will pass
121
+ !IController(controller()).greyList(msg.sender), // If it is a smart contract, then
122
+ "This smart contract has been grey listed" // make sure that it is not on our greyList.
123
+ );
124
+ _;
125
+ }
126
+
127
+ /**
128
+ * Chooses the best strategy and re-invests. If the strategy did not change, it just calls
129
+ * doHardWork on the current strategy. Call this through controller to claim hard rewards.
130
+ */
131
+ function doHardWork() whenStrategyDefined onlyControllerOrGovernance external {
132
+ // ensure that new funds are invested too
133
+ invest();
134
+ IStrategy(strategy()).doHardWork();
135
+ }
136
+
137
+ /*
138
+ * Returns the cash balance across all users in this contract.
139
+ */
140
+ function underlyingBalanceInVault() view public returns (uint256) {
141
+ return IERC20Upgradeable(underlying()).balanceOf(address(this));
142
+ }
143
+
144
+ /* Returns the current underlying (e.g., DAI's) balance together with
145
+ * the invested amount (if DAI is invested elsewhere by the strategy).
146
+ */
147
+ function underlyingBalanceWithInvestment() view public returns (uint256) {
148
+ if (address(strategy()) == address(0)) {
149
+ // initial state, when not set
150
+ return underlyingBalanceInVault();
151
+ }
152
+ return underlyingBalanceInVault().add(IStrategy(strategy()).investedUnderlyingBalance());
153
+ }
154
+
155
+ function getPricePerFullShare() public view returns (uint256) {
156
+ return totalSupply() == 0
157
+ ? underlyingUnit()
158
+ : underlyingUnit().mul(underlyingBalanceWithInvestment()).div(totalSupply());
159
+ }
160
+
161
+ /* get the user's share (in underlying)
162
+ */
163
+ function underlyingBalanceWithInvestmentForHolder(address holder) view external returns (uint256) {
164
+ if (totalSupply() == 0) {
165
+ return 0;
166
+ }
167
+ return underlyingBalanceWithInvestment()
168
+ .mul(balanceOf(holder))
169
+ .div(totalSupply());
170
+ }
171
+
172
+ function nextStrategy() public view returns (address) {
173
+ return _nextStrategy();
174
+ }
175
+
176
+ function nextStrategyTimestamp() public view returns (uint256) {
177
+ return _nextStrategyTimestamp();
178
+ }
179
+
180
+ function canUpdateStrategy(address _strategy) public view returns (bool) {
181
+ bool isStrategyNotSetYet = strategy() == address(0);
182
+ bool hasTimelockPassed = block.timestamp > nextStrategyTimestamp() && nextStrategyTimestamp() != 0;
183
+ return isStrategyNotSetYet || (_strategy == nextStrategy() && hasTimelockPassed);
184
+ }
185
+
186
+ /**
187
+ * Indicates that the strategy update will happen in the future
188
+ */
189
+ function announceStrategyUpdate(address _strategy) public onlyControllerOrGovernance {
190
+ // records a new timestamp
191
+ uint256 when = block.timestamp.add(nextImplementationDelay());
192
+ _setNextStrategyTimestamp(when);
193
+ _setNextStrategy(_strategy);
194
+ emit StrategyAnnounced(_strategy, when);
195
+ }
196
+
197
+ /**
198
+ * Finalizes (or cancels) the strategy update by resetting the data
199
+ */
200
+ function finalizeStrategyUpdate() public onlyControllerOrGovernance {
201
+ _setNextStrategyTimestamp(0);
202
+ _setNextStrategy(address(0));
203
+ }
204
+
205
+ function setStrategy(address _strategy) public onlyControllerOrGovernance {
206
+ require(canUpdateStrategy(_strategy),
207
+ "The strategy exists and switch timelock did not elapse yet");
208
+ require(_strategy != address(0), "new _strategy cannot be empty");
209
+ require(IStrategy(_strategy).underlying() == address(underlying()), "Vault underlying must match Strategy underlying");
210
+ require(IStrategy(_strategy).vault() == address(this), "the strategy does not belong to this vault");
211
+
212
+ emit StrategyChanged(_strategy, strategy());
213
+ if (address(_strategy) != address(strategy())) {
214
+ if (address(strategy()) != address(0)) { // if the original strategy (no underscore) is defined
215
+ IERC20Upgradeable(underlying()).safeApprove(address(strategy()), 0);
216
+ IStrategy(strategy()).withdrawAllToVault();
217
+ }
218
+ _setStrategy(_strategy);
219
+ IERC20Upgradeable(underlying()).safeApprove(address(strategy()), 0);
220
+ IERC20Upgradeable(underlying()).safeApprove(address(strategy()), type(uint256).max);
221
+ }
222
+ finalizeStrategyUpdate();
223
+ }
224
+
225
+ function setVaultFractionToInvest(uint256 numerator, uint256 denominator) external onlyGovernance {
226
+ require(denominator > 0, "denominator must be greater than 0");
227
+ require(numerator <= denominator, "denominator must be greater than or equal to the numerator");
228
+ _setVaultFractionToInvestNumerator(numerator);
229
+ _setVaultFractionToInvestDenominator(denominator);
230
+ }
231
+
232
+ function rebalance() external onlyControllerOrGovernance {
233
+ withdrawAll();
234
+ invest();
235
+ }
236
+
237
+ function availableToInvestOut() public view returns (uint256) {
238
+ uint256 wantInvestInTotal = underlyingBalanceWithInvestment()
239
+ .mul(vaultFractionToInvestNumerator())
240
+ .div(vaultFractionToInvestDenominator());
241
+ uint256 alreadyInvested = IStrategy(strategy()).investedUnderlyingBalance();
242
+ if (alreadyInvested >= wantInvestInTotal) {
243
+ return 0;
244
+ } else {
245
+ uint256 remainingToInvest = wantInvestInTotal.sub(alreadyInvested);
246
+ return remainingToInvest <= underlyingBalanceInVault()
247
+ // TODO: we think that the "else" branch of the ternary operation is not
248
+ // going to get hit
249
+ ? remainingToInvest : underlyingBalanceInVault();
250
+ }
251
+ }
252
+
253
+ function invest() internal whenStrategyDefined {
254
+ uint256 availableAmount = availableToInvestOut();
255
+ if (availableAmount > 0) {
256
+ IERC20Upgradeable(underlying()).safeTransfer(address(strategy()), availableAmount);
257
+ emit Invest(availableAmount);
258
+ }
259
+ }
260
+
261
+ /*
262
+ * Allows for depositing the underlying asset in exchange for shares.
263
+ * Approval is assumed.
264
+ */
265
+ function deposit(uint256 amount) external nonReentrant defense returns (uint256 minted) {
266
+ minted = _deposit(amount, msg.sender, msg.sender);
267
+ }
268
+
269
+ /*
270
+ * Allows for depositing the underlying asset in exchange for shares
271
+ * assigned to the holder.
272
+ * This facilitates depositing for someone else (using DepositHelper)
273
+ */
274
+ function depositFor(uint256 amount, address holder) public nonReentrant defense returns (uint256 minted) {
275
+ minted = _deposit(amount, msg.sender, holder);
276
+ }
277
+
278
+ function withdraw(uint256 shares) external nonReentrant defense returns (uint256 amtUnderlying) {
279
+ amtUnderlying = _withdraw(shares, msg.sender, msg.sender);
280
+ }
281
+
282
+ function withdrawAll() public onlyControllerOrGovernance whenStrategyDefined {
283
+ IStrategy(strategy()).withdrawAllToVault();
284
+ }
285
+
286
+ function _deposit(uint256 amount, address sender, address beneficiary) internal returns (uint256) {
287
+ require(amount > 0, "Cannot deposit 0");
288
+ require(beneficiary != address(0), "holder must be defined");
289
+
290
+ IERC20Upgradeable(underlying()).safeTransferFrom(sender, address(this), amount);
291
+
292
+ if (investOnDeposit()) {
293
+ invest();
294
+ IStrategy(strategy()).doHardWork();
295
+ }
296
+
297
+ uint256 toMint = totalSupply() == 0
298
+ ? amount
299
+ : amount.mul(totalSupply()).div(underlyingBalanceWithInvestment().sub(amount));
300
+ _mint(beneficiary, toMint);
301
+
302
+ emit IERC4626.Deposit(sender, beneficiary, amount, toMint);
303
+ return toMint;
304
+ }
305
+
306
+ function _withdraw(uint256 numberOfShares, address receiver, address owner) internal returns (uint256) {
307
+ require(totalSupply() > 0, "Vault has no shares");
308
+ require(numberOfShares > 0, "numberOfShares must be greater than 0");
309
+ uint256 totalSupply = totalSupply();
310
+
311
+ address sender = msg.sender;
312
+ if (sender != owner) {
313
+ uint256 currentAllowance = allowance(owner, sender);
314
+ if (currentAllowance != type(uint256).max) {
315
+ require(currentAllowance >= numberOfShares, "ERC20: transfer amount exceeds allowance");
316
+ _approve(owner, sender, currentAllowance - numberOfShares);
317
+ }
318
+ }
319
+ _burn(owner, numberOfShares);
320
+
321
+ if (compoundOnWithdraw()) {
322
+ IStrategy(strategy()).doHardWork();
323
+ }
324
+
325
+ uint256 underlyingAmountToWithdraw = underlyingBalanceWithInvestment()
326
+ .mul(numberOfShares)
327
+ .div(totalSupply);
328
+ if (underlyingAmountToWithdraw > underlyingBalanceInVault()) {
329
+ if (numberOfShares == totalSupply) {
330
+ IStrategy(strategy()).withdrawAllToVault();
331
+ } else {
332
+ uint256 missing = underlyingAmountToWithdraw.sub(underlyingBalanceInVault());
333
+ IStrategy(strategy()).withdrawToVault(missing);
334
+ }
335
+ underlyingAmountToWithdraw = MathUpgradeable.min(underlyingBalanceWithInvestment()
336
+ .mul(numberOfShares)
337
+ .div(totalSupply), underlyingBalanceInVault());
338
+ }
339
+
340
+ IERC20Upgradeable(underlying()).safeTransfer(receiver, underlyingAmountToWithdraw);
341
+ emit IERC4626.Withdraw(sender, receiver, owner, underlyingAmountToWithdraw, numberOfShares);
342
+ return underlyingAmountToWithdraw;
343
+ }
344
+
345
+ /**
346
+ * Schedules an upgrade for this vault's proxy.
347
+ */
348
+ function scheduleUpgrade(address impl) public onlyGovernance {
349
+ _setNextImplementation(impl);
350
+ _setNextImplementationTimestamp(block.timestamp.add(nextImplementationDelay()));
351
+ }
352
+
353
+ function shouldUpgrade() external view override returns (bool, address) {
354
+ return (
355
+ nextImplementationTimestamp() != 0
356
+ && block.timestamp > nextImplementationTimestamp()
357
+ && nextImplementation() != address(0),
358
+ nextImplementation()
359
+ );
360
+ }
361
+
362
+ function finalizeUpgrade() external override onlyGovernance {
363
+ _setDecimals(ERC20Upgradeable(underlying()).decimals());
364
+ _setInvestOnDeposit(true);
365
+ _setCompoundOnWithdraw(true);
366
+ _setNextImplementation(address(0));
367
+ _setNextImplementationTimestamp(0);
368
+ }
369
+
370
+ uint256[50] private ______gap;
371
+ }