Skip to content

Commit

Permalink
Merge pull request #116 from stabilitydao/erc4626strategy
Browse files Browse the repository at this point in the history
24.05.0-alpha; ERC4626StrategyBase, YearnStrategy, StrategyBase 1.1.0
  • Loading branch information
0xhokugava authored May 4, 2024
2 parents 34868d0 + 481dc8f commit 17a6420
Show file tree
Hide file tree
Showing 27 changed files with 835 additions and 103 deletions.
29 changes: 27 additions & 2 deletions chains/PolygonLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ library PolygonLib {
address public constant POOL_UNISWAPV3_USDCe_WETH_500 = 0x45dDa9cb7c25131DF268515131f647d726f50608;
address public constant POOL_UNISWAPV3_PROFIT_WETH_100 = 0xE5e70cb76446BEE0053b1EdF22CaDa861c80D51F;
address public constant POOL_UNISWAPV3_WETH_COMP_3000 = 0x2260E0081A2A042DC55A07D379eb3c18bE28A1F2;
address public constant POOL_UNISWAPV3_WMATIC_COMP_3000 = 0x495b3576e2f67fa870e14d0996433FbdB4015794;
address public constant POOL_QUICKSWAPV3_USDCe_USDT = 0x7B925e617aefd7FB3a93Abe3a701135D7a1Ba710;
address public constant POOL_QUICKSWAPV3_USDCe_DAI = 0xe7E0eB9F6bCcCfe847fDf62a3628319a092F11a2;
address public constant POOL_QUICKSWAPV3_USDCe_WETH = 0x55CAaBB0d2b704FD0eF8192A7E35D8837e678207;
Expand Down Expand Up @@ -153,14 +154,21 @@ library PolygonLib {
address public constant CONVEX_REWARD_POOL_crvUSD_DAI = 0xaCb744c7e7C95586DB83Eda3209e6483Fb1FCbA4;
address public constant CONVEX_REWARD_POOL_crvUSD_USDC = 0x11F2217fa1D5c44Eae310b9b985E2964FC47D8f9;

// Yearn V3
address public constant YEARN_DAI = 0x90b2f54C6aDDAD41b8f6c4fCCd555197BC0F773B;
address public constant YEARN_USDT = 0xBb287E6017d3DEb0e2E65061e8684eab21060123;
address public constant YEARN_USDCe = 0xA013Fbd4b711f9ded6fB09C1c0d358E2FbC2EAA0;
address public constant YEARN_WMATIC = 0x28F53bA70E5c8ce8D03b1FaD41E9dF11Bb646c36;
address public constant YEARN_WETH = 0x305F25377d0a39091e99B975558b1bdfC3975654;

function runDeploy(bool showLog) internal returns (address platform) {
//region ----- DeployPlatform -----
uint[] memory buildingPrice = new uint[](3);
buildingPrice[0] = 50_000e18;
buildingPrice[1] = 50_000e18;
buildingPrice[2] = 100_000e18;
platform = DeployLib.deployPlatform(
"24.01.1-alpha",
"24.05.0-alpha",
MULTISIG,
TOKEN_PM,
TOKEN_SDIV,
Expand Down Expand Up @@ -260,6 +268,19 @@ library PolygonLib {
DeployLib.logAddedFarms(address(factory), showLog);
//endregion -- Add farms -----

//region ----- Add strategy available init params -----
IFactory.StrategyAvailableInitParams memory p;
p.initAddresses = new address[](5);
p.initAddresses[0] = YEARN_USDCe;
p.initAddresses[1] = YEARN_USDT;
p.initAddresses[2] = YEARN_DAI;
p.initAddresses[3] = YEARN_WETH;
p.initAddresses[4] = YEARN_WMATIC;
p.initNums = new uint[](0);
p.initTicks = new int24[](0);
factory.setStrategyAvailableInitParams(StrategyIdLib.YEARN, p);
//endregion -- Add strategy available init params -----

//region ----- Reward tokens -----
IPlatform(platform).setAllowedBBTokenVaults(TOKEN_PROFIT, 2);
address[] memory allowedBoostRewardToken = new address[](2);
Expand All @@ -281,6 +302,7 @@ library PolygonLib {
DeployStrategyLib.deployStrategy(platform, StrategyIdLib.ICHI_RETRO_MERKL_FARM, true);
DeployStrategyLib.deployStrategy(platform, StrategyIdLib.GAMMA_RETRO_MERKL_FARM, true);
DeployStrategyLib.deployStrategy(platform, StrategyIdLib.CURVE_CONVEX_FARM, true);
DeployStrategyLib.deployStrategy(platform, StrategyIdLib.YEARN, false);
DeployLib.logDeployStrategies(platform, showLog);
//endregion -- Deploy strategy logics -----

Expand Down Expand Up @@ -736,7 +758,10 @@ library PolygonLib {
_farms[i++] = _makeCurveConvexFarm(POOL_CURVE_crvUSD_USDC, CONVEX_REWARD_POOL_crvUSD_USDC);
}

function _makeCurveConvexFarm(address curvePool, address convexRewardPool) internal view returns (IFactory.Farm memory) {
function _makeCurveConvexFarm(
address curvePool,
address convexRewardPool
) internal view returns (IFactory.Farm memory) {
IFactory.Farm memory farm;
uint rewardTokensLength = IConvexRewardPool(convexRewardPool).rewardLength();
farm.status = 0;
Expand Down
35 changes: 35 additions & 0 deletions script/PrepareUpgrade.24.05.0-alpha.Polygon.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;

import "forge-std/Script.sol";
import "../src/core/Factory.sol";
import "../src/core/vaults/CVault.sol";
import "../src/core/vaults/RVault.sol";
import "../src/core/vaults/RMVault.sol";
import "../src/strategies/YearnStrategy.sol";

contract PrepareUpgrade5Polygon is Script {
function run() external {
uint deployerPrivateKey = vm.envUint("PRIVATE_KEY");
vm.startBroadcast(deployerPrivateKey);

// Factory 1.1.0: getDeploymentKey fix for not farming strategies, strategyAvailableInitParams
new Factory();

// CVault 1.3.0: VaultBase 1.3.0
new CVault();

// RVault 1.3.0: VaultBase 1.3.0
new RVault();

// RMVault 1.3.0: VaultBase 1.3.0
new RMVault();

// new strategy implementation
new YearnStrategy();

vm.stopBroadcast();
}

function testDeployPolygon() external {}
}
5 changes: 5 additions & 0 deletions script/libs/DeployStrategyLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import "../../src/strategies/IchiQuickSwapMerklFarmStrategy.sol";
import "../../src/strategies/IchiRetroMerklFarmStrategy.sol";
import "../../src/strategies/GammaRetroMerklFarmStrategy.sol";
import "../../src/strategies/CurveConvexFarmStrategy.sol";
import "../../src/strategies/YearnStrategy.sol";
import "../../src/strategies/libs/StrategyDeveloperLib.sol";

library DeployStrategyLib {
Expand Down Expand Up @@ -59,6 +60,10 @@ library DeployStrategyLib {
implementation = address(new CurveConvexFarmStrategy());
}

if (CommonLib.eq(id, StrategyIdLib.YEARN)) {
implementation = address(new YearnStrategy());
}

// nosemgrep
require(implementation != address(0), "DeployStrategyLib: unknown strategy");

Expand Down
56 changes: 22 additions & 34 deletions src/core/Factory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import "../interfaces/IStrategyLogic.sol";

/// @notice Platform factory assembling vaults. Stores vault settings, strategy logic, farms.
/// Provides the opportunity to upgrade vaults and strategies.
/// Changelog:
/// 1.1.0: getDeploymentKey fix for not farming strategies, strategyAvailableInitParams
/// @author Alien Deployer (https://github.com/a17)
/// @author Jude (https://github.com/iammrjude)
/// @author JodsMigel (https://github.com/JodsMigel)
Expand All @@ -31,7 +33,7 @@ contract Factory is Controllable, ReentrancyGuardUpgradeable, IFactory {
//region ----- Constants -----

/// @inheritdoc IControllable
string public constant VERSION = "1.0.3";
string public constant VERSION = "1.1.0";

uint internal constant _WEEK = 60 * 60 * 24 * 7;

Expand All @@ -43,29 +45,6 @@ contract Factory is Controllable, ReentrancyGuardUpgradeable, IFactory {

//endregion -- Constants -----

//region ----- Storage -----

/// @custom:storage-location erc7201:stability.Factory
struct FactoryStorage {
/// @inheritdoc IFactory
mapping(bytes32 typeHash => VaultConfig) vaultConfig;
/// @inheritdoc IFactory
mapping(bytes32 idHash => StrategyLogicConfig) strategyLogicConfig;
/// @inheritdoc IFactory
mapping(bytes32 deploymentKey => address vaultProxy) deploymentKey;
/// @inheritdoc IFactory
mapping(address vault => uint status) vaultStatus;
/// @inheritdoc IFactory
mapping(address address_ => bool isStrategy_) isStrategy;
EnumerableSet.Bytes32Set vaultTypeHashes;
EnumerableSet.Bytes32Set strategyLogicIdHashes;
mapping(uint week => mapping(uint builderPermitTokenId => uint vaultsBuilt)) vaultsBuiltByPermitTokenId;
address[] deployedVaults;
Farm[] farms;
}

//endregion -- Storage -----

//region ----- Data types -----

struct DeployVaultAndStrategyVars {
Expand Down Expand Up @@ -100,16 +79,9 @@ contract Factory is Controllable, ReentrancyGuardUpgradeable, IFactory {
/// @inheritdoc IFactory
function setVaultConfig(VaultConfig memory vaultConfig_) external onlyOperator {
FactoryStorage storage $ = _getStorage();
string memory type_ = vaultConfig_.vaultType;
bytes32 typeHash = keccak256(abi.encodePacked(type_));
$.vaultConfig[typeHash] = vaultConfig_;
bool newVaultType = $.vaultTypeHashes.add(typeHash);
if (!newVaultType) {
if (FactoryLib.setVaultConfig($, vaultConfig_)) {
_requireGovernanceOrMultisig();
}
emit VaultConfigChanged(
type_, vaultConfig_.implementation, vaultConfig_.deployAllowed, vaultConfig_.upgradeAllowed, newVaultType
);
}

/// @inheritdoc IFactory
Expand Down Expand Up @@ -165,12 +137,22 @@ contract Factory is Controllable, ReentrancyGuardUpgradeable, IFactory {
emit UpdateFarm(id, farm_);
}

/// @inheritdoc IFactory
function setStrategyAvailableInitParams(
string memory id,
StrategyAvailableInitParams memory initParams
) external onlyOperator {
FactoryStorage storage $ = _getStorage();
bytes32 idHash = keccak256(abi.encodePacked(id));
$.strategyAvailableInitParams[idHash] = initParams;
emit SetStrategyAvailableInitParams(id, initParams.initAddresses, initParams.initNums, initParams.initTicks);
}

//endregion -- Restricted actions ----

//region ----- User actions -----

/// @inheritdoc IFactory

//slither-disable-next-line cyclomatic-complexity reentrancy-benign
function deployVaultAndStrategy(
string memory vaultType,
Expand Down Expand Up @@ -536,7 +518,7 @@ contract Factory is Controllable, ReentrancyGuardUpgradeable, IFactory {
initStrategyAddresses,
initStrategyNums,
initStrategyTicks,
[1, 0, 0, 1, 0]
[1, 0, 1, 1, 0]
);
}

Expand Down Expand Up @@ -594,6 +576,12 @@ contract Factory is Controllable, ReentrancyGuardUpgradeable, IFactory {
return _getStorage().vaultsBuiltByPermitTokenId[week][builderPermitTokenId];
}

/// @inheritdoc IFactory
function strategyAvailableInitParams(bytes32 idHash) external view returns (StrategyAvailableInitParams memory) {
FactoryStorage storage $ = _getStorage();
return $.strategyAvailableInitParams[idHash];
}

//endregion -- View functions -----

//region ----- Internal logic -----
Expand Down
25 changes: 22 additions & 3 deletions src/core/base/VaultBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol
import "./Controllable.sol";
import "../libs/ConstantsLib.sol";
import "../libs/VaultStatusLib.sol";
import "../libs/VaultBaseLib.sol";
import "../../interfaces/IVault.sol";
import "../../interfaces/IStrategy.sol";
import "../../interfaces/IPriceReader.sol";
Expand All @@ -19,6 +20,11 @@ import "../../interfaces/IFactory.sol";
/// User can deposit and withdraw a changing set of assets managed by the strategy.
/// Start price of vault share is $1.
/// @dev Used by all vault implementations (CVault, RVault, etc)
/// Changelog:
/// 1.3.0: hardWorkMintFeeCallback
/// 1.2.0: isHardWorkOnDepositAllowed
/// 1.1.0: setName, setSymbol, gas optimization
/// 1.0.1: add receiver and owner args to withdrawAssets method
/// @author Alien Deployer (https://github.com/a17)
/// @author JodsMigel (https://github.com/JodsMigel)
abstract contract VaultBase is Controllable, ERC20Upgradeable, ReentrancyGuardUpgradeable, IVault {
Expand All @@ -29,7 +35,7 @@ abstract contract VaultBase is Controllable, ERC20Upgradeable, ReentrancyGuardUp
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

/// @dev Version of VaultBase implementation
string public constant VERSION_VAULT_BASE = "1.2.0";
string public constant VERSION_VAULT_BASE = "1.3.0";

/// @dev Delay between deposits/transfers and withdrawals
uint internal constant _WITHDRAW_REQUEST_BLOCKS = 5;
Expand All @@ -41,7 +47,7 @@ abstract contract VaultBase is Controllable, ERC20Upgradeable, ReentrancyGuardUp
uint internal constant _MIN_HARDWORK_DELAY = 3600;

// keccak256(abi.encode(uint256(keccak256("erc7201:stability.VaultBase")) - 1)) & ~bytes32(uint256(0xff));
bytes32 private constant VAULTBASE_STORAGE_LOCATION =
bytes32 private constant _VAULTBASE_STORAGE_LOCATION =
0xd602ae9af1fed726d4890dcf3c81a074ed87a6343646550e5de293c5a9330a00;

/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
Expand Down Expand Up @@ -98,6 +104,19 @@ abstract contract VaultBase is Controllable, ERC20Upgradeable, ReentrancyGuardUp
/// @dev Need to receive ETH for HardWork and re-balance gas compensation
receive() external payable {}

/// @inheritdoc IVault
function hardWorkMintFeeCallback(address[] memory revenueAssets, uint[] memory revenueAmounts) external virtual {
(address[] memory feeReceivers, uint[] memory feeShares) = VaultBaseLib.hardWorkMintFeeCallback(
IPlatform(platform()), revenueAssets, revenueAmounts, _getVaultBaseStorage()
);
uint len = feeReceivers.length;
for (uint i; i < len; ++i) {
if (feeShares[i] != 0) {
_mint(feeReceivers[i], feeShares[i]);
}
}
}

/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* RESTRICTED ACTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
Expand Down Expand Up @@ -415,7 +434,7 @@ abstract contract VaultBase is Controllable, ERC20Upgradeable, ReentrancyGuardUp
function _getVaultBaseStorage() internal pure returns (VaultBaseStorage storage $) {
//slither-disable-next-line assembly
assembly {
$.slot := VAULTBASE_STORAGE_LOCATION
$.slot := _VAULTBASE_STORAGE_LOCATION
}
}

Expand Down
21 changes: 19 additions & 2 deletions src/core/libs/FactoryLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import "../../interfaces/IRVault.sol";

library FactoryLib {
using SafeERC20 for IERC20;
using EnumerableSet for EnumerableSet.Bytes32Set;

uint public constant BOOST_REWARD_DURATION = 86400 * 30;

Expand Down Expand Up @@ -182,7 +183,7 @@ library FactoryLib {
vars.strategyInitAddresses,
vars.strategyInitNums,
vars.strategyInitTicks,
[1, 0, 0, 1, 0]
[1, 0, 1, 1, 0]
);

if (factory.deploymentKey(_deploymentKey) == address(0)) {
Expand Down Expand Up @@ -293,7 +294,7 @@ library FactoryLib {
vars.strategyInitAddresses,
vars.strategyInitNums,
vars.strategyInitTicks,
[1, 0, 0, 1, 0]
[1, 0, 1, 1, 0]
);

if (factory.deploymentKey(_deploymentKey) == address(0)) {
Expand Down Expand Up @@ -637,4 +638,20 @@ library FactoryLib {
}
}
}

function setVaultConfig(
IFactory.FactoryStorage storage $,
IFactory.VaultConfig memory vaultConfig_
) external returns (bool needGovOrMultisigAccess) {
string memory type_ = vaultConfig_.vaultType;
bytes32 typeHash = keccak256(abi.encodePacked(type_));
$.vaultConfig[typeHash] = vaultConfig_;
bool newVaultType = $.vaultTypeHashes.add(typeHash);
if (!newVaultType) {
needGovOrMultisigAccess = true;
}
emit IFactory.VaultConfigChanged(
type_, vaultConfig_.implementation, vaultConfig_.deployAllowed, vaultConfig_.upgradeAllowed, newVaultType
);
}
}
Loading

0 comments on commit 17a6420

Please sign in to comment.