diff --git a/pallets/issue/Cargo.toml b/pallets/issue/Cargo.toml index 3ca3aac97..6cd32235e 100644 --- a/pallets/issue/Cargo.toml +++ b/pallets/issue/Cargo.toml @@ -35,7 +35,7 @@ stellar-relay = { path = "../stellar-relay", default-features = false } vault-registry = { path = "../vault-registry", default-features = false } pooled-rewards = { path = "../pooled-rewards", default-features = false } reward-distribution = { path = "../reward-distribution", default-features = false } -nomination = {path = "../nomination", default-features = false} + primitives = { package = "spacewalk-primitives", path = "../../primitives", default-features = false } @@ -47,6 +47,7 @@ orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-li [dev-dependencies] mocktopus = "0.8.0" frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40" } +nomination = {path = "../nomination", default-features = false} currency = { path = "../currency", features = ['testing-utils', 'testing-constants'] } reward = { path = "../reward" } diff --git a/pallets/issue/src/tests.rs b/pallets/issue/src/tests.rs index 97f1ae9db..160760edf 100644 --- a/pallets/issue/src/tests.rs +++ b/pallets/issue/src/tests.rs @@ -634,7 +634,6 @@ mod integration_tests { CurrencyId, DefaultVaultId, Balance, - CurrencyId, >>::compute_reward(&vault.collateral_currency(), vault, reward_currency) .unwrap() } diff --git a/pallets/vault-registry/src/tests.rs b/pallets/vault-registry/src/tests.rs index 1d732564f..66108ece3 100644 --- a/pallets/vault-registry/src/tests.rs +++ b/pallets/vault-registry/src/tests.rs @@ -1713,145 +1713,274 @@ fn test_offchain_worker_unsigned_transaction_submission() { }) } -#[test] -fn integration_single_vault_receives_per_block_reward() { - run_test(|| { - //set up reward values - let reward_per_block: u64 = 1000u64; - assert_ok!(ext::staking::add_reward_currency::(DEFAULT_WRAPPED_CURRENCY)); - assert_ok!(>::set_reward_per_block( - RawOrigin::Root.into(), - reward_per_block.into() - )); - //register vault and issue tokens. - let issue_tokens: u128 = DEFAULT_COLLATERAL / 10 / 2; // = 5 - let id = create_vault_and_issue_tokens(issue_tokens, DEFAULT_COLLATERAL, DEFAULT_ID); - assert_eq!( - ::VaultRewards::get_stake(&id.collateral_currency(), &id), - Ok(DEFAULT_COLLATERAL) - ); - assert_eq!(>::free_balance(&id.account_id), 0u128); +mod integration { + use super::{assert_eq, *}; + use oracle::OracleApi; - //distribute fee rewards - >::execute_on_init(2u32.into()); - //collect rewards - let origin = RuntimeOrigin::signed(id.account_id); - assert_ok!(>::collect_reward( - origin.into(), - id.clone(), - DEFAULT_NATIVE_CURRENCY, - None, - )); - assert_eq!( - >::free_balance(&id.account_id), - reward_per_block.into() - ); - }); -} + fn to_usd(amount: &Balance, currency: &CurrencyId) -> Balance { + ::OracleApi::currency_to_usd(amount, currency) + .expect("prices have been set in mock configuration") + } + #[test] + fn integration_single_vault_receives_per_block_reward() { + run_test(|| { + //set up reward values + let initial_block_number = 1u64; + let reward_per_block: u64 = 1000u64; + assert_ok!(ext::staking::add_reward_currency::(DEFAULT_WRAPPED_CURRENCY)); + assert_ok!(>::set_reward_per_block( + RawOrigin::Root.into(), + reward_per_block.into() + )); + //register vault and issue tokens. + //the number of issue tokens is not relevant for these tests + let issue_tokens: u128 = 2; + let id = create_vault_and_issue_tokens(issue_tokens, DEFAULT_COLLATERAL, DEFAULT_ID); + assert_eq!( + ::VaultRewards::get_stake(&id.collateral_currency(), &id), + Ok(DEFAULT_COLLATERAL) + ); + assert_eq!(>::free_balance(&id.account_id), 0u128); + + //distribute fee rewards + >::execute_on_init((initial_block_number + 1).into()); + //collect rewards + let origin = RuntimeOrigin::signed(id.account_id); + assert_ok!(>::collect_reward( + origin.into(), + id.clone(), + DEFAULT_NATIVE_CURRENCY, + None, + )); + assert_eq!( + >::free_balance(&id.account_id), + reward_per_block.into() + ); + }); + } -#[test] -fn integration_multiple_vault_same_collateral_per_block_reward() { - run_test(|| { - //set up reward values - let reward_per_block: u64 = 100000u64; - assert_ok!(ext::staking::add_reward_currency::(DEFAULT_WRAPPED_CURRENCY)); - assert_ok!(>::set_reward_per_block( - RawOrigin::Root.into(), - reward_per_block.into() - )); + #[test] + fn integration_multiple_vault_same_collateral_per_block_reward() { + run_test(|| { + //ARRANGE + //set up reward values + let initial_block_number = 1u64; + let reward_per_block: u128 = 100000u128; + assert_ok!(ext::staking::add_reward_currency::(DEFAULT_WRAPPED_CURRENCY)); + assert_ok!(>::set_reward_per_block( + RawOrigin::Root.into(), + reward_per_block.into() + )); - //register vaults and issue tokens. - let issue_tokens: u128 = 5; + //register vaults and issue tokens. + let issue_tokens: u128 = 2; - let collateral_vault_1 = 1000u128; - let id = create_vault_and_issue_tokens(issue_tokens, collateral_vault_1, DEFAULT_ID); - assert_eq!( - ::VaultRewards::get_stake(&id.collateral_currency(), &id), - Ok(collateral_vault_1) - ); + let collateral_vault_1 = 1000u128; + let id_1 = create_vault_and_issue_tokens(issue_tokens, collateral_vault_1, DEFAULT_ID); + assert_eq!( + ::VaultRewards::get_stake(&id_1.collateral_currency(), &id_1), + Ok(collateral_vault_1) + ); - let collateral_vault_2 = 5000u128; - let id2 = create_vault_and_issue_tokens(issue_tokens, collateral_vault_2, OTHER_ID); - assert_eq!( - ::VaultRewards::get_stake(&id2.collateral_currency(), &id2), - Ok(collateral_vault_2) - ); + let collateral_vault_2 = 5000u128; + let id_2 = create_vault_and_issue_tokens(issue_tokens, collateral_vault_2, OTHER_ID); + assert_eq!( + ::VaultRewards::get_stake(&id_2.collateral_currency(), &id_2), + Ok(collateral_vault_2) + ); - //distribute fee rewards - >::execute_on_init(2u32.into()); - //collect rewards - let origin = RuntimeOrigin::signed(id.account_id); - assert_ok!(>::collect_reward( - origin.into(), - id.clone(), - DEFAULT_NATIVE_CURRENCY, - None, - )); + //ACT - distribute fee rewards + >::execute_on_init((initial_block_number + 1).into()); - //expected value = (1000*5/(5000*5 + 1000*5))*100000 = 16666 - assert_eq!(>::free_balance(&id.account_id), 16666u128.into()); - }); -} + //collect rewards for vault 1 and 2 + let origin_1 = RuntimeOrigin::signed(id_1.account_id); + assert_ok!(>::collect_reward( + origin_1.into(), + id_1.clone(), + DEFAULT_NATIVE_CURRENCY, + None, + )); -#[test] -fn integration_multiple_vault_multiple_collateral_per_block_reward() { - run_test(|| { - //set up reward values and threshold - assert_ok!(ext::staking::add_reward_currency::(DEFAULT_WRAPPED_CURRENCY)); - let reward_per_block: u64 = 100000u64; - assert_ok!(>::set_reward_per_block( - RawOrigin::Root.into(), - reward_per_block.into() - )); + let origin_2 = RuntimeOrigin::signed(id_2.account_id); + assert_ok!(>::collect_reward( + origin_2.into(), + id_2.clone(), + DEFAULT_NATIVE_CURRENCY, + None, + )); - //register vaults and issue tokens. - let issue_tokens: u128 = 5; + // ASSERT + //MODEL: reward_vault_i = ( usdPrice(vault_i_collateral)/ ( SUM_i { + // usdPrice(vault_i_collateral) })*reward_per_block + let vault_1_collateral_usd = to_usd(&collateral_vault_1, &DEFAULT_COLLATERAL_CURRENCY); + let vault_2_collateral_usd = to_usd(&collateral_vault_2, &DEFAULT_COLLATERAL_CURRENCY); - let collateral_vault_1 = 1000u128; - let id = create_vault_and_issue_tokens(issue_tokens, collateral_vault_1, DEFAULT_ID); - assert_eq!( - ::VaultRewards::get_stake(&id.collateral_currency(), &id), - Ok(collateral_vault_1) - ); + let expected_value_vault_1: u128 = ((vault_1_collateral_usd as f64 / + (vault_1_collateral_usd + vault_2_collateral_usd) as f64) * + reward_per_block as f64) + .floor() as u128; - let collateral_vault_2 = 5000u128; - let id2 = create_vault_and_issue_tokens(issue_tokens, collateral_vault_2, OTHER_ID); - assert_eq!( - ::VaultRewards::get_stake(&id2.collateral_currency(), &id2), - Ok(collateral_vault_2) - ); + //collect rewards for vault 2 + let expected_value_vault_2: u128 = ((vault_2_collateral_usd as f64 / + (vault_1_collateral_usd + vault_2_collateral_usd) as f64) * + reward_per_block as f64) + .floor() as u128; - let collateral_vault_3 = 3000u128; - let id3 = create_vault_and_issue_tokens(issue_tokens, collateral_vault_3, ID_COLLATERAL_21); - assert_eq!( - ::VaultRewards::get_stake(&id3.collateral_currency(), &id3), - Ok(collateral_vault_3) - ); + assert_eq!( + >::free_balance(&id_1.account_id), + expected_value_vault_1.into() + ); + assert_eq!( + >::free_balance(&id_2.account_id), + expected_value_vault_2.into() + ); + }); + } - let collateral_vault_4 = 2000u128; - let id4 = create_vault_and_issue_tokens(issue_tokens, collateral_vault_4, ID_COLLATERAL_22); - assert_eq!( - ::VaultRewards::get_stake(&id4.collateral_currency(), &id4), - Ok(collateral_vault_4) - ); + #[test] + fn integration_multiple_vault_multiple_collateral_per_block_reward() { + run_test(|| { + //ARRANGE + //set up reward values and threshold + assert_ok!(ext::staking::add_reward_currency::(DEFAULT_WRAPPED_CURRENCY)); + let reward_per_block: u128 = 100000; + assert_ok!(>::set_reward_per_block( + RawOrigin::Root.into(), + reward_per_block.into() + )); - //distribute fee rewards - >::execute_on_init(2u32.into()); - //collect rewards - let origin = RuntimeOrigin::signed(id4.account_id); - assert_ok!(>::collect_reward( - origin.into(), - id4.clone(), - DEFAULT_NATIVE_CURRENCY, - None, - )); + //register vaults and issue tokens. + let issue_tokens: u128 = 2; - //Explicit calc for the expected reward on this test for id4 - //expected value = ((2000*10 + 3000*10)/(5000*5 + 1000*5 + 2000*10 + - // 3000*10))*(2000/(3000+2000))*100000 = 25000 - assert_eq!( - >::free_balance(&id4.account_id), - 25000u128.into() - ); - }); + let collateral_vault_1 = 1000u128; + let id_1 = create_vault_and_issue_tokens(issue_tokens, collateral_vault_1, DEFAULT_ID); + assert_eq!( + ::VaultRewards::get_stake(&id_1.collateral_currency(), &id_1), + Ok(collateral_vault_1) + ); + + let collateral_vault_2 = 5000u128; + let id_2 = create_vault_and_issue_tokens(issue_tokens, collateral_vault_2, OTHER_ID); + assert_eq!( + ::VaultRewards::get_stake(&id_2.collateral_currency(), &id_2), + Ok(collateral_vault_2) + ); + + let collateral_vault_3 = 3000u128; + let id_3 = + create_vault_and_issue_tokens(issue_tokens, collateral_vault_3, ID_COLLATERAL_21); + assert_eq!( + ::VaultRewards::get_stake(&id_3.collateral_currency(), &id_3), + Ok(collateral_vault_3) + ); + + let collateral_vault_4 = 2000u128; + let id_4 = + create_vault_and_issue_tokens(issue_tokens, collateral_vault_4, ID_COLLATERAL_22); + assert_eq!( + ::VaultRewards::get_stake(&id_4.collateral_currency(), &id_4), + Ok(collateral_vault_4) + ); + + //ACT + //distribute fee rewards + >::execute_on_init(2u32.into()); + + //collect rewards + let origin_1 = RuntimeOrigin::signed(id_1.account_id); + assert_ok!(>::collect_reward( + origin_1.into(), + id_1.clone(), + DEFAULT_NATIVE_CURRENCY, + None, + )); + + let origin_2 = RuntimeOrigin::signed(id_2.account_id); + assert_ok!(>::collect_reward( + origin_2.into(), + id_2.clone(), + DEFAULT_NATIVE_CURRENCY, + None, + )); + + let origin_3 = RuntimeOrigin::signed(id_3.account_id); + assert_ok!(>::collect_reward( + origin_3.into(), + id_3.clone(), + DEFAULT_NATIVE_CURRENCY, + None, + )); + + let origin_4 = RuntimeOrigin::signed(id_4.account_id); + assert_ok!(>::collect_reward( + origin_4.into(), + id_4.clone(), + DEFAULT_NATIVE_CURRENCY, + None, + )); + + //ASSERT + let vault_1_collateral_usd = + to_usd(&collateral_vault_1, &DEFAULT_ID.collateral_currency()); + let vault_2_collateral_usd = + to_usd(&collateral_vault_2, &OTHER_ID.collateral_currency()); + let vault_3_collateral_usd = + to_usd(&collateral_vault_3, &ID_COLLATERAL_21.collateral_currency()); + let vault_4_collateral_usd = + to_usd(&collateral_vault_4, &ID_COLLATERAL_22.collateral_currency()); + + let total_usd_amount = vault_1_collateral_usd + + vault_2_collateral_usd + + vault_3_collateral_usd + + vault_4_collateral_usd; + + let expected_value_vault_1: u128 = ((((vault_1_collateral_usd + vault_2_collateral_usd) + as f64 / total_usd_amount as f64) * + reward_per_block as f64) + .floor() * (collateral_vault_1 as f64 / + (collateral_vault_1 + collateral_vault_2) as f64)) + .floor() as u128; + + let expected_value_vault_2: u128 = ((((vault_1_collateral_usd + vault_2_collateral_usd) + as f64 / total_usd_amount as f64) * + reward_per_block as f64) + .floor() * (collateral_vault_2 as f64 / + (collateral_vault_1 + collateral_vault_2) as f64)) + .floor() as u128; + + let expected_value_vault_3: u128 = ((((vault_4_collateral_usd + vault_3_collateral_usd) + as f64 / total_usd_amount as f64) * + reward_per_block as f64) + .floor() * (collateral_vault_3 as f64 / + (collateral_vault_3 + collateral_vault_4) as f64)) + .floor() as u128; + + let expected_value_vault_4: u128 = ((((vault_4_collateral_usd + vault_3_collateral_usd) + as f64 / total_usd_amount as f64) * + reward_per_block as f64) + .floor() * (collateral_vault_4 as f64 / + (collateral_vault_3 + collateral_vault_4) as f64)) + .floor() as u128; + + assert_eq!( + >::free_balance(&id_1.account_id), + expected_value_vault_1.into() + ); + + assert_eq!( + >::free_balance(&id_2.account_id), + expected_value_vault_2.into() + ); + + assert_eq!( + >::free_balance(&id_3.account_id), + expected_value_vault_3.into() + ); + + assert_eq!( + >::free_balance(&id_4.account_id), + expected_value_vault_4.into() + ); + }); + } }