Skip to content
Open
Show file tree
Hide file tree
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 Sep 29, 2025
fc89964
permission withdraw performence fees
waelsy123 Sep 29, 2025
7922536
feat: make master vault beacon upgradable
waelsy123 Oct 1, 2025
6331e7a
fixup! feat: make master vault beacon upgradable
waelsy123 Oct 3, 2025
5632d3d
satisify slither
waelsy123 Oct 3, 2025
2b8f151
remove unnecessary checks
waelsy123 Oct 16, 2025
5348604
fixup! feat: make master vault beacon upgradable
waelsy123 Oct 16, 2025
3a24b45
fix: set subvault in between depsoit and _subVaultExchRateWad calcula…
waelsy123 Oct 16, 2025
db0feb1
fixup! feat: make master vault beacon upgradable
waelsy123 Oct 19, 2025
1e0c267
fixup! feat: make master vault beacon upgradable
waelsy123 Oct 19, 2025
4aad0dd
fix: remove not used beacon address from storage
waelsy123 Oct 19, 2025
9ff2c39
fixup! feat: make master vault beacon upgradable
waelsy123 Oct 19, 2025
e9d49e5
feat: make master vault upgradable
waelsy123 Oct 22, 2025
cd1a25d
feat: access control roles (#132)
waelsy123 Nov 7, 2025
72956ed
add MasterVault contract natspec
godzillaba Nov 10, 2025
35c2a3c
remove subVaultExchRateWad
godzillaba Nov 10, 2025
9b4809c
remove unused errors
godzillaba Nov 10, 2025
a05eddc
remove switchSubVault
godzillaba Nov 10, 2025
fc74ddd
Merge branch 'ha/mv-remove-switch-func' into ha/mv-docs
godzillaba Nov 10, 2025
302d590
role comment
godzillaba Nov 10, 2025
bd1dffb
Merge pull request #133 from OffchainLabs/ha/mv-remove-stored-exch-rate
godzillaba Nov 12, 2025
724abf5
Merge pull request #134 from OffchainLabs/ha/mv-remove-switch-func
godzillaba Nov 12, 2025
cc04f52
document roles
godzillaba Nov 12, 2025
b37aec9
add fee requirement
godzillaba Nov 12, 2025
4470279
wip: continuous fee accounting
godzillaba Nov 12, 2025
9932afd
Revert "add fee requirement"
godzillaba Nov 12, 2025
78b172d
Merge branch 'ha/mv-docs' into ha/mv-fix-perf-fee-principal-tracking
godzillaba Nov 12, 2025
cb72759
wip continuous accounting
godzillaba Dec 1, 2025
fe0d73b
finish continuous accounting
godzillaba Dec 3, 2025
bc27b40
rearrange
godzillaba Dec 5, 2025
6b68210
Merge pull request #135 from OffchainLabs/ha/mv-docs
godzillaba Dec 8, 2025
76fccff
Merge pull request #136 from OffchainLabs/ha/mv-fix-perf-fee-principa…
godzillaba Dec 8, 2025
e225136
remove unused errors
godzillaba Dec 8, 2025
eb26c62
avoid principal underflow
godzillaba Dec 8, 2025
a376e34
Merge pull request #139 from OffchainLabs/ha/fix-perf-fee-underflow
godzillaba Dec 9, 2025
cf71c56
tests: core functionality (#140)
waelsy123 Dec 23, 2025
dc5c3a3
fuzz test sub vault double in assets (#143)
waelsy123 Dec 23, 2025
f4a9ea6
tests: move util methods into core MasterVaultCoreTests contract
waelsy123 Jan 3, 2026
6393094
test: add test_scenario01_noGainNoLoss
waelsy123 Jan 4, 2026
50cb6e4
test: add test_scenario02_socializeLosses & test_scenario03_profitToB…
waelsy123 Jan 4, 2026
f9c6a61
test: add test_scenario04_secondDepositAfterFeeClaim
waelsy123 Jan 4, 2026
26b6907
test: add test_scenario05_profitThenLoss & test_scenario06_profitClai…
waelsy123 Jan 4, 2026
8a850ec
test: add test_scenario07_afterLossNewDeposit
waelsy123 Jan 4, 2026
b01306b
test: add test_scenario08_depositAfterLoss
waelsy123 Jan 4, 2026
1f888a5
test: add MasterVaultScenarioCoreTest and its util methods
waelsy123 Jan 7, 2026
a299f38
Merge pull request #147 from OffchainLabs/cleanup-tests
godzillaba Jan 7, 2026
9cf303e
account for capacity constraints during rebalance
godzillaba Jan 7, 2026
c8c05a7
minimum rebalance amount
godzillaba Jan 7, 2026
ddfc513
set minimum rebalance amount
godzillaba Jan 7, 2026
5c55f23
rename variable
godzillaba Jan 7, 2026
1dd80c7
check actual amount instead of desired amount
godzillaba Jan 7, 2026
c95c99f
clean up modifiers
godzillaba Jan 7, 2026
b257cad
update comment
godzillaba Jan 7, 2026
24f6d96
Merge pull request #149 from OffchainLabs/ha/mv-rebalance-improvements
godzillaba Jan 7, 2026
b5fd393
clamp _totalAssetsLessProfit
godzillaba Jan 6, 2026
5af3e53
feat: rebalance with `KEEPER` (#151)
waelsy123 Jan 12, 2026
d986bb0
replace ERC4626 inheritance with ERC20
godzillaba Jan 12, 2026
c9dcc07
remove maxmint and maxdeposit
godzillaba Jan 12, 2026
71fc5b0
external deposit and redeem
godzillaba Jan 12, 2026
f98c9de
add note about rounding direction
godzillaba Jan 13, 2026
3f83a2d
Merge pull request #152 from OffchainLabs/ha/mv-ditch-4626
waelsy123 Jan 13, 2026
21ab1f7
add onlyGateway modifier
waelsy123 Jan 13, 2026
8024439
fixup! add onlyGateway modifier
waelsy123 Jan 13, 2026
b90ec63
Merge pull request #153 from OffchainLabs/ybb/gateway-role
waelsy123 Jan 13, 2026
ec8f4a9
ybb: whitelist subvaults (#154)
waelsy123 Jan 13, 2026
660358b
split roles into separate contract
godzillaba Jan 13, 2026
64ec041
Merge branch 'wa/master-vault-isolated' into ha/mv-roles-registry
godzillaba Jan 13, 2026
5b3f52f
add external roles registry
godzillaba Jan 13, 2026
fb81950
doc
godzillaba Jan 13, 2026
3a1b986
document roles
godzillaba Jan 13, 2026
b35455b
Merge pull request #156 from OffchainLabs/ha/mv-roles-overhaul
waelsy123 Jan 13, 2026
000d61c
fix role admin overwriting
godzillaba Jan 14, 2026
fd759ff
redundant init
godzillaba Jan 14, 2026
9b4365d
Merge pull request #155 from OffchainLabs/ha/mv-roles-registry
waelsy123 Jan 14, 2026
cf7dbe8
redeem internal -> external
godzillaba Jan 14, 2026
b79da31
fix role admin overwriting 2
godzillaba Jan 14, 2026
234f81d
Merge pull request #157 from OffchainLabs/ha/mv-roles-fix
waelsy123 Jan 14, 2026
2157058
set cooldown period in seconds for rebalancing
waelsy123 Jan 14, 2026
a876fd6
move lastRebalanceTime update
godzillaba Jan 14, 2026
0d12372
add default of 1
godzillaba Jan 14, 2026
dcc5ac4
Revert "move lastRebalanceTime update"
godzillaba Jan 14, 2026
6d4f011
Merge pull request #159 from OffchainLabs/ha/cooldown-review
waelsy123 Jan 14, 2026
25a0864
Merge pull request #158 from OffchainLabs/ybb/cooldown
waelsy123 Jan 14, 2026
a91da02
remove unused rounding params
godzillaba Jan 14, 2026
65ac084
confirm no fee req
godzillaba Jan 14, 2026
b1b8173
remove arbitrary call feature
godzillaba Jan 14, 2026
ec7120f
remove old todo about 4626 vulns
godzillaba Jan 14, 2026
8fd63ca
docs
godzillaba Jan 14, 2026
44e6ddf
fmt
godzillaba Jan 14, 2026
1343057
Merge branch 'ha/mv-tighten-rounding' into ha/mv-docs
godzillaba Jan 14, 2026
d42323a
principalPriceWad
godzillaba Jan 14, 2026
38c3149
more docs
godzillaba Jan 14, 2026
ca4a895
Merge branch 'ha/mv-docs' into ha/safer-principal-tracking
godzillaba Jan 14, 2026
8f21eb0
more docs
godzillaba Jan 14, 2026
44918d3
Merge branch 'ha/mv-docs' into ha/safer-principal-tracking
godzillaba Jan 14, 2026
b39016e
fmt
godzillaba Jan 14, 2026
3cdc7a4
remove internal _rebalance
godzillaba Jan 15, 2026
e4bc23e
never skip rebalancing, always revert
godzillaba Jan 15, 2026
d7dbb22
fmt
godzillaba Jan 15, 2026
54a15c3
document extra decimals better
godzillaba Jan 15, 2026
c2a6b44
Merge branch 'ha/safer-principal-tracking' into ha/rebalance-small-re…
godzillaba Jan 15, 2026
a6251f0
make _totalPrincipal internal
godzillaba Jan 15, 2026
528d704
Merge branch 'ha/safer-principal-tracking' into ha/rebalance-small-re…
godzillaba Jan 15, 2026
34ae58b
document _totalPrincipal
godzillaba Jan 15, 2026
485383e
Merge branch 'ha/safer-principal-tracking' into ha/rebalance-small-re…
godzillaba Jan 15, 2026
6f85180
Merge pull request #163 from OffchainLabs/ha/rebalance-small-refactor
waelsy123 Jan 15, 2026
610870c
Merge pull request #162 from OffchainLabs/ha/safer-principal-tracking
waelsy123 Jan 15, 2026
a3db478
Merge pull request #161 from OffchainLabs/ha/mv-docs
waelsy123 Jan 15, 2026
f89d010
Merge pull request #160 from OffchainLabs/ha/mv-tighten-rounding
waelsy123 Jan 15, 2026
85a27b1
pack storage
godzillaba Jan 15, 2026
e336fbe
Merge branch 'wa/master-vault-isolated' into ha/mv-storage-packing
godzillaba Jan 15, 2026
7de28e9
fmt
godzillaba Jan 15, 2026
3866f91
update comment
godzillaba Jan 15, 2026
33b0506
add error PerformanceFeeUnchanged
godzillaba Jan 15, 2026
0ededc8
improve docs, create constants, add minimum cooldown
godzillaba Jan 15, 2026
9372ad8
Merge pull request #164 from OffchainLabs/ha/mv-storage-packing
waelsy123 Jan 16, 2026
db943e6
... or sublinear previewDeposit
godzillaba Jan 16, 2026
3ac7d1e
Merge pull request #165 from OffchainLabs/ha/mv-fix-setters
waelsy123 Jan 16, 2026
650cc76
test: fix master vault core tests
waelsy123 Jan 20, 2026
592ea0e
set principalPriceWad to 1e18 when vault hold no assets yet
waelsy123 Jan 20, 2026
057cb5f
add virtual asset
waelsy123 Jan 20, 2026
603d26d
fix +1 virtual asset comments
godzillaba Jan 20, 2026
5f365a6
Merge pull request #168 from OffchainLabs/fix/init-principalPriceWad
waelsy123 Jan 20, 2026
339356a
Merge pull request #167 from OffchainLabs/ybb/tests
waelsy123 Jan 20, 2026
e7b8835
tests: add more scenario tests
waelsy123 Jan 22, 2026
6740ad5
Merge pull request #170 from OffchainLabs/ybb/more-tests2
waelsy123 Jan 22, 2026
3eacbce
fix: keeper can be address(0)
waelsy123 Jan 29, 2026
2fb5df2
fix: implement IMasterVault interface
waelsy123 Jan 29, 2026
b8d2e36
fix: approve assets to subvault only during the deposit
waelsy123 Jan 29, 2026
32f2e22
Merge pull request #171 from OffchainLabs/fix/keeper-address-zero
waelsy123 Jan 30, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions contracts/tokenbridge/libraries/vault/IMasterVault.sol
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;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wrong sig

}
13 changes: 13 additions & 0 deletions contracts/tokenbridge/libraries/vault/IMasterVaultFactory.sol
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);
}
516 changes: 516 additions & 0 deletions contracts/tokenbridge/libraries/vault/MasterVault.sol

Large diffs are not rendered by default.

84 changes: 84 additions & 0 deletions contracts/tokenbridge/libraries/vault/MasterVaultFactory.sol
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 contracts/tokenbridge/libraries/vault/MasterVaultRoles.sol
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);
}
}
22 changes: 22 additions & 0 deletions contracts/tokenbridge/test/MockSubVault.sol
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);
}
}
4 changes: 4 additions & 0 deletions contracts/tokenbridge/test/TestERC20.sol
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ contract TestERC20 is aeERC20 {
function mint() external {
_mint(msg.sender, 50000000);
}

function mint(uint256 amount) external {
_mint(msg.sender, amount);
}
}

// test token code inspired from maker
Expand Down
18 changes: 17 additions & 1 deletion foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,23 @@ fs_permissions = [{ access = "read", path = "node_modules/@offchainlabs/stableco
[fmt]
number_underscore = 'thousands'
line_length = 100
# See more config options https://github.com/foundry-rs/foundry/tree/master/config
tab_width = 4
style = "space"
bracket_spacing = false
int_types = "long"
multiline_func_header = "attributes_first"
quote_style = "double"
hex_underscore = "remove"
single_line_statement_blocks = "preserve"
override_spacing = false
wrap_comments = false
docs_style = "preserve"
ignore = []
contract_new_lines = false
sort_imports = false
pow_no_space = false
prefer_compact = "all"
single_line_imports = false

[lint]
lint_on_build = false
146 changes: 146 additions & 0 deletions test-foundry/libraries/vault/MasterVault.t.sol
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)));
// }
// }
Loading
Loading