@@ -50,39 +50,44 @@ fn pool_net_asset_value(
5050 let pool_rent_exempt_reserve = rent. minimum_balance ( pool_stake_info. data_len ( ) ) ;
5151 let onramp_rent_exempt_reserve = rent. minimum_balance ( pool_onramp_info. data_len ( ) ) ;
5252
53- // NEV is all lamports in both accounts less rent
54- pool_stake_info
53+ // NAV is all lamports in both accounts less rent
54+
55+ let main_stake_value = pool_stake_info
56+ . lamports ( )
57+ . saturating_sub ( pool_rent_exempt_reserve) ;
58+
59+ let onramp_value = pool_onramp_info
5560 . lamports ( )
56- . saturating_add ( pool_onramp_info . lamports ( ) )
57- . saturating_sub ( pool_rent_exempt_reserve )
58- . saturating_sub ( onramp_rent_exempt_reserve )
61+ . saturating_sub ( onramp_rent_exempt_reserve ) ;
62+
63+ main_stake_value . saturating_add ( onramp_value )
5964}
6065
61- /// Calculate pool tokens to mint, given outstanding token supply, pool NEV , and deposit amount
66+ /// Calculate pool tokens to mint, given outstanding token supply, pool NAV , and deposit amount
6267fn calculate_deposit_amount (
6368 pre_token_supply : u64 ,
64- pre_pool_nev : u64 ,
69+ pre_pool_nav : u64 ,
6570 user_deposit_amount : u64 ,
6671) -> Option < u64 > {
67- if pre_pool_nev == 0 || pre_token_supply == 0 {
72+ if pre_pool_nav == 0 || pre_token_supply == 0 {
6873 Some ( user_deposit_amount)
6974 } else {
7075 u64:: try_from (
7176 ( user_deposit_amount as u128 )
7277 . checked_mul ( pre_token_supply as u128 ) ?
73- . checked_div ( pre_pool_nev as u128 ) ?,
78+ . checked_div ( pre_pool_nav as u128 ) ?,
7479 )
7580 . ok ( )
7681 }
7782}
7883
79- /// Calculate pool value to return, given outstanding token supply, pool NEV , and tokens to redeem
84+ /// Calculate pool value to return, given outstanding token supply, pool NAV , and tokens to redeem
8085fn calculate_withdraw_amount (
8186 pre_token_supply : u64 ,
82- pre_pool_nev : u64 ,
87+ pre_pool_nav : u64 ,
8388 user_tokens_to_burn : u64 ,
8489) -> Option < u64 > {
85- let numerator = ( user_tokens_to_burn as u128 ) . checked_mul ( pre_pool_nev as u128 ) ?;
90+ let numerator = ( user_tokens_to_burn as u128 ) . checked_mul ( pre_pool_nav as u128 ) ?;
8691 let denominator = pre_token_supply as u128 ;
8792 if numerator < denominator || denominator == 0 {
8893 Some ( 0 )
@@ -1048,8 +1053,14 @@ impl Processor {
10481053 unreachable ! ( ) ;
10491054 } ;
10501055
1056+ // onramp must exist
1057+ match deserialize_stake ( pool_onramp_info) {
1058+ Ok ( StakeStateV2 :: Initialized ( _) ) | Ok ( StakeStateV2 :: Stake ( _, _, _) ) => ( ) ,
1059+ _ => return Err ( SinglePoolError :: OnRampDoesntExist . into ( ) ) ,
1060+ } ;
1061+
10511062 // tokens for deposit are determined off the total stakeable value of both pool-owned accounts
1052- let pre_total_nev = pool_net_asset_value ( pool_stake_info, pool_onramp_info, rent) ;
1063+ let pre_total_nav = pool_net_asset_value ( pool_stake_info, pool_onramp_info, rent) ;
10531064
10541065 let pre_user_lamports = user_stake_info. lamports ( ) ;
10551066 let ( user_stake_meta, user_stake_status) = match deserialize_stake ( user_stake_info) {
@@ -1114,7 +1125,7 @@ impl Processor {
11141125
11151126 // deposit amount is determined off stake added because we return excess lamports
11161127 let new_pool_tokens =
1117- calculate_deposit_amount ( token_supply, pre_total_nev , new_stake_added)
1128+ calculate_deposit_amount ( token_supply, pre_total_nav , new_stake_added)
11181129 . ok_or ( SinglePoolError :: UnexpectedMathError ) ?;
11191130
11201131 if new_pool_tokens == 0 {
@@ -1204,12 +1215,9 @@ impl Processor {
12041215
12051216 let minimum_delegation = stake:: tools:: get_minimum_delegation ( ) ?;
12061217
1207- // tokens for withdraw are determined off the total stakeable value of both pool-owned accounts
1208- let pre_total_nev = pool_net_asset_value ( pool_stake_info, pool_onramp_info, rent) ;
1209-
12101218 // note we deliberately do NOT validate the activation status of the pool account.
12111219 // neither warmup/cooldown nor validator delinquency prevent a user withdrawal.
1212- // however, because we calculate NEV from all lamports in both pool accounts,
1220+ // however, because we calculate NAV from all lamports in both pool accounts,
12131221 // but can only split stake from the main account (unless inactive), we must determine whether this is possible
12141222 let ( withdrawable_value, pool_is_fully_inactive) = {
12151223 let ( _, pool_stake_state) = get_stake_state ( pool_stake_info) ?;
@@ -1235,9 +1243,19 @@ impl Processor {
12351243 }
12361244 } ;
12371245
1238- // withdraw amount is determined off pool NEV just like deposit amount
1246+ // onramp must exist. this does not create an edge case where withdrawals may be blocked,
1247+ // because we also require the onramp to exist for deposits
1248+ match deserialize_stake ( pool_onramp_info) {
1249+ Ok ( StakeStateV2 :: Initialized ( _) ) | Ok ( StakeStateV2 :: Stake ( _, _, _) ) => ( ) ,
1250+ _ => return Err ( SinglePoolError :: OnRampDoesntExist . into ( ) ) ,
1251+ } ;
1252+
1253+ // tokens for withdraw are determined off the total stakeable value of both pool-owned accounts
1254+ let pre_total_nav = pool_net_asset_value ( pool_stake_info, pool_onramp_info, rent) ;
1255+
1256+ // withdraw amount is determined off pool NAV just like deposit amount
12391257 let stake_to_withdraw =
1240- calculate_withdraw_amount ( token_supply, pre_total_nev , token_amount)
1258+ calculate_withdraw_amount ( token_supply, pre_total_nav , token_amount)
12411259 . ok_or ( SinglePoolError :: UnexpectedMathError ) ?;
12421260
12431261 // self-explanatory. we catch 0 deposit above so we only hit this if we rounded to 0
0 commit comments