@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,44 @@
1
+ //SPDX-License-Identifier: Unlicense
2
+ pragma solidity 0.8.26;
3
+
4
+ interface INProxy {
5
+ /// @notice Specifies different deposit actions that can occur during BalanceAction or BalanceActionWithTrades
6
+ enum DepositActionType {
7
+ // No deposit action
8
+ None,
9
+ // Deposit asset cash, depositActionAmount is specified in asset cash external precision
10
+ DepositAsset,
11
+ // Deposit underlying tokens that are mintable to asset cash, depositActionAmount is specified in underlying token
12
+ // external precision
13
+ DepositUnderlying,
14
+ // Deposits specified asset cash external precision amount into an nToken and mints the corresponding amount of
15
+ // nTokens into the account
16
+ DepositAssetAndMintNToken,
17
+ // Deposits specified underlying in external precision, mints asset cash, and uses that asset cash to mint nTokens
18
+ DepositUnderlyingAndMintNToken,
19
+ // Redeems an nToken balance to asset cash. depositActionAmount is specified in nToken precision. Considered a deposit action
20
+ // because it deposits asset cash into an account. If there are fCash residuals that cannot be sold off, will revert.
21
+ RedeemNToken,
22
+ // Converts specified amount of asset cash balance already in Notional to nTokens. depositActionAmount is specified in
23
+ // Notional internal 8 decimal precision.
24
+ ConvertCashToNToken
25
+ }
26
+ /// @notice Defines a balance action for batchAction
27
+ struct BalanceAction {
28
+ // Deposit action to take (if any)
29
+ DepositActionType actionType;
30
+ uint16 currencyId;
31
+ // Deposit action amount must correspond to the depositActionType, see documentation above.
32
+ uint256 depositActionAmount;
33
+ // Withdraw an amount of asset cash specified in Notional internal 8 decimal precision
34
+ uint256 withdrawAmountInternalPrecision;
35
+ // If set to true, will withdraw entire cash balance. Useful if there may be an unknown amount of asset cash
36
+ // residual left from trading.
37
+ bool withdrawEntireCashBalance;
38
+ // If set to true, will redeem asset cash to the underlying token on withdraw.
39
+ bool redeemToUnderlying;
40
+ }
41
+ function getCurrencyId(address token) external view returns(uint16 currencyId);
42
+ function batchBalanceAction(address account, BalanceAction[] calldata actions) external payable;
43
+ function nTokenClaimIncentives() external;
44
+ }
@@ -0,0 +1,6 @@
1
+ //SPDX-License-Identifier: Unlicense
2
+ pragma solidity 0.8.26;
3
+
4
+ interface IPrimeToken {
5
+ function asset() external view returns(address);
6
+ }
@@ -0,0 +1,6 @@
1
+ //SPDX-License-Identifier: Unlicense
2
+ pragma solidity 0.8.26;
3
+
4
+ interface IRewardsDistributor {
5
+ function claimRewardToken(address holder) external;
6
+ }
@@ -0,0 +1,39 @@
1
+ // SPDX-License-Identifier: Unlicense
2
+ // based on https://etherscan.io/address/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2#code
3
+
4
+ /**
5
+ *Submitted for verification at Etherscan.io on 2017-12-12
6
+ */
7
+
8
+ // Copyright (C) 2015, 2016, 2017 Dapphub
9
+
10
+ // This program is free software: you can redistribute it and/or modify
11
+ // it under the terms of the GNU General Public License as published by
12
+ // the Free Software Foundation, either version 3 of the License, or
13
+ // (at your option) any later version.
14
+
15
+ // This program is distributed in the hope that it will be useful,
16
+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
17
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
+ // GNU General Public License for more details.
19
+
20
+ // You should have received a copy of the GNU General Public License
21
+ // along with this program. If not, see <http://www.gnu.org/licenses/>.
22
+ pragma solidity 0.8.26;
23
+
24
+ interface IWETH {
25
+
26
+ function balanceOf(address target) external view returns (uint256);
27
+
28
+ function deposit() external payable ;
29
+
30
+ function withdraw(uint wad) external ;
31
+
32
+ function totalSupply() external view returns (uint) ;
33
+
34
+ function approve(address guy, uint wad) external returns (bool) ;
35
+
36
+ function transfer(address dst, uint wad) external returns (bool) ;
37
+
38
+ function transferFrom(address src, address dst, uint wad) external returns (bool);
39
+ }
@@ -0,0 +1,54 @@
1
+
2
+ // SPDX-License-Identifier: BUSL-1.1
3
+ pragma solidity 0.8.26;
4
+
5
+ import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol";
6
+ import {IERC4626} from "@openzeppelin/contracts/interfaces/IERC4626.sol";
7
+ import {IERC20Metadata} from "@openzeppelin/contracts/interfaces/IERC20Metadata.sol";
8
+ import {IMarketBalanceFuse} from "../interface/ipor/IMarketBalanceFuse.sol";
9
+ import {IPriceOracleMiddleware} from "../interface/ipor/IPriceOracleMiddleware.sol";
10
+ import {PlasmaVaultConfigLib} from "../interface/ipor/PlasmaVaultConfigLib.sol";
11
+ import {IporMath} from "../interface/ipor/IporMath.sol";
12
+ import {PlasmaVaultLib} from "../interface/ipor/PlasmaVaultLib.sol";
13
+
14
+ /// @title Generic fuse for ERC4626 vaults responsible for calculating the balance of the Plasma Vault in the ERC4626 vaults based on preconfigured market substrates
15
+ /// @dev Substrates in this fuse are the assets that are used in the ERC4626 vaults for a given MARKET_ID
16
+ contract Erc4626BalanceFuse is IMarketBalanceFuse {
17
+ using SafeCast for uint256;
18
+
19
+ uint256 public immutable MARKET_ID;
20
+
21
+ constructor(uint256 marketId_) {
22
+ MARKET_ID = marketId_;
23
+ }
24
+
25
+ /// @return The balance of the Plasma Vault in associated with Fuse Balance marketId in USD, represented in 18 decimals
26
+ function balanceOf() external view override returns (uint256) {
27
+ bytes32[] memory vaults = PlasmaVaultConfigLib.getMarketSubstrates(MARKET_ID);
28
+
29
+ uint256 len = vaults.length;
30
+
31
+ if (len == 0) {
32
+ return 0;
33
+ }
34
+
35
+ uint256 balance;
36
+ uint256 vaultAssets;
37
+ IERC4626 vault;
38
+ address asset;
39
+ uint256 price;
40
+ uint256 priceDecimals;
41
+ address priceOracleMiddleware = PlasmaVaultLib.getPriceOracleMiddleware();
42
+ address plasmaVault = address(this);
43
+
44
+ for (uint256 i; i < len; ++i) {
45
+ vault = IERC4626(PlasmaVaultConfigLib.bytes32ToAddress(vaults[i]));
46
+ vaultAssets = vault.convertToAssets(vault.balanceOf(plasmaVault));
47
+ asset = vault.asset();
48
+ (price, priceDecimals) = IPriceOracleMiddleware(priceOracleMiddleware).getAssetPrice(asset);
49
+ balance += IporMath.convertToWad(vaultAssets * price, IERC20Metadata(asset).decimals() + priceDecimals);
50
+ }
51
+
52
+ return balance;
53
+ }
54
+ }
@@ -0,0 +1,134 @@
1
+
2
+ // SPDX-License-Identifier: BUSL-1.1
3
+ pragma solidity 0.8.26;
4
+
5
+ import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol";
6
+ import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
7
+ import {IERC4626} from "@openzeppelin/contracts/interfaces/IERC4626.sol";
8
+ import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
9
+ import {IFuseCommon} from "../interface/ipor/IFuseCommon.sol";
10
+ import {IporMath} from "../interface/ipor/IporMath.sol";
11
+ import {IFuseInstantWithdraw} from "../interface/ipor/IFuseInstantWithdraw.sol";
12
+ import {PlasmaVaultConfigLib} from "../interface/ipor/PlasmaVaultConfigLib.sol";
13
+
14
+ /// @notice Data structure for entering - supply - the ERC4626 vault
15
+ struct Erc4626SupplyFuseEnterData {
16
+ /// @dev ERC4626 vault address
17
+ address vault;
18
+ /// @dev amount to supply, this is amount of underlying asset in the given ERC4626 vault
19
+ uint256 vaultAssetAmount;
20
+ }
21
+
22
+ /// @notice Data structure for exiting - withdrawing - the ERC4626 vault
23
+ struct Erc4626SupplyFuseExitData {
24
+ /// @dev ERC4626 vault address
25
+ address vault;
26
+ /// @dev amount to withdraw, this is amount of underlying asset in the given ERC4626 vault
27
+ uint256 vaultAssetAmount;
28
+ }
29
+
30
+ /// @title Generic fuse for ERC4626 vaults responsible for supplying and withdrawing assets from the ERC4626 vaults based on preconfigured market substrates
31
+ /// @dev Substrates in this fuse are the assets that are used in the ERC4626 vaults for a given MARKET_ID
32
+ contract Erc4626SupplyFuse is IFuseCommon, IFuseInstantWithdraw {
33
+ using SafeCast for uint256;
34
+ using SafeERC20 for ERC20;
35
+
36
+ event Erc4626SupplyFuseEnter(address version, address asset, address vault, uint256 vaultAssetAmount);
37
+ event Erc4626SupplyFuseExit(
38
+ address version,
39
+ address asset,
40
+ address vault,
41
+ uint256 vaultAssetAmount,
42
+ uint256 shares
43
+ );
44
+ event Erc4626SupplyFuseExitFailed(address version, address asset, address vault, uint256 vaultAssetAmount);
45
+
46
+ error Erc4626SupplyFuseUnsupportedVault(string action, address asset);
47
+
48
+ address public immutable VERSION;
49
+ uint256 public immutable MARKET_ID;
50
+
51
+ constructor(uint256 marketId_) {
52
+ VERSION = address(this);
53
+ MARKET_ID = marketId_;
54
+ }
55
+
56
+ function enter(Erc4626SupplyFuseEnterData memory data_) external {
57
+ if (data_.vaultAssetAmount == 0) {
58
+ return;
59
+ }
60
+
61
+ if (!PlasmaVaultConfigLib.isSubstrateAsAssetGranted(MARKET_ID, data_.vault)) {
62
+ revert Erc4626SupplyFuseUnsupportedVault("enter", data_.vault);
63
+ }
64
+
65
+ address underlyingAsset = IERC4626(data_.vault).asset();
66
+
67
+ uint256 finalVaultAssetAmount = IporMath.min(
68
+ data_.vaultAssetAmount,
69
+ IERC4626(underlyingAsset).balanceOf(address(this))
70
+ );
71
+
72
+ if (finalVaultAssetAmount == 0) {
73
+ return;
74
+ }
75
+
76
+ ERC20(underlyingAsset).forceApprove(data_.vault, finalVaultAssetAmount);
77
+
78
+ IERC4626(data_.vault).deposit(finalVaultAssetAmount, address(this));
79
+
80
+ emit Erc4626SupplyFuseEnter(VERSION, underlyingAsset, data_.vault, finalVaultAssetAmount);
81
+ }
82
+
83
+ function exit(Erc4626SupplyFuseExitData calldata data_) external {
84
+ _exit(data_);
85
+ }
86
+
87
+ /// @dev params[0] - amount in underlying asset, params[1] - vault address
88
+ function instantWithdraw(bytes32[] calldata params_) external override {
89
+ uint256 amount = uint256(params_[0]);
90
+
91
+ address vault = PlasmaVaultConfigLib.bytes32ToAddress(params_[1]);
92
+
93
+ _exit(Erc4626SupplyFuseExitData(vault, amount));
94
+ }
95
+
96
+ function _exit(Erc4626SupplyFuseExitData memory data_) internal {
97
+ if (data_.vaultAssetAmount == 0) {
98
+ return;
99
+ }
100
+
101
+ if (!PlasmaVaultConfigLib.isSubstrateAsAssetGranted(MARKET_ID, data_.vault)) {
102
+ revert Erc4626SupplyFuseUnsupportedVault("exit", data_.vault);
103
+ }
104
+
105
+ uint256 finalVaultAssetAmount = IporMath.min(
106
+ data_.vaultAssetAmount,
107
+ IERC4626(data_.vault).convertToAssets(IERC4626(data_.vault).balanceOf(address(this)))
108
+ );
109
+
110
+ if (finalVaultAssetAmount == 0) {
111
+ return;
112
+ }
113
+
114
+ try IERC4626(data_.vault).withdraw(finalVaultAssetAmount, address(this), address(this)) returns (
115
+ uint256 shares
116
+ ) {
117
+ emit Erc4626SupplyFuseExit(
118
+ VERSION,
119
+ IERC4626(data_.vault).asset(),
120
+ data_.vault,
121
+ finalVaultAssetAmount,
122
+ shares
123
+ );
124
+ } catch {
125
+ /// @dev if withdraw failed, continue with the next step
126
+ emit Erc4626SupplyFuseExitFailed(
127
+ VERSION,
128
+ IERC4626(data_.vault).asset(),
129
+ data_.vault,
130
+ finalVaultAssetAmount
131
+ );
132
+ }
133
+ }
134
+ }
@@ -0,0 +1,90 @@
1
+ //SPDX-License-Identifier: Unlicense
2
+ pragma solidity 0.8.26;
3
+
4
+ import "@openzeppelin/contracts/utils/math/Math.sol";
5
+ import "@openzeppelin/contracts/utils/math/SafeMath.sol";
6
+ import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
7
+ import "../interface/IVault.sol";
8
+ import "../upgradability/BaseUpgradeableStrategy.sol";
9
+
10
+ contract NoopStrategyUpgradeable is BaseUpgradeableStrategy {
11
+
12
+ using SafeMath for uint256;
13
+ using SafeERC20 for IERC20;
14
+
15
+ constructor() BaseUpgradeableStrategy() {}
16
+
17
+ function initializeBaseStrategy(
18
+ address _storage,
19
+ address _underlying,
20
+ address _vault
21
+ ) public initializer {
22
+
23
+ require(_vault != address(0), "_vault cannot be empty");
24
+ require(_underlying == IVault(_vault).underlying(), "underlying mismatch");
25
+
26
+ BaseUpgradeableStrategy.initialize(
27
+ _storage,
28
+ _underlying,
29
+ _vault,
30
+ address(0),
31
+ address(0),
32
+ address(0)
33
+ );
34
+ }
35
+
36
+ function depositArbCheck() public pure returns(bool) {
37
+ return true;
38
+ }
39
+
40
+ function investedUnderlyingBalance() external view returns (uint256 balance) {
41
+ balance = IERC20(underlying()).balanceOf(address(this));
42
+ }
43
+
44
+ function unsalvagableTokens(address token) public view returns (bool) {
45
+ return (token == rewardToken() || token == underlying());
46
+ }
47
+
48
+ /*
49
+ * Withdraws all the asset to the vault
50
+ */
51
+ function withdrawAllToVault() external restricted {
52
+ address _underlying = underlying();
53
+ if (IERC20(_underlying).balanceOf(address(this)) > 0) {
54
+ IERC20(_underlying).safeTransfer(address(vault()), IERC20(_underlying).balanceOf(address(this)));
55
+ }
56
+ }
57
+
58
+ /*
59
+ * Cashes some amount out and withdraws to the vault
60
+ */
61
+ function withdrawToVault(uint256 amount) external restricted {
62
+ address _underlying = underlying();
63
+ require(IERC20(_underlying).balanceOf(address(this)) >= amount,
64
+ "insufficient balance for the withdrawal");
65
+ if (amount > 0) {
66
+ IERC20(_underlying).safeTransfer(address(vault()), amount);
67
+ }
68
+ }
69
+
70
+ /*
71
+ * Governance or Controller can claim coins that are somehow transferred into the contract
72
+ * Note that they cannot come in take away coins that are used and defined in the strategy itself
73
+ */
74
+ function salvage(address recipient, address token, uint256 amount) external onlyControllerOrGovernance {
75
+ // To make sure that governance cannot come in and take away the coins
76
+ require(!unsalvagableTokens(token), "token is defined as not salvagable");
77
+ IERC20(token).safeTransfer(recipient, amount);
78
+ }
79
+
80
+ /*
81
+ * Honest harvesting. It's not much, but it pays off
82
+ */
83
+ function doHardWork() external restricted {
84
+ // a no-op
85
+ }
86
+
87
+ function finalizeUpgrade() external onlyGovernance {
88
+ _finalizeUpgrade();
89
+ }
90
+ }
@@ -0,0 +1,60 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity 0.8.26;
3
+
4
+ import "@openzeppelin/contracts/proxy/Proxy.sol";
5
+ import "@openzeppelin/contracts/utils/Address.sol";
6
+
7
+ /**
8
+ * @title BaseUpgradeabilityProxy
9
+ * @dev This contract implements a proxy that allows to change the
10
+ * implementation address to which it will delegate.
11
+ * Such a change is called an implementation upgrade.
12
+ */
13
+ contract BaseUpgradeabilityProxy is Proxy {
14
+ /**
15
+ * @dev Emitted when the implementation is upgraded.
16
+ * @param implementation Address of the new implementation.
17
+ */
18
+ event Upgraded(address indexed implementation);
19
+
20
+ /**
21
+ * @dev Storage slot with the address of the current implementation.
22
+ * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
23
+ * validated in the constructor.
24
+ */
25
+ bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
26
+
27
+ /**
28
+ * @dev Returns the current implementation.
29
+ * @return impl Address of the current implementation
30
+ */
31
+ function _implementation() internal view override returns (address impl) {
32
+ bytes32 slot = IMPLEMENTATION_SLOT;
33
+ assembly {
34
+ impl := sload(slot)
35
+ }
36
+ }
37
+
38
+ /**
39
+ * @dev Upgrades the proxy to a new implementation.
40
+ * @param newImplementation Address of the new implementation.
41
+ */
42
+ function _upgradeTo(address newImplementation) internal {
43
+ _setImplementation(newImplementation);
44
+ emit Upgraded(newImplementation);
45
+ }
46
+
47
+ /**
48
+ * @dev Sets the implementation address of the proxy.
49
+ * @param newImplementation Address of the new implementation.
50
+ */
51
+ function _setImplementation(address newImplementation) internal {
52
+ require(Address.isContract(newImplementation), "Cannot set a proxy implementation to a non-contract address");
53
+
54
+ bytes32 slot = IMPLEMENTATION_SLOT;
55
+
56
+ assembly {
57
+ sstore(slot, newImplementation)
58
+ }
59
+ }
60
+ }
@@ -0,0 +1,144 @@
1
+ //SPDX-License-Identifier: Unlicense
2
+ pragma solidity 0.8.26;
3
+
4
+ import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
5
+ import "./BaseUpgradeableStrategyStorage.sol";
6
+ import "../inheritance/ControllableInit.sol";
7
+ import "../interface/IController.sol";
8
+ import "../interface/IRewardForwarder.sol";
9
+ import "../interface/merkl/IDistributor.sol";
10
+ import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
11
+ import "@openzeppelin/contracts/utils/math/SafeMath.sol";
12
+ import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
13
+
14
+ contract BaseUpgradeableStrategy is Initializable, ControllableInit, BaseUpgradeableStrategyStorage {
15
+ using SafeMath for uint256;
16
+ using SafeERC20 for IERC20;
17
+
18
+ event ProfitsNotCollected(bool sell, bool floor);
19
+ event ProfitLogInReward(uint256 profitAmount, uint256 feeAmount, uint256 timestamp);
20
+
21
+ modifier restricted() {
22
+ require(msg.sender == vault() || msg.sender == controller()
23
+ || msg.sender == governance(),
24
+ "not allowed");
25
+ _;
26
+ }
27
+
28
+ // This is only used in `investAllUnderlying()`
29
+ // The user can still freely withdraw from the strategy
30
+ modifier onlyNotPausedInvesting() {
31
+ require(!pausedInvesting(), "emergency state");
32
+ _;
33
+ }
34
+
35
+ constructor() BaseUpgradeableStrategyStorage() {
36
+ }
37
+
38
+ function initialize(
39
+ address _storage,
40
+ address _underlying,
41
+ address _vault,
42
+ address _rewardPool,
43
+ address _rewardToken,
44
+ address _strategist
45
+ ) public initializer {
46
+ ControllableInit.initialize(
47
+ _storage
48
+ );
49
+ _setUnderlying(_underlying);
50
+ _setVault(_vault);
51
+ _setRewardPool(_rewardPool);
52
+ _setRewardToken(_rewardToken);
53
+ _setStrategist(_strategist);
54
+ _setSell(true);
55
+ // _setSellFloor(0);
56
+ _setPausedInvesting(false);
57
+ }
58
+
59
+ /**
60
+ * Schedules an upgrade for this vault's proxy.
61
+ */
62
+ function scheduleUpgrade(address impl) public onlyGovernance {
63
+ _setNextImplementation(impl);
64
+ _setNextImplementationTimestamp(block.timestamp.add(nextImplementationDelay()));
65
+ }
66
+
67
+ function _finalizeUpgrade() internal {
68
+ _setNextImplementation(address(0));
69
+ _setNextImplementationTimestamp(0);
70
+ }
71
+
72
+ function shouldUpgrade() external view returns (bool, address) {
73
+ return (
74
+ nextImplementationTimestamp() != 0
75
+ && block.timestamp > nextImplementationTimestamp()
76
+ && nextImplementation() != address(0),
77
+ nextImplementation()
78
+ );
79
+ }
80
+
81
+ function toggleMerklOperator(address merklClaim, address operator) external onlyGovernance {
82
+ IDistributor(merklClaim).toggleOperator(address(this), operator);
83
+ }
84
+
85
+ // ========================= Internal & Private Functions =========================
86
+
87
+ // ==================== Functionality ====================
88
+
89
+ /**
90
+ * @dev Same as `_notifyProfitAndBuybackInRewardToken` but does not perform a compounding buyback. Just takes fees
91
+ * instead.
92
+ */
93
+ function _notifyProfitInRewardToken(
94
+ address _rewardToken,
95
+ uint256 _rewardBalance
96
+ ) internal {
97
+ if (_rewardBalance > 100) {
98
+ uint _feeDenominator = feeDenominator();
99
+ uint256 strategistFee = _rewardBalance.mul(strategistFeeNumerator()).div(_feeDenominator);
100
+ uint256 platformFee = _rewardBalance.mul(platformFeeNumerator()).div(_feeDenominator);
101
+ uint256 profitSharingFee = _rewardBalance.mul(profitSharingNumerator()).div(_feeDenominator);
102
+
103
+ address strategyFeeRecipient = strategist();
104
+ address platformFeeRecipient = IController(controller()).governance();
105
+
106
+ emit ProfitLogInReward(
107
+ _rewardToken,
108
+ _rewardBalance,
109
+ profitSharingFee,
110
+ block.timestamp
111
+ );
112
+ emit PlatformFeeLogInReward(
113
+ platformFeeRecipient,
114
+ _rewardToken,
115
+ _rewardBalance,
116
+ platformFee,
117
+ block.timestamp
118
+ );
119
+ emit StrategistFeeLogInReward(
120
+ strategyFeeRecipient,
121
+ _rewardToken,
122
+ _rewardBalance,
123
+ strategistFee,
124
+ block.timestamp
125
+ );
126
+
127
+ address rewardForwarder = IController(controller()).rewardForwarder();
128
+ IERC20(_rewardToken).safeApprove(rewardForwarder, 0);
129
+ IERC20(_rewardToken).safeApprove(rewardForwarder, _rewardBalance);
130
+
131
+ // Distribute/send the fees
132
+ IRewardForwarder(rewardForwarder).notifyFee(
133
+ _rewardToken,
134
+ profitSharingFee,
135
+ strategistFee,
136
+ platformFee
137
+ );
138
+ } else {
139
+ emit ProfitLogInReward(_rewardToken, 0, 0, block.timestamp);
140
+ emit PlatformFeeLogInReward(IController(controller()).governance(), _rewardToken, 0, 0, block.timestamp);
141
+ emit StrategistFeeLogInReward(strategist(), _rewardToken, 0, 0, block.timestamp);
142
+ }
143
+ }
144
+ }