-
Notifications
You must be signed in to change notification settings - Fork 156
feat: add master vault #126
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
| function _deposit( | ||
| address caller, | ||
| address receiver, | ||
| uint256 assets, | ||
| uint256 shares | ||
| ) internal virtual override { | ||
| super._deposit(caller, receiver, assets, shares); | ||
| totalPrincipal += assets; | ||
| ERC4626 _subVault = subVault; | ||
| if (address(_subVault) != address(0)) { | ||
| _subVault.deposit(assets, address(this)); | ||
| } | ||
| } |
Check warning
Code scanning / Slither
Unused return Medium
| function _withdraw( | ||
| address caller, | ||
| address receiver, | ||
| address _owner, | ||
| uint256 assets, | ||
| uint256 shares | ||
| ) internal virtual override { | ||
| ERC4626 _subVault = subVault; | ||
| if (address(_subVault) != address(0)) { | ||
| _subVault.withdraw(assets, address(this), address(this)); | ||
| } | ||
|
|
||
| ////// PERF FEE STUFF ////// | ||
| // determine profit portion and principal portion of assets | ||
| uint256 _totalProfit = totalProfit(); | ||
| // use shares because they are rounded up vs assets which are rounded down | ||
| uint256 profitPortion = shares.mulDiv(_totalProfit, totalSupply(), Math.Rounding.Up); | ||
| uint256 principalPortion = assets - profitPortion; | ||
|
|
||
| // subtract principal portion from totalPrincipal | ||
| totalPrincipal -= principalPortion; | ||
|
|
||
| // send fee to owner (todo should be a separate beneficiary addr set by owner) | ||
| if (performanceFeeBps > 0 && profitPortion > 0) { | ||
| uint256 fee = profitPortion.mulDiv(performanceFeeBps, 10000, Math.Rounding.Up); | ||
| // send fee to owner | ||
| IERC20(asset()).safeTransfer(owner(), fee); | ||
|
|
||
| // note subtraction | ||
| assets -= fee; | ||
| } | ||
|
|
||
| ////// END PERF FEE STUFF ////// | ||
|
|
||
| // call super._withdraw with remaining assets | ||
| super._withdraw(caller, receiver, _owner, assets, shares); | ||
| } |
Check warning
Code scanning / Slither
Unused return Medium
590a713 to
fc89964
Compare
| if (address(oldSubVault) == address(0)) revert NoExistingSubVault(); | ||
|
|
||
| uint256 _totalSupply = totalSupply(); | ||
| uint256 assetReceived = oldSubVault.withdraw(oldSubVault.maxWithdraw(address(this)), address(this), address(this)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there is an edge case here - the subvault may not have enough liquidity to serve this big withdrawal all at once.
we probably need to make switching vaults more robust to those liquidity constaints.
the same could be said about depositing to the new vault, it could be such a large deposit that slippage starts to become a serious issue
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we could do check whether maxWithdraw will return same amount of what master vault actually own
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
function withdraw(uint256 assets, address receiver, address owner) public returns (uint256 shares)
note ERC4626.withdraw returns share withdrawn not assetReceived
Make master vault upgradable
| function withdrawPerformanceFees() external onlyRole(FEE_MANAGER_ROLE) { | ||
| if (!enablePerformanceFee) revert PerformanceFeeDisabled(); | ||
| if (beneficiary == address(0)) revert BeneficiaryNotSet(); | ||
|
|
||
| uint256 totalProfits = totalProfit(); | ||
| if (totalProfits > 0) { | ||
| IERC4626 _subVault = subVault; | ||
| if (address(_subVault) != address(0)) { | ||
| _subVault.withdraw(totalProfits, address(this), address(this)); | ||
| } | ||
| IERC20(asset()).safeTransfer(beneficiary, totalProfits); | ||
| } | ||
| } |
Check warning
Code scanning / Slither
Unused return Medium
fdd512f to
e9d49e5
Compare
* feat: access control roles * remove OwnableUpgradeable * add note about permissionless fee manager --------- Co-authored-by: Henry <[email protected]>
MasterVault: remove stored subvault exchange rate
MasterVault: remove switchSubVault
| function setSubVault(IERC4626 _subVault, uint256 minSubVaultExchRateWad) external onlyRole(VAULT_MANAGER_ROLE) { | ||
| IERC20 underlyingAsset = IERC20(asset()); | ||
| if (address(subVault) != address(0)) revert SubVaultAlreadySet(); | ||
| if (address(_subVault.asset()) != address(underlyingAsset)) revert SubVaultAssetMismatch(); | ||
|
|
||
| subVault = _subVault; | ||
|
|
||
| IERC20(asset()).safeApprove(address(_subVault), type(uint256).max); | ||
| _subVault.deposit(underlyingAsset.balanceOf(address(this)), address(this)); | ||
|
|
||
| uint256 subVaultExchRateWad = _subVault.balanceOf(address(this)).mulDiv(1e18, totalSupply(), MathUpgradeable.Rounding.Down); | ||
| if (subVaultExchRateWad < minSubVaultExchRateWad) revert NewSubVaultExchangeRateTooLow(); | ||
|
|
||
| emit SubvaultChanged(address(0), address(_subVault)); | ||
| } |
Check warning
Code scanning / Slither
Unused return Medium
| function revokeSubVault(uint256 minAssetExchRateWad) external onlyRole(VAULT_MANAGER_ROLE) { | ||
| IERC4626 oldSubVault = subVault; | ||
| if (address(oldSubVault) == address(0)) revert NoExistingSubVault(); | ||
|
|
||
| subVault = IERC4626(address(0)); | ||
|
|
||
| oldSubVault.redeem(oldSubVault.balanceOf(address(this)), address(this), address(this)); | ||
| IERC20(asset()).safeApprove(address(oldSubVault), 0); | ||
|
|
||
| uint256 assetExchRateWad = IERC20(asset()).balanceOf(address(this)).mulDiv(1e18, totalSupply(), MathUpgradeable.Rounding.Down); | ||
| if (assetExchRateWad < minAssetExchRateWad) revert SubVaultExchangeRateTooLow(); | ||
|
|
||
| emit SubvaultChanged(address(oldSubVault), address(0)); | ||
| } |
Check warning
Code scanning / Slither
Unused return Medium
This isolate the implementation for the master vault and its related factory and subvault.