@@ -35,7 +35,7 @@ import { Math } from "@openzeppelin/contracts/utils/math/Math.sol";
3535 * - Users cannot transfer locked shares to other addresses
3636 * - Available shares = total balance - locked shares
3737 * - Prevents rage quit cooldown bypass through share transfers
38- * - Use `getTransferableShares() ` to check available balance for transfers
38+ * - Check `custodyInfo(user).lockedShares ` to calculate available balance for transfers
3939 *
4040 * 4. **Withdrawal Rules:**
4141 * - Users can only withdraw shares if they have active custody
@@ -44,10 +44,10 @@ import { Math } from "@openzeppelin/contracts/utils/math/Math.sol";
4444 * - New rage quit required after custody is fully withdrawn
4545 * - `maxWithdraw()` and `maxRedeem()` return 0 if no custody or still in cooldown
4646 *
47- * 5. **Utility Functions :**
48- * - `getTransferableShares (user)`: Returns shares available for transfer
49- * - `getRageQuitableShares (user)`: Returns shares available for rage quit initiation
50- * - `custodyInfo(user)`: Returns custody details (locked shares, unlock time)
47+ * 5. **Querying Custody State :**
48+ * - `custodyInfo (user)`: Returns custody details (lockedShares, unlockTime)
49+ * - Transferable shares = `balanceOf (user) - custodyInfo(user).lockedShares`
50+ * - User can initiate rage quit if `custodyInfo(user).lockedShares == 0`
5151 *
5252 * ## Two-Step Cooldown Period Changes:
5353 *
@@ -78,7 +78,7 @@ import { Math } from "@openzeppelin/contracts/utils/math/Math.sol";
7878 * **Scenario A - Basic Custody Flow:**
7979 * 1. User has 1000 shares, initiates rage quit for 500 shares
8080 * 2. 500 shares locked in custody, 500 shares remain transferable
81- * 3. `getTransferableShares (user)` returns 500, `getRageQuitableShares( user)` returns 0
81+ * 3. `custodyInfo (user).lockedShares ` returns 500, user cannot initiate another rage quit
8282 * 4. After cooldown, user can withdraw up to 500 shares
8383 * 5. User withdraws 300 shares, 200 shares remain in custody
8484 * 6. User can later withdraw remaining 200 shares without new rage quit
@@ -90,13 +90,13 @@ import { Math } from "@openzeppelin/contracts/utils/math/Math.sol";
9090 * 4. Change finalized after grace period
9191 * 5. User B rage quits after finalization → uses 14-day cooldown
9292 *
93- * **Scenario C - Utility Function Usage :**
93+ * **Scenario C - Querying Custody State :**
9494 * 1. User has 1000 shares, no active rage quit
95- * 2. `getTransferableShares (user)` returns 1000
96- * 3. `getRageQuitableShares(user)` returns 1000
95+ * 2. `custodyInfo (user).lockedShares ` returns 0, transferable = 1000
96+ * 3. User can initiate rage quit (no active custody)
9797 * 4. User initiates rage quit for 400 shares
98- * 5. `getTransferableShares (user)` returns 600
99- * 6. `getRageQuitableShares(user)` returns 0 (already has active rage quit )
98+ * 5. `custodyInfo (user).lockedShares ` returns 400, transferable = 600
99+ * 6. User cannot initiate another rage quit (already has active custody )
100100 */
101101contract MultistrategyLockedVault is MultistrategyVault , IMultistrategyLockedVault {
102102 // ============================================
@@ -134,15 +134,15 @@ contract MultistrategyLockedVault is MultistrategyVault, IMultistrategyLockedVau
134134
135135 /// @notice Initial rage quit cooldown period set at deployment
136136 /// @dev 7 days in seconds. Applied until governance changes it
137- uint256 public constant INITIAL_RAGE_QUIT_COOLDOWN_PERIOD = 7 days ;
137+ uint256 private constant INITIAL_RAGE_QUIT_COOLDOWN_PERIOD = 7 days ;
138138
139139 /// @notice Minimum allowed rage quit cooldown period
140140 /// @dev 1 day in seconds. Prevents cooldown from being set too short
141- uint256 public constant RANGE_MINIMUM_RAGE_QUIT_COOLDOWN_PERIOD = 1 days ;
141+ uint256 private constant RANGE_MINIMUM_RAGE_QUIT_COOLDOWN_PERIOD = 1 days ;
142142
143143 /// @notice Maximum allowed rage quit cooldown period
144144 /// @dev 30 days in seconds. Prevents cooldown from being set too long
145- uint256 public constant RANGE_MAXIMUM_RAGE_QUIT_COOLDOWN_PERIOD = 30 days ;
145+ uint256 private constant RANGE_MAXIMUM_RAGE_QUIT_COOLDOWN_PERIOD = 30 days ;
146146
147147 /// @notice Grace period delay for cooldown changes
148148 /// @dev 14 days in seconds. Users have this time to rage quit under old terms
@@ -534,19 +534,15 @@ contract MultistrategyLockedVault is MultistrategyVault, IMultistrategyLockedVau
534534 revert SharesStillLocked ();
535535 }
536536
537- // Ensure user has sufficient balance
538- uint256 userBalance = balanceOf (owner);
539- if (userBalance < shares) {
540- revert InsufficientBalance ();
541- }
542-
543537 // Can only withdraw up to locked amount
544538 if (shares > custody.lockedShares) {
545539 revert ExceedsCustodiedAmount ();
546540 }
547541
548542 // Reduce locked shares by withdrawn amount
549- custody.lockedShares -= shares;
543+ unchecked {
544+ custody.lockedShares -= shares;
545+ }
550546
551547 // If all custodied shares withdrawn, reset custody info
552548 if (custody.lockedShares == 0 ) {
@@ -572,7 +568,11 @@ contract MultistrategyLockedVault is MultistrategyVault, IMultistrategyLockedVau
572568
573569 if (custody.lockedShares > 0 ) {
574570 uint256 senderBalance = balanceOf (sender_);
575- uint256 availableShares = senderBalance - custody.lockedShares;
571+
572+ uint256 availableShares;
573+ unchecked {
574+ availableShares = senderBalance - custody.lockedShares;
575+ }
576576
577577 // Revert if trying to transfer more than available shares
578578 if (amount_ > availableShares) {
@@ -625,7 +625,7 @@ contract MultistrategyLockedVault is MultistrategyVault, IMultistrategyLockedVau
625625 function maxWithdraw (
626626 address owner_ ,
627627 uint256 maxLoss_
628- ) public view override (MultistrategyVault, IMultistrategyVault) returns (uint256 ) {
628+ ) external view override (MultistrategyVault, IMultistrategyVault) returns (uint256 ) {
629629 return maxWithdraw (owner_, maxLoss_, new address [](0 ));
630630 }
631631
@@ -670,11 +670,8 @@ contract MultistrategyLockedVault is MultistrategyVault, IMultistrategyLockedVau
670670 balanceOf (owner_)
671671 );
672672
673- // Get custody info to determine locked shares
674- uint256 lockedShares = custody.lockedShares;
675-
676673 // Return minimum of parent max and custody limit
677- return Math.min (parentMax, lockedShares);
674+ return Math.min (parentMax, custody. lockedShares);
678675 }
679676
680677 /**
@@ -689,7 +686,7 @@ contract MultistrategyLockedVault is MultistrategyVault, IMultistrategyLockedVau
689686 function maxRedeem (
690687 address owner_ ,
691688 uint256 maxLoss_
692- ) public view override (MultistrategyVault, IMultistrategyVault) returns (uint256 ) {
689+ ) external view override (MultistrategyVault, IMultistrategyVault) returns (uint256 ) {
693690 return maxRedeem (owner_, maxLoss_, new address [](0 ));
694691 }
695692
@@ -700,7 +697,9 @@ contract MultistrategyLockedVault is MultistrategyVault, IMultistrategyLockedVau
700697 * @param owner_ Address that owns the shares
701698 * @return max Maximum redeemable shares (constrained by custody)
702699 */
703- function maxRedeem (address owner_ ) public view override (MultistrategyVault, IMultistrategyVault) returns (uint256 ) {
700+ function maxRedeem (
701+ address owner_
702+ ) external view override (MultistrategyVault, IMultistrategyVault) returns (uint256 ) {
704703 return maxRedeem (owner_, MAX_BPS, new address [](0 ));
705704 }
706705}
0 commit comments