-
Notifications
You must be signed in to change notification settings - Fork 165
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
Open
waelsy123
wants to merge
130
commits into
main
Choose a base branch
from
wa/master-vault-isolated
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 109 commits
Commits
Show all changes
130 commits
Select commit
Hold shift + click to select a range
951c33c
feat: add master vault
waelsy123 fc89964
permission withdraw performence fees
waelsy123 7922536
feat: make master vault beacon upgradable
waelsy123 6331e7a
fixup! feat: make master vault beacon upgradable
waelsy123 5632d3d
satisify slither
waelsy123 2b8f151
remove unnecessary checks
waelsy123 5348604
fixup! feat: make master vault beacon upgradable
waelsy123 3a24b45
fix: set subvault in between depsoit and _subVaultExchRateWad calcula…
waelsy123 db0feb1
fixup! feat: make master vault beacon upgradable
waelsy123 1e0c267
fixup! feat: make master vault beacon upgradable
waelsy123 4aad0dd
fix: remove not used beacon address from storage
waelsy123 9ff2c39
fixup! feat: make master vault beacon upgradable
waelsy123 e9d49e5
feat: make master vault upgradable
waelsy123 cd1a25d
feat: access control roles (#132)
waelsy123 72956ed
add MasterVault contract natspec
godzillaba 35c2a3c
remove subVaultExchRateWad
godzillaba 9b4809c
remove unused errors
godzillaba a05eddc
remove switchSubVault
godzillaba fc74ddd
Merge branch 'ha/mv-remove-switch-func' into ha/mv-docs
godzillaba 302d590
role comment
godzillaba bd1dffb
Merge pull request #133 from OffchainLabs/ha/mv-remove-stored-exch-rate
godzillaba 724abf5
Merge pull request #134 from OffchainLabs/ha/mv-remove-switch-func
godzillaba cc04f52
document roles
godzillaba b37aec9
add fee requirement
godzillaba 4470279
wip: continuous fee accounting
godzillaba 9932afd
Revert "add fee requirement"
godzillaba 78b172d
Merge branch 'ha/mv-docs' into ha/mv-fix-perf-fee-principal-tracking
godzillaba cb72759
wip continuous accounting
godzillaba fe0d73b
finish continuous accounting
godzillaba bc27b40
rearrange
godzillaba 6b68210
Merge pull request #135 from OffchainLabs/ha/mv-docs
godzillaba 76fccff
Merge pull request #136 from OffchainLabs/ha/mv-fix-perf-fee-principa…
godzillaba e225136
remove unused errors
godzillaba eb26c62
avoid principal underflow
godzillaba a376e34
Merge pull request #139 from OffchainLabs/ha/fix-perf-fee-underflow
godzillaba cf71c56
tests: core functionality (#140)
waelsy123 dc5c3a3
fuzz test sub vault double in assets (#143)
waelsy123 f4a9ea6
tests: move util methods into core MasterVaultCoreTests contract
waelsy123 6393094
test: add test_scenario01_noGainNoLoss
waelsy123 50cb6e4
test: add test_scenario02_socializeLosses & test_scenario03_profitToB…
waelsy123 f9c6a61
test: add test_scenario04_secondDepositAfterFeeClaim
waelsy123 26b6907
test: add test_scenario05_profitThenLoss & test_scenario06_profitClai…
waelsy123 8a850ec
test: add test_scenario07_afterLossNewDeposit
waelsy123 b01306b
test: add test_scenario08_depositAfterLoss
waelsy123 1f888a5
test: add MasterVaultScenarioCoreTest and its util methods
waelsy123 a299f38
Merge pull request #147 from OffchainLabs/cleanup-tests
godzillaba 9cf303e
account for capacity constraints during rebalance
godzillaba c8c05a7
minimum rebalance amount
godzillaba ddfc513
set minimum rebalance amount
godzillaba 5c55f23
rename variable
godzillaba 1dd80c7
check actual amount instead of desired amount
godzillaba c95c99f
clean up modifiers
godzillaba b257cad
update comment
godzillaba 24f6d96
Merge pull request #149 from OffchainLabs/ha/mv-rebalance-improvements
godzillaba b5fd393
clamp _totalAssetsLessProfit
godzillaba 5af3e53
feat: rebalance with `KEEPER` (#151)
waelsy123 d986bb0
replace ERC4626 inheritance with ERC20
godzillaba c9dcc07
remove maxmint and maxdeposit
godzillaba 71fc5b0
external deposit and redeem
godzillaba f98c9de
add note about rounding direction
godzillaba 3f83a2d
Merge pull request #152 from OffchainLabs/ha/mv-ditch-4626
waelsy123 21ab1f7
add onlyGateway modifier
waelsy123 8024439
fixup! add onlyGateway modifier
waelsy123 b90ec63
Merge pull request #153 from OffchainLabs/ybb/gateway-role
waelsy123 ec8f4a9
ybb: whitelist subvaults (#154)
waelsy123 660358b
split roles into separate contract
godzillaba 64ec041
Merge branch 'wa/master-vault-isolated' into ha/mv-roles-registry
godzillaba 5b3f52f
add external roles registry
godzillaba fb81950
doc
godzillaba 3a1b986
document roles
godzillaba b35455b
Merge pull request #156 from OffchainLabs/ha/mv-roles-overhaul
waelsy123 000d61c
fix role admin overwriting
godzillaba fd759ff
redundant init
godzillaba 9b4365d
Merge pull request #155 from OffchainLabs/ha/mv-roles-registry
waelsy123 cf7dbe8
redeem internal -> external
godzillaba b79da31
fix role admin overwriting 2
godzillaba 234f81d
Merge pull request #157 from OffchainLabs/ha/mv-roles-fix
waelsy123 2157058
set cooldown period in seconds for rebalancing
waelsy123 a876fd6
move lastRebalanceTime update
godzillaba 0d12372
add default of 1
godzillaba dcc5ac4
Revert "move lastRebalanceTime update"
godzillaba 6d4f011
Merge pull request #159 from OffchainLabs/ha/cooldown-review
waelsy123 25a0864
Merge pull request #158 from OffchainLabs/ybb/cooldown
waelsy123 a91da02
remove unused rounding params
godzillaba 65ac084
confirm no fee req
godzillaba b1b8173
remove arbitrary call feature
godzillaba ec7120f
remove old todo about 4626 vulns
godzillaba 8fd63ca
docs
godzillaba 44e6ddf
fmt
godzillaba 1343057
Merge branch 'ha/mv-tighten-rounding' into ha/mv-docs
godzillaba d42323a
principalPriceWad
godzillaba 38c3149
more docs
godzillaba ca4a895
Merge branch 'ha/mv-docs' into ha/safer-principal-tracking
godzillaba 8f21eb0
more docs
godzillaba 44918d3
Merge branch 'ha/mv-docs' into ha/safer-principal-tracking
godzillaba b39016e
fmt
godzillaba 3cdc7a4
remove internal _rebalance
godzillaba e4bc23e
never skip rebalancing, always revert
godzillaba d7dbb22
fmt
godzillaba 54a15c3
document extra decimals better
godzillaba c2a6b44
Merge branch 'ha/safer-principal-tracking' into ha/rebalance-small-re…
godzillaba a6251f0
make _totalPrincipal internal
godzillaba 528d704
Merge branch 'ha/safer-principal-tracking' into ha/rebalance-small-re…
godzillaba 34ae58b
document _totalPrincipal
godzillaba 485383e
Merge branch 'ha/safer-principal-tracking' into ha/rebalance-small-re…
godzillaba 6f85180
Merge pull request #163 from OffchainLabs/ha/rebalance-small-refactor
waelsy123 610870c
Merge pull request #162 from OffchainLabs/ha/safer-principal-tracking
waelsy123 a3db478
Merge pull request #161 from OffchainLabs/ha/mv-docs
waelsy123 f89d010
Merge pull request #160 from OffchainLabs/ha/mv-tighten-rounding
waelsy123 85a27b1
pack storage
godzillaba e336fbe
Merge branch 'wa/master-vault-isolated' into ha/mv-storage-packing
godzillaba 7de28e9
fmt
godzillaba 3866f91
update comment
godzillaba 33b0506
add error PerformanceFeeUnchanged
godzillaba 0ededc8
improve docs, create constants, add minimum cooldown
godzillaba 9372ad8
Merge pull request #164 from OffchainLabs/ha/mv-storage-packing
waelsy123 db943e6
... or sublinear previewDeposit
godzillaba 3ac7d1e
Merge pull request #165 from OffchainLabs/ha/mv-fix-setters
waelsy123 650cc76
test: fix master vault core tests
waelsy123 592ea0e
set principalPriceWad to 1e18 when vault hold no assets yet
waelsy123 057cb5f
add virtual asset
waelsy123 603d26d
fix +1 virtual asset comments
godzillaba 5f365a6
Merge pull request #168 from OffchainLabs/fix/init-principalPriceWad
waelsy123 339356a
Merge pull request #167 from OffchainLabs/ybb/tests
waelsy123 e7b8835
tests: add more scenario tests
waelsy123 6740ad5
Merge pull request #170 from OffchainLabs/ybb/more-tests2
waelsy123 3eacbce
fix: keeper can be address(0)
waelsy123 2fb5df2
fix: implement IMasterVault interface
waelsy123 b8d2e36
fix: approve assets to subvault only during the deposit
waelsy123 32f2e22
Merge pull request #171 from OffchainLabs/fix/keeper-address-zero
waelsy123 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
| pragma solidity ^0.8.0; | ||
|
|
||
| interface IMasterVault { | ||
| function setSubVault(address subVault, uint256 minSubVaultExchRateWad) external; | ||
| } | ||
13 changes: 13 additions & 0 deletions
13
contracts/tokenbridge/libraries/vault/IMasterVaultFactory.sol
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
| pragma solidity ^0.8.0; | ||
|
|
||
| import "../gateway/IGatewayRouter.sol"; | ||
|
|
||
| interface IMasterVaultFactory { | ||
| event VaultDeployed(address indexed token, address indexed vault); | ||
|
|
||
| function initialize(address _owner, IGatewayRouter _gatewayRouter) external; | ||
| function deployVault(address token) external returns (address vault); | ||
| function calculateVaultAddress(address token) external view returns (address); | ||
| function getVault(address token) external returns (address); | ||
| } |
Large diffs are not rendered by default.
Oops, something went wrong.
84 changes: 84 additions & 0 deletions
84
contracts/tokenbridge/libraries/vault/MasterVaultFactory.sol
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,84 @@ | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
|
|
||
| pragma solidity ^0.8.0; | ||
|
|
||
| import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; | ||
| import "@openzeppelin/contracts/proxy/beacon/UpgradeableBeacon.sol"; | ||
| import "@openzeppelin/contracts/token/ERC20/extensions/ERC4626.sol"; | ||
| import "../ClonableBeaconProxy.sol"; | ||
| import "./IMasterVault.sol"; | ||
| import "./IMasterVaultFactory.sol"; | ||
| import "./MasterVault.sol"; | ||
| import "../gateway/IGatewayRouter.sol"; | ||
|
|
||
| contract DefaultSubVault is ERC4626 { | ||
| constructor(address token) ERC4626(IERC20(token)) ERC20("Default SubVault", "DSV") {} | ||
| } | ||
|
|
||
| // todo: slim down this contract | ||
| contract MasterVaultFactory is IMasterVaultFactory, Initializable { | ||
| error ZeroAddress(); | ||
| error BeaconNotDeployed(); | ||
|
|
||
| BeaconProxyFactory public beaconProxyFactory; | ||
| MasterVaultRoles public rolesRegistry; | ||
| IGatewayRouter public gatewayRouter; | ||
|
|
||
| function initialize(address _owner, IGatewayRouter _gatewayRouter) public initializer { | ||
| rolesRegistry = new MasterVaultRoles(); | ||
| rolesRegistry.initialize(_owner); | ||
|
|
||
| gatewayRouter = _gatewayRouter; | ||
| MasterVault masterVaultImplementation = new MasterVault(); | ||
| UpgradeableBeacon beacon = new UpgradeableBeacon(address(masterVaultImplementation)); | ||
| beaconProxyFactory = new BeaconProxyFactory(); | ||
| beaconProxyFactory.initialize(address(beacon)); | ||
| beacon.transferOwnership(_owner); | ||
| } | ||
|
|
||
| function deployVault(address token) public returns (address vault) { | ||
| bytes32 userSalt = _getUserSalt(token); | ||
| vault = beaconProxyFactory.createProxy(userSalt); | ||
|
|
||
| string memory name = string(abi.encodePacked("Master ", _tryGetTokenName(token))); | ||
| string memory symbol = string(abi.encodePacked("m", _tryGetTokenSymbol(token))); | ||
|
|
||
| MasterVault(vault) | ||
| .initialize(new DefaultSubVault(token), name, symbol, rolesRegistry, gatewayRouter); | ||
|
|
||
| emit VaultDeployed(token, vault); | ||
| } | ||
|
|
||
| function _getUserSalt(address token) internal pure returns (bytes32) { | ||
| return keccak256(abi.encode(token)); | ||
| } | ||
|
|
||
| function calculateVaultAddress(address token) public view returns (address) { | ||
| bytes32 userSalt = _getUserSalt(token); | ||
| return beaconProxyFactory.calculateExpectedAddress(address(this), userSalt); | ||
| } | ||
|
|
||
| function getVault(address token) external returns (address) { | ||
| address vault = calculateVaultAddress(token); | ||
| if (vault.code.length == 0) { | ||
| return deployVault(token); | ||
| } | ||
| return vault; | ||
| } | ||
|
|
||
| function _tryGetTokenName(address token) internal view returns (string memory) { | ||
| try IERC20Metadata(token).name() returns (string memory name) { | ||
| return name; | ||
| } catch { | ||
| return ""; | ||
| } | ||
| } | ||
|
|
||
| function _tryGetTokenSymbol(address token) internal view returns (string memory) { | ||
| try IERC20Metadata(token).symbol() returns (string memory symbol) { | ||
| return symbol; | ||
| } catch { | ||
| return ""; | ||
| } | ||
| } | ||
| } |
52 changes: 52 additions & 0 deletions
52
contracts/tokenbridge/libraries/vault/MasterVaultRoles.sol
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
| pragma solidity ^0.8.0; | ||
|
|
||
| import { | ||
| AccessControlEnumerableUpgradeable | ||
| } from "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol"; | ||
|
|
||
| /// @notice Roles system for MasterVaults. | ||
| /// Each MasterVault will have a reference to a singleton MasterVaultRoles contract, in addition to inheriting MasterVaultRoles directly. | ||
| /// This allows for easier management of roles across multiple vaults. | ||
| contract MasterVaultRoles is AccessControlEnumerableUpgradeable { | ||
| /// @notice The admin can: | ||
| /// - Grant/revoke GENERAL_MANAGER_ROLE and ADMIN_ROLE | ||
| /// - Add/remove whitelisted subvaults | ||
| bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE"); | ||
| /// @notice The general manager can: | ||
| /// - Grant/revoke FEE_MANAGER_ROLE, PAUSER_ROLE, and KEEPER_ROLE | ||
| /// - Set the subVault to any whitelisted subVault | ||
| /// - Set the target allocation | ||
| /// - Set the minimum rebalance amount | ||
| /// - Set the rebalance cooldown | ||
| bytes32 public constant GENERAL_MANAGER_ROLE = keccak256("GENERAL_MANAGER_ROLE"); | ||
| /// @notice The fee manager can: | ||
| /// - Toggle performance fees on/off | ||
| /// - Set the performance fee beneficiary | ||
| bytes32 public constant FEE_MANAGER_ROLE = keccak256("FEE_MANAGER_ROLE"); | ||
| /// @notice The pauser can: | ||
| /// - pause/unpause deposits and withdrawals | ||
| bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE"); | ||
| /// @notice The keeper can: | ||
| /// - rebalance | ||
| /// - distribute performance fees | ||
| bytes32 public constant KEEPER_ROLE = keccak256("KEEPER_ROLE"); | ||
|
|
||
| function __MasterVaultRoles_init() internal onlyInitializing { | ||
| __AccessControlEnumerable_init(); | ||
| } | ||
|
|
||
| function initialize(address admin) external initializer { | ||
| // set ADMIN_ROLE as admin of appropriate roles | ||
| _setRoleAdmin(ADMIN_ROLE, ADMIN_ROLE); | ||
| _setRoleAdmin(GENERAL_MANAGER_ROLE, ADMIN_ROLE); | ||
|
|
||
| // set GENERAL_MANAGER_ROLE as admin of appropriate roles | ||
| _setRoleAdmin(FEE_MANAGER_ROLE, GENERAL_MANAGER_ROLE); | ||
| _setRoleAdmin(PAUSER_ROLE, GENERAL_MANAGER_ROLE); | ||
| _setRoleAdmin(KEEPER_ROLE, GENERAL_MANAGER_ROLE); | ||
|
|
||
| // grant ADMIN_ROLE to admin | ||
| _grantRole(ADMIN_ROLE, admin); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| // SPDX-License-Identifier: Apache-2.0 | ||
| pragma solidity ^0.8.0; | ||
|
|
||
| import {ERC4626} from "@openzeppelin/contracts/token/ERC20/extensions/ERC4626.sol"; | ||
| import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; | ||
| import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; | ||
|
|
||
| contract MockSubVault is ERC4626 { | ||
| constructor( | ||
| IERC20 _asset, | ||
| string memory _name, | ||
| string memory _symbol | ||
| ) ERC20(_name, _symbol) ERC4626(_asset) {} | ||
|
|
||
| function totalAssets() public view override returns (uint256) { | ||
| return IERC20(asset()).balanceOf(address(this)); | ||
| } | ||
|
|
||
| function adminMint(address to, uint256 amount) external { | ||
| _mint(to, amount); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,146 @@ | ||
| // SPDX-License-Identifier: UNLICENSED | ||
| pragma solidity ^0.8.0; | ||
|
|
||
| import { MasterVaultCoreTest } from "./MasterVaultCore.t.sol"; | ||
| import { MockSubVault } from "../../../contracts/tokenbridge/test/MockSubVault.sol"; | ||
| import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; | ||
| import { IERC4626 } from "@openzeppelin/contracts/interfaces/IERC4626.sol"; | ||
| import { Math } from "@openzeppelin/contracts/utils/math/Math.sol"; | ||
|
|
||
| contract MasterVaultFirstDepositTest is MasterVaultCoreTest { | ||
| using Math for uint256; | ||
|
|
||
| // first deposit | ||
| function test_deposit(uint96 _depositAmount) public { | ||
| uint256 depositAmount = _depositAmount; | ||
| vm.startPrank(user); | ||
| token.mint(depositAmount); | ||
| token.approve(address(vault), depositAmount); | ||
| uint256 shares = vault.deposit(depositAmount, user); | ||
| vm.stopPrank(); | ||
| _checkState( | ||
| State({ | ||
| userShares: depositAmount * DEAD_SHARES, | ||
| masterVaultTotalAssets: depositAmount, | ||
| masterVaultTotalSupply: (1 + depositAmount) * DEAD_SHARES, | ||
| masterVaultTokenBalance: depositAmount, | ||
| masterVaultSubVaultShareBalance: 0, | ||
| masterVaultTotalPrincipal: 0, | ||
| subVaultTotalAssets: 0, | ||
| subVaultTotalSupply: 0, | ||
| subVaultTokenBalance: 0 | ||
| }) | ||
| ); | ||
| assertEq(shares, depositAmount * DEAD_SHARES, "shares mismatch deposit return value"); | ||
| } | ||
|
|
||
| function test_mint(uint96 _mintAmount) public { | ||
| uint256 mintAmount = _mintAmount; | ||
| vm.startPrank(user); | ||
| token.mint(mintAmount); | ||
| token.approve(address(vault), mintAmount); | ||
| uint256 assets = vault.mint(mintAmount, user); | ||
| vm.stopPrank(); | ||
| _checkState( | ||
| State({ | ||
| userShares: mintAmount, | ||
| masterVaultTotalAssets: mintAmount.ceilDiv(1e18), | ||
| masterVaultTotalSupply: mintAmount + DEAD_SHARES, | ||
| masterVaultTokenBalance: mintAmount.ceilDiv(1e18), | ||
| masterVaultSubVaultShareBalance: 0, | ||
| masterVaultTotalPrincipal: 0, | ||
| subVaultTotalAssets: 0, | ||
| subVaultTotalSupply: 0, | ||
| subVaultTokenBalance: 0 | ||
| }) | ||
| ); | ||
| assertEq(assets, mintAmount.ceilDiv(1e18), "assets mismatch mint return value"); | ||
| } | ||
|
|
||
| function test_withdraw(uint96 _firstDeposit, uint96 _withdrawAmount) public { | ||
| uint256 firstDeposit = _firstDeposit; | ||
| uint256 withdrawAmount = _withdrawAmount; | ||
| vm.assume(withdrawAmount <= firstDeposit); | ||
| test_deposit(_firstDeposit); | ||
| vm.startPrank(user); | ||
| uint256 sharesRedeemed = vault.withdraw(withdrawAmount, user, user); | ||
| vm.stopPrank(); | ||
| _checkState( | ||
| State({ | ||
| userShares: (firstDeposit - withdrawAmount) * DEAD_SHARES, | ||
| masterVaultTotalAssets: firstDeposit - withdrawAmount, | ||
| masterVaultTotalSupply: (1 + firstDeposit - withdrawAmount) * DEAD_SHARES, | ||
| masterVaultTokenBalance: firstDeposit - withdrawAmount, | ||
| masterVaultSubVaultShareBalance: 0, | ||
| masterVaultTotalPrincipal: 0, | ||
| subVaultTotalAssets: 0, | ||
| subVaultTotalSupply: 0, | ||
| subVaultTokenBalance: 0 | ||
| }) | ||
| ); | ||
| assertEq( | ||
| sharesRedeemed, | ||
| withdrawAmount * DEAD_SHARES, | ||
| "sharesRedeemed mismatch withdraw return value" | ||
| ); | ||
| } | ||
|
|
||
| function test_redeem(uint96 _firstMint, uint96 _redeemAmount) public { | ||
| uint256 firstMint = _firstMint; | ||
| uint256 redeemAmount = _redeemAmount; | ||
| vm.assume(redeemAmount <= firstMint); | ||
| test_mint(_firstMint); | ||
| State memory beforeState = _getState(); | ||
| vm.startPrank(user); | ||
| uint256 assets = vault.redeem(redeemAmount, user, user); | ||
| uint256 expectedAssets = ((1 + beforeState.masterVaultTotalAssets) * redeemAmount) / | ||
| (beforeState.masterVaultTotalSupply); | ||
| vm.stopPrank(); | ||
| _checkState( | ||
| State({ | ||
| userShares: beforeState.userShares - redeemAmount, | ||
| masterVaultTotalAssets: beforeState.masterVaultTotalAssets - expectedAssets, | ||
| masterVaultTotalSupply: beforeState.masterVaultTotalSupply - redeemAmount, | ||
| masterVaultTokenBalance: beforeState.masterVaultTokenBalance - expectedAssets, | ||
| masterVaultSubVaultShareBalance: 0, | ||
| masterVaultTotalPrincipal: 0, | ||
| subVaultTotalAssets: 0, | ||
| subVaultTotalSupply: 0, | ||
| subVaultTokenBalance: 0 | ||
| }) | ||
| ); | ||
| assertEq(assets, expectedAssets, "assets mismatch redeem return value"); | ||
| } | ||
| } | ||
|
|
||
| // contract MasterVaultTestWithSubvaultFresh is MasterVaultFirstDepositTest { | ||
| // function setUp() public override { | ||
| // super.setUp(); | ||
| // MockSubVault _subvault = new MockSubVault(IERC20(address(token)), "TestSubvault", "TSV"); | ||
| // vault.setSubVault(IERC4626(address(_subvault))); | ||
| // } | ||
| // } | ||
|
|
||
| // contract MasterVaultTestWithSubvaultHoldingAssets is MasterVaultFirstDepositTest { | ||
| // function setUp() public override { | ||
| // super.setUp(); | ||
|
|
||
| // MockSubVault _subvault = new MockSubVault(IERC20(address(token)), "TestSubvault", "TSV"); | ||
| // uint256 _initAmount = 97659743; | ||
| // token.mint(_initAmount); | ||
| // token.approve(address(_subvault), _initAmount); | ||
| // _subvault.deposit(_initAmount, address(this)); | ||
| // assertEq( | ||
| // _initAmount, | ||
| // _subvault.totalAssets(), | ||
| // "subvault should be initiated with assets = _initAmount" | ||
| // ); | ||
| // assertEq( | ||
| // _initAmount, | ||
| // _subvault.totalSupply(), | ||
| // "subvault should be initiated with shares = _initAmount" | ||
| // ); | ||
|
|
||
| // vault.setSubVault(IERC4626(address(_subvault))); | ||
| // } | ||
| // } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
wrong sig