@@ -22,6 +22,8 @@ contract MasterVaultHandler is Test {
2222
2323 // --- Ghost variables ---
2424
25+ uint256 public random;
26+
2527 /// @notice Cumulative assets deposited into the MasterVault
2628 uint256 public ghost_deposited;
2729
@@ -46,6 +48,11 @@ contract MasterVaultHandler is Test {
4648 /// @notice Whether subvault has been negatively manipulated (loss-like: removed assets, inflated shares, rounding errors)
4749 bool public ghost_negativeManipulation;
4850
51+ modifier updateRandom (uint256 val ) {
52+ random = uint256 (keccak256 (abi.encodePacked (random, val)));
53+ _;
54+ }
55+
4956 constructor (
5057 MasterVault _vault ,
5158 FuzzSubVault _subVault ,
@@ -64,7 +71,7 @@ contract MasterVaultHandler is Test {
6471
6572 /// @notice Deposit assets into the MasterVault via the gateway user
6673 /// @dev Bounds amount to [1, 1e30] to stay within reasonable range
67- function deposit (uint256 amount ) external {
74+ function deposit (uint256 amount ) external updateRandom ( uint256 ( keccak256 ( " deposit " ))) updateRandom (amount) {
6875 amount = bound (amount, 1 , 1e30 );
6976
7077 vm.prank (user);
@@ -81,7 +88,7 @@ contract MasterVaultHandler is Test {
8188
8289 /// @notice Redeem shares from the MasterVault as user
8390 /// @dev Bounds shares to [1, user balance]
84- function redeem (uint256 shares ) external {
91+ function redeem (uint256 shares ) external updateRandom ( uint256 ( keccak256 ( " redeem " ))) updateRandom (shares) {
8592 uint256 bal = vault.balanceOf (user);
8693 if (bal == 0 ) return ;
8794 shares = bound (shares, 1 , bal);
@@ -99,7 +106,7 @@ contract MasterVaultHandler is Test {
99106
100107 /// @notice Warp time and call rebalance with permissive slippage
101108 /// @dev Uses extreme slippage bounds to avoid exchange rate reverts masking real bugs
102- function rebalance () external {
109+ function rebalance () external updateRandom ( uint256 ( keccak256 ( " rebalance " ))) {
103110 vm.warp (block .timestamp + 2 );
104111
105112 int256 minExchRate;
@@ -122,7 +129,7 @@ contract MasterVaultHandler is Test {
122129 }
123130
124131 /// @notice Distribute performance fees to beneficiary
125- function distributePerformanceFee () external {
132+ function distributePerformanceFee () external updateRandom ( uint256 ( keccak256 ( " distributePerformanceFee " ))) {
126133 address beneficiary = vault.beneficiary ();
127134 uint256 before = token.balanceOf (beneficiary);
128135
@@ -137,7 +144,7 @@ contract MasterVaultHandler is Test {
137144 // --- Manager actions ---
138145
139146 /// @notice Set target allocation (bounded 0 to 1e18)
140- function setTargetAllocation (uint256 seed ) external {
147+ function setTargetAllocation (uint256 seed ) external updateRandom ( uint256 ( keccak256 ( " setTargetAllocation " ))) updateRandom (seed) {
141148 uint64 alloc = uint64 (bound (seed, 0 , 1e18 ));
142149 try vault.setTargetAllocationWad (alloc) {
143150 ghost_callCount[this .setTargetAllocation.selector ]++ ;
@@ -147,7 +154,7 @@ contract MasterVaultHandler is Test {
147154 // --- Environment manipulation ---
148155
149156 /// @notice Send tokens directly to the subvault (simulates yield / A increases)
150- function simulateSubVaultProfit (uint256 amt ) external {
157+ function simulateSubVaultProfit (uint256 amt ) external updateRandom ( uint256 ( keccak256 ( " simulateSubVaultProfit " ))) updateRandom (amt) {
151158 amt = bound (amt, 1 , 1e24 );
152159 token.mintAmount (amt);
153160 token.transfer (address (subVault), amt);
@@ -157,7 +164,7 @@ contract MasterVaultHandler is Test {
157164 }
158165
159166 /// @notice Remove tokens from the subvault (simulates loss / A decreases)
160- function simulateSubVaultLoss (uint256 amt ) external {
167+ function simulateSubVaultLoss (uint256 amt ) external updateRandom ( uint256 ( keccak256 ( " simulateSubVaultLoss " ))) updateRandom (amt) {
161168 uint256 subBal = token.balanceOf (address (subVault));
162169 if (subBal == 0 ) return ;
163170 amt = bound (amt, 1 , subBal);
@@ -170,15 +177,15 @@ contract MasterVaultHandler is Test {
170177 }
171178
172179 /// @notice Mint shares without backing assets on FuzzSubVault (T increases, A < T)
173- function inflateSubVaultShares (uint256 amt ) external {
180+ function inflateSubVaultShares (uint256 amt ) external updateRandom ( uint256 ( keccak256 ( " inflateSubVaultShares " ))) updateRandom (amt) {
174181 amt = bound (amt, 1 , 1e24 );
175182 subVault.adminMint (address (vault), amt);
176183 ghost_negativeManipulation = true ;
177184 ghost_callCount[this .inflateSubVaultShares.selector ]++ ;
178185 }
179186
180187 /// @notice Burn shares without withdrawing assets on FuzzSubVault (T decreases, A > T)
181- function deflateSubVaultShares (uint256 amt ) external {
188+ function deflateSubVaultShares (uint256 amt ) external updateRandom ( uint256 ( keccak256 ( " deflateSubVaultShares " ))) updateRandom (amt) {
182189 uint256 vaultShares = subVault.balanceOf (address (vault));
183190 if (vaultShares == 0 ) return ;
184191 amt = bound (amt, 1 , vaultShares);
@@ -188,60 +195,60 @@ contract MasterVaultHandler is Test {
188195 }
189196
190197 /// @notice Set maxWithdraw limit on the subvault
191- function capSubVaultMaxWithdraw (uint256 lim ) external {
198+ function capSubVaultMaxWithdraw (uint256 lim ) external updateRandom ( uint256 ( keccak256 ( " capSubVaultMaxWithdraw " ))) updateRandom (lim) {
192199 lim = bound (lim, 0 , type (uint128 ).max);
193200 subVault.setMaxWithdrawLimit (lim);
194201 ghost_callCount[this .capSubVaultMaxWithdraw.selector ]++ ;
195202 }
196203
197204 /// @notice Set maxDeposit limit on the subvault
198- function capSubVaultMaxDeposit (uint256 lim ) external {
205+ function capSubVaultMaxDeposit (uint256 lim ) external updateRandom ( uint256 ( keccak256 ( " capSubVaultMaxDeposit " ))) updateRandom (lim) {
199206 lim = bound (lim, 0 , type (uint128 ).max);
200207 subVault.setMaxDepositLimit (lim);
201208 ghost_callCount[this .capSubVaultMaxDeposit.selector ]++ ;
202209 }
203210
204211 /// @notice Set maxRedeem limit on the subvault
205- function capSubVaultMaxRedeem (uint256 lim ) external {
212+ function capSubVaultMaxRedeem (uint256 lim ) external updateRandom ( uint256 ( keccak256 ( " capSubVaultMaxRedeem " ))) updateRandom (lim) {
206213 lim = bound (lim, 0 , type (uint128 ).max);
207214 subVault.setMaxRedeemLimit (lim);
208215 ghost_callCount[this .capSubVaultMaxRedeem.selector ]++ ;
209216 }
210217
211218 /// @notice Set deposit rounding error on the subvault (0–10% in wad)
212- function setDepositError (uint256 seed ) external {
219+ function setDepositError (uint256 seed ) external updateRandom ( uint256 ( keccak256 ( " setDepositError " ))) updateRandom (seed) {
213220 uint256 wad = bound (seed, 0 , 1e17 );
214221 subVault.setDepositErrorWad (wad);
215222 if (wad > 0 ) ghost_negativeManipulation = true ;
216223 ghost_callCount[this .setDepositError.selector ]++ ;
217224 }
218225
219226 /// @notice Set withdraw rounding error on the subvault (0–10% in wad)
220- function setWithdrawError (uint256 seed ) external {
227+ function setWithdrawError (uint256 seed ) external updateRandom ( uint256 ( keccak256 ( " setWithdrawError " ))) updateRandom (seed) {
221228 uint256 wad = bound (seed, 0 , 1e17 );
222229 subVault.setWithdrawErrorWad (wad);
223230 if (wad > 0 ) ghost_negativeManipulation = true ;
224231 ghost_callCount[this .setWithdrawError.selector ]++ ;
225232 }
226233
227234 /// @notice Set redeem rounding error on the subvault (0–10% in wad)
228- function setRedeemError (uint256 seed ) external {
235+ function setRedeemError (uint256 seed ) external updateRandom ( uint256 ( keccak256 ( " setRedeemError " ))) updateRandom (seed) {
229236 uint256 wad = bound (seed, 0 , 1e17 );
230237 subVault.setRedeemErrorWad (wad);
231238 if (wad > 0 ) ghost_negativeManipulation = true ;
232239 ghost_callCount[this .setRedeemError.selector ]++ ;
233240 }
234241
235242 /// @notice Set previewMint rounding error on the subvault (0–10% in wad)
236- function setPreviewMintError (uint256 seed ) external {
243+ function setPreviewMintError (uint256 seed ) external updateRandom ( uint256 ( keccak256 ( " setPreviewMintError " ))) updateRandom (seed) {
237244 uint256 wad = bound (seed, 0 , 1e17 );
238245 subVault.setPreviewMintErrorWad (wad);
239246 if (wad > 0 ) ghost_negativeManipulation = true ;
240247 ghost_callCount[this .setPreviewMintError.selector ]++ ;
241248 }
242249
243250 /// @notice Set previewRedeem rounding error on the subvault (0–10% in wad)
244- function setPreviewRedeemError (uint256 seed ) external {
251+ function setPreviewRedeemError (uint256 seed ) external updateRandom ( uint256 ( keccak256 ( " setPreviewRedeemError " ))) updateRandom (seed) {
245252 uint256 wad = bound (seed, 0 , 1e17 );
246253 subVault.setPreviewRedeemErrorWad (wad);
247254 if (wad > 0 ) ghost_negativeManipulation = true ;
0 commit comments