@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.
- package/README.md +127 -5
- package/contracts/base/Controller.sol +358 -0
- package/contracts/base/Drip.sol +86 -0
- package/contracts/base/PotPool.sol +367 -0
- package/contracts/base/ProfitSharingReceiver.sol +38 -0
- package/contracts/base/Reader.sol +54 -0
- package/contracts/base/RewardForwarder.sol +109 -0
- package/contracts/base/VaultProxy.sol +34 -0
- package/contracts/base/VaultStorage.sol +205 -0
- package/contracts/base/VaultV1.sol +371 -0
- package/contracts/base/VaultV1GMX.sol +465 -0
- package/contracts/base/VaultV2.sol +111 -0
- package/contracts/base/VaultV2GMX.sol +111 -0
- package/contracts/base/factory/MegaFactory.sol +120 -0
- package/contracts/base/factory/interface/IPoolFactory.sol +6 -0
- package/contracts/base/factory/interface/IStrategyFactory.sol +6 -0
- package/contracts/base/factory/interface/IVaultFactory.sol +7 -0
- package/contracts/base/factory/pool/PotPoolFactory.sol +41 -0
- package/contracts/base/factory/strategy/UpgradableStrategyFactory.sol +19 -0
- package/contracts/base/factory/vault/RegularVaultFactory.sol +34 -0
- package/contracts/base/incentives/GlobalIncentivesExecutor.sol +85 -0
- package/contracts/base/incentives/GlobalIncentivesHelper.sol +174 -0
- package/contracts/base/incentives/NotifyHelperGeneric.sol +61 -0
- package/contracts/base/incentives/NotifyHelperStateful.sol +290 -0
- package/contracts/base/incentives/ViewerNotifyHelperStateful.sol +25 -0
- package/contracts/base/inheritance/Controllable.sol +25 -0
- package/contracts/base/inheritance/ControllableInit.sol +30 -0
- package/contracts/base/inheritance/Governable.sol +28 -0
- package/contracts/base/inheritance/GovernableInit.sol +50 -0
- package/contracts/base/inheritance/IUpgradeSource.sol +7 -0
- package/contracts/base/inheritance/OwnableWhitelist.sol +17 -0
- package/contracts/base/inheritance/Storage.sol +35 -0
- package/contracts/base/interface/IBalDex.sol +7 -0
- package/contracts/base/interface/IController.sol +132 -0
- package/contracts/base/interface/IDex.sol +9 -0
- package/contracts/base/interface/IERC4626.sol +261 -0
- package/contracts/base/interface/IGMXStrategy.sol +37 -0
- package/contracts/base/interface/IGlobalIncentivesHelper.sol +6 -0
- package/contracts/base/interface/IPotPool.sol +70 -0
- package/contracts/base/interface/IProfitSharingReceiver.sol +9 -0
- package/contracts/base/interface/IRewardForwarder.sol +57 -0
- package/contracts/base/interface/IStrategy.sol +37 -0
- package/contracts/base/interface/IUniversalLiquidator.sol +21 -0
- package/contracts/base/interface/IUniversalLiquidatorRegistry.sol +20 -0
- package/contracts/base/interface/IUpgradeSource.sol +9 -0
- package/contracts/base/interface/IVault.sol +58 -0
- package/contracts/base/interface/IVaultGMX.sol +71 -0
- package/contracts/base/interface/aura/IAuraBaseRewardPool.sol +25 -0
- package/contracts/base/interface/aura/IAuraBooster.sol +17 -0
- package/contracts/base/interface/aura/IAuraDepositor.sol +7 -0
- package/contracts/base/interface/balancer/Gauge.sol +22 -0
- package/contracts/base/interface/balancer/IBVault.sol +580 -0
- package/contracts/base/interface/balancer/IBalancerMinter.sol +114 -0
- package/contracts/base/interface/balancer/IGyroPool.sol +7 -0
- package/contracts/base/interface/balancer/linearPool/ILinearPool.sol +184 -0
- package/contracts/base/interface/balancer/linearPool/ILinearPoolFactory.sol +16 -0
- package/contracts/base/interface/balancer/linearPool/ILinearPoolRebalancer.sol +8 -0
- package/contracts/base/interface/balancer/linearPool/IPoolSwapStructs.sol +56 -0
- package/contracts/base/interface/compound/CTokenInterface.sol +29 -0
- package/contracts/base/interface/compound/IComptroller.sol +9 -0
- package/contracts/base/interface/dolomite/IDepositWithdraw.sol +13 -0
- package/contracts/base/interface/dolomite/IDolomiteMargin.sol +15 -0
- package/contracts/base/interface/dolomite/IRewardsDistributor.sol +11 -0
- package/contracts/base/interface/gamma/IClearing.sol +7 -0
- package/contracts/base/interface/gamma/IHypervisor.sol +9 -0
- package/contracts/base/interface/gamma/IUniProxy.sol +14 -0
- package/contracts/base/interface/gmx/EventUtils.sol +253 -0
- package/contracts/base/interface/gmx/ICallbackReceiver.sol +119 -0
- package/contracts/base/interface/gmx/IDataStore.sol +7 -0
- package/contracts/base/interface/gmx/IExchangeRouter.sol +38 -0
- package/contracts/base/interface/gmx/IGMXViewer.sol +7 -0
- package/contracts/base/interface/gmx/IHandler.sol +12 -0
- package/contracts/base/interface/gmx/IMarket.sol +7 -0
- package/contracts/base/interface/gmx/IOracle.sol +6 -0
- package/contracts/base/interface/gmx/IPriceFeed.sol +12 -0
- package/contracts/base/interface/gmx/IReader.sol +49 -0
- package/contracts/base/interface/gmx/IRoleStore.sol +6 -0
- package/contracts/base/interface/ipor/Errors.sol +20 -0
- package/contracts/base/interface/ipor/FuseStorageLib.sol +71 -0
- package/contracts/base/interface/ipor/FusesLib.sol +149 -0
- package/contracts/base/interface/ipor/IFuseCommon.sol +9 -0
- package/contracts/base/interface/ipor/IFuseInstantWithdraw.sol +14 -0
- package/contracts/base/interface/ipor/IMarketBalanceFuse.sol +10 -0
- package/contracts/base/interface/ipor/IPriceOracleMiddleware.sol +42 -0
- package/contracts/base/interface/ipor/IporMath.sol +110 -0
- package/contracts/base/interface/ipor/PlasmaVaultConfigLib.sol +106 -0
- package/contracts/base/interface/ipor/PlasmaVaultLib.sol +293 -0
- package/contracts/base/interface/ipor/PlasmaVaultStorageLib.sol +352 -0
- package/contracts/base/interface/merkl/IDistributor.sol +6 -0
- package/contracts/base/interface/notional/INProxy.sol +44 -0
- package/contracts/base/interface/notional/IPrimeToken.sol +6 -0
- package/contracts/base/interface/venus/IRewardsDistributor.sol +6 -0
- package/contracts/base/interface/weth/IWETH.sol +39 -0
- package/contracts/base/ipor/Erc4626BalanceFuse.sol +54 -0
- package/contracts/base/ipor/Erc4626SupplyFuse.sol +134 -0
- package/contracts/base/noop/NoopStrategyUpgradeable.sol +90 -0
- package/contracts/base/upgradability/BaseUpgradeabilityProxy.sol +60 -0
- package/contracts/base/upgradability/BaseUpgradeableStrategy.sol +144 -0
- package/contracts/base/upgradability/BaseUpgradeableStrategyStorage.sol +284 -0
- package/contracts/base/upgradability/IUpgradable.sol +7 -0
- package/contracts/base/upgradability/ReentrancyGuardUpgradeable.sol +51 -0
- package/contracts/base/upgradability/StrategyProxy.sol +34 -0
- package/contracts/strategies/aura/AuraStrategy.sol +403 -0
- package/contracts/strategies/aura/AuraStrategyMainnet_MORE_GYD.sol +32 -0
- package/contracts/strategies/aura/AuraStrategyMainnet_sUSDe_GYD.sol +31 -0
- package/contracts/strategies/aura/AuraStrategyMainnet_waFRAX_sFRAX.sol +31 -0
- package/contracts/strategies/aura/AuraStrategyMainnet_waGHO_GYD.sol +31 -0
- package/contracts/strategies/aura/AuraStrategyMainnet_waUSDC_GHO.sol +32 -0
- package/contracts/strategies/aura/AuraStrategyMainnet_waUSDC_GYD.sol +31 -0
- package/contracts/strategies/aura/AuraStrategyMainnet_waUSDT_GYD.sol +31 -0
- package/contracts/strategies/aura/AuraStrategyMainnet_wstETH_GYD.sol +31 -0
- package/contracts/strategies/camelot/CamelotV3Strategy.sol +304 -0
- package/contracts/strategies/camelot/CamelotV3StrategyMainnet_ARB_USDC.sol +28 -0
- package/contracts/strategies/camelot/CamelotV3StrategyMainnet_ETH_USDC.sol +28 -0
- package/contracts/strategies/camelot/CamelotV3StrategyMainnet_ETH_USDT.sol +28 -0
- package/contracts/strategies/camelot/CamelotV3StrategyMainnet_GMX_ETH.sol +28 -0
- package/contracts/strategies/camelot/CamelotV3StrategyMainnet_GRAIL_ETH.sol +28 -0
- package/contracts/strategies/camelot/CamelotV3StrategyMainnet_USDC_USDT.sol +28 -0
- package/contracts/strategies/camelot/CamelotV3StrategyMainnet_WBTC_ETH.sol +28 -0
- package/contracts/strategies/dolomite/DolomiteLendStrategy.sol +273 -0
- package/contracts/strategies/dolomite/DolomiteLendStrategyMainnet_DAI.sol +26 -0
- package/contracts/strategies/dolomite/DolomiteLendStrategyMainnet_GMX.sol +26 -0
- package/contracts/strategies/dolomite/DolomiteLendStrategyMainnet_USDC.sol +26 -0
- package/contracts/strategies/dolomite/DolomiteLendStrategyMainnet_USDCe.sol +26 -0
- package/contracts/strategies/dolomite/DolomiteLendStrategyMainnet_USDT.sol +26 -0
- package/contracts/strategies/dolomite/DolomiteLendStrategyMainnet_WBTC.sol +26 -0
- package/contracts/strategies/dolomite/DolomiteLendStrategyMainnet_WETH.sol +26 -0
- package/contracts/strategies/fluid/FluidLendStrategy.sol +241 -0
- package/contracts/strategies/fluid/FluidLendStrategyMainnet_ETH.sol +25 -0
- package/contracts/strategies/fluid/FluidLendStrategyMainnet_USDC.sol +25 -0
- package/contracts/strategies/fluid/FluidLendStrategyMainnet_USDT.sol +25 -0
- package/contracts/strategies/gmx/GMXStrategy.sol +472 -0
- package/contracts/strategies/gmx/GMXStrategyMainnet_WBTC.sol +25 -0
- package/contracts/strategies/gmx/GMXViewer.sol +110 -0
- package/contracts/strategies/notional/NotionalStrategy.sol +223 -0
- package/contracts/strategies/notional/NotionalStrategyMainnet_nETH.sol +27 -0
- package/contracts/strategies/notional/NotionalStrategyMainnet_nUSDC.sol +27 -0
- package/contracts/strategies/notional/NotionalStrategyMainnet_nUSDT.sol +27 -0
- package/contracts/strategies/notional/NotionalStrategyMainnet_nwstETH.sol +27 -0
- package/contracts/strategies/venus/VenusFoldStrategy.sol +591 -0
- package/contracts/strategies/venus/VenusFoldStrategyMainnet_ARB.sol +32 -0
- package/contracts/strategies/venus/VenusFoldStrategyMainnet_ETH_core.sol +32 -0
- package/contracts/strategies/venus/VenusFoldStrategyMainnet_ETH_lsd.sol +32 -0
- package/contracts/strategies/venus/VenusFoldStrategyMainnet_USDC.sol +32 -0
- package/contracts/strategies/venus/VenusFoldStrategyMainnet_USDT.sol +32 -0
- package/contracts/strategies/venus/VenusFoldStrategyMainnet_WBTC.sol +32 -0
- package/hardhat.config.js +60 -0
- package/index.js +42 -0
- package/package.json +39 -6
- package/scripts/01-deploy-vault-regular-with-upgradable-strategy.js +41 -0
- package/scripts/02-deploy-vault-regular.js +35 -0
- package/scripts/03-deploy-upgradable-strategy.js +40 -0
- package/scripts/04-deploy-new-implementation.js +24 -0
- package/scripts/05-deploy-GMXViewer.js +17 -0
- package/scripts/06-deploy-GMXVault.js +49 -0
- package/scripts/07-deploy-ipor-fuses.js +29 -0
- package/scripts/08-deploy-drip.js +20 -0
- package/scripts/README.md +55 -0
- package/scripts/utils.js +22 -0
- package/test/aura/more-gyd.js +140 -0
- package/test/aura/susde-gyd.js +140 -0
- package/test/aura/wafrax-sfrax.js +140 -0
- package/test/aura/wagho-gyd.js +140 -0
- package/test/aura/wausdc-gho.js +141 -0
- package/test/aura/wausdc-gyd.js +140 -0
- package/test/aura/wausdt-gyd.js +140 -0
- package/test/aura/wsteth-gyd.js +138 -0
- package/test/camelot/arb-usdc.js +125 -0
- package/test/camelot/eth-usdc.js +125 -0
- package/test/camelot/eth-usdt.js +125 -0
- package/test/camelot/gmx-eth.js +125 -0
- package/test/camelot/grail-eth.js +125 -0
- package/test/camelot/usdc-usdt.js +125 -0
- package/test/camelot/wbtc-eth.js +125 -0
- package/test/dolomite/dai.js +127 -0
- package/test/dolomite/gmx.js +134 -0
- package/test/dolomite/usdc.js +127 -0
- package/test/dolomite/usdce.js +127 -0
- package/test/dolomite/usdt.js +127 -0
- package/test/dolomite/wbtc.js +127 -0
- package/test/dolomite/weth.js +127 -0
- package/test/fluid/eth.js +127 -0
- package/test/fluid/usdc.js +134 -0
- package/test/fluid/usdt.js +134 -0
- package/test/gmx/wbtc.js +184 -0
- package/test/notional/neth.js +133 -0
- package/test/notional/nusdc.js +133 -0
- package/test/notional/nusdt.js +133 -0
- package/test/notional/nwsteth.js +133 -0
- package/test/test-config.js +28 -0
- package/test/utilities/Utils.js +96 -0
- package/test/utilities/hh-utils.js +248 -0
- package/test/utilities/make-vault.js +16 -0
- package/test/venus/arb.js +135 -0
- package/test/venus/eth-core.js +133 -0
- package/test/venus/eth-lsd.js +133 -0
- package/test/venus/usdc.js +133 -0
- package/test/venus/usdt.js +133 -0
- 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,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
|
+
}
|