Skip to content

Commit 17a6420

Browse files
authored
Merge pull request #116 from stabilitydao/erc4626strategy
24.05.0-alpha; ERC4626StrategyBase, YearnStrategy, StrategyBase 1.1.0
2 parents 34868d0 + 481dc8f commit 17a6420

27 files changed

+835
-103
lines changed

chains/PolygonLib.sol

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ library PolygonLib {
5858
address public constant POOL_UNISWAPV3_USDCe_WETH_500 = 0x45dDa9cb7c25131DF268515131f647d726f50608;
5959
address public constant POOL_UNISWAPV3_PROFIT_WETH_100 = 0xE5e70cb76446BEE0053b1EdF22CaDa861c80D51F;
6060
address public constant POOL_UNISWAPV3_WETH_COMP_3000 = 0x2260E0081A2A042DC55A07D379eb3c18bE28A1F2;
61+
address public constant POOL_UNISWAPV3_WMATIC_COMP_3000 = 0x495b3576e2f67fa870e14d0996433FbdB4015794;
6162
address public constant POOL_QUICKSWAPV3_USDCe_USDT = 0x7B925e617aefd7FB3a93Abe3a701135D7a1Ba710;
6263
address public constant POOL_QUICKSWAPV3_USDCe_DAI = 0xe7E0eB9F6bCcCfe847fDf62a3628319a092F11a2;
6364
address public constant POOL_QUICKSWAPV3_USDCe_WETH = 0x55CAaBB0d2b704FD0eF8192A7E35D8837e678207;
@@ -153,14 +154,21 @@ library PolygonLib {
153154
address public constant CONVEX_REWARD_POOL_crvUSD_DAI = 0xaCb744c7e7C95586DB83Eda3209e6483Fb1FCbA4;
154155
address public constant CONVEX_REWARD_POOL_crvUSD_USDC = 0x11F2217fa1D5c44Eae310b9b985E2964FC47D8f9;
155156

157+
// Yearn V3
158+
address public constant YEARN_DAI = 0x90b2f54C6aDDAD41b8f6c4fCCd555197BC0F773B;
159+
address public constant YEARN_USDT = 0xBb287E6017d3DEb0e2E65061e8684eab21060123;
160+
address public constant YEARN_USDCe = 0xA013Fbd4b711f9ded6fB09C1c0d358E2FbC2EAA0;
161+
address public constant YEARN_WMATIC = 0x28F53bA70E5c8ce8D03b1FaD41E9dF11Bb646c36;
162+
address public constant YEARN_WETH = 0x305F25377d0a39091e99B975558b1bdfC3975654;
163+
156164
function runDeploy(bool showLog) internal returns (address platform) {
157165
//region ----- DeployPlatform -----
158166
uint[] memory buildingPrice = new uint[](3);
159167
buildingPrice[0] = 50_000e18;
160168
buildingPrice[1] = 50_000e18;
161169
buildingPrice[2] = 100_000e18;
162170
platform = DeployLib.deployPlatform(
163-
"24.01.1-alpha",
171+
"24.05.0-alpha",
164172
MULTISIG,
165173
TOKEN_PM,
166174
TOKEN_SDIV,
@@ -260,6 +268,19 @@ library PolygonLib {
260268
DeployLib.logAddedFarms(address(factory), showLog);
261269
//endregion -- Add farms -----
262270

271+
//region ----- Add strategy available init params -----
272+
IFactory.StrategyAvailableInitParams memory p;
273+
p.initAddresses = new address[](5);
274+
p.initAddresses[0] = YEARN_USDCe;
275+
p.initAddresses[1] = YEARN_USDT;
276+
p.initAddresses[2] = YEARN_DAI;
277+
p.initAddresses[3] = YEARN_WETH;
278+
p.initAddresses[4] = YEARN_WMATIC;
279+
p.initNums = new uint[](0);
280+
p.initTicks = new int24[](0);
281+
factory.setStrategyAvailableInitParams(StrategyIdLib.YEARN, p);
282+
//endregion -- Add strategy available init params -----
283+
263284
//region ----- Reward tokens -----
264285
IPlatform(platform).setAllowedBBTokenVaults(TOKEN_PROFIT, 2);
265286
address[] memory allowedBoostRewardToken = new address[](2);
@@ -281,6 +302,7 @@ library PolygonLib {
281302
DeployStrategyLib.deployStrategy(platform, StrategyIdLib.ICHI_RETRO_MERKL_FARM, true);
282303
DeployStrategyLib.deployStrategy(platform, StrategyIdLib.GAMMA_RETRO_MERKL_FARM, true);
283304
DeployStrategyLib.deployStrategy(platform, StrategyIdLib.CURVE_CONVEX_FARM, true);
305+
DeployStrategyLib.deployStrategy(platform, StrategyIdLib.YEARN, false);
284306
DeployLib.logDeployStrategies(platform, showLog);
285307
//endregion -- Deploy strategy logics -----
286308

@@ -736,7 +758,10 @@ library PolygonLib {
736758
_farms[i++] = _makeCurveConvexFarm(POOL_CURVE_crvUSD_USDC, CONVEX_REWARD_POOL_crvUSD_USDC);
737759
}
738760

739-
function _makeCurveConvexFarm(address curvePool, address convexRewardPool) internal view returns (IFactory.Farm memory) {
761+
function _makeCurveConvexFarm(
762+
address curvePool,
763+
address convexRewardPool
764+
) internal view returns (IFactory.Farm memory) {
740765
IFactory.Farm memory farm;
741766
uint rewardTokensLength = IConvexRewardPool(convexRewardPool).rewardLength();
742767
farm.status = 0;
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.23;
3+
4+
import "forge-std/Script.sol";
5+
import "../src/core/Factory.sol";
6+
import "../src/core/vaults/CVault.sol";
7+
import "../src/core/vaults/RVault.sol";
8+
import "../src/core/vaults/RMVault.sol";
9+
import "../src/strategies/YearnStrategy.sol";
10+
11+
contract PrepareUpgrade5Polygon is Script {
12+
function run() external {
13+
uint deployerPrivateKey = vm.envUint("PRIVATE_KEY");
14+
vm.startBroadcast(deployerPrivateKey);
15+
16+
// Factory 1.1.0: getDeploymentKey fix for not farming strategies, strategyAvailableInitParams
17+
new Factory();
18+
19+
// CVault 1.3.0: VaultBase 1.3.0
20+
new CVault();
21+
22+
// RVault 1.3.0: VaultBase 1.3.0
23+
new RVault();
24+
25+
// RMVault 1.3.0: VaultBase 1.3.0
26+
new RMVault();
27+
28+
// new strategy implementation
29+
new YearnStrategy();
30+
31+
vm.stopBroadcast();
32+
}
33+
34+
function testDeployPolygon() external {}
35+
}

script/libs/DeployStrategyLib.sol

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import "../../src/strategies/IchiQuickSwapMerklFarmStrategy.sol";
1313
import "../../src/strategies/IchiRetroMerklFarmStrategy.sol";
1414
import "../../src/strategies/GammaRetroMerklFarmStrategy.sol";
1515
import "../../src/strategies/CurveConvexFarmStrategy.sol";
16+
import "../../src/strategies/YearnStrategy.sol";
1617
import "../../src/strategies/libs/StrategyDeveloperLib.sol";
1718

1819
library DeployStrategyLib {
@@ -59,6 +60,10 @@ library DeployStrategyLib {
5960
implementation = address(new CurveConvexFarmStrategy());
6061
}
6162

63+
if (CommonLib.eq(id, StrategyIdLib.YEARN)) {
64+
implementation = address(new YearnStrategy());
65+
}
66+
6267
// nosemgrep
6368
require(implementation != address(0), "DeployStrategyLib: unknown strategy");
6469

src/core/Factory.sol

Lines changed: 22 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ import "../interfaces/IStrategyLogic.sol";
2121

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

3335
/// @inheritdoc IControllable
34-
string public constant VERSION = "1.0.3";
36+
string public constant VERSION = "1.1.0";
3537

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

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

4446
//endregion -- Constants -----
4547

46-
//region ----- Storage -----
47-
48-
/// @custom:storage-location erc7201:stability.Factory
49-
struct FactoryStorage {
50-
/// @inheritdoc IFactory
51-
mapping(bytes32 typeHash => VaultConfig) vaultConfig;
52-
/// @inheritdoc IFactory
53-
mapping(bytes32 idHash => StrategyLogicConfig) strategyLogicConfig;
54-
/// @inheritdoc IFactory
55-
mapping(bytes32 deploymentKey => address vaultProxy) deploymentKey;
56-
/// @inheritdoc IFactory
57-
mapping(address vault => uint status) vaultStatus;
58-
/// @inheritdoc IFactory
59-
mapping(address address_ => bool isStrategy_) isStrategy;
60-
EnumerableSet.Bytes32Set vaultTypeHashes;
61-
EnumerableSet.Bytes32Set strategyLogicIdHashes;
62-
mapping(uint week => mapping(uint builderPermitTokenId => uint vaultsBuilt)) vaultsBuiltByPermitTokenId;
63-
address[] deployedVaults;
64-
Farm[] farms;
65-
}
66-
67-
//endregion -- Storage -----
68-
6948
//region ----- Data types -----
7049

7150
struct DeployVaultAndStrategyVars {
@@ -100,16 +79,9 @@ contract Factory is Controllable, ReentrancyGuardUpgradeable, IFactory {
10079
/// @inheritdoc IFactory
10180
function setVaultConfig(VaultConfig memory vaultConfig_) external onlyOperator {
10281
FactoryStorage storage $ = _getStorage();
103-
string memory type_ = vaultConfig_.vaultType;
104-
bytes32 typeHash = keccak256(abi.encodePacked(type_));
105-
$.vaultConfig[typeHash] = vaultConfig_;
106-
bool newVaultType = $.vaultTypeHashes.add(typeHash);
107-
if (!newVaultType) {
82+
if (FactoryLib.setVaultConfig($, vaultConfig_)) {
10883
_requireGovernanceOrMultisig();
10984
}
110-
emit VaultConfigChanged(
111-
type_, vaultConfig_.implementation, vaultConfig_.deployAllowed, vaultConfig_.upgradeAllowed, newVaultType
112-
);
11385
}
11486

11587
/// @inheritdoc IFactory
@@ -165,12 +137,22 @@ contract Factory is Controllable, ReentrancyGuardUpgradeable, IFactory {
165137
emit UpdateFarm(id, farm_);
166138
}
167139

140+
/// @inheritdoc IFactory
141+
function setStrategyAvailableInitParams(
142+
string memory id,
143+
StrategyAvailableInitParams memory initParams
144+
) external onlyOperator {
145+
FactoryStorage storage $ = _getStorage();
146+
bytes32 idHash = keccak256(abi.encodePacked(id));
147+
$.strategyAvailableInitParams[idHash] = initParams;
148+
emit SetStrategyAvailableInitParams(id, initParams.initAddresses, initParams.initNums, initParams.initTicks);
149+
}
150+
168151
//endregion -- Restricted actions ----
169152

170153
//region ----- User actions -----
171154

172155
/// @inheritdoc IFactory
173-
174156
//slither-disable-next-line cyclomatic-complexity reentrancy-benign
175157
function deployVaultAndStrategy(
176158
string memory vaultType,
@@ -536,7 +518,7 @@ contract Factory is Controllable, ReentrancyGuardUpgradeable, IFactory {
536518
initStrategyAddresses,
537519
initStrategyNums,
538520
initStrategyTicks,
539-
[1, 0, 0, 1, 0]
521+
[1, 0, 1, 1, 0]
540522
);
541523
}
542524

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

579+
/// @inheritdoc IFactory
580+
function strategyAvailableInitParams(bytes32 idHash) external view returns (StrategyAvailableInitParams memory) {
581+
FactoryStorage storage $ = _getStorage();
582+
return $.strategyAvailableInitParams[idHash];
583+
}
584+
597585
//endregion -- View functions -----
598586

599587
//region ----- Internal logic -----

src/core/base/VaultBase.sol

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol
77
import "./Controllable.sol";
88
import "../libs/ConstantsLib.sol";
99
import "../libs/VaultStatusLib.sol";
10+
import "../libs/VaultBaseLib.sol";
1011
import "../../interfaces/IVault.sol";
1112
import "../../interfaces/IStrategy.sol";
1213
import "../../interfaces/IPriceReader.sol";
@@ -19,6 +20,11 @@ import "../../interfaces/IFactory.sol";
1920
/// User can deposit and withdraw a changing set of assets managed by the strategy.
2021
/// Start price of vault share is $1.
2122
/// @dev Used by all vault implementations (CVault, RVault, etc)
23+
/// Changelog:
24+
/// 1.3.0: hardWorkMintFeeCallback
25+
/// 1.2.0: isHardWorkOnDepositAllowed
26+
/// 1.1.0: setName, setSymbol, gas optimization
27+
/// 1.0.1: add receiver and owner args to withdrawAssets method
2228
/// @author Alien Deployer (https://github.com/a17)
2329
/// @author JodsMigel (https://github.com/JodsMigel)
2430
abstract contract VaultBase is Controllable, ERC20Upgradeable, ReentrancyGuardUpgradeable, IVault {
@@ -29,7 +35,7 @@ abstract contract VaultBase is Controllable, ERC20Upgradeable, ReentrancyGuardUp
2935
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
3036

3137
/// @dev Version of VaultBase implementation
32-
string public constant VERSION_VAULT_BASE = "1.2.0";
38+
string public constant VERSION_VAULT_BASE = "1.3.0";
3339

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

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

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

107+
/// @inheritdoc IVault
108+
function hardWorkMintFeeCallback(address[] memory revenueAssets, uint[] memory revenueAmounts) external virtual {
109+
(address[] memory feeReceivers, uint[] memory feeShares) = VaultBaseLib.hardWorkMintFeeCallback(
110+
IPlatform(platform()), revenueAssets, revenueAmounts, _getVaultBaseStorage()
111+
);
112+
uint len = feeReceivers.length;
113+
for (uint i; i < len; ++i) {
114+
if (feeShares[i] != 0) {
115+
_mint(feeReceivers[i], feeShares[i]);
116+
}
117+
}
118+
}
119+
101120
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
102121
/* RESTRICTED ACTIONS */
103122
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
@@ -415,7 +434,7 @@ abstract contract VaultBase is Controllable, ERC20Upgradeable, ReentrancyGuardUp
415434
function _getVaultBaseStorage() internal pure returns (VaultBaseStorage storage $) {
416435
//slither-disable-next-line assembly
417436
assembly {
418-
$.slot := VAULTBASE_STORAGE_LOCATION
437+
$.slot := _VAULTBASE_STORAGE_LOCATION
419438
}
420439
}
421440

src/core/libs/FactoryLib.sol

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import "../../interfaces/IRVault.sol";
1515

1616
library FactoryLib {
1717
using SafeERC20 for IERC20;
18+
using EnumerableSet for EnumerableSet.Bytes32Set;
1819

1920
uint public constant BOOST_REWARD_DURATION = 86400 * 30;
2021

@@ -182,7 +183,7 @@ library FactoryLib {
182183
vars.strategyInitAddresses,
183184
vars.strategyInitNums,
184185
vars.strategyInitTicks,
185-
[1, 0, 0, 1, 0]
186+
[1, 0, 1, 1, 0]
186187
);
187188

188189
if (factory.deploymentKey(_deploymentKey) == address(0)) {
@@ -293,7 +294,7 @@ library FactoryLib {
293294
vars.strategyInitAddresses,
294295
vars.strategyInitNums,
295296
vars.strategyInitTicks,
296-
[1, 0, 0, 1, 0]
297+
[1, 0, 1, 1, 0]
297298
);
298299

299300
if (factory.deploymentKey(_deploymentKey) == address(0)) {
@@ -637,4 +638,20 @@ library FactoryLib {
637638
}
638639
}
639640
}
641+
642+
function setVaultConfig(
643+
IFactory.FactoryStorage storage $,
644+
IFactory.VaultConfig memory vaultConfig_
645+
) external returns (bool needGovOrMultisigAccess) {
646+
string memory type_ = vaultConfig_.vaultType;
647+
bytes32 typeHash = keccak256(abi.encodePacked(type_));
648+
$.vaultConfig[typeHash] = vaultConfig_;
649+
bool newVaultType = $.vaultTypeHashes.add(typeHash);
650+
if (!newVaultType) {
651+
needGovOrMultisigAccess = true;
652+
}
653+
emit IFactory.VaultConfigChanged(
654+
type_, vaultConfig_.implementation, vaultConfig_.deployAllowed, vaultConfig_.upgradeAllowed, newVaultType
655+
);
656+
}
640657
}

0 commit comments

Comments
 (0)