@@ -26,12 +26,9 @@ contract MasterVault is Initializable, ERC4626Upgradeable, AccessControlUpgradea
2626 error TooManyAssetsDeposited ();
2727 error TooFewAssetsReceived ();
2828 error SubVaultAlreadySet ();
29- error SubVaultCannotBeZeroAddress ();
30- error MustHaveSupplyBeforeSettingSubVault ();
3129 error SubVaultAssetMismatch ();
3230 error SubVaultExchangeRateTooLow ();
3331 error NoExistingSubVault ();
34- error MustHaveSupplyBeforeSwitchingSubVault ();
3532 error NewSubVaultExchangeRateTooLow ();
3633 error BeneficiaryNotSet ();
3734 error PerformanceFeeDisabled ();
@@ -42,12 +39,6 @@ contract MasterVault is Initializable, ERC4626Upgradeable, AccessControlUpgradea
4239 // we may need a minimum asset or master share amount when setting subvaults (bc of exchange rate calc)
4340 IERC4626 public subVault;
4441
45- // how many subVault shares one MV2 share can be redeemed for
46- // initially 1 to 1
47- // constant per subvault
48- // changes when subvault is set
49- uint256 public subVaultExchRateWad;
50-
5142 // note: the performance fee can be avoided if the underlying strategy can be sandwiched (eg ETH to wstETH dex swap)
5243 // maybe a simpler and more robust implementation would be for the owner to adjust the subVaultExchRateWad directly
5344 // this would also avoid the need for totalPrincipal tracking
@@ -77,8 +68,6 @@ contract MasterVault is Initializable, ERC4626Upgradeable, AccessControlUpgradea
7768 _grantRole (VAULT_MANAGER_ROLE, _owner);
7869 _grantRole (FEE_MANAGER_ROLE, _owner); // todo: consider permissionless by default
7970 _grantRole (PAUSER_ROLE, _owner);
80-
81- subVaultExchRateWad = 1e18 ;
8271 }
8372
8473
@@ -110,7 +99,6 @@ contract MasterVault is Initializable, ERC4626Upgradeable, AccessControlUpgradea
11099 /// @param _subVault The subvault to set. Must be an ERC4626 vault with the same asset as this MasterVault.
111100 /// @param minSubVaultExchRateWad Minimum acceptable ratio (times 1e18) of new subvault shares to outstanding MasterVault shares after deposit.
112101 function setSubVault (IERC4626 _subVault , uint256 minSubVaultExchRateWad ) external onlyRole (VAULT_MANAGER_ROLE) {
113- if (address (subVault) != address (0 )) revert SubVaultAlreadySet ();
114102 _setSubVault (_subVault, minSubVaultExchRateWad);
115103 }
116104
@@ -121,18 +109,17 @@ contract MasterVault is Initializable, ERC4626Upgradeable, AccessControlUpgradea
121109 }
122110
123111 function _setSubVault (IERC4626 _subVault , uint256 minSubVaultExchRateWad ) internal {
124- if (address (_subVault) == address (0 )) revert SubVaultCannotBeZeroAddress ();
125- if (totalSupply () == 0 ) revert MustHaveSupplyBeforeSettingSubVault ();
126- if (address (_subVault.asset ()) != address (asset ())) revert SubVaultAssetMismatch ();
127-
128- IERC20 (asset ()).safeApprove (address (_subVault), type (uint256 ).max);
129- uint256 subShares = _subVault.deposit (totalAssets (), address (this ));
112+ IERC20 underlyingAsset = IERC20 (asset ());
113+ if (address (subVault) != address (0 )) revert SubVaultAlreadySet ();
114+ if (address (_subVault.asset ()) != address (underlyingAsset)) revert SubVaultAssetMismatch ();
130115
131116 subVault = _subVault;
132117
133- uint256 _subVaultExchRateWad = subShares.mulDiv (1e18 , totalAssets (), MathUpgradeable.Rounding.Down);
134- if (_subVaultExchRateWad < minSubVaultExchRateWad) revert SubVaultExchangeRateTooLow ();
135- subVaultExchRateWad = _subVaultExchRateWad;
118+ IERC20 (asset ()).safeApprove (address (_subVault), type (uint256 ).max);
119+ _subVault.deposit (underlyingAsset.balanceOf (address (this )), address (this ));
120+
121+ uint256 subVaultExchRateWad = _subVault.balanceOf (address (this )).mulDiv (1e18 , totalSupply (), MathUpgradeable.Rounding.Down);
122+ if (subVaultExchRateWad < minSubVaultExchRateWad) revert NewSubVaultExchangeRateTooLow ();
136123
137124 emit SubvaultChanged (address (0 ), address (_subVault));
138125 }
@@ -141,14 +128,13 @@ contract MasterVault is Initializable, ERC4626Upgradeable, AccessControlUpgradea
141128 IERC4626 oldSubVault = subVault;
142129 if (address (oldSubVault) == address (0 )) revert NoExistingSubVault ();
143130
144- uint256 _totalSupply = totalSupply ();
145- uint256 assetReceived = oldSubVault.withdraw (oldSubVault.maxWithdraw (address (this )), address (this ), address (this ));
146- uint256 effectiveAssetExchRateWad = assetReceived.mulDiv (1e18 , _totalSupply, MathUpgradeable.Rounding.Down);
147- if (effectiveAssetExchRateWad < minAssetExchRateWad) revert TooFewAssetsReceived ();
131+ subVault = IERC4626 (address (0 ));
148132
133+ oldSubVault.redeem (oldSubVault.balanceOf (address (this )), address (this ), address (this ));
149134 IERC20 (asset ()).safeApprove (address (oldSubVault), 0 );
150- subVault = IERC4626 (address (0 ));
151- subVaultExchRateWad = 1e18 ;
135+
136+ uint256 assetExchRateWad = IERC20 (asset ()).balanceOf (address (this )).mulDiv (1e18 , totalSupply (), MathUpgradeable.Rounding.Down);
137+ if (assetExchRateWad < minAssetExchRateWad) revert SubVaultExchangeRateTooLow ();
152138
153139 emit SubvaultChanged (address (oldSubVault), address (0 ));
154140 }
@@ -166,11 +152,13 @@ contract MasterVault is Initializable, ERC4626Upgradeable, AccessControlUpgradea
166152 }
167153
168154 function masterSharesToSubShares (uint256 masterShares , MathUpgradeable.Rounding rounding ) public view returns (uint256 ) {
169- return masterShares.mulDiv (subVaultExchRateWad, 1e18 , rounding);
155+ // masterShares * totalSubVaultShares / totalMasterShares
156+ return masterShares.mulDiv (subVault.balanceOf (address (this )), totalSupply (), rounding);
170157 }
171158
172159 function subSharesToMasterShares (uint256 subShares , MathUpgradeable.Rounding rounding ) public view returns (uint256 ) {
173- return subShares.mulDiv (1e18 , subVaultExchRateWad, rounding);
160+ // subShares * totalMasterShares / totalSubVaultShares
161+ return subShares.mulDiv (totalSupply (), subVault.balanceOf (address (this )), rounding);
174162 }
175163
176164 /// @notice Toggle performance fee collection on/off
0 commit comments