@@ -656,11 +656,52 @@ where
656656 Ok ( storage. read :: < token:: Amount > ( & key) ?. unwrap_or_default ( ) )
657657}
658658
659+ /// Compute an estimation of the most recent staking rewards rate.
660+ pub fn estimate_staking_reward_rate < S , Token , Parameters > (
661+ storage : & S ,
662+ ) -> Result < Dec >
663+ where
664+ S : StorageRead ,
665+ Parameters : parameters:: Read < S > ,
666+ Token : trans_token:: Read < S > + trans_token:: Write < S > ,
667+ {
668+ // Get needed data in desired form
669+ let total_native_tokens =
670+ Token :: get_effective_total_native_supply ( storage) ?;
671+ let last_staked_ratio = read_last_staked_ratio ( storage) ?
672+ . expect ( "Last staked ratio should exist in PoS storage" ) ;
673+ let last_inflation_amount = read_last_pos_inflation_amount ( storage) ?
674+ . expect ( "Last inflation amount should exist in PoS storage" ) ;
675+ let epochs_per_year: u64 = Parameters :: epochs_per_year ( storage) ?;
676+
677+ let total_native_tokens =
678+ Dec :: try_from ( total_native_tokens) . into_storage_result ( ) ?;
679+ let last_inflation_amount =
680+ Dec :: try_from ( last_inflation_amount) . into_storage_result ( ) ?;
681+
682+ // Estimate annual inflation rate
683+ let est_inflation_rate = checked ! (
684+ last_inflation_amount * epochs_per_year / total_native_tokens
685+ ) ?;
686+
687+ // Estimate annual staking rewards rate
688+ let est_staking_reward_rate =
689+ checked ! ( est_inflation_rate / last_staked_ratio) ?;
690+
691+ Ok ( est_staking_reward_rate)
692+ }
693+
659694#[ cfg( test) ]
660695mod tests {
661696 use std:: str:: FromStr ;
662697
698+ use namada_parameters:: storage:: get_epochs_per_year_key;
699+ use namada_state:: testing:: TestState ;
700+ use namada_trans_token:: storage_key:: minted_balance_key;
701+ use storage:: write_pos_params;
702+
663703 use super :: * ;
704+ use crate :: OwnedPosParams ;
664705
665706 #[ test]
666707 fn test_inflation_calc_up ( ) {
@@ -842,10 +883,19 @@ mod tests {
842883
843884 #[ test]
844885 fn test_pos_inflation_playground ( ) {
886+ let mut storage = TestState :: default ( ) ;
887+ let gov_params =
888+ namada_governance:: parameters:: GovernanceParameters :: default ( ) ;
889+ gov_params. init_storage ( & mut storage) . unwrap ( ) ;
890+ write_pos_params ( & mut storage, & OwnedPosParams :: default ( ) ) . unwrap ( ) ;
891+
845892 let epochs_per_year = 365_u64 ;
893+ let epy_key = get_epochs_per_year_key ( ) ;
894+ storage. write ( & epy_key, epochs_per_year) . unwrap ( ) ;
846895
847896 let init_locked_ratio = Dec :: from_str ( "0.1" ) . unwrap ( ) ;
848897 let mut last_locked_ratio = init_locked_ratio;
898+
849899 let total_native_tokens = 1_000_000_000_u64 ;
850900 let locked_amount = u64:: try_from (
851901 ( init_locked_ratio * total_native_tokens) . to_uint ( ) . unwrap ( ) ,
@@ -856,6 +906,13 @@ mod tests {
856906 let mut total_native_tokens =
857907 token:: Amount :: native_whole ( total_native_tokens) ;
858908
909+ update_state_for_pos_playground (
910+ & mut storage,
911+ last_locked_ratio,
912+ last_inflation_amount,
913+ total_native_tokens,
914+ ) ;
915+
859916 let max_reward_rate = Dec :: from_str ( "0.1" ) . unwrap ( ) ;
860917 let target_ratio = Dec :: from_str ( "0.66666666" ) . unwrap ( ) ;
861918 let p_gain_nom = Dec :: from_str ( "0.25" ) . unwrap ( ) ;
@@ -882,17 +939,42 @@ mod tests {
882939 let locked_ratio = Dec :: try_from ( locked_amount) . unwrap ( )
883940 / Dec :: try_from ( total_native_tokens) . unwrap ( ) ;
884941
885- let rate = Dec :: try_from ( inflation) . unwrap ( )
942+ let inflation_rate = Dec :: try_from ( inflation) . unwrap ( )
886943 * Dec :: from ( epochs_per_year)
887944 / Dec :: try_from ( total_native_tokens) . unwrap ( ) ;
945+ let staking_rate = inflation_rate / locked_ratio;
946+
888947 println ! (
889948 "Round {round}: Locked ratio: {locked_ratio}, inflation rate: \
890- {rate}",
949+ {inflation_rate}, staking rate: {staking_rate }",
891950 ) ;
892951
893952 last_inflation_amount = inflation;
894953 total_native_tokens += inflation;
895954 last_locked_ratio = locked_ratio;
955+ update_state_for_pos_playground (
956+ & mut storage,
957+ last_locked_ratio,
958+ last_inflation_amount,
959+ total_native_tokens,
960+ ) ;
961+
962+ let query_staking_rate = estimate_staking_reward_rate :: <
963+ _ ,
964+ namada_trans_token:: Store < _ > ,
965+ namada_parameters:: Store < _ > ,
966+ > ( & storage)
967+ . unwrap ( ) ;
968+ // println!(" ----> Query staking rate: {query_staking_rate}");
969+ if !staking_rate. is_zero ( ) && !query_staking_rate. is_zero ( ) {
970+ let ratio = staking_rate / query_staking_rate;
971+ let residual = ratio. abs_diff ( Dec :: one ( ) ) . unwrap ( ) ;
972+ assert ! ( residual < Dec :: from_str( "0.001" ) . unwrap( ) ) ;
973+ // println!(
974+ // " ----> Ratio: {}\n",
975+ // staking_rate / query_staking_rate
976+ // );
977+ }
896978
897979 // if rate.abs_diff(&controller.max_reward_rate)
898980 // < Dec::from_str("0.01").unwrap()
@@ -930,4 +1012,22 @@ mod tests {
9301012 // );
9311013 }
9321014 }
1015+
1016+ fn update_state_for_pos_playground < S > (
1017+ storage : & mut S ,
1018+ last_staked_ratio : Dec ,
1019+ last_inflation_amount : token:: Amount ,
1020+ total_native_amount : token:: Amount ,
1021+ ) where
1022+ S : StorageRead + StorageWrite ,
1023+ {
1024+ write_last_staked_ratio ( storage, last_staked_ratio) . unwrap ( ) ;
1025+ write_last_pos_inflation_amount ( storage, last_inflation_amount)
1026+ . unwrap ( ) ;
1027+ let total_native_tokens_key =
1028+ minted_balance_key ( & storage. get_native_token ( ) . unwrap ( ) ) ;
1029+ storage
1030+ . write ( & total_native_tokens_key, total_native_amount)
1031+ . unwrap ( ) ;
1032+ }
9331033}
0 commit comments