@@ -83,6 +83,12 @@ contract MasterVault is Initializable, ERC4626Upgradeable, AccessControlUpgradea
8383 _grantRole (PAUSER_ROLE, _owner);
8484 }
8585
86+ function distributePerformanceFee () external whenNotPaused {
87+ if (! enablePerformanceFee) revert PerformanceFeeDisabled ();
88+ subVault.redeem (totalProfitInSubVaultShares (MathUpgradeable.Rounding.Down), beneficiary, address (this ));
89+ // todo emit event
90+ }
91+
8692 /// @notice Set a subvault. Can only be called if there is not already a subvault set.
8793 /// @param _subVault The subvault to set. Must be an ERC4626 vault with the same asset as this MasterVault.
8894 /// @param minSubVaultExchRateWad Minimum acceptable ratio (times 1e18) of new subvault shares to outstanding MasterVault shares after deposit.
@@ -152,13 +158,6 @@ contract MasterVault is Initializable, ERC4626Upgradeable, AccessControlUpgradea
152158 return _totalAssets (MathUpgradeable.Rounding.Down);
153159 }
154160
155- function _totalAssets (MathUpgradeable.Rounding rounding ) internal view returns (uint256 ) {
156- if (address (subVault) == address (0 )) {
157- return IERC20 (asset ()).balanceOf (address (this ));
158- }
159- return _subVaultSharesToAssets (subVault.balanceOf (address (this )), rounding);
160- }
161-
162161 /** @dev See {IERC4626-maxDeposit}. */
163162 function maxDeposit (address ) public view virtual override returns (uint256 ) {
164163 if (address (subVault) == address (0 )) {
@@ -179,6 +178,67 @@ contract MasterVault is Initializable, ERC4626Upgradeable, AccessControlUpgradea
179178 return totalSupply ().mulDiv (subShares, subVault.balanceOf (address (this )), MathUpgradeable.Rounding.Down); // todo: check rounding direction
180179 }
181180
181+ function totalProfit (MathUpgradeable.Rounding rounding ) public view returns (uint256 ) {
182+ uint256 __totalAssets = _totalAssets (rounding);
183+ return __totalAssets > totalPrincipal ? __totalAssets - totalPrincipal : 0 ;
184+ }
185+
186+ function totalProfitInSubVaultShares (MathUpgradeable.Rounding rounding ) public view returns (uint256 ) {
187+ if (address (subVault) == address (0 )) {
188+ revert ("Subvault not set " );
189+ }
190+ uint256 profitAssets = totalProfit (rounding);
191+ if (profitAssets == 0 ) {
192+ return 0 ;
193+ }
194+ return _assetsToSubVaultShares (profitAssets, rounding);
195+ }
196+
197+ /**
198+ * @dev Deposit/mint common workflow.
199+ */
200+ function _deposit (
201+ address caller ,
202+ address receiver ,
203+ uint256 assets ,
204+ uint256 shares
205+ ) internal virtual override whenNotPaused {
206+ super ._deposit (caller, receiver, assets, shares);
207+
208+ totalPrincipal += assets;
209+ IERC4626 _subVault = subVault;
210+ if (address (_subVault) != address (0 )) {
211+ _subVault.deposit (assets, address (this ));
212+ }
213+ }
214+
215+ /**
216+ * @dev Withdraw/redeem common workflow.
217+ */
218+ function _withdraw (
219+ address caller ,
220+ address receiver ,
221+ address _owner ,
222+ uint256 assets ,
223+ uint256 shares
224+ ) internal virtual override whenNotPaused {
225+ totalPrincipal -= assets;
226+
227+ IERC4626 _subVault = subVault;
228+ if (address (_subVault) != address (0 )) {
229+ _subVault.withdraw (assets, address (this ), address (this ));
230+ }
231+
232+ super ._withdraw (caller, receiver, _owner, assets, shares);
233+ }
234+
235+ function _totalAssets (MathUpgradeable.Rounding rounding ) internal view returns (uint256 ) {
236+ if (address (subVault) == address (0 )) {
237+ return IERC20 (asset ()).balanceOf (address (this ));
238+ }
239+ return _subVaultSharesToAssets (subVault.balanceOf (address (this )), rounding);
240+ }
241+
182242 /**
183243 * @dev Internal conversion function (from assets to shares) with support for rounding direction.
184244 *
@@ -243,64 +303,4 @@ contract MasterVault is Initializable, ERC4626Upgradeable, AccessControlUpgradea
243303 function _flipRounding (MathUpgradeable.Rounding rounding ) internal pure returns (MathUpgradeable.Rounding) {
244304 return rounding == MathUpgradeable.Rounding.Up ? MathUpgradeable.Rounding.Down : MathUpgradeable.Rounding.Up;
245305 }
246-
247- function totalProfit (MathUpgradeable.Rounding rounding ) public view returns (uint256 ) {
248- uint256 __totalAssets = _totalAssets (rounding);
249- return __totalAssets > totalPrincipal ? __totalAssets - totalPrincipal : 0 ;
250- }
251-
252- function totalProfitInSubVaultShares (MathUpgradeable.Rounding rounding ) public view returns (uint256 ) {
253- if (address (subVault) == address (0 )) {
254- revert ("Subvault not set " );
255- }
256- uint256 profitAssets = totalProfit (rounding);
257- if (profitAssets == 0 ) {
258- return 0 ;
259- }
260- return _assetsToSubVaultShares (profitAssets, rounding);
261- }
262-
263- /**
264- * @dev Deposit/mint common workflow.
265- */
266- function _deposit (
267- address caller ,
268- address receiver ,
269- uint256 assets ,
270- uint256 shares
271- ) internal virtual override whenNotPaused {
272- super ._deposit (caller, receiver, assets, shares);
273-
274- totalPrincipal += assets;
275- IERC4626 _subVault = subVault;
276- if (address (_subVault) != address (0 )) {
277- _subVault.deposit (assets, address (this ));
278- }
279- }
280-
281- /**
282- * @dev Withdraw/redeem common workflow.
283- */
284- function _withdraw (
285- address caller ,
286- address receiver ,
287- address _owner ,
288- uint256 assets ,
289- uint256 shares
290- ) internal virtual override whenNotPaused {
291- totalPrincipal -= assets;
292-
293- IERC4626 _subVault = subVault;
294- if (address (_subVault) != address (0 )) {
295- _subVault.withdraw (assets, address (this ), address (this ));
296- }
297-
298- super ._withdraw (caller, receiver, _owner, assets, shares);
299- }
300-
301- function distributePerformanceFee () external whenNotPaused {
302- if (! enablePerformanceFee) revert PerformanceFeeDisabled ();
303- subVault.redeem (totalProfitInSubVaultShares (MathUpgradeable.Rounding.Down), beneficiary, address (this ));
304- // todo emit event
305- }
306306}
0 commit comments