diff --git a/packages/rs-dpp/src/data_contract/associated_token/token_perpetual_distribution/distribution_function/evaluate.rs b/packages/rs-dpp/src/data_contract/associated_token/token_perpetual_distribution/distribution_function/evaluate.rs index 78a2dde2c73..9b7326781b0 100644 --- a/packages/rs-dpp/src/data_contract/associated_token/token_perpetual_distribution/distribution_function/evaluate.rs +++ b/packages/rs-dpp/src/data_contract/associated_token/token_perpetual_distribution/distribution_function/evaluate.rs @@ -72,12 +72,12 @@ impl DistributionFunction { return Ok(*distribution_start_amount); } - let steps_passed = (x - s_val) / (*step_count as u64); + let era_intervals_passed = (x - s_val) / (*step_count as u64); let max_intervals = max_interval_count.unwrap_or( DEFAULT_STEP_DECREASING_AMOUNT_MAX_CYCLES_BEFORE_TRAILING_DISTRIBUTION, ) as u64; - if steps_passed > max_intervals { + if era_intervals_passed > max_intervals { return Ok(*trailing_distribution_interval_amount); } @@ -86,7 +86,7 @@ impl DistributionFunction { let reduction_numerator = denominator.saturating_sub(*decrease_per_interval_numerator as u64); - for _ in 0..steps_passed { + for _ in 0..era_intervals_passed { numerator = numerator * reduction_numerator / denominator; } @@ -101,9 +101,12 @@ impl DistributionFunction { Ok(result) } DistributionFunction::Stepwise(steps) => { + if x < contract_registration_step { + return Ok(0); + } // Return the emission corresponding to the greatest key <= x. Ok(steps - .range(..=x) + .range(..=(x - contract_registration_step)) .next_back() .map(|(_, amount)| *amount) .unwrap_or(0)) diff --git a/packages/rs-drive-abci/src/execution/check_tx/v0/mod.rs b/packages/rs-drive-abci/src/execution/check_tx/v0/mod.rs index 205c53cfafc..287058514e3 100644 --- a/packages/rs-drive-abci/src/execution/check_tx/v0/mod.rs +++ b/packages/rs-drive-abci/src/execution/check_tx/v0/mod.rs @@ -3658,6 +3658,7 @@ mod tests { )] .into(), ), + None, platform_version, ); diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/creation.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/creation.rs index 484b40d03cd..56ecc6f0dfd 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/creation.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/document/creation.rs @@ -3662,6 +3662,7 @@ mod creation_tests { None::, None, None, + None, platform_version, ); diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/burn/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/burn/mod.rs index 48923a42d90..857e977336e 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/burn/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/burn/mod.rs @@ -25,6 +25,7 @@ mod token_burn_tests { None::, None, None, + None, platform_version, ); @@ -110,6 +111,7 @@ mod token_burn_tests { None::, None, None, + None, platform_version, ); @@ -202,6 +204,7 @@ mod token_burn_tests { None::, None, None, + None, platform_version, ); @@ -321,6 +324,7 @@ mod token_burn_tests { )] .into(), ), + None, platform_version, ); @@ -582,6 +586,7 @@ mod token_burn_tests { )] .into(), ), + None, platform_version, ); diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/config_update/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/config_update/mod.rs index 38e9a486e5f..3c04f5ddd84 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/config_update/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/config_update/mod.rs @@ -42,6 +42,7 @@ mod token_config_update_tests { }), None, None, + None, platform_version, ); @@ -145,6 +146,7 @@ mod token_config_update_tests { }), None, None, + None, platform_version, ); @@ -291,6 +293,7 @@ mod token_config_update_tests { }), None, None, + None, platform_version, ); @@ -400,6 +403,7 @@ mod token_config_update_tests { }), None, None, + None, platform_version, ); @@ -553,6 +557,7 @@ mod token_config_update_tests { }), None, None, + None, platform_version, ); @@ -643,6 +648,7 @@ mod token_config_update_tests { }), None, None, + None, platform_version, ); @@ -733,6 +739,7 @@ mod token_config_update_tests { }), None, None, + None, platform_version, ); @@ -829,6 +836,7 @@ mod token_config_update_tests { )] .into(), ), + None, platform_version, ); @@ -949,6 +957,7 @@ mod token_config_update_tests { )] .into(), ), + None, platform_version, ); @@ -1065,6 +1074,7 @@ mod token_config_update_tests { )] .into(), ), + None, platform_version, ); @@ -1279,6 +1289,7 @@ mod token_config_update_tests { ] .into(), ), + None, platform_version, ); @@ -1669,6 +1680,7 @@ mod token_config_update_tests { ] .into(), ), + None, platform_version, ); @@ -2130,6 +2142,7 @@ mod token_config_update_tests { ] .into(), ), + None, platform_version, ); @@ -2879,6 +2892,7 @@ mod token_config_update_tests { )] .into(), ), + None, platform_version, ); diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/direct_selling/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/direct_selling/mod.rs index 9fd8f2ee568..04d8585e882 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/direct_selling/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/direct_selling/mod.rs @@ -197,6 +197,7 @@ mod token_selling_tests { )] .into(), ), + None, platform_version, ); @@ -268,6 +269,7 @@ mod token_selling_tests { }), None, None, + None, platform_version, ); @@ -386,6 +388,7 @@ mod token_selling_tests { }), None, None, + None, platform_version, ); @@ -619,6 +622,7 @@ mod token_selling_tests { }), None, None, + None, platform_version, ); diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/distribution/perpetual/block_based.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/distribution/perpetual/block_based.rs index 1d88338934b..c66bdee11a9 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/distribution/perpetual/block_based.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/distribution/perpetual/block_based.rs @@ -56,6 +56,7 @@ mod perpetual_distribution_block { }), None, None, + None, platform_version, ); @@ -298,6 +299,7 @@ mod perpetual_distribution_block { }), None, None, + None, platform_version, ); @@ -419,6 +421,7 @@ mod perpetual_distribution_block { }), None, None, + None, platform_version, ); @@ -2695,6 +2698,7 @@ mod test_suite { token_config_fn, self.start_time, None, + None, self.platform_version, ); diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/distribution/perpetual/time_based.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/distribution/perpetual/time_based.rs index acc01b16ce0..8f1e65eb1e0 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/distribution/perpetual/time_based.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/distribution/perpetual/time_based.rs @@ -9,6 +9,7 @@ use dpp::state_transition::batch_transition::BatchTransition; use platform_version::version::PlatformVersion; use rand::prelude::StdRng; mod perpetual_distribution_time { + use std::collections::BTreeMap; use dpp::block::epoch::Epoch; use dpp::data_contract::associated_token::token_distribution_key::TokenDistributionType; use dpp::data_contract::associated_token::token_perpetual_distribution::distribution_function::{DistributionFunction, MAX_DISTRIBUTION_PARAM, MAX_LINEAR_SLOPE_A_PARAM}; @@ -52,6 +53,7 @@ mod perpetual_distribution_time { }), None, None, + None, platform_version, ); @@ -296,6 +298,7 @@ mod perpetual_distribution_time { }), None, None, + None, platform_version, ); @@ -418,6 +421,7 @@ mod perpetual_distribution_time { }), None, None, + None, platform_version, ); @@ -534,6 +538,7 @@ mod perpetual_distribution_time { }), None, None, + None, platform_version, ); @@ -720,6 +725,7 @@ mod perpetual_distribution_time { }), None, None, + None, platform_version, ); @@ -909,6 +915,7 @@ mod perpetual_distribution_time { }), Some(9_000_000), None, + None, platform_version, ); @@ -1096,6 +1103,7 @@ mod perpetual_distribution_time { }), None, None, + None, platform_version, ); @@ -1277,6 +1285,7 @@ mod perpetual_distribution_time { }), None, None, + None, platform_version, ); @@ -1350,4 +1359,134 @@ mod perpetual_distribution_time { // This is i64::Max assert_eq!(token_balance, Some(9223372036854675807)); } + + #[test] + fn test_token_perpetual_distribution_stepwise_distribution() { + let platform_version = PlatformVersion::latest(); + let mut platform = TestPlatformBuilder::new() + .with_latest_protocol_version() + .build_with_mock_rpc() + .set_genesis_state(); + + let mut rng = StdRng::seed_from_u64(4981); + + let platform_state = platform.state.load(); + + let (identity, _, _) = setup_identity(&mut platform, rng.gen(), dash_to_credits!(0.5)); + + let (identity_2, signer_2, key_2) = + setup_identity(&mut platform, rng.gen(), dash_to_credits!(0.5)); + + fast_forward_to_block(&platform, 10_000_000, 40, 42, 1, false); + + let (contract, token_id) = create_token_contract_with_owner_identity( + &mut platform, + identity.id(), + Some(|token_configuration: &mut TokenConfiguration| { + token_configuration + .distribution_rules_mut() + .set_perpetual_distribution(Some(TokenPerpetualDistribution::V0( + TokenPerpetualDistributionV0 { + distribution_type: RewardDistributionType::TimeBasedDistribution { + // every 5 minutes + interval: 300_000, + function: DistributionFunction::Stepwise(BTreeMap::from([ + (5, 1), + (50, 1000), + ])), + }, + distribution_recipient: TokenDistributionRecipient::Identity( + identity_2.id(), + ), + }, + ))); + }), + Some(10_000_000), + None, + Some(40), + platform_version, + ); + + let token_balance = platform + .drive + .fetch_identity_token_balance( + token_id.to_buffer(), + identity_2.id().to_buffer(), + None, + platform_version, + ) + .expect("expected to fetch token balance"); + + assert_eq!(token_balance, None); + + // 5 hours later + fast_forward_to_block(&platform, 28_000_000, 50, 42, 1, false); + + // We have gone 18_000_000, which is 60 steps, with the initial step also counting, so 61 + // We should get 5*0 + // 45*1 + // 11*1000 + let claim_transition = BatchTransition::new_token_claim_transition( + token_id, + identity_2.id(), + contract.id(), + 0, + TokenDistributionType::Perpetual, + None, + &key_2, + 2, + 0, + &signer_2, + platform_version, + None, + ) + .expect("expect to create documents batch transition"); + + let claim_serialized_transition = claim_transition + .serialize_to_bytes() + .expect("expected documents batch serialized state transition"); + + let transaction = platform.drive.grove.start_transaction(); + + let processing_result = platform + .platform + .process_raw_state_transitions( + &vec![claim_serialized_transition.clone()], + &platform_state, + &BlockInfo { + time_ms: 28_000_000, + height: 50, + core_height: 42, + epoch: Epoch::new(1).unwrap(), + }, + &transaction, + platform_version, + false, + None, + ) + .expect("expected to process state transition"); + + assert_matches!( + processing_result.execution_results().as_slice(), + [StateTransitionExecutionResult::SuccessfulExecution(_, _)] + ); + + platform + .drive + .grove + .commit_transaction(transaction) + .unwrap() + .expect("expected to commit transaction"); + + let token_balance = platform + .drive + .fetch_identity_token_balance( + token_id.to_buffer(), + identity_2.id().to_buffer(), + None, + platform_version, + ) + .expect("expected to fetch token balance"); + assert_eq!(token_balance, Some(11045)); + } } diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/distribution/pre_programmed.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/distribution/pre_programmed.rs index ab3ee2b5c2b..96b681f1260 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/distribution/pre_programmed.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/distribution/pre_programmed.rs @@ -47,6 +47,7 @@ mod pre_programmed_distribution { }), None, None, + None, platform_version, ); @@ -213,6 +214,7 @@ mod pre_programmed_distribution { }), None, None, + None, platform_version, ); @@ -382,6 +384,7 @@ mod pre_programmed_distribution { }), None, None, + None, platform_version, ); @@ -490,6 +493,7 @@ mod pre_programmed_distribution { }), None, None, + None, platform_version, ); @@ -659,6 +663,7 @@ mod pre_programmed_distribution { }), None, None, + None, platform_version, ); @@ -778,6 +783,7 @@ mod pre_programmed_distribution { }), None, None, + None, platform_version, ); diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/freeze/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/freeze/mod.rs index b8ace2ed981..aa36ad2c690 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/freeze/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/freeze/mod.rs @@ -39,6 +39,7 @@ mod token_freeze_tests { }), None, None, + None, platform_version, ); @@ -136,6 +137,7 @@ mod token_freeze_tests { }), None, None, + None, platform_version, ); @@ -246,6 +248,7 @@ mod token_freeze_tests { }), None, None, + None, platform_version, ); @@ -413,6 +416,7 @@ mod token_freeze_tests { }), None, None, + None, platform_version, ); @@ -810,6 +814,7 @@ mod token_freeze_tests { }), None, None, + None, platform_version, ); @@ -1008,6 +1013,7 @@ mod token_freeze_tests { )] .into(), ), + None, platform_version, ); @@ -1103,6 +1109,7 @@ mod token_freeze_tests { )] .into(), ), + None, version, ); @@ -1212,6 +1219,7 @@ mod token_freeze_tests { )] .into(), ), + None, version, ); @@ -1324,6 +1332,7 @@ mod token_freeze_tests { )] .into(), ), + None, platform_version, ); @@ -1584,6 +1593,7 @@ mod token_freeze_tests { )] .into(), ), + None, platform_version, ); @@ -1935,6 +1945,7 @@ mod token_freeze_tests { )] .into(), ), + None, platform_version, ); diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/mint/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/mint/mod.rs index 9527c6860cd..47157f303de 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/mint/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/mint/mod.rs @@ -26,6 +26,7 @@ mod token_mint_tests { None::, None, None, + None, platform_version, ); @@ -111,6 +112,7 @@ mod token_mint_tests { None::, None, None, + None, platform_version, ); @@ -198,6 +200,7 @@ mod token_mint_tests { }), None, None, + None, platform_version, ); @@ -288,6 +291,7 @@ mod token_mint_tests { None::, None, None, + None, platform_version, ); @@ -375,6 +379,7 @@ mod token_mint_tests { None::, None, None, + None, platform_version, ); @@ -463,6 +468,7 @@ mod token_mint_tests { None::, None, None, + None, platform_version, ); @@ -550,6 +556,7 @@ mod token_mint_tests { }), None, None, + None, platform_version, ); @@ -646,6 +653,7 @@ mod token_mint_tests { }), None, None, + None, platform_version, ); @@ -740,6 +748,7 @@ mod token_mint_tests { }), None, None, + None, platform_version, ); @@ -830,6 +839,7 @@ mod token_mint_tests { }), None, None, + None, platform_version, ); @@ -929,6 +939,7 @@ mod token_mint_tests { }), None, None, + None, platform_version, ); @@ -1026,6 +1037,7 @@ mod token_mint_tests { }), None, None, + None, platform_version, ); @@ -1138,6 +1150,7 @@ mod token_mint_tests { }), None, None, + None, platform_version, ); @@ -1248,6 +1261,7 @@ mod token_mint_tests { )] .into(), ), + None, platform_version, ); @@ -1360,6 +1374,7 @@ mod token_mint_tests { )] .into(), ), + None, platform_version, ); @@ -1480,6 +1495,7 @@ mod token_mint_tests { )] .into(), ), + None, platform_version, ); @@ -1757,6 +1773,7 @@ mod token_mint_tests { )] .into(), ), + None, platform_version, ); @@ -2079,6 +2096,7 @@ mod token_mint_tests { )] .into(), ), + None, platform_version, ); @@ -2307,6 +2325,7 @@ mod token_mint_tests { )] .into(), ), + None, platform_version, ); @@ -2544,6 +2563,7 @@ mod token_mint_tests { )] .into(), ), + None, platform_version, ); @@ -2832,6 +2852,7 @@ mod token_mint_tests { )] .into(), ), + None, platform_version, ); @@ -3130,6 +3151,7 @@ mod token_mint_tests { )] .into(), ), + None, platform_version, ); @@ -3244,6 +3266,7 @@ mod token_mint_tests { )] .into(), ), + None, platform_version, ); @@ -3440,6 +3463,7 @@ mod token_mint_tests { )] .into(), ), + None, platform_version, ); @@ -3580,6 +3604,7 @@ mod token_mint_tests { )] .into(), ), + None, platform_version, ); diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/transfer/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/transfer/mod.rs index 5bfd09f7ce8..a40f9110549 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/transfer/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/batch/tests/token/transfer/mod.rs @@ -41,6 +41,7 @@ mod token_transfer_tests { None::, None, None, + None, platform_version, ); @@ -141,6 +142,7 @@ mod token_transfer_tests { None::, None, None, + None, platform_version, ); @@ -256,6 +258,7 @@ mod token_transfer_tests { }), None, None, + None, platform_version, ); @@ -513,6 +516,7 @@ mod token_transfer_tests { }), None, None, + None, platform_version, ); @@ -805,6 +809,7 @@ mod token_transfer_tests { None::, None, None, + None, platform_version, ); @@ -895,6 +900,7 @@ mod token_transfer_tests { None::, None, None, + None, platform_version, ); @@ -1021,6 +1027,7 @@ mod token_transfer_tests { )] .into(), ), + None, platform_version, ); diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/mod.rs index f4a7178ffec..e7918294dfb 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/data_contract_create/mod.rs @@ -1135,6 +1135,7 @@ mod tests { None::, None, None, + None, platform_version, ); @@ -2338,6 +2339,7 @@ mod tests { None::, None, None, + None, platform_version, ); @@ -2578,6 +2580,7 @@ mod tests { None::, None, None, + None, platform_version, ); diff --git a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs index 6de07feec4e..9d402e22339 100644 --- a/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs +++ b/packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/mod.rs @@ -59,7 +59,7 @@ pub(in crate::execution) mod tests { use dpp::fee::Credits; use dpp::identity::identity_public_key::accessors::v0::IdentityPublicKeyGettersV0; use dpp::identity::{Identity, IdentityPublicKey, IdentityV0, KeyID, KeyType, Purpose, SecurityLevel, TimestampMillis}; - use dpp::prelude::{Identifier, IdentityNonce}; + use dpp::prelude::{BlockHeight, Identifier, IdentityNonce}; use dpp::state_transition::data_contract_create_transition::methods::DataContractCreateTransitionMethodsV0; use dpp::state_transition::data_contract_create_transition::DataContractCreateTransition; use dpp::system_data_contracts::load_system_data_contract; @@ -2335,6 +2335,7 @@ pub(in crate::execution) mod tests { token_configuration_modification: Option, contract_start_time: Option, add_groups: Option>, + contract_start_block: Option, platform_version: &PlatformVersion, ) -> (DataContract, Identifier) { let data_contract_id = DataContract::generate_data_contract_id_v0(identity_id, 1); @@ -2347,7 +2348,8 @@ pub(in crate::execution) mod tests { Some(|data_contract: &mut DataContract| { data_contract.set_created_at_epoch(Some(0)); data_contract.set_created_at(Some(contract_start_time.unwrap_or_default())); - data_contract.set_created_at_block_height(Some(0)); + data_contract + .set_created_at_block_height(Some(contract_start_block.unwrap_or_default())); if let Some(token_configuration_modification) = token_configuration_modification { let token_configuration = data_contract .token_configuration_mut(0)