diff --git a/Cargo.lock b/Cargo.lock index dbb5b9699..636172862 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -783,8 +783,6 @@ dependencies = [ "bifrost-system-maker", "bifrost-system-staking", "bifrost-token-issuer", - "bifrost-ve-minting", - "bifrost-ve-minting-rpc-runtime-api", "bifrost-vesting", "bifrost-vsbond-auction", "bifrost-vstoken-conversion", @@ -1010,6 +1008,7 @@ version = "0.8.0" dependencies = [ "bifrost-asset-registry", "bifrost-call-switchgear", + "bifrost-cross-in-out", "bifrost-farming", "bifrost-farming-rpc-runtime-api", "bifrost-fee-share", @@ -1021,6 +1020,8 @@ dependencies = [ "bifrost-slp", "bifrost-system-maker", "bifrost-system-staking", + "bifrost-ve-minting", + "bifrost-ve-minting-rpc-runtime-api", "bifrost-vesting", "bifrost-vstoken-conversion", "bifrost-vtoken-minting", @@ -1366,7 +1367,6 @@ dependencies = [ "orml-tokens", "orml-traits", "pallet-balances", - "pallet-timestamp", "parity-scale-codec", "scale-info", "sp-core", @@ -1376,6 +1376,22 @@ dependencies = [ "xcm", ] +[[package]] +name = "bifrost-ve-minting-rpc-api" +version = "0.8.0" +dependencies = [ + "bifrost-ve-minting-rpc-runtime-api", + "jsonrpsee", + "node-primitives", + "parity-scale-codec", + "serde", + "sp-api", + "sp-blockchain", + "sp-core", + "sp-rpc", + "sp-runtime", +] + [[package]] name = "bifrost-ve-minting-rpc-runtime-api" version = "0.8.0" @@ -6017,6 +6033,8 @@ dependencies = [ "bifrost-liquidity-mining-rpc-runtime-api", "bifrost-salp-rpc-api", "bifrost-salp-rpc-runtime-api", + "bifrost-ve-minting-rpc-api", + "bifrost-ve-minting-rpc-runtime-api", "jsonrpsee", "node-primitives", "pallet-transaction-payment-rpc", @@ -6027,6 +6045,7 @@ dependencies = [ "sp-api", "sp-block-builder", "sp-blockchain", + "sp-runtime", "substrate-frame-rpc-system", "zenlink-protocol", "zenlink-protocol-rpc", @@ -6046,6 +6065,7 @@ dependencies = [ "bifrost-polkadot-runtime", "bifrost-runtime-common", "bifrost-salp-rpc-runtime-api", + "bifrost-ve-minting-rpc-runtime-api", "cumulus-client-cli", "cumulus-client-consensus-aura", "cumulus-client-consensus-common", diff --git a/node/primitives/src/currency.rs b/node/primitives/src/currency.rs index df5fb2084..5bf774693 100644 --- a/node/primitives/src/currency.rs +++ b/node/primitives/src/currency.rs @@ -39,7 +39,7 @@ pub const DOT_TOKEN_ID: u8 = 0u8; pub const DOT: CurrencyId = CurrencyId::Token2(DOT_TOKEN_ID); pub const GLMR_TOKEN_ID: u8 = 1u8; pub const GLMR: CurrencyId = CurrencyId::Token2(GLMR_TOKEN_ID); -pub const FIL_TOKEN_ID: u8 = 2u8; +pub const FIL_TOKEN_ID: u8 = 4u8; pub const FIL: CurrencyId = CurrencyId::Token2(FIL_TOKEN_ID); macro_rules! create_currency_id { diff --git a/node/rpc/Cargo.toml b/node/rpc/Cargo.toml index 4365f41fa..143e7f6af 100644 --- a/node/rpc/Cargo.toml +++ b/node/rpc/Cargo.toml @@ -17,6 +17,7 @@ sc-transaction-pool-api = { git = "https://github.com/paritytech/substrate", bra sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.37" } sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.37" } sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.37" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.37" } pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.37" } substrate-frame-rpc-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.37" } bifrost-flexible-fee-rpc = { path = "../../pallets/flexible-fee/rpc" } @@ -27,6 +28,8 @@ bifrost-liquidity-mining-rpc-api = { path = "../../pallets/liquidity-mining/rpc" bifrost-liquidity-mining-rpc-runtime-api = { path = "../../pallets/liquidity-mining/rpc/runtime-api" } bifrost-farming-rpc-api = { path = "../../pallets/farming/rpc" } bifrost-farming-rpc-runtime-api = { path = "../../pallets/farming/rpc/runtime-api" } +bifrost-ve-minting-rpc-api = { path = "../../pallets/ve-minting/rpc" } +bifrost-ve-minting-rpc-runtime-api = { path = "../../pallets/ve-minting/rpc/runtime-api" } zenlink-protocol = "*" zenlink-protocol-rpc = "*" zenlink-protocol-runtime-api = "*" diff --git a/node/rpc/src/lib.rs b/node/rpc/src/lib.rs index 30f8d1421..f2f59072f 100644 --- a/node/rpc/src/lib.rs +++ b/node/rpc/src/lib.rs @@ -41,6 +41,8 @@ use bifrost_liquidity_mining_rpc_api::{LiquidityMiningRpc, LiquidityMiningRpcApi use bifrost_liquidity_mining_rpc_runtime_api::LiquidityMiningRuntimeApi; use bifrost_salp_rpc_api::{SalpRpc, SalpRpcApiServer}; use bifrost_salp_rpc_runtime_api::SalpRuntimeApi; +use bifrost_ve_minting_rpc_api::{VeMintingRpc, VeMintingRpcApiServer}; +use bifrost_ve_minting_rpc_runtime_api::VeMintingRuntimeApi; use node_primitives::{AccountId, Balance, Block, CurrencyId, Nonce, ParaId, PoolId}; use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApiServer}; use sc_rpc_api::DenyUnsafe; @@ -48,12 +50,12 @@ use sc_transaction_pool_api::TransactionPool; use sp_api::ProvideRuntimeApi; use sp_block_builder::BlockBuilder; use sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata}; +use sp_runtime::traits::BlockIdTo; use substrate_frame_rpc_system::{System, SystemApiServer}; use zenlink_protocol::AssetId; use zenlink_protocol_rpc::{ZenlinkProtocol, ZenlinkProtocolApiServer}; use zenlink_protocol_runtime_api::ZenlinkProtocolApi as ZenlinkProtocolRuntimeApi; use zenlink_stable_amm_rpc::{StableAmm, StableAmmApiServer}; - /// Full client dependencies. pub struct FullDeps { /// The client instance to use. @@ -116,12 +118,14 @@ where + HeaderMetadata + Send + Sync - + 'static, + + 'static + + BlockIdTo, C::Api: pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi, C::Api: substrate_frame_rpc_system::AccountNonceApi, C::Api: FarmingRuntimeApi, C::Api: FeeRuntimeApi, C::Api: SalpRuntimeApi, + C::Api: VeMintingRuntimeApi, C::Api: ZenlinkProtocolRuntimeApi, C::Api: BlockBuilder, P: TransactionPool + Sync + Send + 'static, @@ -135,6 +139,7 @@ where module.merge(FarmingRpc::new(client.clone()).into_rpc())?; module.merge(FlexibleFeeRpc::new(client.clone()).into_rpc())?; module.merge(SalpRpc::new(client.clone()).into_rpc())?; + module.merge(VeMintingRpc::new(client.clone()).into_rpc())?; module.merge(ZenlinkProtocol::new(client).into_rpc())?; Ok(module) diff --git a/node/service/Cargo.toml b/node/service/Cargo.toml index 664ab2011..3e094d6ca 100644 --- a/node/service/Cargo.toml +++ b/node/service/Cargo.toml @@ -100,6 +100,7 @@ bifrost-flexible-fee-rpc-runtime-api = { path = "../../pallets/flexible-fee/rpc/ bifrost-salp-rpc-runtime-api = { path = "../../pallets/salp/rpc/runtime-api" } bifrost-liquidity-mining-rpc-runtime-api = { path = "../../pallets/liquidity-mining/rpc/runtime-api" } bifrost-farming-rpc-runtime-api = { path = "../../pallets/farming/rpc/runtime-api" } +bifrost-ve-minting-rpc-runtime-api = { path = "../../pallets/ve-minting/rpc/runtime-api" } [features] default = [ "std" ] diff --git a/node/service/src/client_polkadot.rs b/node/service/src/client_polkadot.rs index c382df3d3..05e385fe4 100644 --- a/node/service/src/client_polkadot.rs +++ b/node/service/src/client_polkadot.rs @@ -85,6 +85,7 @@ pub trait RuntimeApiCollection: + bifrost_flexible_fee_rpc_runtime_api::FlexibleFeeRuntimeApi + bifrost_farming_rpc_runtime_api::FarmingRuntimeApi + bifrost_salp_rpc_runtime_api::SalpRuntimeApi + + bifrost_ve_minting_rpc_runtime_api::VeMintingRuntimeApi + zenlink_protocol_runtime_api::ZenlinkProtocolApi where >::StateBackend: sp_api::StateBackend, @@ -106,6 +107,7 @@ where + bifrost_flexible_fee_rpc_runtime_api::FlexibleFeeRuntimeApi + bifrost_farming_rpc_runtime_api::FarmingRuntimeApi + bifrost_salp_rpc_runtime_api::SalpRuntimeApi + + bifrost_ve_minting_rpc_runtime_api::VeMintingRuntimeApi + zenlink_protocol_runtime_api::ZenlinkProtocolApi, >::StateBackend: sp_api::StateBackend, { diff --git a/pallets/cross-in-out/src/lib.rs b/pallets/cross-in-out/src/lib.rs index 469f22efe..13c106f29 100644 --- a/pallets/cross-in-out/src/lib.rs +++ b/pallets/cross-in-out/src/lib.rs @@ -25,13 +25,16 @@ extern crate alloc; use alloc::vec::Vec; -use frame_support::{ensure, pallet_prelude::*}; +use frame_support::{ensure, pallet_prelude::*, sp_runtime::traits::AccountIdConversion, PalletId}; use frame_system::pallet_prelude::*; use node_primitives::CurrencyId; use orml_traits::MultiCurrency; use sp_std::boxed::Box; pub use weights::WeightInfo; -use xcm::latest::MultiLocation; +use xcm::{ + latest::MultiLocation, + opaque::latest::{Junction::AccountId32, Junctions::X1, NetworkId::Any}, +}; #[cfg(feature = "runtime-benchmarks")] mod benchmarking; @@ -59,6 +62,9 @@ pub mod pallet { /// The only origin that can edit token issuer list type ControlOrigin: EnsureOrigin; + /// Entrance account Pallet Id + type EntrancePalletId: Get; + /// Weight information for extrinsics in this module. type WeightInfo: WeightInfo; } @@ -207,8 +213,21 @@ pub mod pallet { Self::get_issue_whitelist(currency_id).ok_or(Error::::NotAllowed)?; ensure!(issue_whitelist.contains(&issuer), Error::::NotAllowed); - let dest = Self::outer_multilocation_to_account(currency_id, location.clone()) - .ok_or(Error::::NoAccountIdMapping)?; + let entrance_account_mutlilcaition = Box::new(MultiLocation { + parents: 0, + interior: X1(AccountId32 { + network: Any, + id: T::EntrancePalletId::get().into_account_truncating(), + }), + }); + + // If the cross_in destination is entrance account, it is not required to be registered. + let dest = if entrance_account_mutlilcaition == location { + T::EntrancePalletId::get().into_account_truncating() + } else { + Self::outer_multilocation_to_account(currency_id, location.clone()) + .ok_or(Error::::NoAccountIdMapping)? + }; T::MultiCurrency::deposit(currency_id, &dest, amount)?; @@ -305,8 +324,9 @@ pub mod pallet { origin: OriginFor, currency_id: CurrencyId, foreign_location: Box, + account: AccountIdOf, ) -> DispatchResult { - let account = ensure_signed(origin)?; + T::ControlOrigin::ensure_origin(origin)?; ensure!( CrossCurrencyRegistry::::contains_key(currency_id), diff --git a/pallets/cross-in-out/src/mock.rs b/pallets/cross-in-out/src/mock.rs index 2ead37a21..8083db571 100644 --- a/pallets/cross-in-out/src/mock.rs +++ b/pallets/cross-in-out/src/mock.rs @@ -152,10 +152,15 @@ ord_parameter_types! { pub const One: AccountId = ALICE; } +parameter_types! { + pub const SlpEntrancePalletId: PalletId = PalletId(*b"bf/vtkin"); +} + impl bifrost_cross_in_out::Config for Runtime { type RuntimeEvent = RuntimeEvent; type MultiCurrency = Currencies; type ControlOrigin = EnsureSignedBy; + type EntrancePalletId = SlpEntrancePalletId; type WeightInfo = (); } diff --git a/pallets/cross-in-out/src/tests.rs b/pallets/cross-in-out/src/tests.rs index 2e697a06a..b132e4d9c 100644 --- a/pallets/cross-in-out/src/tests.rs +++ b/pallets/cross-in-out/src/tests.rs @@ -251,7 +251,18 @@ fn change_outer_linked_account_should_work() { CrossInOut::change_outer_linked_account( RuntimeOrigin::signed(BOB), KSM, - Box::new(location.clone()) + Box::new(location2.clone()), + BOB + ), + BadOrigin + ); + + assert_noop!( + CrossInOut::change_outer_linked_account( + RuntimeOrigin::signed(ALICE), + KSM, + Box::new(location.clone()), + BOB ), Error::::CurrencyNotSupportCrossInAndOut ); @@ -260,17 +271,19 @@ fn change_outer_linked_account_should_work() { assert_noop!( CrossInOut::change_outer_linked_account( - RuntimeOrigin::signed(BOB), + RuntimeOrigin::signed(ALICE), KSM, - Box::new(location.clone()) + Box::new(location.clone()), + BOB ), Error::::AlreadyExist ); assert_ok!(CrossInOut::change_outer_linked_account( - RuntimeOrigin::signed(BOB), + RuntimeOrigin::signed(ALICE), KSM, - Box::new(location2.clone()) + Box::new(location2.clone()), + BOB )); }); } diff --git a/pallets/salp/src/lib.rs b/pallets/salp/src/lib.rs index b5ce8c873..49098ffcf 100644 --- a/pallets/salp/src/lib.rs +++ b/pallets/salp/src/lib.rs @@ -19,11 +19,7 @@ // Ensure we're `no_std` when compiling for Wasm. #![cfg_attr(not(feature = "std"), no_std)] -pub mod migration { - pub fn migrate() { - log::info!("salp migration..."); - } -} +pub mod migration; #[cfg(feature = "runtime-benchmarks")] pub mod benchmarking; @@ -301,7 +297,7 @@ pub mod pallet { /// The balance can be redeemed to users. #[pallet::storage] #[pallet::getter(fn redeem_pool)] - pub(super) type RedeemPool = StorageValue<_, BalanceOf, ValueQuery>; + pub type RedeemPool = StorageValue<_, BalanceOf, ValueQuery>; #[pallet::storage] #[pallet::getter(fn failed_funds_to_refund)] diff --git a/pallets/salp/src/migration.rs b/pallets/salp/src/migration.rs new file mode 100644 index 000000000..c3fadb3c3 --- /dev/null +++ b/pallets/salp/src/migration.rs @@ -0,0 +1,29 @@ +// This file is part of Bifrost. + +// Copyright (C) 2019-2022 Liebi Technologies (UK) Ltd. +// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#![cfg_attr(not(feature = "std"), no_std)] + +use super::{Config, RedeemPool, Weight}; +use frame_support::traits::Get; +use sp_runtime::traits::UniqueSaturatedInto; + +pub fn update_redeem_pool() -> Weight { + RedeemPool::::set(147_780_374_204_392u128.unique_saturated_into()); + + T::DbWeight::get().reads(1) + T::DbWeight::get().writes(1) +} diff --git a/pallets/slp/src/agents/common.rs b/pallets/slp/src/agents/common.rs index ef868e9fa..71363d117 100644 --- a/pallets/slp/src/agents/common.rs +++ b/pallets/slp/src/agents/common.rs @@ -208,6 +208,7 @@ impl Pallet { let dest = Box::new(VersionedMultiLocation::from(X1(Parachain(T::ParachainId::get().into())))); + let beneficiary = Box::new(VersionedMultiLocation::from(X1(AccountId32 { network: Any, id: to_32 }))); diff --git a/pallets/slp/src/agents/phala_agent/agent.rs b/pallets/slp/src/agents/phala_agent/agent.rs index 7a3891b80..a4acc0239 100644 --- a/pallets/slp/src/agents/phala_agent/agent.rs +++ b/pallets/slp/src/agents/phala_agent/agent.rs @@ -16,7 +16,9 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . use crate::{ - agents::{PhalaCall, PhalaUtilityCall, SystemCall, VaultCall, WrappedBalancesCall, XcmCall}, + agents::{ + PhalaCall, PhalaSystemCall, PhalaUtilityCall, VaultCall, WrappedBalancesCall, XtransferCall, + }, pallet::{Error, Event}, primitives::{ Ledger, PhalaLedger, QueryId, SubstrateLedgerUpdateEntry, SubstrateLedgerUpdateOperation, @@ -35,10 +37,12 @@ pub use cumulus_primitives_core::ParaId; use frame_support::{ensure, traits::Get}; use frame_system::pallet_prelude::BlockNumberFor; use node_primitives::{TokenSymbol, VtokenMintingOperator}; +use polkadot_parachain::primitives::Sibling; use sp_core::U256; use sp_runtime::{ traits::{ - CheckedAdd, CheckedSub, Convert, Saturating, UniqueSaturatedFrom, UniqueSaturatedInto, Zero, + AccountIdConversion, CheckedAdd, CheckedSub, Convert, Saturating, UniqueSaturatedFrom, + UniqueSaturatedInto, Zero, }, DispatchResult, SaturatedConversion, }; @@ -50,7 +54,6 @@ use xcm::{ Junctions::X1, MultiLocation, }, - VersionedMultiAssets, }; use xcm_interface::traits::parachains; @@ -140,8 +143,7 @@ impl interior: X2(GeneralIndex(total_value), GeneralIndex(total_shares)), }) = share_price { - ensure!(total_shares > &0u128, Error::::DividedByZero); - total_value.checked_div(*total_shares).ok_or(Error::::OverFlow) + Self::calculate_shares(total_value, total_shares, amount) } else { Err(Error::::SharePriceNotValid) }?; @@ -157,7 +159,8 @@ impl )?; // Send out the xcm message. - T::XcmRouter::send_xcm(Parent, xcm_message).map_err(|_e| Error::::XcmFailure)?; + let dest = Self::get_pha_multilocation(); + T::XcmRouter::send_xcm(dest, xcm_message).map_err(|_e| Error::::XcmFailure)?; Ok(query_id) } @@ -207,18 +210,10 @@ impl interior: X2(GeneralIndex(total_value), GeneralIndex(total_shares)), }) = share_price { - ensure!(total_shares > &0u128, Error::::DividedByZero); - let shares: u128 = U256::from((*total_shares).saturated_into::()) - .saturating_mul(amount.saturated_into::().into()) - .checked_div((*total_value).saturated_into::().into()) - .ok_or(Error::::OverFlow)? - .as_u128() - .saturated_into(); - - BalanceOf::::unique_saturated_from(shares) + Self::calculate_shares(total_value, total_shares, amount) } else { - Err(Error::::SharePriceNotValid)? - }; + Err(Error::::SharePriceNotValid) + }?; // Check if shares exceeds the minimum requirement > 1000(existential value for shares). ensure!( @@ -256,7 +251,8 @@ impl )?; // Send out the xcm message. - T::XcmRouter::send_xcm(Parent, xcm_message).map_err(|_e| Error::::XcmFailure)?; + let dest = Self::get_pha_multilocation(); + T::XcmRouter::send_xcm(dest, xcm_message).map_err(|_e| Error::::XcmFailure)?; Ok(query_id) } @@ -461,7 +457,8 @@ impl )?; // Send out the xcm message. - T::XcmRouter::send_xcm(Parent, xcm_message).map_err(|_e| Error::::XcmFailure)?; + let dest = Self::get_pha_multilocation(); + T::XcmRouter::send_xcm(dest, xcm_message).map_err(|_e| Error::::XcmFailure)?; Ok(query_id) } @@ -527,27 +524,21 @@ impl // Ensure amount is greater than zero. ensure!(!amount.is_zero(), Error::::AmountZero); - let (dest, beneficiary) = - Pallet::::get_transfer_back_dest_and_beneficiary(from, to, currency_id)?; + let dest_account_32 = Pallet::::multilocation_to_account_32(to)?; + let dest = Pallet::::account_32_to_parachain_location( + dest_account_32, + T::ParachainId::get().into(), + )?; // Prepare parameter assets. let asset = MultiAsset { fun: Fungible(amount.unique_saturated_into()), id: Concrete(Self::get_pha_multilocation()), }; - let assets: Box = - Box::new(VersionedMultiAssets::from(MultiAssets::from(asset))); - - // Prepare parameter fee_asset_item. - let fee_asset_item: u32 = 0; // Construct xcm message. - let call = PhalaCall::Xcm(Box::new(XcmCall::ReserveTransferAssets( - dest, - beneficiary, - assets, - fee_asset_item, - ))); + let call = + PhalaCall::Xtransfer(XtransferCall::Transfer(Box::new(asset), Box::new(dest), None)); // Wrap the xcm message as it is sent from a subaccount of the parachain account, and // send it out. @@ -623,7 +614,8 @@ impl )?; // Send out the xcm message. - T::XcmRouter::send_xcm(Parent, xcm_message).map_err(|_e| Error::::XcmFailure)?; + let dest = Self::get_pha_multilocation(); + T::XcmRouter::send_xcm(dest, xcm_message).map_err(|_e| Error::::XcmFailure)?; Ok(query_id) } @@ -632,7 +624,7 @@ impl &self, who: &Option, token_amount: BalanceOf, - shares_amount: BalanceOf, + _vtoken_amount: BalanceOf, currency_id: CurrencyId, ) -> Result<(), Error> { let who = who.as_ref().ok_or(Error::::DelegatorNotExist)?; @@ -650,20 +642,6 @@ impl currency_id, )?; - // update delegator ledger - DelegatorLedgers::::mutate(currency_id, who, |old_ledger| -> Result<(), Error> { - if let Some(Ledger::Phala(ref mut old_phala_ledger)) = old_ledger { - // Increase both the active and total amount. - old_phala_ledger.active_shares = old_phala_ledger - .active_shares - .checked_add(&shares_amount) - .ok_or(Error::::OverFlow)?; - Ok(()) - } else { - Err(Error::::Unexpected)? - } - })?; - Ok(()) } @@ -830,6 +808,9 @@ impl fun: Fungibility::Fungible(extra_fee.unique_saturated_into()), }; + let self_sibling_parachain_account: [u8; 32] = + Sibling::from(T::ParachainId::get()).into_account_truncating(); + Ok(Xcm(vec![ WithdrawAsset(asset.clone().into()), BuyExecution { fees: asset, weight_limit: Unlimited }, @@ -844,7 +825,7 @@ impl max_assets: u32::MAX, beneficiary: MultiLocation { parents: 0, - interior: X1(Parachain(T::ParachainId::get().into())), + interior: X1(AccountId32 { network: Any, id: self_sibling_parachain_account }), }, }, ])) @@ -894,7 +875,7 @@ impl PhalaAgent { let call_as_subaccount = { // Temporary wrapping remark event in Kusama for ease use of backend service. let remark_call = - PhalaCall::System(SystemCall::RemarkWithEvent(Box::new(query_id.encode()))); + PhalaCall::System(PhalaSystemCall::RemarkWithEvent(Box::new(query_id.encode()))); let mut all_calls = Vec::new(); all_calls.extend(calls.into_iter()); @@ -932,7 +913,8 @@ impl PhalaAgent { let xcm_message = Self::construct_xcm_message(call_as_subaccount, fee, weight, currency_id)?; - T::XcmRouter::send_xcm(Parent, xcm_message).map_err(|_e| Error::::XcmFailure)?; + let dest = Self::get_pha_multilocation(); + T::XcmRouter::send_xcm(dest, xcm_message).map_err(|_e| Error::::XcmFailure)?; Ok(()) } @@ -1101,4 +1083,20 @@ impl PhalaAgent { Ok(()) } + + fn calculate_shares( + total_value: &u128, + total_shares: &u128, + amount: BalanceOf, + ) -> Result, Error> { + ensure!(total_shares > &0u128, Error::::DividedByZero); + let shares: u128 = U256::from((*total_shares).saturated_into::()) + .saturating_mul(amount.saturated_into::().into()) + .checked_div((*total_value).saturated_into::().into()) + .ok_or(Error::::OverFlow)? + .as_u128() + .saturated_into(); + + Ok(BalanceOf::::unique_saturated_from(shares)) + } } diff --git a/pallets/slp/src/agents/phala_agent/types.rs b/pallets/slp/src/agents/phala_agent/types.rs index ab07407f9..bd9e444bd 100644 --- a/pallets/slp/src/agents/phala_agent/types.rs +++ b/pallets/slp/src/agents/phala_agent/types.rs @@ -16,30 +16,34 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use crate::{ - agents::{BalancesCall, SystemCall, XcmCall}, - BalanceOf, Config, -}; +use crate::{agents::BalancesCall, BalanceOf, Config, MultiLocation}; use codec::{Decode, Encode}; use frame_support::RuntimeDebug; use sp_std::{boxed::Box, vec::Vec}; +use xcm::{latest::Weight as XCMWeight, opaque::latest::MultiAsset}; #[derive(Encode, Decode, RuntimeDebug)] pub enum PhalaCall { #[codec(index = 0)] - System(SystemCall), + System(PhalaSystemCall), #[codec(index = 3)] Utility(Box>), - #[codec(index = 33)] - Xcm(Box), #[codec(index = 40)] Balances(BalancesCall), + #[codec(index = 82)] + Xtransfer(XtransferCall), #[codec(index = 94)] PhalaVault(VaultCall), #[codec(index = 95)] PhalaWrappedBalances(WrappedBalancesCall), } +#[derive(Encode, Decode, RuntimeDebug, Clone)] +pub enum XtransferCall { + #[codec(index = 0)] + Transfer(Box, Box, Option), +} + #[derive(Encode, Decode, RuntimeDebug, Clone)] pub enum VaultCall { #[codec(index = 4)] @@ -67,3 +71,9 @@ pub enum PhalaUtilityCall { #[codec(index = 2)] BatchAll(Box>>), } + +#[derive(Encode, Decode, RuntimeDebug, Clone)] +pub enum PhalaSystemCall { + #[codec(index = 8)] + RemarkWithEvent(Box>), +} diff --git a/pallets/slp/src/agents/polkadot_agent/agent.rs b/pallets/slp/src/agents/polkadot_agent/agent.rs index 055638a7f..3d5e57704 100644 --- a/pallets/slp/src/agents/polkadot_agent/agent.rs +++ b/pallets/slp/src/agents/polkadot_agent/agent.rs @@ -16,17 +16,14 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . use crate::{ - agents::{ - KusamaCall, KusamaUtilityCall, PolkadotCall, PolkadotUtilityCall, RewardDestination, - StakingCall, SubstrateCall, SystemCall, XcmCall, - }, + agents::SubstrateCall, pallet::{Error, Event}, primitives::{ Ledger, QueryId, SubstrateLedger, SubstrateLedgerUpdateEntry, SubstrateLedgerUpdateOperation, SubstrateValidatorsByDelegatorUpdateEntry, UnlockChunk, ValidatorsByDelegatorUpdateEntry, XcmOperation, KSM, TIMEOUT_BLOCKS, }, - traits::{InstructionBuilder, QueryResponseManager, StakingAgent, XcmBuilder}, + traits::{QueryResponseManager, StakingAgent, XcmBuilder}, AccountIdOf, BalanceOf, Config, CurrencyDelays, DelegatorLedgerXcmUpdateQueue, DelegatorLedgers, DelegatorsMultilocation2Index, Hash, LedgerUpdateEntry, MinimumsAndMaximums, Pallet, TimeUnit, ValidatorsByDelegator, ValidatorsByDelegatorXcmUpdateQueue, @@ -116,19 +113,7 @@ impl let delegator_account = Pallet::::multilocation_to_account(who)?; // Construct xcm message. - let call = match currency_id { - KSM => Ok(SubstrateCall::Kusama(KusamaCall::Staking(StakingCall::Bond( - T::Lookup::unlookup(delegator_account), - amount, - RewardDestination::>::Staked, - )))), - DOT => Ok(SubstrateCall::Polkadot(PolkadotCall::Staking(StakingCall::Bond( - T::Lookup::unlookup(delegator_account), - amount, - RewardDestination::>::Staked, - )))), - _ => Err(Error::NotSupportedCurrencyId), - }?; + let call = SubstrateCall::::get_bond_call(currency_id, amount, delegator_account)?; // Wrap the xcm message as it is sent from a subaccount of the parachain account, and // send it out. @@ -197,12 +182,7 @@ impl Err(Error::::Unexpected)?; } // Construct xcm message.. - let call = match currency_id { - KSM => Ok(SubstrateCall::Kusama(KusamaCall::Staking(StakingCall::BondExtra(amount)))), - DOT => - Ok(SubstrateCall::Polkadot(PolkadotCall::Staking(StakingCall::BondExtra(amount)))), - _ => Err(Error::NotSupportedCurrencyId), - }?; + let call = SubstrateCall::::get_bond_extra_call(currency_id, amount)?; // Wrap the xcm message as it is sent from a subaccount of the parachain account, and // send it out. @@ -267,11 +247,7 @@ impl } // Construct xcm message. - let call = match currency_id { - KSM => Ok(SubstrateCall::Kusama(KusamaCall::Staking(StakingCall::Unbond(amount)))), - DOT => Ok(SubstrateCall::Polkadot(PolkadotCall::Staking(StakingCall::Unbond(amount)))), - _ => Err(Error::NotSupportedCurrencyId), - }?; + let call = SubstrateCall::::get_unbond_call(currency_id, amount)?; // Wrap the xcm message as it is sent from a subaccount of the parachain account, and // send it out. @@ -312,12 +288,7 @@ impl let amount = substrate_ledger.active; // Construct xcm message. - let call = match currency_id { - KSM => Ok(SubstrateCall::Kusama(KusamaCall::Staking(StakingCall::Unbond(amount)))), - DOT => - Ok(SubstrateCall::Polkadot(PolkadotCall::Staking(StakingCall::Unbond(amount)))), - _ => Err(Error::NotSupportedCurrencyId), - }?; + let call = SubstrateCall::::get_unbond_call(currency_id, amount)?; // Wrap the xcm message as it is sent from a subaccount of the parachain account, and // send it out. @@ -380,11 +351,7 @@ impl } // Construct xcm message. - let call = match currency_id { - KSM => Ok(SubstrateCall::Kusama(KusamaCall::Staking(StakingCall::Rebond(amount)))), - DOT => Ok(SubstrateCall::Polkadot(PolkadotCall::Staking(StakingCall::Rebond(amount)))), - _ => Err(Error::NotSupportedCurrencyId), - }?; + let call = SubstrateCall::::get_rebond_call(currency_id, amount)?; // Wrap the xcm message as it is sent from a subaccount of the parachain account, and // send it out. @@ -445,12 +412,7 @@ impl } // Construct xcm message. - let call = match currency_id { - KSM => Ok(SubstrateCall::Kusama(KusamaCall::Staking(StakingCall::Nominate(accounts)))), - DOT => - Ok(SubstrateCall::Polkadot(PolkadotCall::Staking(StakingCall::Nominate(accounts)))), - _ => Err(Error::NotSupportedCurrencyId), - }?; + let call = SubstrateCall::::get_nominate_call(currency_id, accounts)?; // Wrap the xcm message as it is sent from a subaccount of the parachain account, and // send it out. @@ -517,12 +479,7 @@ impl } // Construct xcm message. - let call = match currency_id { - KSM => Ok(SubstrateCall::Kusama(KusamaCall::Staking(StakingCall::Nominate(accounts)))), - DOT => - Ok(SubstrateCall::Polkadot(PolkadotCall::Staking(StakingCall::Nominate(accounts)))), - _ => Err(Error::NotSupportedCurrencyId), - }?; + let call = SubstrateCall::::get_nominate_call(currency_id, accounts)?; // Wrap the xcm message as it is sent from a subaccount of the parachain account, and // send it out. @@ -578,17 +535,11 @@ impl Err(Error::::InvalidTimeUnit)? }; // Construct xcm message. - let call = match currency_id { - KSM => Ok(SubstrateCall::Kusama(KusamaCall::Staking(StakingCall::PayoutStakers( - validator_account, - payout_era, - )))), - DOT => Ok(SubstrateCall::Polkadot(PolkadotCall::Staking(StakingCall::PayoutStakers( - validator_account, - payout_era, - )))), - _ => Err(Error::NotSupportedCurrencyId), - }?; + let call = SubstrateCall::::get_payout_stakers_call( + currency_id, + validator_account, + payout_era, + )?; // Wrap the xcm message as it is sent from a subaccount of the parachain account, and // send it out. @@ -628,15 +579,7 @@ impl }; // Construct xcm message. - let call = match currency_id { - KSM => Ok(SubstrateCall::Kusama(KusamaCall::Staking(StakingCall::WithdrawUnbonded( - num_slashing_spans, - )))), - DOT => Ok(SubstrateCall::Polkadot(PolkadotCall::Staking( - StakingCall::WithdrawUnbonded(num_slashing_spans), - ))), - _ => Err(Error::NotSupportedCurrencyId), - }?; + let call = SubstrateCall::::get_withdraw_unbonded_call(currency_id, num_slashing_spans)?; // Wrap the xcm message as it is sent from a subaccount of the parachain account, and // send it out. @@ -674,11 +617,7 @@ impl ); // Construct xcm message. - let call = match currency_id { - KSM => Ok(SubstrateCall::Kusama(KusamaCall::Staking(StakingCall::Chill))), - DOT => Ok(SubstrateCall::Polkadot(PolkadotCall::Staking(StakingCall::Chill))), - _ => Err(Error::NotSupportedCurrencyId), - }?; + let call = SubstrateCall::::get_chill_call(currency_id)?; // Wrap the xcm message as it is sent from a subaccount of the parachain account, and // send it out. @@ -741,15 +680,13 @@ impl let fee_asset_item: u32 = 0; // Construct xcm message. - let call = match currency_id { - KSM => Ok(SubstrateCall::Kusama(KusamaCall::Xcm(Box::new( - XcmCall::ReserveTransferAssets(dest, beneficiary, assets, fee_asset_item), - )))), - DOT => Ok(SubstrateCall::Polkadot(PolkadotCall::Xcm(Box::new( - XcmCall::ReserveTransferAssets(dest, beneficiary, assets, fee_asset_item), - )))), - _ => Err(Error::NotSupportedCurrencyId), - }?; + let call = SubstrateCall::::get_reserve_transfer_assets_call( + currency_id, + dest, + beneficiary, + assets, + fee_asset_item, + )?; // Wrap the xcm message as it is sent from a subaccount of the parachain account, and // send it out. @@ -1017,38 +954,13 @@ impl // response_back_location: MultiLocation ) -> Result, Error> { let mut xcm_message = Self::inner_construct_xcm_message(extra_fee); - let transact_instruct = match call { - SubstrateCall::Kusama(ksm_call) => Self::construct_instruction(ksm_call, weight), - SubstrateCall::Polkadot(dot_call) => Self::construct_instruction(dot_call, weight), - }; + let transact_instruct = call.get_transact_instruct(weight); xcm_message.insert(2, transact_instruct); Ok(Xcm(xcm_message)) } } -// for kusama call -impl InstructionBuilder> for PolkadotAgent { - fn construct_instruction(call: KusamaCall, weight: XcmWeight) -> Instruction { - Transact { - origin_type: OriginKind::SovereignAccount, - require_weight_at_most: weight, - call: call.encode().into(), - } - } -} - -// for polkadot call -impl InstructionBuilder> for PolkadotAgent { - fn construct_instruction(call: PolkadotCall, weight: XcmWeight) -> Instruction { - Transact { - origin_type: OriginKind::SovereignAccount, - require_weight_at_most: weight, - call: call.encode().into(), - } - } -} - /// Internal functions. impl PolkadotAgent { fn prepare_send_as_subaccount_call_params_with_query_id( @@ -1062,43 +974,8 @@ impl PolkadotAgent { let sub_account_index = DelegatorsMultilocation2Index::::get(currency_id, who) .ok_or(Error::::DelegatorNotExist)?; - let call_as_subaccount = match call { - SubstrateCall::Kusama(ksm_call) => { - // Temporary wrapping remark event in Kusama for ease use of backend service. - let remark_call = - KusamaCall::System(SystemCall::RemarkWithEvent(Box::new(query_id.encode()))); - - let call_batched_with_remark = - KusamaCall::Utility(Box::new(KusamaUtilityCall::BatchAll(Box::new(vec![ - Box::new(ksm_call), - Box::new(remark_call), - ])))); - - Ok(SubstrateCall::Kusama(KusamaCall::Utility(Box::new( - KusamaUtilityCall::AsDerivative( - sub_account_index, - Box::new(call_batched_with_remark), - ), - )))) - }, - SubstrateCall::Polkadot(dot_call) => { - let remark_call = - PolkadotCall::System(SystemCall::RemarkWithEvent(Box::new(query_id.encode()))); - - let call_batched_with_remark = - PolkadotCall::Utility(Box::new(PolkadotUtilityCall::BatchAll(Box::new(vec![ - Box::new(dot_call), - Box::new(remark_call), - ])))); - - Ok(SubstrateCall::Polkadot(PolkadotCall::Utility(Box::new( - PolkadotUtilityCall::AsDerivative( - sub_account_index, - Box::new(call_batched_with_remark), - ), - )))) - }, - }?; + let call_as_subaccount = + call.get_call_as_subaccount_from_call(Some(query_id), sub_account_index)?; let (weight, fee) = XcmDestWeightAndFee::::get(currency_id, operation) .ok_or(Error::::WeightAndFeeNotExists)?; @@ -1116,15 +993,7 @@ impl PolkadotAgent { let sub_account_index = DelegatorsMultilocation2Index::::get(currency_id, who) .ok_or(Error::::DelegatorNotExist)?; - let call_as_subaccount = match call { - SubstrateCall::Kusama(ksm_call) => Ok(SubstrateCall::Kusama(KusamaCall::Utility( - Box::new(KusamaUtilityCall::AsDerivative(sub_account_index, Box::new(ksm_call))), - ))), - SubstrateCall::Polkadot(dot_call) => - Ok(SubstrateCall::Polkadot(PolkadotCall::Utility(Box::new( - PolkadotUtilityCall::AsDerivative(sub_account_index, Box::new(dot_call)), - )))), - }?; + let call_as_subaccount = call.get_call_as_subaccount_from_call(None, sub_account_index)?; let (weight, fee) = XcmDestWeightAndFee::::get(currency_id, operation) .ok_or(Error::::WeightAndFeeNotExists)?; diff --git a/pallets/slp/src/agents/polkadot_agent/types.rs b/pallets/slp/src/agents/polkadot_agent/types.rs index c041620be..2274aafbe 100644 --- a/pallets/slp/src/agents/polkadot_agent/types.rs +++ b/pallets/slp/src/agents/polkadot_agent/types.rs @@ -16,14 +16,18 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +use crate::{pallet::Error, primitives::KSM, vec, AccountIdOf, BalanceOf, Config, CurrencyId}; use codec::{Decode, Encode}; use frame_support::RuntimeDebug; +use node_primitives::DOT; use scale_info::TypeInfo; use sp_runtime::traits::StaticLookup; use sp_std::{boxed::Box, vec::Vec}; -use xcm::{VersionedMultiAssets, VersionedMultiLocation}; - -use crate::{BalanceOf, Config}; +use xcm::{ + latest::{prelude::*, Weight as XcmWeight}, + opaque::latest::Instruction, + VersionedMultiAssets, VersionedMultiLocation, +}; #[derive(Encode, Decode, RuntimeDebug)] pub enum SubstrateCall { @@ -31,6 +35,174 @@ pub enum SubstrateCall { Polkadot(PolkadotCall), } +impl SubstrateCall { + pub fn get_bond_call( + currency_id: CurrencyId, + amount: BalanceOf, + delegator_account: AccountIdOf, + ) -> Result> { + match currency_id { + KSM => Ok(Self::Kusama(KusamaCall::Staking(StakingCall::Bond( + T::Lookup::unlookup(delegator_account), + amount, + RewardDestination::>::Staked, + )))), + DOT => Ok(Self::Polkadot(PolkadotCall::Staking(StakingCall::Bond( + T::Lookup::unlookup(delegator_account), + amount, + RewardDestination::>::Staked, + )))), + _ => Err(Error::::NotSupportedCurrencyId), + } + } + + pub fn get_bond_extra_call( + currency_id: CurrencyId, + amount: BalanceOf, + ) -> Result> { + match currency_id { + KSM => Ok(Self::Kusama(KusamaCall::Staking(StakingCall::BondExtra(amount)))), + DOT => Ok(Self::Polkadot(PolkadotCall::Staking(StakingCall::BondExtra(amount)))), + _ => Err(Error::NotSupportedCurrencyId), + } + } + + pub fn get_unbond_call( + currency_id: CurrencyId, + amount: BalanceOf, + ) -> Result> { + match currency_id { + KSM => Ok(Self::Kusama(KusamaCall::Staking(StakingCall::Unbond(amount)))), + DOT => Ok(Self::Polkadot(PolkadotCall::Staking(StakingCall::Unbond(amount)))), + _ => Err(Error::NotSupportedCurrencyId), + } + } + + pub fn get_rebond_call( + currency_id: CurrencyId, + amount: BalanceOf, + ) -> Result> { + match currency_id { + KSM => Ok(Self::Kusama(KusamaCall::Staking(StakingCall::Rebond(amount)))), + DOT => Ok(Self::Polkadot(PolkadotCall::Staking(StakingCall::Rebond(amount)))), + _ => Err(Error::NotSupportedCurrencyId), + } + } + + pub fn get_nominate_call( + currency_id: CurrencyId, + accounts: Vec<::Source>, + ) -> Result> { + match currency_id { + KSM => Ok(Self::Kusama(KusamaCall::Staking(StakingCall::Nominate(accounts)))), + DOT => Ok(Self::Polkadot(PolkadotCall::Staking(StakingCall::Nominate(accounts)))), + _ => Err(Error::NotSupportedCurrencyId), + } + } + + pub fn get_payout_stakers_call( + currency_id: CurrencyId, + validator_account: AccountIdOf, + payout_era: u32, + ) -> Result> { + match currency_id { + KSM => Ok(Self::Kusama(KusamaCall::Staking(StakingCall::PayoutStakers( + validator_account, + payout_era, + )))), + DOT => Ok(Self::Polkadot(PolkadotCall::Staking(StakingCall::PayoutStakers( + validator_account, + payout_era, + )))), + _ => Err(Error::NotSupportedCurrencyId), + } + } + + pub fn get_withdraw_unbonded_call( + currency_id: CurrencyId, + num_slashing_spans: u32, + ) -> Result> { + match currency_id { + KSM => Ok(Self::Kusama(KusamaCall::Staking(StakingCall::WithdrawUnbonded( + num_slashing_spans, + )))), + DOT => Ok(Self::Polkadot(PolkadotCall::Staking(StakingCall::WithdrawUnbonded( + num_slashing_spans, + )))), + _ => Err(Error::NotSupportedCurrencyId), + } + } + + pub fn get_chill_call(currency_id: CurrencyId) -> Result> { + match currency_id { + KSM => Ok(Self::Kusama(KusamaCall::Staking(StakingCall::Chill))), + DOT => Ok(Self::Polkadot(PolkadotCall::Staking(StakingCall::Chill))), + _ => Err(Error::NotSupportedCurrencyId), + } + } + + pub fn get_reserve_transfer_assets_call( + currency_id: CurrencyId, + dest: Box, + beneficiary: Box, + assets: Box, + fee_asset_item: u32, + ) -> Result> { + match currency_id { + KSM => Ok(Self::Kusama(KusamaCall::Xcm(Box::new(XcmCall::ReserveTransferAssets( + dest, + beneficiary, + assets, + fee_asset_item, + ))))), + DOT => Ok(Self::Polkadot(PolkadotCall::Xcm(Box::new(XcmCall::ReserveTransferAssets( + dest, + beneficiary, + assets, + fee_asset_item, + ))))), + _ => Err(Error::NotSupportedCurrencyId), + } + } + + pub fn get_call_as_subaccount_from_call( + self, + query_id_op: Option, + sub_account_index: u16, + ) -> Result> { + match self { + SubstrateCall::Kusama(kusama_call) => + if let Some(query_id) = query_id_op { + kusama_call + .get_call_as_subaccount_from_call_with_query_id(query_id, sub_account_index) + } else { + kusama_call.get_call_as_subaccount_from_call_without_query_id(sub_account_index) + }, + SubstrateCall::Polkadot(polkadot_call) => + if let Some(query_id) = query_id_op { + polkadot_call + .get_call_as_subaccount_from_call_with_query_id(query_id, sub_account_index) + } else { + polkadot_call + .get_call_as_subaccount_from_call_without_query_id(sub_account_index) + }, + } + } + + pub fn get_transact_instruct(self, weight: XcmWeight) -> Instruction { + let encoded_call = match &self { + SubstrateCall::Kusama(call) => call.encode(), + SubstrateCall::Polkadot(call) => call.encode(), + }; + + Transact { + origin_type: OriginKind::SovereignAccount, + require_weight_at_most: weight, + call: encoded_call.into(), + } + } +} + #[derive(Encode, Decode, RuntimeDebug)] pub enum KusamaCall { #[codec(index = 0)] @@ -45,6 +217,48 @@ pub enum KusamaCall { Xcm(Box), } +impl KusamaCall { + pub fn get_remark_with_event_call(query_id: u64) -> Self { + Self::System(SystemCall::RemarkWithEvent(Box::new(query_id.encode()))) + } + + pub fn get_derivative_call(sub_account_index: u16, call: Self) -> Self { + Self::Utility(Box::new(KusamaUtilityCall::AsDerivative(sub_account_index, Box::new(call)))) + } + + pub fn get_batch_all_two_calls(call_1: Self, call_2: Self) -> Self { + KusamaCall::Utility(Box::new(KusamaUtilityCall::BatchAll(Box::new(vec![ + Box::new(call_1), + Box::new(call_2), + ])))) + } + + pub fn get_call_as_subaccount_from_call_with_query_id( + self, + query_id: u64, + sub_account_index: u16, + ) -> Result, Error> { + // Temporary wrapping remark event in Kusama for ease use of backend service. + let remark_call = KusamaCall::::get_remark_with_event_call(query_id); + + let call_batched_with_remark = KusamaCall::::get_batch_all_two_calls(self, remark_call); + + let derivative_call = + KusamaCall::::get_derivative_call(sub_account_index, call_batched_with_remark); + + Ok(SubstrateCall::::Kusama(derivative_call)) + } + + pub fn get_call_as_subaccount_from_call_without_query_id( + self, + sub_account_index: u16, + ) -> Result, Error> { + let derivative_call = KusamaCall::::get_derivative_call(sub_account_index, self); + + Ok(SubstrateCall::::Kusama(derivative_call)) + } +} + #[derive(Encode, Decode, RuntimeDebug)] pub enum PolkadotCall { #[codec(index = 0)] @@ -59,6 +273,52 @@ pub enum PolkadotCall { Xcm(Box), } +impl PolkadotCall { + pub fn get_remark_with_event_call(query_id: u64) -> Self { + Self::System(SystemCall::RemarkWithEvent(Box::new(query_id.encode()))) + } + + pub fn get_derivative_call(sub_account_index: u16, call: Self) -> Self { + Self::Utility(Box::new(PolkadotUtilityCall::AsDerivative( + sub_account_index, + Box::new(call), + ))) + } + + pub fn get_batch_all_two_calls(call_1: Self, call_2: Self) -> Self { + Self::Utility(Box::new(PolkadotUtilityCall::BatchAll(Box::new(vec![ + Box::new(call_1), + Box::new(call_2), + ])))) + } + + pub fn get_call_as_subaccount_from_call_with_query_id( + self, + query_id: u64, + sub_account_index: u16, + ) -> Result, Error> { + // Temporary wrapping remark event in Kusama for ease use of backend service. + let remark_call = PolkadotCall::::get_remark_with_event_call(query_id); + + let call_batched_with_remark = + PolkadotCall::::get_batch_all_two_calls(self, remark_call); + + let derivative_call = + PolkadotCall::::get_derivative_call(sub_account_index, call_batched_with_remark); + + Ok(SubstrateCall::::Polkadot(derivative_call)) + } + + pub fn get_call_as_subaccount_from_call_without_query_id( + self, + sub_account_index: u16, + ) -> Result, Error> { + let derivative_call = PolkadotCall::::get_derivative_call(sub_account_index, self); + + Ok(SubstrateCall::::Polkadot(derivative_call)) + } +} + #[derive(Encode, Decode, RuntimeDebug, Clone)] pub enum SystemCall { #[codec(index = 7)] diff --git a/pallets/slp/src/benchmarking.rs b/pallets/slp/src/benchmarking.rs index f1cd78670..9a0cf5e4b 100644 --- a/pallets/slp/src/benchmarking.rs +++ b/pallets/slp/src/benchmarking.rs @@ -555,7 +555,7 @@ benchmarks! { let call = Call::::charge_host_fee_and_tune_vtoken_exchange_rate { currency_id:KSM, value:BalanceOf::::unique_saturated_from(100u128), - who:Some(subaccount_0_location.clone()) + who:Some(subaccount_0_location.clone()), }; }: {call.dispatch_bypass_filter(RawOrigin::Signed(who.clone()).into())?} diff --git a/pallets/slp/src/mocks/mock.rs b/pallets/slp/src/mocks/mock.rs index a92bd3b32..69d3abd32 100644 --- a/pallets/slp/src/mocks/mock.rs +++ b/pallets/slp/src/mocks/mock.rs @@ -20,10 +20,9 @@ #![cfg(test)] -use bifrost_asset_registry::AssetIdMaps; -// use parachain_staking::ParachainStakingInterface; use crate as bifrost_slp; use crate::{Config, QueryResponseManager}; +use bifrost_asset_registry::AssetIdMaps; use codec::{Decode, Encode}; pub use cumulus_primitives_core::ParaId; use frame_support::{ @@ -59,6 +58,8 @@ pub const KSM: CurrencyId = CurrencyId::Token(TokenSymbol::KSM); pub const VMOVR: CurrencyId = CurrencyId::VToken(TokenSymbol::MOVR); pub const VFIL: CurrencyId = CurrencyId::VToken2(2u8); pub const VPHA: CurrencyId = CurrencyId::VToken(TokenSymbol::PHA); +#[cfg(feature = "runtime-benchmarks")] +pub const VKSM: CurrencyId = CurrencyId::VToken(TokenSymbol::KSM); construct_runtime!( pub enum Runtime where @@ -74,6 +75,7 @@ construct_runtime!( VtokenMinting: bifrost_vtoken_minting::{Pallet, Call, Storage, Event}, AssetRegistry: bifrost_asset_registry::{Pallet, Call, Event, Storage}, ParachainStaking: parachain_staking::{Pallet, Call, Storage, Event}, + Utility: pallet_utility::{Pallet, Call, Event} } ); @@ -82,6 +84,13 @@ parameter_types! { pub const RelayCurrencyId: CurrencyId = KSM; } +impl pallet_utility::Config for Runtime { + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; + type PalletsOrigin = OriginCaller; + type WeightInfo = (); +} + parameter_types! { pub const BlockHashCount: u64 = 250; } diff --git a/pallets/slp/src/mocks/mock_kusama.rs b/pallets/slp/src/mocks/mock_kusama.rs index f17f86791..81532abb8 100644 --- a/pallets/slp/src/mocks/mock_kusama.rs +++ b/pallets/slp/src/mocks/mock_kusama.rs @@ -66,15 +66,16 @@ construct_runtime!( NodeBlock = Block, UncheckedExtrinsic = UncheckedExtrinsic, { - System: frame_system::{Pallet, Call, Config, Storage, Event}, - Indices: pallet_indices::{Pallet, Call, Storage, Event}, - Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, - Currencies: orml_currencies::{Pallet, Call}, - Tokens: orml_tokens::{Pallet, Call, Storage, Event}, - Slp: bifrost_slp::{Pallet, Call, Storage, Event}, - VtokenMinting: bifrost_vtoken_minting::{Pallet, Call, Storage, Event}, - AssetRegistry: bifrost_asset_registry::{Pallet, Call, Event, Storage}, - ParachainStaking: parachain_staking::{Pallet, Call, Storage, Event}, + System: frame_system::{Pallet, Call, Config, Storage, Event} = 0, + Indices: pallet_indices::{Pallet, Call, Storage, Event} = 2, + Balances: pallet_balances::{Pallet, Call, Storage, Config, Event} = 10, + Currencies: orml_currencies::{Pallet, Call} = 72, + Tokens: orml_tokens::{Pallet, Call, Storage, Event} = 71, + Slp: bifrost_slp::{Pallet, Call, Storage, Event} = 116, + VtokenMinting: bifrost_vtoken_minting::{Pallet, Call, Storage, Event} = 115, + AssetRegistry: bifrost_asset_registry::{Pallet, Call, Event, Storage} = 114, + ParachainStaking: parachain_staking::{Pallet, Call, Storage, Event} = 25, + Utility: pallet_utility::{Pallet, Call, Event} = 50 } ); @@ -83,6 +84,13 @@ parameter_types! { pub const RelayCurrencyId: CurrencyId = KSM; } +impl pallet_utility::Config for Runtime { + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; + type PalletsOrigin = OriginCaller; + type WeightInfo = (); +} + parameter_types! { pub const BlockHashCount: u64 = 250; } diff --git a/pallets/slp/src/tests/filecoin_tests.rs b/pallets/slp/src/tests/filecoin_tests.rs index e1107bc05..004e9c60f 100644 --- a/pallets/slp/src/tests/filecoin_tests.rs +++ b/pallets/slp/src/tests/filecoin_tests.rs @@ -23,8 +23,8 @@ use crate::{ primitives::FilecoinLedger, FIL, *, }; -use frame_support::{assert_noop, assert_ok}; -use sp_runtime::WeakBoundedVec; +use frame_support::{assert_noop, assert_ok, PalletId}; +use sp_runtime::{traits::AccountIdConversion, WeakBoundedVec}; use xcm::opaque::latest::NetworkId::Any; fn mins_maxs_setup() { @@ -385,11 +385,8 @@ fn charge_host_fee_and_tune_vtoken_exchange_rate_should_work() { interior: X1(Junction::GeneralKey(WeakBoundedVec::default())), }; - let treasury_id: AccountId = - hex_literal::hex!["6d6f646c62662f74727372790000000000000000000000000000000000000000"] - .into(); - let treasury_32: [u8; 32] = - hex_literal::hex!["6d6f646c62662f74727372790000000000000000000000000000000000000000"]; + let treasury_id: AccountId = PalletId(*b"bf/trsry").into_account_truncating(); + let treasury_32: [u8; 32] = treasury_id.clone().into(); assert_noop!( Slp::charge_host_fee_and_tune_vtoken_exchange_rate( diff --git a/pallets/slp/src/tests/kusama_tests.rs b/pallets/slp/src/tests/kusama_tests.rs index 8fe5113ec..3fee353f4 100644 --- a/pallets/slp/src/tests/kusama_tests.rs +++ b/pallets/slp/src/tests/kusama_tests.rs @@ -19,11 +19,16 @@ #![cfg(test)] use crate::{mocks::mock_kusama::*, BNC, KSM, *}; -use frame_support::{assert_noop, assert_ok}; +use frame_support::{assert_noop, assert_ok, PalletId}; use orml_traits::MultiCurrency; use sp_runtime::{traits::AccountIdConversion, MultiAddress}; use xcm::opaque::latest::NetworkId::Any; +const SUBACCOUNT_0_32: [u8; 32] = + hex_literal::hex!["5a53736d8e96f1c007cf0d630acf5209b20611617af23ce924c8e25328eb5d28"]; +const SUBACCOUNT_0_LOCATION: MultiLocation = + MultiLocation { parents: 1, interior: X1(AccountId32 { network: Any, id: SUBACCOUNT_0_32 }) }; + #[test] fn set_xcm_dest_weight_and_fee_should_work() { ExtBuilder::default().build().execute_with(|| { @@ -142,10 +147,8 @@ fn supplement_fee_reserve_works() { #[test] fn remove_delegator_works() { ExtBuilder::default().build().execute_with(|| { - // 5E78xTBiaN3nAGYtcNnqTJQJqYAkSDGggKqaDfpNsKyPpbcb - let subaccount_0: AccountId = - hex_literal::hex!["5a53736d8e96f1c007cf0d630acf5209b20611617af23ce924c8e25328eb5d28"] - .into(); + let para_chain_account: AccountId = ParaId::from(2001).into_account_truncating(); + let subaccount_0: AccountId = Utility::derivative_account_id(para_chain_account, 0); let subaccount_0_32: [u8; 32] = Slp::account_id_to_account_32(subaccount_0).unwrap(); let subaccount_0_location: MultiLocation = Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); @@ -447,20 +450,15 @@ fn refund_currency_due_unbond_works() { #[test] fn charge_host_fee_and_tune_vtoken_exchange_rate_works() { - // 5E78xTBiaN3nAGYtcNnqTJQJqYAkSDGggKqaDfpNsKyPpbcb - let subaccount_0: AccountId = - hex_literal::hex!["5a53736d8e96f1c007cf0d630acf5209b20611617af23ce924c8e25328eb5d28"] - .into(); + let para_chain_account: AccountId = ParaId::from(2001).into_account_truncating(); + let subaccount_0: AccountId = Utility::derivative_account_id(para_chain_account, 0); let subaccount_0_32: [u8; 32] = Slp::account_id_to_account_32(subaccount_0).unwrap(); let subaccount_0_location: MultiLocation = Slp::account_32_to_parent_location(subaccount_0_32).unwrap(); ExtBuilder::default().build().execute_with(|| { - let treasury_id: AccountId = - hex_literal::hex!["6d6f646c62662f74727372790000000000000000000000000000000000000000"] - .into(); - let treasury_32: [u8; 32] = - hex_literal::hex!["6d6f646c62662f74727372790000000000000000000000000000000000000000"]; + let treasury_id: AccountId = PalletId(*b"bf/trsry").into_account_truncating(); + let treasury_32: [u8; 32] = treasury_id.clone().into(); bifrost_vtoken_minting::OngoingTimeUnit::::insert(KSM, TimeUnit::Era(1)); @@ -544,8 +542,7 @@ fn charge_host_fee_and_tune_vtoken_exchange_rate_works() { #[test] fn set_hosting_fees_works() { ExtBuilder::default().build().execute_with(|| { - let treasury_32: [u8; 32] = - hex_literal::hex!["6d6f646c62662f74727372790000000000000000000000000000000000000000"]; + let treasury_32: [u8; 32] = PalletId(*b"bf/trsry").into_account_truncating(); // Set the hosting fee to be 20%, and the beneficiary to be bifrost treasury account. let pct = Permill::from_percent(20); @@ -565,3 +562,144 @@ fn set_hosting_fees_works() { assert_eq!(location, treasury_location); }); } + +// test for DOT +#[test] +fn bond_works() { + ExtBuilder::default().build().execute_with(|| { + register_subaccount_index_0(); + + // Bond 1 ksm for sub-account index 0 + assert_noop!( + Slp::bond( + RuntimeOrigin::signed(ALICE), + DOT, + Box::new(SUBACCOUNT_0_LOCATION), + 1_000_000_000_000, + None + ), + Error::::XcmFailure + ); + }); +} + +// Preparation: register sub-account index 0. +fn register_subaccount_index_0() { + // Set OngoingTimeUnitUpdateInterval as 1/3 Era(1800 blocks per Era, 12 seconds per + // block) + assert_ok!(Slp::set_ongoing_time_unit_update_interval( + RuntimeOrigin::signed(ALICE), + DOT, + Some(600) + )); + + System::set_block_number(600); + + // Initialize ongoing timeunit as 0. + assert_ok!(Slp::update_ongoing_time_unit(RuntimeOrigin::signed(ALICE), DOT, TimeUnit::Era(0))); + + // Initialize currency delays. + let delay = + Delays { unlock_delay: TimeUnit::Era(10), leave_delegators_delay: Default::default() }; + assert_ok!(Slp::set_currency_delays(RuntimeOrigin::signed(ALICE), DOT, Some(delay))); + + let mins_and_maxs = MinimumsMaximums { + delegator_bonded_minimum: 100_000_000_000, + bond_extra_minimum: 0, + unbond_minimum: 0, + rebond_minimum: 0, + unbond_record_maximum: 32, + validators_back_maximum: 36, + delegator_active_staking_maximum: 200_000_000_000_000, + validators_reward_maximum: 0, + delegation_amount_minimum: 0, + delegators_maximum: 100, + validators_maximum: 300, + }; + + // Set minimums and maximums + assert_ok!(Slp::set_minimums_and_maximums( + RuntimeOrigin::signed(ALICE), + DOT, + Some(mins_and_maxs) + )); + + // First to setup index-multilocation relationship of subaccount_0 + assert_ok!(Slp::add_delegator( + RuntimeOrigin::signed(ALICE), + DOT, + 0u16, + Box::new(SUBACCOUNT_0_LOCATION), + )); + + // Register Operation weight and fee + assert_ok!(Slp::set_xcm_dest_weight_and_fee( + RuntimeOrigin::signed(ALICE), + DOT, + XcmOperation::TransferTo, + Some((20_000_000_000, 10_000_000_000)), + )); + + assert_ok!(Slp::set_xcm_dest_weight_and_fee( + RuntimeOrigin::signed(ALICE), + DOT, + XcmOperation::Bond, + Some((20_000_000_000, 10_000_000_000)), + )); + + assert_ok!(Slp::set_xcm_dest_weight_and_fee( + RuntimeOrigin::signed(ALICE), + DOT, + XcmOperation::BondExtra, + Some((20_000_000_000, 10_000_000_000)), + )); + + assert_ok!(Slp::set_xcm_dest_weight_and_fee( + RuntimeOrigin::signed(ALICE), + DOT, + XcmOperation::Unbond, + Some((20_000_000_000, 10_000_000_000)), + )); + + assert_ok!(Slp::set_xcm_dest_weight_and_fee( + RuntimeOrigin::signed(ALICE), + DOT, + XcmOperation::Rebond, + Some((20_000_000_000, 10_000_000_000)), + )); + + assert_ok!(Slp::set_xcm_dest_weight_and_fee( + RuntimeOrigin::signed(ALICE), + DOT, + XcmOperation::Delegate, + Some((20_000_000_000, 10_000_000_000)), + )); + + assert_ok!(Slp::set_xcm_dest_weight_and_fee( + RuntimeOrigin::signed(ALICE), + DOT, + XcmOperation::Payout, + Some((20_000_000_000, 10_000_000_000)), + )); + + assert_ok!(Slp::set_xcm_dest_weight_and_fee( + RuntimeOrigin::signed(ALICE), + DOT, + XcmOperation::Liquidize, + Some((20_000_000_000, 10_000_000_000)), + )); + + assert_ok!(Slp::set_xcm_dest_weight_and_fee( + RuntimeOrigin::signed(ALICE), + DOT, + XcmOperation::Chill, + Some((20_000_000_000, 10_000_000_000)), + )); + + assert_ok!(Slp::set_xcm_dest_weight_and_fee( + RuntimeOrigin::signed(ALICE), + DOT, + XcmOperation::TransferBack, + Some((20_000_000_000, 10_000_000_000)), + )); +} diff --git a/pallets/slp/src/tests/moonriver_tests.rs b/pallets/slp/src/tests/moonriver_tests.rs index efed00ea5..2d0689555 100644 --- a/pallets/slp/src/tests/moonriver_tests.rs +++ b/pallets/slp/src/tests/moonriver_tests.rs @@ -20,21 +20,40 @@ use crate::{ mocks::mock::*, - primitives::{MoonbeamLedgerUpdateEntry, OneToManyDelegationAction, OneToManyScheduledRequest}, + primitives::{ + MoonbeamLedgerUpdateEntry, MoonbeamLedgerUpdateOperation, OneToManyDelegationAction, + OneToManyDelegatorStatus, OneToManyLedger, OneToManyScheduledRequest, + }, Junction::Parachain, Junctions::X2, -}; -use frame_support::{assert_noop, assert_ok}; -use xcm::opaque::latest::NetworkId::Any; - -use crate::{ - primitives::{MoonbeamLedgerUpdateOperation, OneToManyDelegatorStatus, OneToManyLedger}, MOVR, *, }; use codec::alloc::collections::BTreeMap; +use frame_support::{assert_noop, assert_ok, PalletId}; use node_primitives::Balance; use polkadot_parachain::primitives::Sibling; use sp_runtime::traits::AccountIdConversion; +use xcm::opaque::latest::NetworkId::Any; + +const VALIDATOR_0_ACCOUNT_ID_20: [u8; 20] = + hex_literal::hex!["3Cd0A705a2DC65e5b1E1205896BaA2be8A07c6e0"]; +const VALIDATOR_0_LOCATION: MultiLocation = MultiLocation { + parents: 1, + interior: X2( + Parachain(2023), + Junction::AccountKey20 { network: Any, key: VALIDATOR_0_ACCOUNT_ID_20 }, + ), +}; + +const VALIDATOR_1_ACCOUNT_ID_20: [u8; 20] = + hex_literal::hex!["f24FF3a9CF04c71Dbc94D0b566f7A27B94566cac"]; +const VALIDATOR_1_LOCATION: MultiLocation = MultiLocation { + parents: 1, + interior: X2( + Parachain(2023), + Junction::AccountKey20 { network: Any, key: VALIDATOR_1_ACCOUNT_ID_20 }, + ), +}; #[test] fn initialize_moonriver_delegator() { @@ -100,20 +119,7 @@ fn initialize_moonriver_delegator() { } fn moonriver_setup() { - let validator_0_account_id_20: [u8; 20] = - hex_literal::hex!["3Cd0A705a2DC65e5b1E1205896BaA2be8A07c6e0"].into(); - - let validator_0_location = MultiLocation { - parents: 1, - interior: X2( - Parachain(2023), - Junction::AccountKey20 { network: Any, key: validator_0_account_id_20 }, - ), - }; - - let treasury_account_id_32: [u8; 32] = - hex_literal::hex!["6d6f646c62662f74727372790000000000000000000000000000000000000000"] - .into(); + let treasury_account_id_32: [u8; 32] = PalletId(*b"bf/trsry").into_account_truncating(); let treasury_location = MultiLocation { parents: 0, interior: X1(AccountId32 { network: Any, id: treasury_account_id_32 }), @@ -271,7 +277,7 @@ fn moonriver_setup() { assert_ok!(Slp::add_validator( RuntimeOrigin::signed(ALICE), MOVR, - Box::new(validator_0_location.clone()), + Box::new(VALIDATOR_0_LOCATION.clone()), )); // initialize delegator @@ -279,8 +285,10 @@ fn moonriver_setup() { #[test] fn moonriver_bond_works() { + let bifrost_parachain_account_id_20: [u8; 20] = Sibling::from(2001).into_account_truncating(); + let subaccount_0_account_id_20: [u8; 20] = - hex_literal::hex!["863c1faef3c3b8f8735ecb7f8ed18996356dd3de"].into(); + Slp::derivative_account_id_20(bifrost_parachain_account_id_20, 0).into(); let subaccount_0_location = MultiLocation { parents: 1, @@ -290,17 +298,6 @@ fn moonriver_bond_works() { ), }; - let validator_0_account_id_20: [u8; 20] = - hex_literal::hex!["3Cd0A705a2DC65e5b1E1205896BaA2be8A07c6e0"].into(); - - let validator_0_location = MultiLocation { - parents: 1, - interior: X2( - Parachain(2023), - Junction::AccountKey20 { network: Any, key: validator_0_account_id_20 }, - ), - }; - ExtBuilder::default().build().execute_with(|| { // environment setup moonriver_setup(); @@ -310,7 +307,7 @@ fn moonriver_bond_works() { MOVR, Box::new(subaccount_0_location.clone()), 5_000_000_000_000_000_000, - Some(validator_0_location.clone()) + Some(VALIDATOR_0_LOCATION.clone()) ), Error::::XcmFailure ); @@ -319,8 +316,10 @@ fn moonriver_bond_works() { #[test] fn moonriver_bond_extra_works() { + let bifrost_parachain_account_id_20: [u8; 20] = Sibling::from(2001).into_account_truncating(); + let subaccount_0_account_id_20: [u8; 20] = - hex_literal::hex!["863c1faef3c3b8f8735ecb7f8ed18996356dd3de"].into(); + Slp::derivative_account_id_20(bifrost_parachain_account_id_20, 0).into(); let subaccount_0_location = MultiLocation { parents: 1, @@ -330,23 +329,12 @@ fn moonriver_bond_extra_works() { ), }; - let validator_0_account_id_20: [u8; 20] = - hex_literal::hex!["3Cd0A705a2DC65e5b1E1205896BaA2be8A07c6e0"].into(); - - let validator_0_location = MultiLocation { - parents: 1, - interior: X2( - Parachain(2023), - Junction::AccountKey20 { network: Any, key: validator_0_account_id_20 }, - ), - }; - ExtBuilder::default().build().execute_with(|| { // environment setup moonriver_setup(); let mut delegation_set: BTreeMap> = BTreeMap::new(); - delegation_set.insert(validator_0_location.clone(), 5_000_000_000_000_000_000); + delegation_set.insert(VALIDATOR_0_LOCATION.clone(), 5_000_000_000_000_000_000); let request_briefs_set: BTreeMap)> = BTreeMap::new(); @@ -371,7 +359,7 @@ fn moonriver_bond_extra_works() { RuntimeOrigin::signed(ALICE), MOVR, Box::new(subaccount_0_location), - Some(validator_0_location), + Some(VALIDATOR_0_LOCATION), 5_000_000_000_000_000_000, ), Error::::XcmFailure @@ -381,8 +369,10 @@ fn moonriver_bond_extra_works() { #[test] fn moonriver_unbond_works() { + let bifrost_parachain_account_id_20: [u8; 20] = Sibling::from(2001).into_account_truncating(); + let subaccount_0_account_id_20: [u8; 20] = - hex_literal::hex!["863c1faef3c3b8f8735ecb7f8ed18996356dd3de"].into(); + Slp::derivative_account_id_20(bifrost_parachain_account_id_20, 0).into(); let subaccount_0_location = MultiLocation { parents: 1, @@ -392,23 +382,12 @@ fn moonriver_unbond_works() { ), }; - let validator_0_account_id_20: [u8; 20] = - hex_literal::hex!["3Cd0A705a2DC65e5b1E1205896BaA2be8A07c6e0"].into(); - - let validator_0_location = MultiLocation { - parents: 1, - interior: X2( - Parachain(2023), - Junction::AccountKey20 { network: Any, key: validator_0_account_id_20 }, - ), - }; - ExtBuilder::default().build().execute_with(|| { // environment setup moonriver_setup(); let mut delegation_set: BTreeMap> = BTreeMap::new(); - delegation_set.insert(validator_0_location.clone(), 8_000_000_000_000_000_000); + delegation_set.insert(VALIDATOR_0_LOCATION.clone(), 8_000_000_000_000_000_000); let request_briefs_set: BTreeMap)> = BTreeMap::new(); @@ -433,7 +412,7 @@ fn moonriver_unbond_works() { RuntimeOrigin::signed(ALICE), MOVR, Box::new(subaccount_0_location), - Some(validator_0_location), + Some(VALIDATOR_0_LOCATION), 2_000_000_000_000_000_000, ), Error::::XcmFailure @@ -443,8 +422,10 @@ fn moonriver_unbond_works() { #[test] fn moonriver_unbond_all_works() { + let bifrost_parachain_account_id_20: [u8; 20] = Sibling::from(2001).into_account_truncating(); + let subaccount_0_account_id_20: [u8; 20] = - hex_literal::hex!["863c1faef3c3b8f8735ecb7f8ed18996356dd3de"].into(); + Slp::derivative_account_id_20(bifrost_parachain_account_id_20, 0).into(); let subaccount_0_location = MultiLocation { parents: 1, @@ -454,23 +435,12 @@ fn moonriver_unbond_all_works() { ), }; - let validator_0_account_id_20: [u8; 20] = - hex_literal::hex!["3Cd0A705a2DC65e5b1E1205896BaA2be8A07c6e0"].into(); - - let validator_0_location = MultiLocation { - parents: 1, - interior: X2( - Parachain(2023), - Junction::AccountKey20 { network: Any, key: validator_0_account_id_20 }, - ), - }; - ExtBuilder::default().build().execute_with(|| { // environment setup moonriver_setup(); let mut delegation_set: BTreeMap> = BTreeMap::new(); - delegation_set.insert(validator_0_location.clone(), 8_000_000_000_000_000_000); + delegation_set.insert(VALIDATOR_0_LOCATION.clone(), 8_000_000_000_000_000_000); let request_briefs_set: BTreeMap)> = BTreeMap::new(); @@ -499,8 +469,10 @@ fn moonriver_unbond_all_works() { #[test] fn moonriver_rebond_works() { + let bifrost_parachain_account_id_20: [u8; 20] = Sibling::from(2001).into_account_truncating(); + let subaccount_0_account_id_20: [u8; 20] = - hex_literal::hex!["863c1faef3c3b8f8735ecb7f8ed18996356dd3de"].into(); + Slp::derivative_account_id_20(bifrost_parachain_account_id_20, 0).into(); let subaccount_0_location = MultiLocation { parents: 1, @@ -510,26 +482,15 @@ fn moonriver_rebond_works() { ), }; - let validator_0_account_id_20: [u8; 20] = - hex_literal::hex!["3Cd0A705a2DC65e5b1E1205896BaA2be8A07c6e0"].into(); - - let validator_0_location = MultiLocation { - parents: 1, - interior: X2( - Parachain(2023), - Junction::AccountKey20 { network: Any, key: validator_0_account_id_20 }, - ), - }; - ExtBuilder::default().build().execute_with(|| { // environment setup moonriver_setup(); let mut delegation_set: BTreeMap> = BTreeMap::new(); - delegation_set.insert(validator_0_location.clone(), 8_000_000_000_000_000_000); + delegation_set.insert(VALIDATOR_0_LOCATION.clone(), 8_000_000_000_000_000_000); let request = OneToManyScheduledRequest { - validator: validator_0_location.clone(), + validator: VALIDATOR_0_LOCATION.clone(), when_executable: TimeUnit::Round(24), action: OneToManyDelegationAction::Decrease(2_000_000_000_000_000_000), }; @@ -538,7 +499,7 @@ fn moonriver_rebond_works() { let mut request_briefs_set: BTreeMap)> = BTreeMap::new(); request_briefs_set - .insert(validator_0_location.clone(), (TimeUnit::Round(24), 2_000_000_000_000_000_000)); + .insert(VALIDATOR_0_LOCATION.clone(), (TimeUnit::Round(24), 2_000_000_000_000_000_000)); // set delegator_0 ledger let moonriver_ledger = OneToManyLedger { @@ -561,7 +522,7 @@ fn moonriver_rebond_works() { RuntimeOrigin::signed(ALICE), MOVR, Box::new(subaccount_0_location), - Some(validator_0_location.clone()), + Some(VALIDATOR_0_LOCATION.clone()), None ), Error::::XcmFailure @@ -571,8 +532,10 @@ fn moonriver_rebond_works() { #[test] fn moonriver_undelegate_works() { + let bifrost_parachain_account_id_20: [u8; 20] = Sibling::from(2001).into_account_truncating(); + let subaccount_0_account_id_20: [u8; 20] = - hex_literal::hex!["863c1faef3c3b8f8735ecb7f8ed18996356dd3de"].into(); + Slp::derivative_account_id_20(bifrost_parachain_account_id_20, 0).into(); let subaccount_0_location = MultiLocation { parents: 1, @@ -582,35 +545,13 @@ fn moonriver_undelegate_works() { ), }; - let validator_0_account_id_20: [u8; 20] = - hex_literal::hex!["3Cd0A705a2DC65e5b1E1205896BaA2be8A07c6e0"].into(); - - let validator_0_location = MultiLocation { - parents: 1, - interior: X2( - Parachain(2023), - Junction::AccountKey20 { network: Any, key: validator_0_account_id_20 }, - ), - }; - - let validator_1_account_id_20: [u8; 20] = - hex_literal::hex!["f24FF3a9CF04c71Dbc94D0b566f7A27B94566cac"].into(); - - let validator_1_location = MultiLocation { - parents: 1, - interior: X2( - Parachain(2023), - Junction::AccountKey20 { network: Any, key: validator_1_account_id_20 }, - ), - }; - ExtBuilder::default().build().execute_with(|| { // environment setup moonriver_setup(); let mut delegation_set: BTreeMap> = BTreeMap::new(); - delegation_set.insert(validator_0_location.clone(), 5_000_000_000_000_000_000); - delegation_set.insert(validator_1_location.clone(), 5_000_000_000_000_000_000); + delegation_set.insert(VALIDATOR_0_LOCATION.clone(), 5_000_000_000_000_000_000); + delegation_set.insert(VALIDATOR_1_LOCATION.clone(), 5_000_000_000_000_000_000); let request_briefs_set: BTreeMap)> = BTreeMap::new(); @@ -635,7 +576,7 @@ fn moonriver_undelegate_works() { RuntimeOrigin::signed(ALICE), MOVR, Box::new(subaccount_0_location), - vec![validator_0_location], + vec![VALIDATOR_0_LOCATION], ), Error::::XcmFailure ); @@ -644,8 +585,10 @@ fn moonriver_undelegate_works() { #[test] fn moonriver_redelegate_works() { + let bifrost_parachain_account_id_20: [u8; 20] = Sibling::from(2001).into_account_truncating(); + let subaccount_0_account_id_20: [u8; 20] = - hex_literal::hex!["863c1faef3c3b8f8735ecb7f8ed18996356dd3de"].into(); + Slp::derivative_account_id_20(bifrost_parachain_account_id_20, 0).into(); let subaccount_0_location = MultiLocation { parents: 1, @@ -655,26 +598,15 @@ fn moonriver_redelegate_works() { ), }; - let validator_0_account_id_20: [u8; 20] = - hex_literal::hex!["3Cd0A705a2DC65e5b1E1205896BaA2be8A07c6e0"].into(); - - let validator_0_location = MultiLocation { - parents: 1, - interior: X2( - Parachain(2023), - Junction::AccountKey20 { network: Any, key: validator_0_account_id_20 }, - ), - }; - ExtBuilder::default().build().execute_with(|| { // environment setup moonriver_setup(); let mut delegation_set: BTreeMap> = BTreeMap::new(); - delegation_set.insert(validator_0_location.clone(), 8_000_000_000_000_000_000); + delegation_set.insert(VALIDATOR_0_LOCATION.clone(), 8_000_000_000_000_000_000); let request = OneToManyScheduledRequest { - validator: validator_0_location.clone(), + validator: VALIDATOR_0_LOCATION.clone(), when_executable: TimeUnit::Round(24), action: OneToManyDelegationAction::Revoke(8_000_000_000_000_000_000), }; @@ -683,7 +615,7 @@ fn moonriver_redelegate_works() { let mut request_briefs_set: BTreeMap)> = BTreeMap::new(); request_briefs_set - .insert(validator_0_location.clone(), (TimeUnit::Round(24), 8_000_000_000_000_000_000)); + .insert(VALIDATOR_0_LOCATION.clone(), (TimeUnit::Round(24), 8_000_000_000_000_000_000)); // set delegator_0 ledger let moonriver_ledger = OneToManyLedger { @@ -715,8 +647,10 @@ fn moonriver_redelegate_works() { #[test] fn moonriver_liquidize_works() { + let bifrost_parachain_account_id_20: [u8; 20] = Sibling::from(2001).into_account_truncating(); + let subaccount_0_account_id_20: [u8; 20] = - hex_literal::hex!["863c1faef3c3b8f8735ecb7f8ed18996356dd3de"].into(); + Slp::derivative_account_id_20(bifrost_parachain_account_id_20, 0).into(); let subaccount_0_location = MultiLocation { parents: 1, @@ -726,26 +660,15 @@ fn moonriver_liquidize_works() { ), }; - let validator_0_account_id_20: [u8; 20] = - hex_literal::hex!["3Cd0A705a2DC65e5b1E1205896BaA2be8A07c6e0"].into(); - - let validator_0_location = MultiLocation { - parents: 1, - interior: X2( - Parachain(2023), - Junction::AccountKey20 { network: Any, key: validator_0_account_id_20 }, - ), - }; - ExtBuilder::default().build().execute_with(|| { // environment setup moonriver_setup(); let mut delegation_set: BTreeMap> = BTreeMap::new(); - delegation_set.insert(validator_0_location.clone(), 10_000_000_000_000_000_000); + delegation_set.insert(VALIDATOR_0_LOCATION.clone(), 10_000_000_000_000_000_000); let request = OneToManyScheduledRequest { - validator: validator_0_location.clone(), + validator: VALIDATOR_0_LOCATION.clone(), when_executable: TimeUnit::Round(24), action: OneToManyDelegationAction::Decrease(2_000_000_000_000_000_000), }; @@ -756,7 +679,7 @@ fn moonriver_liquidize_works() { let mut request_briefs_set: BTreeMap)> = BTreeMap::new(); request_briefs_set - .insert(validator_0_location.clone(), (TimeUnit::Round(24), 2_000_000_000_000_000_000)); + .insert(VALIDATOR_0_LOCATION.clone(), (TimeUnit::Round(24), 2_000_000_000_000_000_000)); // set delegator_0 ledger let moonriver_ledger = OneToManyLedger { @@ -780,7 +703,7 @@ fn moonriver_liquidize_works() { MOVR, Box::new(subaccount_0_location.clone()), None, - Some(validator_0_location.clone()), + Some(VALIDATOR_0_LOCATION.clone()), None ), Error::::RequestNotDue @@ -800,17 +723,17 @@ fn moonriver_liquidize_works() { MOVR, Box::new(subaccount_0_location.clone()), None, - Some(validator_0_location.clone()), + Some(VALIDATOR_0_LOCATION.clone()), None ), Error::::XcmFailure ); let mut delegation_set: BTreeMap> = BTreeMap::new(); - delegation_set.insert(validator_0_location.clone(), 10_000_000_000_000_000_000); + delegation_set.insert(VALIDATOR_0_LOCATION.clone(), 10_000_000_000_000_000_000); let request = OneToManyScheduledRequest { - validator: validator_0_location.clone(), + validator: VALIDATOR_0_LOCATION.clone(), when_executable: TimeUnit::Round(50), action: OneToManyDelegationAction::Revoke(10_000_000_000_000_000_000), }; @@ -821,7 +744,7 @@ fn moonriver_liquidize_works() { let mut request_briefs_set: BTreeMap)> = BTreeMap::new(); request_briefs_set.insert( - validator_0_location.clone(), + VALIDATOR_0_LOCATION.clone(), (TimeUnit::Round(50), 10_000_000_000_000_000_000), ); @@ -847,7 +770,7 @@ fn moonriver_liquidize_works() { MOVR, Box::new(subaccount_0_location.clone()), None, - Some(validator_0_location.clone()), + Some(VALIDATOR_0_LOCATION.clone()), None ), Error::::LeavingNotDue @@ -867,7 +790,7 @@ fn moonriver_liquidize_works() { MOVR, Box::new(subaccount_0_location), None, - Some(validator_0_location), + Some(VALIDATOR_0_LOCATION), None ), Error::::XcmFailure @@ -877,9 +800,10 @@ fn moonriver_liquidize_works() { #[test] fn moonriver_bond_and_bond_extra_confirm_works() { - let subaccount_0_account_id_20: [u8; 20] = - hex_literal::hex!["863c1faef3c3b8f8735ecb7f8ed18996356dd3de"].into(); + let bifrost_parachain_account_id_20: [u8; 20] = Sibling::from(2001).into_account_truncating(); + let subaccount_0_account_id_20: [u8; 20] = + Slp::derivative_account_id_20(bifrost_parachain_account_id_20, 0).into(); let subaccount_0_location = MultiLocation { parents: 1, interior: X2( @@ -888,17 +812,6 @@ fn moonriver_bond_and_bond_extra_confirm_works() { ), }; - let validator_0_account_id_20: [u8; 20] = - hex_literal::hex!["3Cd0A705a2DC65e5b1E1205896BaA2be8A07c6e0"].into(); - - let validator_0_location = MultiLocation { - parents: 1, - interior: X2( - Parachain(2023), - Junction::AccountKey20 { network: Any, key: validator_0_account_id_20 }, - ), - }; - ExtBuilder::default().build().execute_with(|| { // environment setup moonriver_setup(); @@ -927,7 +840,7 @@ fn moonriver_bond_and_bond_extra_confirm_works() { let update_entry = LedgerUpdateEntry::Moonbeam(MoonbeamLedgerUpdateEntry { currency_id: MOVR, delegator_id: subaccount_0_location.clone(), - validator_id: Some(validator_0_location.clone()), + validator_id: Some(VALIDATOR_0_LOCATION.clone()), update_operation: MoonbeamLedgerUpdateOperation::Bond, amount: 5_000_000_000_000_000_000, unlock_time: None, @@ -949,7 +862,7 @@ fn moonriver_bond_and_bond_extra_confirm_works() { assert_eq!(DelegatorLedgerXcmUpdateQueue::::get(query_id), None); let mut delegation_set: BTreeMap> = BTreeMap::new(); - delegation_set.insert(validator_0_location.clone(), 5_000_000_000_000_000_000); + delegation_set.insert(VALIDATOR_0_LOCATION.clone(), 5_000_000_000_000_000_000); let request_briefs_set: BTreeMap)> = BTreeMap::new(); @@ -976,7 +889,7 @@ fn moonriver_bond_and_bond_extra_confirm_works() { let update_entry_1 = LedgerUpdateEntry::Moonbeam(MoonbeamLedgerUpdateEntry { currency_id: MOVR, delegator_id: subaccount_0_location.clone(), - validator_id: Some(validator_0_location.clone()), + validator_id: Some(VALIDATOR_0_LOCATION.clone()), update_operation: MoonbeamLedgerUpdateOperation::Bond, amount: 5_000_000_000_000_000_000, unlock_time: None, @@ -998,7 +911,7 @@ fn moonriver_bond_and_bond_extra_confirm_works() { assert_eq!(DelegatorLedgerXcmUpdateQueue::::get(query_id), None); let mut delegation_set: BTreeMap> = BTreeMap::new(); - delegation_set.insert(validator_0_location.clone(), 10_000_000_000_000_000_000); + delegation_set.insert(VALIDATOR_0_LOCATION.clone(), 10_000_000_000_000_000_000); let request_briefs_set: BTreeMap)> = BTreeMap::new(); @@ -1024,8 +937,10 @@ fn moonriver_bond_and_bond_extra_confirm_works() { #[test] fn moonriver_unbond_confirm_works() { + let bifrost_parachain_account_id_20: [u8; 20] = Sibling::from(2001).into_account_truncating(); + let subaccount_0_account_id_20: [u8; 20] = - hex_literal::hex!["863c1faef3c3b8f8735ecb7f8ed18996356dd3de"].into(); + Slp::derivative_account_id_20(bifrost_parachain_account_id_20, 0).into(); let subaccount_0_location = MultiLocation { parents: 1, @@ -1035,23 +950,12 @@ fn moonriver_unbond_confirm_works() { ), }; - let validator_0_account_id_20: [u8; 20] = - hex_literal::hex!["3Cd0A705a2DC65e5b1E1205896BaA2be8A07c6e0"].into(); - - let validator_0_location = MultiLocation { - parents: 1, - interior: X2( - Parachain(2023), - Junction::AccountKey20 { network: Any, key: validator_0_account_id_20 }, - ), - }; - ExtBuilder::default().build().execute_with(|| { // environment setup moonriver_setup(); let mut delegation_set: BTreeMap> = BTreeMap::new(); - delegation_set.insert(validator_0_location.clone(), 10_000_000_000_000_000_000); + delegation_set.insert(VALIDATOR_0_LOCATION.clone(), 10_000_000_000_000_000_000); let request_briefs_set: BTreeMap)> = BTreeMap::new(); @@ -1081,7 +985,7 @@ fn moonriver_unbond_confirm_works() { let update_entry_2 = LedgerUpdateEntry::Moonbeam(MoonbeamLedgerUpdateEntry { currency_id: MOVR, delegator_id: subaccount_0_location.clone(), - validator_id: Some(validator_0_location.clone()), + validator_id: Some(VALIDATOR_0_LOCATION.clone()), update_operation: MoonbeamLedgerUpdateOperation::BondLess, amount: 2_000_000_000_000_000_000, unlock_time: Some(TimeUnit::Round(24)), @@ -1103,9 +1007,9 @@ fn moonriver_unbond_confirm_works() { assert_eq!(DelegatorLedgerXcmUpdateQueue::::get(query_id), None); let mut delegation_set: BTreeMap> = BTreeMap::new(); - delegation_set.insert(validator_0_location.clone(), 10_000_000_000_000_000_000); + delegation_set.insert(VALIDATOR_0_LOCATION.clone(), 10_000_000_000_000_000_000); let request = OneToManyScheduledRequest { - validator: validator_0_location.clone(), + validator: VALIDATOR_0_LOCATION.clone(), when_executable: TimeUnit::Round(24), action: OneToManyDelegationAction::Decrease(2_000_000_000_000_000_000), }; @@ -1114,7 +1018,7 @@ fn moonriver_unbond_confirm_works() { let mut request_briefs_set: BTreeMap)> = BTreeMap::new(); request_briefs_set - .insert(validator_0_location.clone(), (TimeUnit::Round(24), 2_000_000_000_000_000_000)); + .insert(VALIDATOR_0_LOCATION.clone(), (TimeUnit::Round(24), 2_000_000_000_000_000_000)); // set delegator_0 ledger let moonriver_ledger = OneToManyLedger { @@ -1139,7 +1043,7 @@ fn moonriver_unbond_confirm_works() { let update_entry_3 = LedgerUpdateEntry::Moonbeam(MoonbeamLedgerUpdateEntry { currency_id: MOVR, delegator_id: subaccount_0_location.clone(), - validator_id: Some(validator_0_location.clone()), + validator_id: Some(VALIDATOR_0_LOCATION.clone()), update_operation: MoonbeamLedgerUpdateOperation::ExecuteRequest, amount: 0, unlock_time: Some(TimeUnit::Round(0)), @@ -1182,7 +1086,7 @@ fn moonriver_unbond_confirm_works() { let update_entry_4 = LedgerUpdateEntry::Moonbeam(MoonbeamLedgerUpdateEntry { currency_id: MOVR, delegator_id: subaccount_0_location.clone(), - validator_id: Some(validator_0_location.clone()), + validator_id: Some(VALIDATOR_0_LOCATION.clone()), update_operation: MoonbeamLedgerUpdateOperation::ExecuteRequest, amount: 0, unlock_time: Some(TimeUnit::Round(24)), @@ -1204,7 +1108,7 @@ fn moonriver_unbond_confirm_works() { assert_eq!(DelegatorLedgerXcmUpdateQueue::::get(query_id), None); let mut delegation_set: BTreeMap> = BTreeMap::new(); - delegation_set.insert(validator_0_location.clone(), 8_000_000_000_000_000_000); + delegation_set.insert(VALIDATOR_0_LOCATION.clone(), 8_000_000_000_000_000_000); let request_briefs_set: BTreeMap)> = BTreeMap::new(); @@ -1230,8 +1134,10 @@ fn moonriver_unbond_confirm_works() { #[test] fn moonriver_unbond_all_confirm_works() { + let bifrost_parachain_account_id_20: [u8; 20] = Sibling::from(2001).into_account_truncating(); + let subaccount_0_account_id_20: [u8; 20] = - hex_literal::hex!["863c1faef3c3b8f8735ecb7f8ed18996356dd3de"].into(); + Slp::derivative_account_id_20(bifrost_parachain_account_id_20, 0).into(); let subaccount_0_location = MultiLocation { parents: 1, @@ -1241,24 +1147,13 @@ fn moonriver_unbond_all_confirm_works() { ), }; - let validator_0_account_id_20: [u8; 20] = - hex_literal::hex!["3Cd0A705a2DC65e5b1E1205896BaA2be8A07c6e0"].into(); - - let validator_0_location = MultiLocation { - parents: 1, - interior: X2( - Parachain(2023), - Junction::AccountKey20 { network: Any, key: validator_0_account_id_20 }, - ), - }; - ExtBuilder::default().build().execute_with(|| { // environment setup moonriver_setup(); // unbond_all confirm // schedule leave let mut delegation_set: BTreeMap> = BTreeMap::new(); - delegation_set.insert(validator_0_location.clone(), 8_000_000_000_000_000_000); + delegation_set.insert(VALIDATOR_0_LOCATION.clone(), 8_000_000_000_000_000_000); let request_briefs_set: BTreeMap)> = BTreeMap::new(); @@ -1329,7 +1224,7 @@ fn moonriver_unbond_all_confirm_works() { let update_entry_6 = LedgerUpdateEntry::Moonbeam(MoonbeamLedgerUpdateEntry { currency_id: MOVR, delegator_id: subaccount_0_location.clone(), - validator_id: Some(validator_0_location.clone()), + validator_id: Some(VALIDATOR_0_LOCATION.clone()), update_operation: MoonbeamLedgerUpdateOperation::ExecuteLeave, amount: 0, unlock_time: Some(TimeUnit::Round(48)), @@ -1373,8 +1268,10 @@ fn moonriver_unbond_all_confirm_works() { #[test] fn moonriver_rebond_confirm_works() { + let bifrost_parachain_account_id_20: [u8; 20] = Sibling::from(2001).into_account_truncating(); + let subaccount_0_account_id_20: [u8; 20] = - hex_literal::hex!["863c1faef3c3b8f8735ecb7f8ed18996356dd3de"].into(); + Slp::derivative_account_id_20(bifrost_parachain_account_id_20, 0).into(); let subaccount_0_location = MultiLocation { parents: 1, @@ -1384,26 +1281,15 @@ fn moonriver_rebond_confirm_works() { ), }; - let validator_0_account_id_20: [u8; 20] = - hex_literal::hex!["3Cd0A705a2DC65e5b1E1205896BaA2be8A07c6e0"].into(); - - let validator_0_location = MultiLocation { - parents: 1, - interior: X2( - Parachain(2023), - Junction::AccountKey20 { network: Any, key: validator_0_account_id_20 }, - ), - }; - ExtBuilder::default().build().execute_with(|| { // environment setup moonriver_setup(); // confirm rebond let mut delegation_set: BTreeMap> = BTreeMap::new(); - delegation_set.insert(validator_0_location.clone(), 10_000_000_000_000_000_000); + delegation_set.insert(VALIDATOR_0_LOCATION.clone(), 10_000_000_000_000_000_000); let request = OneToManyScheduledRequest { - validator: validator_0_location.clone(), + validator: VALIDATOR_0_LOCATION.clone(), when_executable: TimeUnit::Round(24), action: OneToManyDelegationAction::Decrease(2_000_000_000_000_000_000), }; @@ -1412,7 +1298,7 @@ fn moonriver_rebond_confirm_works() { let mut request_briefs_set: BTreeMap)> = BTreeMap::new(); request_briefs_set - .insert(validator_0_location.clone(), (TimeUnit::Round(24), 2_000_000_000_000_000_000)); + .insert(VALIDATOR_0_LOCATION.clone(), (TimeUnit::Round(24), 2_000_000_000_000_000_000)); // set delegator_0 ledger let moonriver_ledger = OneToManyLedger { @@ -1437,7 +1323,7 @@ fn moonriver_rebond_confirm_works() { let update_entry_7 = LedgerUpdateEntry::Moonbeam(MoonbeamLedgerUpdateEntry { currency_id: MOVR, delegator_id: subaccount_0_location.clone(), - validator_id: Some(validator_0_location.clone()), + validator_id: Some(VALIDATOR_0_LOCATION.clone()), update_operation: MoonbeamLedgerUpdateOperation::CancelRequest, amount: 0, unlock_time: Some(TimeUnit::Round(48)), @@ -1459,7 +1345,7 @@ fn moonriver_rebond_confirm_works() { assert_eq!(DelegatorLedgerXcmUpdateQueue::::get(query_id), None); let mut delegation_set: BTreeMap> = BTreeMap::new(); - delegation_set.insert(validator_0_location.clone(), 10_000_000_000_000_000_000); + delegation_set.insert(VALIDATOR_0_LOCATION.clone(), 10_000_000_000_000_000_000); let request_briefs_set: BTreeMap)> = BTreeMap::new(); @@ -1485,8 +1371,10 @@ fn moonriver_rebond_confirm_works() { #[test] fn moonriver_undelegate_confirm_works() { + let bifrost_parachain_account_id_20: [u8; 20] = Sibling::from(2001).into_account_truncating(); + let subaccount_0_account_id_20: [u8; 20] = - hex_literal::hex!["863c1faef3c3b8f8735ecb7f8ed18996356dd3de"].into(); + Slp::derivative_account_id_20(bifrost_parachain_account_id_20, 0).into(); let subaccount_0_location = MultiLocation { parents: 1, @@ -1496,35 +1384,13 @@ fn moonriver_undelegate_confirm_works() { ), }; - let validator_0_account_id_20: [u8; 20] = - hex_literal::hex!["3Cd0A705a2DC65e5b1E1205896BaA2be8A07c6e0"].into(); - - let validator_0_location = MultiLocation { - parents: 1, - interior: X2( - Parachain(2023), - Junction::AccountKey20 { network: Any, key: validator_0_account_id_20 }, - ), - }; - - let validator_1_account_id_20: [u8; 20] = - hex_literal::hex!["f24FF3a9CF04c71Dbc94D0b566f7A27B94566cac"].into(); - - let validator_1_location = MultiLocation { - parents: 1, - interior: X2( - Parachain(2023), - Junction::AccountKey20 { network: Any, key: validator_1_account_id_20 }, - ), - }; - ExtBuilder::default().build().execute_with(|| { // environment setup moonriver_setup(); // undelegate confirm let mut delegation_set: BTreeMap> = BTreeMap::new(); - delegation_set.insert(validator_0_location.clone(), 5_000_000_000_000_000_000); - delegation_set.insert(validator_1_location.clone(), 5_000_000_000_000_000_000); + delegation_set.insert(VALIDATOR_0_LOCATION.clone(), 5_000_000_000_000_000_000); + delegation_set.insert(VALIDATOR_1_LOCATION.clone(), 5_000_000_000_000_000_000); let request_briefs_set: BTreeMap)> = BTreeMap::new(); @@ -1548,7 +1414,7 @@ fn moonriver_undelegate_confirm_works() { let update_entry_8 = LedgerUpdateEntry::Moonbeam(MoonbeamLedgerUpdateEntry { currency_id: MOVR, delegator_id: subaccount_0_location.clone(), - validator_id: Some(validator_0_location.clone()), + validator_id: Some(VALIDATOR_0_LOCATION.clone()), update_operation: MoonbeamLedgerUpdateOperation::Revoke, amount: 0, unlock_time: Some(TimeUnit::Round(24)), @@ -1570,11 +1436,11 @@ fn moonriver_undelegate_confirm_works() { assert_eq!(DelegatorLedgerXcmUpdateQueue::::get(query_id), None); let mut delegation_set: BTreeMap> = BTreeMap::new(); - delegation_set.insert(validator_0_location.clone(), 5_000_000_000_000_000_000); - delegation_set.insert(validator_1_location.clone(), 5_000_000_000_000_000_000); + delegation_set.insert(VALIDATOR_0_LOCATION.clone(), 5_000_000_000_000_000_000); + delegation_set.insert(VALIDATOR_1_LOCATION.clone(), 5_000_000_000_000_000_000); let request = OneToManyScheduledRequest { - validator: validator_0_location.clone(), + validator: VALIDATOR_0_LOCATION.clone(), when_executable: TimeUnit::Round(24), action: OneToManyDelegationAction::::Revoke(5_000_000_000_000_000_000), }; @@ -1584,7 +1450,7 @@ fn moonriver_undelegate_confirm_works() { let mut request_briefs_set: BTreeMap)> = BTreeMap::new(); request_briefs_set - .insert(validator_0_location.clone(), (TimeUnit::Round(24), 5_000_000_000_000_000_000)); + .insert(VALIDATOR_0_LOCATION.clone(), (TimeUnit::Round(24), 5_000_000_000_000_000_000)); // set delegator_0 ledger let moonriver_ledger = OneToManyLedger { @@ -1609,7 +1475,7 @@ fn moonriver_undelegate_confirm_works() { let update_entry_9 = LedgerUpdateEntry::Moonbeam(MoonbeamLedgerUpdateEntry { currency_id: MOVR, delegator_id: subaccount_0_location.clone(), - validator_id: Some(validator_0_location.clone()), + validator_id: Some(VALIDATOR_0_LOCATION.clone()), update_operation: MoonbeamLedgerUpdateOperation::ExecuteRequest, amount: 0, unlock_time: Some(TimeUnit::Round(21)), @@ -1635,7 +1501,7 @@ fn moonriver_undelegate_confirm_works() { let update_entry_10 = LedgerUpdateEntry::Moonbeam(MoonbeamLedgerUpdateEntry { currency_id: MOVR, delegator_id: subaccount_0_location.clone(), - validator_id: Some(validator_0_location.clone()), + validator_id: Some(VALIDATOR_0_LOCATION.clone()), update_operation: MoonbeamLedgerUpdateOperation::ExecuteRequest, amount: 0, unlock_time: Some(TimeUnit::Round(24)), @@ -1657,7 +1523,7 @@ fn moonriver_undelegate_confirm_works() { assert_eq!(DelegatorLedgerXcmUpdateQueue::::get(query_id), None); let mut delegation_set: BTreeMap> = BTreeMap::new(); - delegation_set.insert(validator_1_location.clone(), 5_000_000_000_000_000_000); + delegation_set.insert(VALIDATOR_1_LOCATION.clone(), 5_000_000_000_000_000_000); let request_briefs_set: BTreeMap)> = BTreeMap::new(); @@ -1683,8 +1549,10 @@ fn moonriver_undelegate_confirm_works() { #[test] fn moonriver_redelegate_confirm_works() { + let bifrost_parachain_account_id_20: [u8; 20] = Sibling::from(2001).into_account_truncating(); + let subaccount_0_account_id_20: [u8; 20] = - hex_literal::hex!["863c1faef3c3b8f8735ecb7f8ed18996356dd3de"].into(); + Slp::derivative_account_id_20(bifrost_parachain_account_id_20, 0).into(); let subaccount_0_location = MultiLocation { parents: 1, @@ -1694,26 +1562,15 @@ fn moonriver_redelegate_confirm_works() { ), }; - let validator_0_account_id_20: [u8; 20] = - hex_literal::hex!["3Cd0A705a2DC65e5b1E1205896BaA2be8A07c6e0"].into(); - - let validator_0_location = MultiLocation { - parents: 1, - interior: X2( - Parachain(2023), - Junction::AccountKey20 { network: Any, key: validator_0_account_id_20 }, - ), - }; - ExtBuilder::default().build().execute_with(|| { // environment setup moonriver_setup(); let mut delegation_set: BTreeMap> = BTreeMap::new(); - delegation_set.insert(validator_0_location.clone(), 8_000_000_000_000_000_000); + delegation_set.insert(VALIDATOR_0_LOCATION.clone(), 8_000_000_000_000_000_000); let request = OneToManyScheduledRequest { - validator: validator_0_location.clone(), + validator: VALIDATOR_0_LOCATION.clone(), when_executable: TimeUnit::Round(24), action: OneToManyDelegationAction::Revoke(8_000_000_000_000_000_000), }; @@ -1722,7 +1579,7 @@ fn moonriver_redelegate_confirm_works() { let mut request_briefs_set: BTreeMap)> = BTreeMap::new(); request_briefs_set - .insert(validator_0_location.clone(), (TimeUnit::Round(24), 8_000_000_000_000_000_000)); + .insert(VALIDATOR_0_LOCATION.clone(), (TimeUnit::Round(24), 8_000_000_000_000_000_000)); // set delegator_0 ledger let moonriver_ledger = OneToManyLedger { @@ -1776,7 +1633,7 @@ fn moonriver_redelegate_confirm_works() { assert_eq!(DelegatorLedgerXcmUpdateQueue::::get(query_id), None); let mut delegation_set: BTreeMap> = BTreeMap::new(); - delegation_set.insert(validator_0_location.clone(), 8_000_000_000_000_000_000); + delegation_set.insert(VALIDATOR_0_LOCATION.clone(), 8_000_000_000_000_000_000); let request_briefs_set: BTreeMap)> = BTreeMap::new(); @@ -1802,8 +1659,10 @@ fn moonriver_redelegate_confirm_works() { #[test] fn moonriver_transfer_back_works() { + let bifrost_parachain_account_id_20: [u8; 20] = Sibling::from(2001).into_account_truncating(); + let subaccount_0_account_id_20: [u8; 20] = - hex_literal::hex!["863c1faef3c3b8f8735ecb7f8ed18996356dd3de"].into(); + Slp::derivative_account_id_20(bifrost_parachain_account_id_20, 0).into(); let subaccount_0_location = MultiLocation { parents: 1, @@ -1816,9 +1675,7 @@ fn moonriver_transfer_back_works() { ExtBuilder::default().build().execute_with(|| { // environment setup moonriver_setup(); - let exit_account_id_32: [u8; 32] = - hex_literal::hex!["6d6f646c62662f76746f75740000000000000000000000000000000000000000"] - .into(); + let exit_account_id_32: [u8; 32] = PalletId(*b"bf/vtout").into_account_truncating(); let exit_account_location = MultiLocation { parents: 0, @@ -1840,8 +1697,10 @@ fn moonriver_transfer_back_works() { #[test] fn moonriver_transfer_to_works() { + let bifrost_parachain_account_id_20: [u8; 20] = Sibling::from(2001).into_account_truncating(); + let subaccount_0_account_id_20: [u8; 20] = - hex_literal::hex!["863c1faef3c3b8f8735ecb7f8ed18996356dd3de"].into(); + Slp::derivative_account_id_20(bifrost_parachain_account_id_20, 0).into(); let subaccount_0_location = MultiLocation { parents: 1, @@ -1854,9 +1713,7 @@ fn moonriver_transfer_to_works() { ExtBuilder::default().build().execute_with(|| { // environment setup moonriver_setup(); - let entrance_account_id_32: [u8; 32] = - hex_literal::hex!["6d6f646c62662f76746b696e0000000000000000000000000000000000000000"] - .into(); + let entrance_account_id_32: [u8; 32] = PalletId(*b"bf/vtkin").into_account_truncating(); let entrance_account_location = MultiLocation { parents: 0, @@ -1878,8 +1735,10 @@ fn moonriver_transfer_to_works() { #[test] fn supplement_fee_account_whitelist_works() { + let bifrost_parachain_account_id_20: [u8; 20] = Sibling::from(2001).into_account_truncating(); + let subaccount_0_account_id_20: [u8; 20] = - hex_literal::hex!["863c1faef3c3b8f8735ecb7f8ed18996356dd3de"].into(); + Slp::derivative_account_id_20(bifrost_parachain_account_id_20, 0).into(); let subaccount_0_location = MultiLocation { parents: 1, @@ -1892,31 +1751,21 @@ fn supplement_fee_account_whitelist_works() { ExtBuilder::default().build().execute_with(|| { // environment setup moonriver_setup(); - let entrance_account_id: AccountId = - hex_literal::hex!["6d6f646c62662f76746b696e0000000000000000000000000000000000000000"] - .into(); - - let entrance_account_id_32: [u8; 32] = - hex_literal::hex!["6d6f646c62662f76746b696e0000000000000000000000000000000000000000"] - .into(); + let entrance_account_id_32: [u8; 32] = PalletId(*b"bf/vtkin").into_account_truncating(); + let entrance_account_id: AccountId = entrance_account_id_32.into(); let entrance_account_location = MultiLocation { parents: 0, interior: X1(Junction::AccountId32 { network: Any, id: entrance_account_id_32 }), }; - let exit_account_id_32: [u8; 32] = - hex_literal::hex!["6d6f646c62662f76746f75740000000000000000000000000000000000000000"] - .into(); - + let exit_account_id_32: [u8; 32] = PalletId(*b"bf/vtout").into_account_truncating(); let exit_account_location = MultiLocation { parents: 0, interior: X1(Junction::AccountId32 { network: Any, id: exit_account_id_32 }), }; - let source_account_id_32: [u8; 32] = - hex_literal::hex!["d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d"] - .into(); + let source_account_id_32: [u8; 32] = ALICE.into(); let source_location = Slp::account_32_to_local_location(source_account_id_32).unwrap(); assert_ok!(Slp::set_fee_source( RuntimeOrigin::signed(ALICE), @@ -2004,8 +1853,10 @@ fn supplement_fee_account_whitelist_works() { #[test] fn charge_host_fee_and_tune_vtoken_exchange_rate_works() { + let bifrost_parachain_account_id_20: [u8; 20] = Sibling::from(2001).into_account_truncating(); + let subaccount_0_account_id_20: [u8; 20] = - hex_literal::hex!["863c1faef3c3b8f8735ecb7f8ed18996356dd3de"].into(); + Slp::derivative_account_id_20(bifrost_parachain_account_id_20, 0).into(); let subaccount_0_location = MultiLocation { parents: 1, @@ -2015,23 +1866,9 @@ fn charge_host_fee_and_tune_vtoken_exchange_rate_works() { ), }; - let validator_0_account_id_20: [u8; 20] = - hex_literal::hex!["3Cd0A705a2DC65e5b1E1205896BaA2be8A07c6e0"].into(); - - let validator_0_location = MultiLocation { - parents: 1, - interior: X2( - Parachain(2023), - Junction::AccountKey20 { network: Any, key: validator_0_account_id_20 }, - ), - }; - ExtBuilder::default().build().execute_with(|| { - let treasury_id: AccountId = - hex_literal::hex!["6d6f646c62662f74727372790000000000000000000000000000000000000000"] - .into(); - let treasury_32: [u8; 32] = - hex_literal::hex!["6d6f646c62662f74727372790000000000000000000000000000000000000000"]; + let treasury_id: AccountId = PalletId(*b"bf/trsry").into_account_truncating(); + let treasury_32: [u8; 32] = treasury_id.clone().into(); // moonriver_setup(); @@ -2058,7 +1895,7 @@ fn charge_host_fee_and_tune_vtoken_exchange_rate_works() { MinimumsAndMaximums::::insert(MOVR, mins_and_maxs); let mut delegation_set: BTreeMap> = BTreeMap::new(); - delegation_set.insert(validator_0_location.clone(), 5_000_000_000_000_000_000); + delegation_set.insert(VALIDATOR_0_LOCATION.clone(), 5_000_000_000_000_000_000); let request_briefs_set: BTreeMap)> = BTreeMap::new(); @@ -2129,21 +1966,10 @@ fn charge_host_fee_and_tune_vtoken_exchange_rate_works() { #[test] fn add_validator_and_remove_validator_works() { - let validator_0_account_id_20: [u8; 20] = - hex_literal::hex!["3Cd0A705a2DC65e5b1E1205896BaA2be8A07c6e0"].into(); - - let validator_0_location = MultiLocation { - parents: 1, - interior: X2( - Parachain(2023), - Junction::AccountKey20 { network: Any, key: validator_0_account_id_20 }, - ), - }; - ExtBuilder::default().build().execute_with(|| { let mut valis = vec![]; let multi_hash_0 = - ::Hashing::hash(&validator_0_location.encode()); + ::Hashing::hash(&VALIDATOR_0_LOCATION.encode()); let mins_and_maxs = MinimumsMaximums { delegator_bonded_minimum: 100_000_000_000, @@ -2170,18 +1996,18 @@ fn add_validator_and_remove_validator_works() { assert_ok!(Slp::add_validator( RuntimeOrigin::signed(ALICE), MOVR, - Box::new(validator_0_location.clone()), + Box::new(VALIDATOR_0_LOCATION.clone()), )); // The storage is reordered by hash. So we need to adjust the push order here. - valis.push((validator_0_location.clone(), multi_hash_0)); + valis.push((VALIDATOR_0_LOCATION.clone(), multi_hash_0)); assert_eq!(Slp::get_validators(MOVR), Some(valis)); assert_ok!(Slp::remove_validator( RuntimeOrigin::signed(ALICE), MOVR, - Box::new(validator_0_location.clone()), + Box::new(VALIDATOR_0_LOCATION.clone()), )); assert_eq!(Slp::get_validators(MOVR), Some(vec![])); diff --git a/pallets/slp/src/tests/parachain_staking_tests.rs b/pallets/slp/src/tests/parachain_staking_tests.rs index 329f0f7ce..ba1fe7ba8 100644 --- a/pallets/slp/src/tests/parachain_staking_tests.rs +++ b/pallets/slp/src/tests/parachain_staking_tests.rs @@ -31,6 +31,8 @@ use crate::{ BNC, }; use codec::alloc::collections::BTreeMap; +use frame_support::PalletId; +use sp_runtime::traits::AccountIdConversion; #[test] fn initialize_parachain_staking_delegator() { @@ -65,9 +67,7 @@ fn parachain_staking_setup() { let validator_0_location = MultiLocation { parents: 0, interior: X1(AccountId32 { network: Any, id: BOB.into() }) }; - let treasury_account_id_32: [u8; 32] = - hex_literal::hex!["6d6f646c62662f74727372790000000000000000000000000000000000000000"] - .into(); + let treasury_account_id_32: [u8; 32] = PalletId(*b"bf/trsry").into_account_truncating(); let treasury_location = MultiLocation { parents: 0, interior: X1(AccountId32 { network: Any, id: treasury_account_id_32 }), @@ -262,9 +262,7 @@ fn parachain_staking_bond_to_liquidize_works() { 10_000_000u32 )); - let entrance_account_id_32: [u8; 32] = - hex_literal::hex!["6d6f646c62662f76746b696e0000000000000000000000000000000000000000"] - .into(); + let entrance_account_id_32: [u8; 32] = PalletId(*b"bf/vtkin").into_account_truncating(); let entrance_account_location = MultiLocation { parents: 0, @@ -313,6 +311,7 @@ fn parachain_staking_bond_to_liquidize_works() { let mut request_list = Vec::new(); + // random account to test ordering let validator_10: [u8; 32] = hex_literal::hex!["6d6f646c62662f76746b696e0000000000000000000000000000000000000000"] .into(); @@ -325,6 +324,8 @@ fn parachain_staking_bond_to_liquidize_works() { when_executable: TimeUnit::Round(50), action: OneToManyDelegationAction::Revoke(10_000_000_000_000), }; + + // random account to test ordering let validator_11: [u8; 32] = hex_literal::hex!["624d6a004c72a1abcf93131e185515ebe1410e43a301fe1f25d20d8da345376e"] .into(); @@ -853,9 +854,7 @@ fn parachain_staking_transfer_back_works() { ExtBuilder::default().build().execute_with(|| { // environment setup parachain_staking_setup(); - let exit_account_id_32: [u8; 32] = - hex_literal::hex!["6d6f646c62662f76746f75740000000000000000000000000000000000000000"] - .into(); + let exit_account_id_32: [u8; 32] = PalletId(*b"bf/vtout").into_account_truncating(); let exit_account_location = MultiLocation { parents: 0, @@ -893,9 +892,7 @@ fn parachain_staking_transfer_to_works() { // environment setup parachain_staking_setup(); - let entrance_account_id_32: [u8; 32] = - hex_literal::hex!["6d6f646c62662f76746b696e0000000000000000000000000000000000000000"] - .into(); + let entrance_account_id_32: [u8; 32] = PalletId(*b"bf/vtkin").into_account_truncating(); let entrance_account_location = MultiLocation { parents: 0, @@ -932,31 +929,20 @@ fn supplement_fee_account_whitelist_works() { ExtBuilder::default().build().execute_with(|| { // environment setup parachain_staking_setup(); - let entrance_account_id: AccountId = - hex_literal::hex!["6d6f646c62662f76746b696e0000000000000000000000000000000000000000"] - .into(); - - let entrance_account_id_32: [u8; 32] = - hex_literal::hex!["6d6f646c62662f76746b696e0000000000000000000000000000000000000000"] - .into(); + let entrance_account_id: AccountId = PalletId(*b"bf/vtkin").into_account_truncating(); + let entrance_account_id_32: [u8; 32] = PalletId(*b"bf/vtkin").into_account_truncating(); let entrance_account_location = MultiLocation { parents: 0, interior: X1(Junction::AccountId32 { network: Any, id: entrance_account_id_32 }), }; - - let exit_account_id_32: [u8; 32] = - hex_literal::hex!["6d6f646c62662f76746f75740000000000000000000000000000000000000000"] - .into(); - + let exit_account_id_32: [u8; 32] = PalletId(*b"bf/vtout").into_account_truncating(); let exit_account_location = MultiLocation { parents: 0, interior: X1(Junction::AccountId32 { network: Any, id: exit_account_id_32 }), }; - let source_account_id_32: [u8; 32] = - hex_literal::hex!["d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d"] - .into(); + let source_account_id_32: [u8; 32] = ALICE.into(); let source_location = Slp::account_32_to_local_location(source_account_id_32).unwrap(); assert_ok!(Slp::set_fee_source( RuntimeOrigin::signed(ALICE), @@ -990,15 +976,6 @@ fn supplement_fee_account_whitelist_works() { Some(entrance_account_id) )); - // assert_noop!( - // Slp::supplement_fee_reserve( - // RuntimeOrigin::signed(ALICE), - // BNC, - // Box::new(entrance_account_location.clone()), - // ), - // Error::::XcmFailure - // ); - assert_noop!( Slp::supplement_fee_reserve( RuntimeOrigin::signed(ALICE), @@ -1015,15 +992,6 @@ fn supplement_fee_account_whitelist_works() { Box::new(exit_account_location.clone()), )); - // assert_noop!( - // Slp::supplement_fee_reserve( - // RuntimeOrigin::signed(ALICE), - // BNC, - // Box::new(exit_account_location.clone()), - // ), - // Error::::XcmFailure - // ); - // remove exit_account_location from whitelist assert_ok!(Slp::remove_supplement_fee_account_from_whitelist( RuntimeOrigin::signed(ALICE), diff --git a/pallets/slp/src/tests/phala_tests.rs b/pallets/slp/src/tests/phala_tests.rs index 94a77b3ef..e4aa588f1 100644 --- a/pallets/slp/src/tests/phala_tests.rs +++ b/pallets/slp/src/tests/phala_tests.rs @@ -25,11 +25,26 @@ use crate::{ Junctions::X2, *, }; -use frame_support::{assert_noop, assert_ok}; +use frame_support::{assert_noop, assert_ok, PalletId}; use polkadot_parachain::primitives::Sibling; use sp_runtime::traits::AccountIdConversion; use xcm::opaque::latest::NetworkId::Any; +const VALIDATOR_0_LOCATION: MultiLocation = + MultiLocation { parents: 1, interior: X2(GeneralIndex(0), GeneralIndex(0)) }; +const VALIDATOR_0_ACCOUNT_ID_32: [u8; 32] = + hex_literal::hex!["d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d"]; +const VALIDATOR_0_LOCATION_WRONG: MultiLocation = MultiLocation { + parents: 1, + interior: X2( + Parachain(2004), + Junction::AccountId32 { network: Any, id: VALIDATOR_0_ACCOUNT_ID_32 }, + ), +}; + +const VALIDATOR_1_LOCATION: MultiLocation = + MultiLocation { parents: 1, interior: X2(GeneralIndex(1), GeneralIndex(1)) }; + #[test] fn initialize_phala_delegator_works() { ExtBuilder::default().build().execute_with(|| { @@ -105,27 +120,12 @@ fn initialize_phala_delegator_works() { #[test] fn add_validator_works() { - let validator_0_location = - MultiLocation { parents: 1, interior: X2(GeneralIndex(0), GeneralIndex(0)) }; - - let validator_0_account_id_32 = - hex_literal::hex!["d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d"] - .into(); - - let validator_0_location_wrong = MultiLocation { - parents: 1, - interior: X2( - Parachain(2004), - Junction::AccountId32 { network: Any, id: validator_0_account_id_32 }, - ), - }; - ExtBuilder::default().build().execute_with(|| { assert_noop!( Slp::add_validator( RuntimeOrigin::signed(ALICE), PHA, - Box::new(validator_0_location_wrong) + Box::new(VALIDATOR_0_LOCATION_WRONG) ), Error::::ValidatorMultilocationNotvalid ); @@ -134,7 +134,7 @@ fn add_validator_works() { Slp::add_validator( RuntimeOrigin::signed(ALICE), PHA, - Box::new(validator_0_location.clone()) + Box::new(VALIDATOR_0_LOCATION.clone()) ), Error::::NotExist ); @@ -163,17 +163,17 @@ fn add_validator_works() { assert_ok!(Slp::add_validator( RuntimeOrigin::signed(ALICE), PHA, - Box::new(validator_0_location) + Box::new(VALIDATOR_0_LOCATION) )); }); } #[test] fn phala_delegate_works() { + let bifrost_parachain_account_id: AccountId = Sibling::from(2001).into_account_truncating(); // subaccount_id_0: 41YcGwBLwxbFV7VfbF6zYGgUnYbt96dHcA2DWruRJkWtANFD let subaccount_id_0: AccountId = - hex_literal::hex!["290bf94235666a351d9c8082c77e689813a905d0bbffdbd8b4a619ec5303ba27"] - .into(); + Utility::derivative_account_id(bifrost_parachain_account_id, 0); let subaccount_0_location = MultiLocation { parents: 1, @@ -183,24 +183,6 @@ fn phala_delegate_works() { ), }; - let validator_0_location = - MultiLocation { parents: 1, interior: X2(GeneralIndex(0), GeneralIndex(0)) }; - - let validator_1_location = - MultiLocation { parents: 1, interior: X2(GeneralIndex(1), GeneralIndex(1)) }; - - let validator_0_account_id_32 = - hex_literal::hex!["d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d"] - .into(); - - let validator_0_location_wrong = MultiLocation { - parents: 1, - interior: X2( - Parachain(2004), - Junction::AccountId32 { network: Any, id: validator_0_account_id_32 }, - ), - }; - ExtBuilder::default().build().execute_with(|| { initialize_preparation_setup(); @@ -210,7 +192,7 @@ fn phala_delegate_works() { RuntimeOrigin::signed(ALICE), PHA, Box::new(subaccount_0_location.clone()), - vec![validator_0_location.clone()], + vec![VALIDATOR_0_LOCATION.clone()], ), Error::::DelegatorNotExist ); @@ -232,7 +214,7 @@ fn phala_delegate_works() { RuntimeOrigin::signed(ALICE), PHA, Box::new(subaccount_0_location.clone()), - vec![validator_0_location_wrong], + vec![VALIDATOR_0_LOCATION_WRONG], ), Error::::ValidatorError ); @@ -242,7 +224,7 @@ fn phala_delegate_works() { RuntimeOrigin::signed(ALICE), PHA, Box::new(subaccount_0_location.clone()), - vec![validator_0_location.clone()], + vec![VALIDATOR_0_LOCATION.clone()], ), Error::::ValidatorSetNotExist ); @@ -250,7 +232,7 @@ fn phala_delegate_works() { assert_ok!(Slp::add_validator( RuntimeOrigin::signed(ALICE), PHA, - Box::new(validator_1_location.clone()) + Box::new(VALIDATOR_1_LOCATION.clone()) )); assert_noop!( @@ -258,7 +240,7 @@ fn phala_delegate_works() { RuntimeOrigin::signed(ALICE), PHA, Box::new(subaccount_0_location.clone()), - vec![validator_0_location.clone()], + vec![VALIDATOR_0_LOCATION.clone()], ), Error::::ValidatorNotExist ); @@ -266,14 +248,14 @@ fn phala_delegate_works() { assert_ok!(Slp::add_validator( RuntimeOrigin::signed(ALICE), PHA, - Box::new(validator_0_location.clone()) + Box::new(VALIDATOR_0_LOCATION.clone()) )); assert_ok!(Slp::delegate( RuntimeOrigin::signed(ALICE), PHA, Box::new(subaccount_0_location.clone()), - vec![validator_0_location.clone()], + vec![VALIDATOR_0_LOCATION.clone()], )); let new_ledger = PhalaLedger::> { @@ -335,9 +317,7 @@ fn initialize_preparation_setup() { } fn phala_xcm_setup() { - let treasury_account_id_32: [u8; 32] = - hex_literal::hex!["6d6f646c62662f74727372790000000000000000000000000000000000000000"] - .into(); + let treasury_account_id_32: [u8; 32] = PalletId(*b"bf/trsry").into_account_truncating(); let treasury_location = MultiLocation { parents: 0, interior: X1(AccountId32 { network: Any, id: treasury_account_id_32 }), @@ -386,16 +366,20 @@ fn phala_xcm_setup() { XcmOperation::TransferTo, Some((20_000_000_000, 10_000_000_000)), )); + + assert_ok!(Slp::set_xcm_dest_weight_and_fee( + RuntimeOrigin::signed(ALICE), + PHA, + XcmOperation::ConvertAsset, + Some((20_000_000_000, 10_000_000_000)), + )); } fn phala_setup() { - let validator_0_location = - MultiLocation { parents: 1, interior: X2(GeneralIndex(0), GeneralIndex(0)) }; - + let bifrost_parachain_account_id: AccountId = Sibling::from(2001).into_account_truncating(); // subaccount_id_0: 41YcGwBLwxbFV7VfbF6zYGgUnYbt96dHcA2DWruRJkWtANFD let subaccount_id_0: AccountId = - hex_literal::hex!["290bf94235666a351d9c8082c77e689813a905d0bbffdbd8b4a619ec5303ba27"] - .into(); + Utility::derivative_account_id(bifrost_parachain_account_id, 0); let subaccount_0_location = MultiLocation { parents: 1, @@ -416,7 +400,7 @@ fn phala_setup() { assert_ok!(Slp::add_validator( RuntimeOrigin::signed(ALICE), PHA, - Box::new(validator_0_location.clone()), + Box::new(VALIDATOR_0_LOCATION.clone()), )); // delegate a validator for the delegator @@ -424,27 +408,25 @@ fn phala_setup() { RuntimeOrigin::signed(ALICE), PHA, Box::new(subaccount_0_location.clone()), - vec![validator_0_location.clone()], + vec![VALIDATOR_0_LOCATION.clone()], )); } #[test] fn phala_bond_works() { - let subaccount_0_account_id_32: AccountId = - hex_literal::hex!["290bf94235666a351d9c8082c77e689813a905d0bbffdbd8b4a619ec5303ba27"] - .into(); + let bifrost_parachain_account_id: AccountId = Sibling::from(2001).into_account_truncating(); + // subaccount_id_0: 41YcGwBLwxbFV7VfbF6zYGgUnYbt96dHcA2DWruRJkWtANFD + let subaccount_0_account_id_32: [u8; 32] = + Utility::derivative_account_id(bifrost_parachain_account_id, 0).into(); let subaccount_0_location = MultiLocation { parents: 1, interior: X2( Parachain(2004), - Junction::AccountId32 { network: Any, id: subaccount_0_account_id_32.into() }, + Junction::AccountId32 { network: Any, id: subaccount_0_account_id_32 }, ), }; - let validator_0_location = - MultiLocation { parents: 1, interior: X2(GeneralIndex(0), GeneralIndex(0)) }; - ExtBuilder::default().build().execute_with(|| { let share_price_multilocation = MultiLocation { parents: 1, interior: X2(GeneralIndex(2000), GeneralIndex(1000)) }; @@ -479,13 +461,13 @@ fn phala_bond_works() { assert_ok!(Slp::add_validator( RuntimeOrigin::signed(ALICE), PHA, - Box::new(validator_0_location.clone()), + Box::new(VALIDATOR_0_LOCATION.clone()), )); assert_ok!(Slp::delegate( RuntimeOrigin::signed(ALICE), PHA, Box::new(subaccount_0_location.clone()), - vec![validator_0_location.clone()], + vec![VALIDATOR_0_LOCATION.clone()], )); phala_xcm_setup(); @@ -531,7 +513,7 @@ fn phala_bond_works() { PHA, Box::new(subaccount_0_location.clone()), 1_000_000_000_000, - Some(validator_0_location.clone()) + Some(VALIDATOR_0_LOCATION.clone()) ), Error::::DividedByZero ); @@ -551,10 +533,10 @@ fn phala_bond_works() { #[test] fn phala_unbond_works() { + let bifrost_parachain_account_id: AccountId = Sibling::from(2001).into_account_truncating(); // subaccount_id_0: 41YcGwBLwxbFV7VfbF6zYGgUnYbt96dHcA2DWruRJkWtANFD let subaccount_id_0: AccountId = - hex_literal::hex!["290bf94235666a351d9c8082c77e689813a905d0bbffdbd8b4a619ec5303ba27"] - .into(); + Utility::derivative_account_id(bifrost_parachain_account_id, 0); let subaccount_0_location = MultiLocation { parents: 1, @@ -564,9 +546,6 @@ fn phala_unbond_works() { ), }; - let validator_0_location = - MultiLocation { parents: 1, interior: X2(GeneralIndex(0), GeneralIndex(0)) }; - ExtBuilder::default().build().execute_with(|| { let share_price_multilocation = MultiLocation { parents: 1, interior: X2(GeneralIndex(1000), GeneralIndex(1000)) }; @@ -647,7 +626,7 @@ fn phala_unbond_works() { RuntimeOrigin::signed(ALICE), PHA, Box::new(subaccount_0_location.clone()), - Some(validator_0_location.clone()), + Some(VALIDATOR_0_LOCATION.clone()), 1_000_000, ), Error::::DividedByZero @@ -702,9 +681,10 @@ fn phala_unbond_works() { #[test] fn phala_rebond_works() { - let subaccount_0_account_id_32: AccountId = - hex_literal::hex!["290bf94235666a351d9c8082c77e689813a905d0bbffdbd8b4a619ec5303ba27"] - .into(); + let bifrost_parachain_account_id: AccountId = Sibling::from(2001).into_account_truncating(); + // subaccount_id_0: 41YcGwBLwxbFV7VfbF6zYGgUnYbt96dHcA2DWruRJkWtANFD + let subaccount_0_account_id_32: [u8; 32] = + Utility::derivative_account_id(bifrost_parachain_account_id, 0).into(); let subaccount_0_location = MultiLocation { parents: 1, @@ -758,9 +738,10 @@ fn phala_rebond_works() { #[test] fn phala_undelegate_works() { - let subaccount_0_account_id_32: AccountId = - hex_literal::hex!["290bf94235666a351d9c8082c77e689813a905d0bbffdbd8b4a619ec5303ba27"] - .into(); + let bifrost_parachain_account_id: AccountId = Sibling::from(2001).into_account_truncating(); + // subaccount_id_0: 41YcGwBLwxbFV7VfbF6zYGgUnYbt96dHcA2DWruRJkWtANFD + let subaccount_0_account_id_32: [u8; 32] = + Utility::derivative_account_id(bifrost_parachain_account_id, 0).into(); let subaccount_0_location = MultiLocation { parents: 1, @@ -770,9 +751,6 @@ fn phala_undelegate_works() { ), }; - let validator_0_location = - MultiLocation { parents: 1, interior: X2(GeneralIndex(0), GeneralIndex(0)) }; - ExtBuilder::default().build().execute_with(|| { // environment setup phala_setup(); @@ -794,7 +772,7 @@ fn phala_undelegate_works() { RuntimeOrigin::signed(ALICE), PHA, Box::new(subaccount_0_location.clone()), - vec![validator_0_location.clone()], + vec![VALIDATOR_0_LOCATION.clone()], ), Error::::ValidatorStillInUse ); @@ -816,7 +794,7 @@ fn phala_undelegate_works() { RuntimeOrigin::signed(ALICE), PHA, Box::new(subaccount_0_location.clone()), - vec![validator_0_location.clone()], + vec![VALIDATOR_0_LOCATION.clone()], ), Error::::ValidatorStillInUse ); @@ -837,7 +815,7 @@ fn phala_undelegate_works() { RuntimeOrigin::signed(ALICE), PHA, Box::new(subaccount_0_location.clone()), - vec![validator_0_location.clone()], + vec![VALIDATOR_0_LOCATION.clone()], )); let undelegated_ledger = PhalaLedger::> { @@ -857,9 +835,10 @@ fn phala_undelegate_works() { #[test] fn phala_redelegate_works() { - let subaccount_0_account_id_32: AccountId = - hex_literal::hex!["290bf94235666a351d9c8082c77e689813a905d0bbffdbd8b4a619ec5303ba27"] - .into(); + let bifrost_parachain_account_id: AccountId = Sibling::from(2001).into_account_truncating(); + // subaccount_id_0: 41YcGwBLwxbFV7VfbF6zYGgUnYbt96dHcA2DWruRJkWtANFD + let subaccount_0_account_id_32: [u8; 32] = + Utility::derivative_account_id(bifrost_parachain_account_id, 0).into(); let subaccount_0_location = MultiLocation { parents: 1, @@ -869,9 +848,6 @@ fn phala_redelegate_works() { ), }; - let validator_1_location = - MultiLocation { parents: 1, interior: X2(GeneralIndex(1), GeneralIndex(1)) }; - ExtBuilder::default().build().execute_with(|| { // environment setup phala_setup(); @@ -902,14 +878,14 @@ fn phala_redelegate_works() { assert_ok!(Slp::add_validator( RuntimeOrigin::signed(ALICE), PHA, - Box::new(validator_1_location.clone()) + Box::new(VALIDATOR_1_LOCATION.clone()) )); assert_ok!(Slp::redelegate( RuntimeOrigin::signed(ALICE), PHA, Box::new(subaccount_0_location.clone()), - Some(vec![validator_1_location.clone()]) + Some(vec![VALIDATOR_1_LOCATION.clone()]) )); let new_ledger = PhalaLedger::> { @@ -929,9 +905,10 @@ fn phala_redelegate_works() { #[test] fn phala_liquidize_works() { - let subaccount_0_account_id_32: AccountId = - hex_literal::hex!["290bf94235666a351d9c8082c77e689813a905d0bbffdbd8b4a619ec5303ba27"] - .into(); + let bifrost_parachain_account_id: AccountId = Sibling::from(2001).into_account_truncating(); + // subaccount_id_0: 41YcGwBLwxbFV7VfbF6zYGgUnYbt96dHcA2DWruRJkWtANFD + let subaccount_0_account_id_32: [u8; 32] = + Utility::derivative_account_id(bifrost_parachain_account_id, 0).into(); let subaccount_0_location = MultiLocation { parents: 1, @@ -1017,9 +994,10 @@ fn phala_liquidize_works() { #[test] fn phala_bond_confirm_works() { - let subaccount_0_account_id_32: AccountId = - hex_literal::hex!["290bf94235666a351d9c8082c77e689813a905d0bbffdbd8b4a619ec5303ba27"] - .into(); + let bifrost_parachain_account_id: AccountId = Sibling::from(2001).into_account_truncating(); + // subaccount_id_0: 41YcGwBLwxbFV7VfbF6zYGgUnYbt96dHcA2DWruRJkWtANFD + let subaccount_0_account_id_32: [u8; 32] = + Utility::derivative_account_id(bifrost_parachain_account_id, 0).into(); let subaccount_0_location = MultiLocation { parents: 1, @@ -1093,9 +1071,10 @@ fn phala_bond_confirm_works() { #[test] fn phala_unbond_confirm_works() { - let subaccount_0_account_id_32: AccountId = - hex_literal::hex!["290bf94235666a351d9c8082c77e689813a905d0bbffdbd8b4a619ec5303ba27"] - .into(); + let bifrost_parachain_account_id: AccountId = Sibling::from(2001).into_account_truncating(); + // subaccount_id_0: 41YcGwBLwxbFV7VfbF6zYGgUnYbt96dHcA2DWruRJkWtANFD + let subaccount_0_account_id_32: [u8; 32] = + Utility::derivative_account_id(bifrost_parachain_account_id, 0).into(); let subaccount_0_location = MultiLocation { parents: 1, @@ -1168,9 +1147,10 @@ fn phala_unbond_confirm_works() { #[test] fn phala_transfer_back_works() { - let subaccount_0_account_id_32: AccountId = - hex_literal::hex!["290bf94235666a351d9c8082c77e689813a905d0bbffdbd8b4a619ec5303ba27"] - .into(); + let bifrost_parachain_account_id: AccountId = Sibling::from(2001).into_account_truncating(); + // subaccount_id_0: 41YcGwBLwxbFV7VfbF6zYGgUnYbt96dHcA2DWruRJkWtANFD + let subaccount_0_account_id_32: [u8; 32] = + Utility::derivative_account_id(bifrost_parachain_account_id, 0).into(); let subaccount_0_location = MultiLocation { parents: 1, @@ -1218,9 +1198,10 @@ fn phala_transfer_back_works() { #[test] fn phala_transfer_to_works() { - let subaccount_0_account_id_32: AccountId = - hex_literal::hex!["290bf94235666a351d9c8082c77e689813a905d0bbffdbd8b4a619ec5303ba27"] - .into(); + let bifrost_parachain_account_id: AccountId = Sibling::from(2001).into_account_truncating(); + // subaccount_id_0: 41YcGwBLwxbFV7VfbF6zYGgUnYbt96dHcA2DWruRJkWtANFD + let subaccount_0_account_id_32: [u8; 32] = + Utility::derivative_account_id(bifrost_parachain_account_id, 0).into(); let subaccount_0_location = MultiLocation { parents: 1, @@ -1277,9 +1258,10 @@ fn phala_transfer_to_works() { #[test] fn supplement_fee_account_whitelist_works() { - let subaccount_0_account_id_32: AccountId = - hex_literal::hex!["290bf94235666a351d9c8082c77e689813a905d0bbffdbd8b4a619ec5303ba27"] - .into(); + let bifrost_parachain_account_id: AccountId = Sibling::from(2001).into_account_truncating(); + // subaccount_id_0: 41YcGwBLwxbFV7VfbF6zYGgUnYbt96dHcA2DWruRJkWtANFD + let subaccount_0_account_id_32: [u8; 32] = + Utility::derivative_account_id(bifrost_parachain_account_id, 0).into(); let subaccount_0_location = MultiLocation { parents: 1, @@ -1292,31 +1274,20 @@ fn supplement_fee_account_whitelist_works() { ExtBuilder::default().build().execute_with(|| { // environment setup phala_setup(); - let entrance_account_id: AccountId = - hex_literal::hex!["6d6f646c62662f76746b696e0000000000000000000000000000000000000000"] - .into(); - - let entrance_account_id_32: [u8; 32] = - hex_literal::hex!["6d6f646c62662f76746b696e0000000000000000000000000000000000000000"] - .into(); - + let entrance_account_id: AccountId = PalletId(*b"bf/vtkin").into_account_truncating(); + let entrance_account_id_32: [u8; 32] = PalletId(*b"bf/vtkin").into_account_truncating(); let entrance_account_location = MultiLocation { parents: 0, interior: X1(Junction::AccountId32 { network: Any, id: entrance_account_id_32 }), }; - let exit_account_id_32: [u8; 32] = - hex_literal::hex!["6d6f646c62662f76746f75740000000000000000000000000000000000000000"] - .into(); - + let exit_account_id_32: [u8; 32] = PalletId(*b"bf/vtout").into_account_truncating(); let exit_account_location = MultiLocation { parents: 0, interior: X1(Junction::AccountId32 { network: Any, id: exit_account_id_32 }), }; - let source_account_id_32: [u8; 32] = - hex_literal::hex!["d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d"] - .into(); + let source_account_id_32: [u8; 32] = ALICE.into(); let source_location = Slp::account_32_to_local_location(source_account_id_32).unwrap(); assert_ok!(Slp::set_fee_source( RuntimeOrigin::signed(ALICE), @@ -1404,9 +1375,10 @@ fn supplement_fee_account_whitelist_works() { #[test] fn charge_host_fee_and_tune_vtoken_exchange_rate_works() { - let subaccount_0_account_id_32: AccountId = - hex_literal::hex!["290bf94235666a351d9c8082c77e689813a905d0bbffdbd8b4a619ec5303ba27"] - .into(); + let bifrost_parachain_account_id: AccountId = Sibling::from(2001).into_account_truncating(); + // subaccount_id_0: 41YcGwBLwxbFV7VfbF6zYGgUnYbt96dHcA2DWruRJkWtANFD + let subaccount_0_account_id_32: [u8; 32] = + Utility::derivative_account_id(bifrost_parachain_account_id, 0).into(); let subaccount_0_location = MultiLocation { parents: 1, @@ -1417,11 +1389,8 @@ fn charge_host_fee_and_tune_vtoken_exchange_rate_works() { }; ExtBuilder::default().build().execute_with(|| { - let treasury_id: AccountId = - hex_literal::hex!["6d6f646c62662f74727372790000000000000000000000000000000000000000"] - .into(); - let treasury_32: [u8; 32] = - hex_literal::hex!["6d6f646c62662f74727372790000000000000000000000000000000000000000"]; + let treasury_id: AccountId = PalletId(*b"bf/trsry").into_account_truncating(); + let treasury_32: [u8; 32] = PalletId(*b"bf/trsry").into_account_truncating(); phala_setup(); @@ -1491,9 +1460,10 @@ fn charge_host_fee_and_tune_vtoken_exchange_rate_works() { #[test] fn add_validator_and_remove_validator_works() { - let subaccount_0_account_id_32: AccountId = - hex_literal::hex!["290bf94235666a351d9c8082c77e689813a905d0bbffdbd8b4a619ec5303ba27"] - .into(); + let bifrost_parachain_account_id: AccountId = Sibling::from(2001).into_account_truncating(); + // subaccount_id_0: 41YcGwBLwxbFV7VfbF6zYGgUnYbt96dHcA2DWruRJkWtANFD + let subaccount_0_account_id_32: [u8; 32] = + Utility::derivative_account_id(bifrost_parachain_account_id, 0).into(); let subaccount_0_location = MultiLocation { parents: 1, @@ -1503,13 +1473,10 @@ fn add_validator_and_remove_validator_works() { ), }; - let validator_0_location = - MultiLocation { parents: 1, interior: X2(GeneralIndex(0), GeneralIndex(0)) }; - ExtBuilder::default().build().execute_with(|| { let mut valis = vec![]; let multi_hash_0 = - ::Hashing::hash(&validator_0_location.encode()); + ::Hashing::hash(&VALIDATOR_0_LOCATION.encode()); initialize_preparation_setup(); @@ -1519,11 +1486,11 @@ fn add_validator_and_remove_validator_works() { assert_ok!(Slp::add_validator( RuntimeOrigin::signed(ALICE), PHA, - Box::new(validator_0_location.clone()), + Box::new(VALIDATOR_0_LOCATION.clone()), )); // The storage is reordered by hash. So we need to adjust the push order here. - valis.push((validator_0_location.clone(), multi_hash_0)); + valis.push((VALIDATOR_0_LOCATION.clone(), multi_hash_0)); assert_eq!(Slp::get_validators(PHA), Some(valis)); @@ -1531,15 +1498,46 @@ fn add_validator_and_remove_validator_works() { RuntimeOrigin::signed(ALICE), PHA, Box::new(subaccount_0_location.clone()), - vec![validator_0_location.clone()], + vec![VALIDATOR_0_LOCATION.clone()], )); assert_ok!(Slp::remove_validator( RuntimeOrigin::signed(ALICE), PHA, - Box::new(validator_0_location.clone()), + Box::new(VALIDATOR_0_LOCATION.clone()), )); assert_eq!(Slp::get_validators(PHA), Some(vec![])); }); } + +#[test] +fn phala_convert_asset_works() { + let bifrost_parachain_account_id: AccountId = Sibling::from(2001).into_account_truncating(); + // subaccount_id_0: 41YcGwBLwxbFV7VfbF6zYGgUnYbt96dHcA2DWruRJkWtANFD + let subaccount_0_account_id_32: [u8; 32] = + Utility::derivative_account_id(bifrost_parachain_account_id, 0).into(); + + let subaccount_0_location = MultiLocation { + parents: 1, + interior: X2( + Parachain(2004), + Junction::AccountId32 { network: Any, id: subaccount_0_account_id_32.into() }, + ), + }; + + ExtBuilder::default().build().execute_with(|| { + phala_setup(); + + assert_noop!( + Slp::convert_asset( + RuntimeOrigin::signed(ALICE), + PHA, + Box::new(subaccount_0_location.clone()), + 1_000_000_000_000, + true + ), + Error::::XcmFailure + ); + }); +} diff --git a/pallets/slp/src/traits.rs b/pallets/slp/src/traits.rs index 7f7f921c2..4421ff15a 100644 --- a/pallets/slp/src/traits.rs +++ b/pallets/slp/src/traits.rs @@ -19,7 +19,7 @@ use crate::{primitives::QueryId, Box, MultiLocation, TimeUnit, Xcm}; use node_primitives::CurrencyId; use sp_runtime::DispatchResult; use sp_std::vec::Vec; -use xcm::{latest::Weight as XcmWeight, opaque::latest::Instruction}; +use xcm::latest::Weight as XcmWeight; /// Abstraction over a staking agent for a certain POS chain. pub trait StakingAgent< @@ -240,10 +240,6 @@ pub trait XcmBuilder { ) -> Result, Error>; } -pub trait InstructionBuilder { - fn construct_instruction(call: ChainCallType, weight: XcmWeight) -> Instruction; -} - /// Helper to communicate with pallet_xcm's Queries storage for Substrate chains in runtime. pub trait QueryResponseManager { // If the query exists and we've already got the Response, then True is returned. Otherwise, diff --git a/pallets/ve-minting/Cargo.toml b/pallets/ve-minting/Cargo.toml index 26fcb0b14..5b59462ef 100644 --- a/pallets/ve-minting/Cargo.toml +++ b/pallets/ve-minting/Cargo.toml @@ -26,14 +26,12 @@ pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "p xcm = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.37", default-features = false } cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.37", default-features = false } sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.37", default-features = false } -# sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.37", default-features = false } [dev-dependencies] orml-tokens = "0.4.1-dev" orml-currencies = "0.4.1-dev" sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.37" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.37" } -pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.37", default-features = false } bifrost-slp = { path = "../../pallets/slp", default-features = false } bifrost-vtoken-minting = { path = "../../pallets/vtoken-minting", default-features = false } bifrost-asset-registry = { path = "../asset-registry", default-features = false } diff --git a/pallets/ve-minting/rpc/runtime-api/src/lib.rs b/pallets/ve-minting/rpc/runtime-api/src/lib.rs index f24af121d..f6eb1cb15 100644 --- a/pallets/ve-minting/rpc/runtime-api/src/lib.rs +++ b/pallets/ve-minting/rpc/runtime-api/src/lib.rs @@ -19,21 +19,22 @@ #![cfg_attr(not(feature = "std"), no_std)] use codec::Codec; -use node_primitives::{Balance, BlockNumber, Timestamp}; +use node_primitives::{Balance, BlockNumber}; use sp_api::decl_runtime_apis; use sp_core::U256; decl_runtime_apis! { pub trait VeMintingRuntimeApi where AccountId: Codec, + BlockNumber: Codec, { fn balance_of( who: AccountId, - t: Option, + t: Option, ) -> Balance; fn total_supply( - t: Timestamp, + t: BlockNumber, ) -> Balance; fn find_block_epoch( diff --git a/pallets/ve-minting/rpc/src/lib.rs b/pallets/ve-minting/rpc/src/lib.rs index 9ef4465b0..06dded9f8 100644 --- a/pallets/ve-minting/rpc/src/lib.rs +++ b/pallets/ve-minting/rpc/src/lib.rs @@ -25,33 +25,28 @@ use jsonrpsee::{ proc_macros::rpc, types::error::{CallError, ErrorCode, ErrorObject}, }; -use node_primitives::{Balance, CurrencyId}; +use node_primitives::Balance; use sp_api::ProvideRuntimeApi; use sp_blockchain::HeaderBackend; +use sp_core::U256; use sp_rpc::number::NumberOrHex; -use sp_runtime::{generic::BlockId, traits::Block as BlockT}; +use sp_runtime::{ + generic::BlockId, + traits::{Block as BlockT, BlockIdTo}, + SaturatedConversion, +}; #[rpc(client, server)] pub trait VeMintingRpcApi { /// rpc method for getting user balance #[method(name = "ve_minting_balanceOf")] - fn balance_of( - &self, - who: AccountId, - t: Option, - at: Option, - ) -> RpcResult; + fn balance_of(&self, who: AccountId, at: Option) -> RpcResult; - #[method(name = "ve_minting_total_supply")] - fn total_supply(&self, t: Timestamp, at: Option) -> RpcResult; + #[method(name = "ve_minting_totalSupply")] + fn total_supply(&self, at: Option) -> RpcResult; #[method(name = "ve_minting_findBlockEpoch")] - fn find_block_epoch( - &self, - block: BlockNumber, - max_epoch: U256, - at: Option, - ) -> RpcResult; + fn find_block_epoch(&self, max_epoch: U256, at: Option) -> RpcResult; } #[derive(Clone, Debug)] @@ -60,7 +55,11 @@ pub struct VeMintingRpc { _marker: PhantomData, } -impl VeMintingRpc { +impl VeMintingRpc +where + Block: BlockT, + C: BlockIdTo, +{ pub fn new(client: Arc) -> Self { Self { client, _marker: PhantomData } } @@ -71,24 +70,37 @@ impl VeMintingRpcApiServer<::Hash, Account for VeMintingRpc where Block: BlockT, - C: Send + Sync + 'static + ProvideRuntimeApi + HeaderBackend, - C::Api: VeMintingRuntimeApi, + C: Send + Sync + 'static + ProvideRuntimeApi + HeaderBackend + BlockIdTo, + C::Api: VeMintingRuntimeApi, AccountId: Codec, + // CallError: From<>::Error>, { fn balance_of( &self, who: AccountId, - t: Option, at: Option<::Hash>, ) -> RpcResult { let lm_rpc_api = self.client.runtime_api(); let at = BlockId::::hash(at.unwrap_or_else(|| self.client.info().best_hash)); - - let rs: Result = lm_rpc_api.balance_of(&at, who, t); + let block_number = self + .client + .to_number(&at) + .map(|num| match num { + Some(inner_num) => Some(inner_num.saturated_into::()), + None => None, + }) + .map_err(|e| { + jsonrpsee::core::Error::Call(CallError::Custom(ErrorObject::owned( + ErrorCode::InternalError.code(), + "Failed to get balance_of.", + Some(format!("{:?}", e)), + ))) + })?; + + let rs: Result = lm_rpc_api.balance_of(&at, who, block_number); match rs { - Ok(rewards) => - Ok(rewards.into_iter().map(|amount| NumberOrHex::Hex(amount.into())).collect()), + Ok(balane) => Ok(NumberOrHex::Hex(balane.into())), Err(e) => Err(CallError::Custom(ErrorObject::owned( ErrorCode::InternalError.code(), "Failed to get balance_of.", @@ -98,19 +110,28 @@ where .map_err(|e| jsonrpsee::core::Error::Call(e)) } - fn total_supply( - &self, - t: Timestamp, - at: Option<::Hash>, - ) -> RpcResult { + fn total_supply(&self, at: Option<::Hash>) -> RpcResult { let lm_rpc_api = self.client.runtime_api(); let at = BlockId::::hash(at.unwrap_or_else(|| self.client.info().best_hash)); - - let rs: Result = lm_rpc_api.total_supply(&at, t); + let block_number = self + .client + .to_number(&at) + .map(|num| match num { + Some(inner_num) => Some(inner_num.saturated_into::()), + None => None, + }) + .map_err(|e| { + jsonrpsee::core::Error::Call(CallError::Custom(ErrorObject::owned( + ErrorCode::InternalError.code(), + "Failed to get total_supply.", + Some(format!("{:?}", e)), + ))) + })?; + let rs: Result = + lm_rpc_api.total_supply(&at, block_number.expect("no block found")); match rs { - Ok(rewards) => - Ok(rewards.into_iter().map(|amount| NumberOrHex::Hex(amount.into())).collect()), + Ok(supply) => Ok(NumberOrHex::Hex(supply.into())), Err(e) => Err(CallError::Custom(ErrorObject::owned( ErrorCode::InternalError.code(), "Failed to get total_supply.", @@ -122,18 +143,30 @@ where fn find_block_epoch( &self, - block: BlockNumber, max_epoch: U256, at: Option<::Hash>, ) -> RpcResult { let lm_rpc_api = self.client.runtime_api(); let at = BlockId::::hash(at.unwrap_or_else(|| self.client.info().best_hash)); - - let rs: Result = lm_rpc_api.find_block_epoch(&at, block, max_epoch); + let block_number = self + .client + .to_number(&at) + .map(|num| match num { + Some(inner_num) => Some(inner_num.saturated_into::()), + None => None, + }) + .map_err(|e| { + jsonrpsee::core::Error::Call(CallError::Custom(ErrorObject::owned( + ErrorCode::InternalError.code(), + "Failed to get find_block_epoch.", + Some(format!("{:?}", e)), + ))) + })?; + let rs: Result = + lm_rpc_api.find_block_epoch(&at, block_number.expect("no block found"), max_epoch); match rs { - Ok(rewards) => - Ok(rewards.into_iter().map(|amount| NumberOrHex::Hex(amount.into())).collect()), + Ok(epoch) => Ok(NumberOrHex::Hex(epoch.into())), Err(e) => Err(CallError::Custom(ErrorObject::owned( ErrorCode::InternalError.code(), "Failed to get find_block_epoch.", diff --git a/pallets/ve-minting/src/incentive.rs b/pallets/ve-minting/src/incentive.rs index 7dcd5a954..738ad8d11 100644 --- a/pallets/ve-minting/src/incentive.rs +++ b/pallets/ve-minting/src/incentive.rs @@ -16,180 +16,166 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use crate::{traits::VeMintingInterface, *}; +use crate::{ + traits::{Incentive, VeMintingInterface}, + *, +}; pub use pallet::*; use sp_std::collections::btree_map::BTreeMap; #[derive(Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo, Default)] -pub struct IncentiveConfig { - reward_rate: BTreeMap, - reward_per_token_stored: BTreeMap, - pub rewards_duration: Timestamp, - period_finish: Timestamp, - last_update_time: Timestamp, +pub struct IncentiveConfig { + pub reward_rate: BTreeMap, + pub reward_per_token_stored: BTreeMap, + pub rewards_duration: BlockNumber, + pub period_finish: BlockNumber, + pub last_update_time: BlockNumber, } impl Pallet { - pub fn last_time_reward_applicable() -> Timestamp { - let current_timestamp: Timestamp = T::UnixTime::now().as_millis().saturated_into(); - if current_timestamp < Self::incentive_configs().period_finish { - current_timestamp + pub fn last_time_reward_applicable() -> T::BlockNumber { + let current_block_number: T::BlockNumber = frame_system::Pallet::::block_number(); + if current_block_number < Self::incentive_configs().period_finish { + current_block_number } else { Self::incentive_configs().period_finish } } - pub fn reward_per_token() -> BTreeMap, BalanceOf> { + pub fn reward_per_token() -> Result, BalanceOf>, DispatchError> { let mut conf = Self::incentive_configs(); - let current_timestamp: Timestamp = T::UnixTime::now().as_millis().saturated_into(); - let _total_supply = Self::total_supply(current_timestamp); + let current_block_number: T::BlockNumber = frame_system::Pallet::::block_number(); + let _total_supply = Self::total_supply(current_block_number)?; if _total_supply == BalanceOf::::zero() { - return conf.reward_per_token_stored; + return Ok(conf.reward_per_token_stored); } - conf.reward_per_token_stored.iter_mut().for_each(|(currency, reward)| { - *reward = reward.saturating_add( + conf.reward_rate.iter().try_for_each(|(currency, &reward)| -> DispatchResult { + let increment: BalanceOf = U256::from( Self::last_time_reward_applicable() - .saturated_into::>() - .saturating_sub(conf.last_update_time.saturated_into::>()) - .saturating_mul( - *conf.reward_rate.get(currency).unwrap_or(&BalanceOf::::zero()), - ) - .checked_div(&_total_supply) - .unwrap_or_default(), - ); - }); + .saturating_sub(conf.last_update_time) + .saturated_into::(), + ) + .checked_mul(U256::from(reward.saturated_into::())) + .ok_or(ArithmeticError::Overflow)? + .checked_mul(U256::from(T::Multiplier::get().saturated_into::())) + .ok_or(ArithmeticError::Overflow)? + .checked_div(U256::from(_total_supply.saturated_into::())) + .unwrap_or_default() + .as_u128() + .unique_saturated_into(); + conf.reward_per_token_stored + .entry(*currency) + .and_modify(|total_reward| *total_reward = total_reward.saturating_add(increment)) + .or_insert(increment); + Ok(()) + })?; IncentiveConfigs::::set(conf.clone()); - conf.reward_per_token_stored + Ok(conf.reward_per_token_stored) } pub fn earned( addr: &AccountIdOf, ) -> Result, BalanceOf>, DispatchError> { - let reward_per_token = Self::reward_per_token(); - let vetoken_balance = Self::balance_of(addr, None)?; + let reward_per_token = Self::reward_per_token()?; + let vetoken_balance = Self::balance_of_current_block(addr)?; let mut rewards = if let Some(rewards) = Self::rewards(addr) { rewards } else { BTreeMap::, BalanceOf>::default() }; - - reward_per_token.iter().for_each(|(currency, reward)| { + reward_per_token.iter().try_for_each(|(currency, reward)| -> DispatchResult { + let increment: BalanceOf = U256::from(vetoken_balance.saturated_into::()) + .checked_mul(U256::from( + reward + .saturating_sub( + *Self::user_reward_per_token_paid(addr) + .get(currency) + .unwrap_or(&BalanceOf::::zero()), + ) + .saturated_into::(), + )) + .ok_or(ArithmeticError::Overflow)? + .checked_div(U256::from(T::Multiplier::get().saturated_into::())) + .unwrap_or_default() + .as_u128() + .unique_saturated_into(); rewards .entry(*currency) .and_modify(|total_reward| { - *total_reward = total_reward.saturating_add( - vetoken_balance.saturating_mul( - reward.saturating_sub( - *Self::user_reward_per_token_paid(addr) - .get(currency) - .unwrap_or(&BalanceOf::::zero()), - ), - ), - ); + *total_reward = total_reward.saturating_add(increment); }) - .or_insert( - vetoken_balance.saturating_mul( - Self::reward_per_token() - .get(currency) - .unwrap_or(&BalanceOf::::zero()) - .saturating_sub( - *Self::user_reward_per_token_paid(addr) - .get(currency) - .unwrap_or(&BalanceOf::::zero()), - ), - ), - ); - }); + .or_insert(increment); + Ok(()) + })?; Ok(rewards) } + // Used to update reward when notify_reward or user call + // create_lock/increase_amount/increase_unlock_time/withdraw/get_rewards pub fn update_reward(addr: Option<&AccountIdOf>) -> DispatchResult { - let reward_per_token_stored = Self::reward_per_token(); + let reward_per_token_stored = Self::reward_per_token()?; + IncentiveConfigs::::mutate(|item| { item.reward_per_token_stored = reward_per_token_stored.clone(); item.last_update_time = Self::last_time_reward_applicable(); }); if let Some(address) = addr { - Rewards::::insert(address, Self::earned(&address)?); - UserRewardPerTokenPaid::::insert(address, reward_per_token_stored); + let earned = Self::earned(&address)?; + if earned != BTreeMap::, BalanceOf>::default() { + Rewards::::insert(address, earned); + } + UserRewardPerTokenPaid::::insert(address, reward_per_token_stored.clone()); } Ok(()) } - #[transactional] - pub fn get_reward(addr: &AccountIdOf) -> DispatchResult { + pub fn get_rewards_inner(addr: &AccountIdOf) -> DispatchResult { Self::update_reward(Some(addr))?; if let Some(rewards) = Self::rewards(addr) { rewards.iter().try_for_each(|(currency, &reward)| -> DispatchResult { T::MultiCurrency::transfer( *currency, - &T::VeMintingPalletId::get().into_account_truncating(), + &T::IncentivePalletId::get().into_account_truncating(), addr, reward, ) })?; Rewards::::remove(addr); + Self::deposit_event(Event::Rewarded { + addr: addr.to_owned(), + rewards: rewards.into_iter().collect(), + }); + } else { + return Err(Error::::NoRewards.into()); } Ok(()) } // Motion - #[transactional] - pub fn notify_reward_amount(rewards: Vec<(CurrencyIdOf, BalanceOf)>) -> DispatchResult { + pub fn notify_reward_amount( + addr: &AccountIdOf, + rewards: Vec<(CurrencyIdOf, BalanceOf)>, + ) -> DispatchResult { Self::update_reward(None)?; let mut conf = Self::incentive_configs(); - let current_timestamp: Timestamp = T::UnixTime::now().as_millis().saturated_into(); + let current_block_number: T::BlockNumber = frame_system::Pallet::::block_number(); - if current_timestamp >= conf.period_finish { - rewards.iter().try_for_each(|(currency, reward)| -> DispatchResult { - let currency_amount = T::MultiCurrency::free_balance( - *currency, - &T::VeMintingPalletId::get().into_account_truncating(), - ); - ensure!(*reward <= currency_amount, Error::::Expired); - let new_reward = reward - .checked_div(&conf.rewards_duration.saturated_into::>()) - .unwrap_or_else(Zero::zero); - conf.reward_rate - .entry(*currency) - .and_modify(|total_reward| { - *total_reward = new_reward; - }) - .or_insert(new_reward); - Ok(()) - })?; + if current_block_number >= conf.period_finish { + Self::add_reward(addr, &mut conf, &rewards, Zero::zero())?; } else { - let remaining = conf - .period_finish - .saturating_sub(current_timestamp) - .saturated_into::>(); - rewards.iter().try_for_each(|(currency, reward)| -> DispatchResult { - let leftover: BalanceOf = reward.saturating_mul(remaining); - let total_reward: BalanceOf = reward.saturating_add(leftover); - let currency_amount = T::MultiCurrency::free_balance( - *currency, - &T::VeMintingPalletId::get().into_account_truncating(), - ); - ensure!(total_reward <= currency_amount, Error::::Expired); - let new_reward = total_reward - .checked_div(&conf.rewards_duration.saturated_into::>()) - .unwrap_or_else(|| BalanceOf::::zero()); - conf.reward_rate - .entry(*currency) - .and_modify(|total_reward| { - *total_reward = new_reward; - }) - .or_insert(new_reward); - Ok(()) - })?; + let remaining = T::BlockNumberToBalance::convert( + conf.period_finish.saturating_sub(current_block_number), + ); + Self::add_reward(addr, &mut conf, &rewards, remaining)?; }; - conf.last_update_time = current_timestamp; - conf.period_finish = current_timestamp.saturating_add(conf.rewards_duration); - + conf.last_update_time = current_block_number; + conf.period_finish = current_block_number.saturating_add(conf.rewards_duration); IncentiveConfigs::::set(conf); + + Self::deposit_event(Event::RewardAdded { rewards }); Ok(()) } } diff --git a/pallets/ve-minting/src/lib.rs b/pallets/ve-minting/src/lib.rs index 4c284110f..15c045460 100644 --- a/pallets/ve-minting/src/lib.rs +++ b/pallets/ve-minting/src/lib.rs @@ -32,28 +32,28 @@ pub mod incentive; pub mod traits; pub mod weights; +use crate::traits::Incentive; use frame_support::{ pallet_prelude::*, sp_runtime::{ - traits::{AccountIdConversion, CheckedDiv, Saturating, UniqueSaturatedInto, Zero}, + traits::{ + AccountIdConversion, CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, Convert, + Saturating, UniqueSaturatedInto, Zero, + }, ArithmeticError, DispatchError, SaturatedConversion, }, - traits::{tokens::WithdrawReasons, Currency, LockIdentifier, LockableCurrency, UnixTime}, - transactional, PalletId, + PalletId, }; use frame_system::pallet_prelude::*; pub use incentive::*; -use node_primitives::{CurrencyId, Timestamp, TokenSymbol}; +use node_primitives::CurrencyId; use orml_traits::{MultiCurrency, MultiLockableCurrency}; pub use pallet::*; use sp_core::U256; -use sp_std::{collections::btree_map::BTreeMap, vec, vec::Vec}; +use sp_std::{borrow::ToOwned, collections::btree_map::BTreeMap, vec, vec::Vec}; use traits::VeMintingInterface; pub use weights::WeightInfo; -pub const COLLATOR_LOCK_ID: LockIdentifier = *b"vemintin"; -pub const BNC: CurrencyId = CurrencyId::Native(TokenSymbol::BNC); - #[allow(type_alias_bounds)] type BalanceOf = <::MultiCurrency as MultiCurrency>>::Balance; @@ -66,31 +66,24 @@ pub type CurrencyIdOf = <::MultiCurrency as MultiCurrency< >>::CurrencyId; #[derive(Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo, Default)] -pub struct VeConfig { +pub struct VeConfig { amount: Balance, min_mint: Balance, - min_time: Timestamp, - max_time: Timestamp, - multiplier: u128, - week: Timestamp, - vote_weight_multiplier: Balance, + min_block: BlockNumber, } #[derive(Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo, Default)] -pub struct LockedBalance { +pub struct LockedBalance { amount: Balance, - end: Timestamp, + end: BlockNumber, } -// pub type Epoch = U256; - #[derive(Clone, Copy, Encode, Decode, PartialEq, Eq, RuntimeDebug, TypeInfo, Default)] pub struct Point { - bias: Balance, // i128 - slope: Balance, // dweight / dt - ts: Timestamp, - blk: BlockNumber, // block - fxs_amt: Balance, + bias: i128, // i128 + slope: i128, // dweight / dt + block: BlockNumber, + amount: Balance, } #[frame_support::pallet] @@ -108,34 +101,88 @@ pub mod pallet { type MultiCurrency: MultiCurrency, CurrencyId = CurrencyId> + MultiLockableCurrency, CurrencyId = CurrencyId>; - type Currency: Currency + LockableCurrency; - type ControlOrigin: EnsureOrigin; type WeightInfo: WeightInfo; + #[pallet::constant] + type TokenType: Get; + #[pallet::constant] type VeMintingPalletId: Get; - type UnixTime: UnixTime; + #[pallet::constant] + type IncentivePalletId: Get; + + /// Convert the block number into a balance. + type BlockNumberToBalance: Convert>; + + #[pallet::constant] + type Week: Get; + + #[pallet::constant] + type MaxBlock: Get; + + #[pallet::constant] + type Multiplier: Get>; + + #[pallet::constant] + type VoteWeightMultiplier: Get>; } #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { - Created {}, - Minted { addr: AccountIdOf, value: BalanceOf, end: Timestamp, timestamp: Timestamp }, - Supply { supply_before: BalanceOf, supply: BalanceOf }, + ConfigSet { + config: VeConfig, T::BlockNumber>, + }, + Minted { + addr: AccountIdOf, + value: BalanceOf, + end: T::BlockNumber, + now: T::BlockNumber, + }, + Supply { + supply_before: BalanceOf, + supply: BalanceOf, + }, + LockCreated { + addr: AccountIdOf, + value: BalanceOf, + unlock_time: T::BlockNumber, + }, + UnlockTimeIncreased { + addr: AccountIdOf, + unlock_time: T::BlockNumber, + }, + AmountIncreased { + addr: AccountIdOf, + value: BalanceOf, + }, + Withdrawn { + addr: AccountIdOf, + value: BalanceOf, + }, + IncentiveSet { + rewards_duration: T::BlockNumber, + }, + RewardAdded { + rewards: Vec<(CurrencyIdOf, BalanceOf)>, + }, + Rewarded { + addr: AccountIdOf, + rewards: Vec<(CurrencyIdOf, BalanceOf)>, + }, } #[pallet::error] pub enum Error { NotEnoughBalance, - NotSupportProportion, - CalculationOverflow, - ExistentialDeposit, - DistributionNotExist, Expired, + BelowMinimumMint, + LockNotExist, + LockExist, + NoRewards, } #[pallet::storage] @@ -144,7 +191,8 @@ pub mod pallet { #[pallet::storage] #[pallet::getter(fn ve_configs)] - pub type VeConfigs = StorageValue<_, VeConfig>, ValueQuery>; + pub type VeConfigs = + StorageValue<_, VeConfig, T::BlockNumber>, ValueQuery>; #[pallet::storage] #[pallet::getter(fn epoch)] @@ -152,13 +200,19 @@ pub mod pallet { #[pallet::storage] #[pallet::getter(fn locked)] - pub type Locked = - StorageMap<_, Blake2_128Concat, AccountIdOf, LockedBalance>, ValueQuery>; + pub type Locked = StorageMap< + _, + Blake2_128Concat, + AccountIdOf, + LockedBalance, T::BlockNumber>, + ValueQuery, + >; + // Each week has a Point struct stored in PointHistory. #[pallet::storage] #[pallet::getter(fn point_history)] pub type PointHistory = - StorageMap<_, Twox64Concat, U256, Point, BlockNumberFor>, ValueQuery>; + StorageMap<_, Twox64Concat, U256, Point, T::BlockNumber>, ValueQuery>; #[pallet::storage] #[pallet::getter(fn user_point_history)] @@ -168,7 +222,7 @@ pub mod pallet { AccountIdOf, Blake2_128Concat, U256, - Point, BlockNumberFor>, + Point, T::BlockNumber>, ValueQuery, >; @@ -179,13 +233,14 @@ pub mod pallet { #[pallet::storage] #[pallet::getter(fn slope_changes)] - pub type SlopeChanges = StorageMap<_, Twox64Concat, Timestamp, i128, ValueQuery>; + pub type SlopeChanges = + StorageMap<_, Twox64Concat, T::BlockNumber, i128, ValueQuery>; // Incentive #[pallet::storage] #[pallet::getter(fn incentive_configs)] pub type IncentiveConfigs = - StorageValue<_, IncentiveConfig, BalanceOf>, ValueQuery>; + StorageValue<_, IncentiveConfig, BalanceOf, T::BlockNumber>, ValueQuery>; #[pallet::storage] #[pallet::getter(fn user_reward_per_token_paid)] @@ -208,12 +263,8 @@ pub mod pallet { #[pallet::weight(T::WeightInfo::set_minimum_mint())] pub fn set_config( origin: OriginFor, - min_mint: Option>, // Minimum mint balance - min_time: Option, // Minimum lockup time - max_time: Option, // Maximum lockup time - multiplier: Option, - week: Option, - vote_weight_multiplier: Option>, + min_mint: Option>, // Minimum mint balance + min_block: Option, // Minimum lockup time ) -> DispatchResult { T::ControlOrigin::ensure_origin(origin)?; @@ -221,24 +272,12 @@ pub mod pallet { if let Some(min_mint) = min_mint { ve_config.min_mint = min_mint; }; - if let Some(min_time) = min_time { - ve_config.min_time = min_time; - }; - if let Some(max_time) = max_time { - ve_config.max_time = max_time; - }; - if let Some(multiplier) = multiplier { - ve_config.multiplier = multiplier; + if let Some(min_block) = min_block { + ve_config.min_block = min_block; }; - if let Some(week) = week { - ve_config.week = week; - }; - if let Some(vote_weight_multiplier) = vote_weight_multiplier { - ve_config.vote_weight_multiplier = vote_weight_multiplier; - }; - VeConfigs::::set(ve_config); + VeConfigs::::set(ve_config.clone()); - Self::deposit_event(Event::Created {}); + Self::deposit_event(Event::ConfigSet { config: ve_config }); Ok(()) } @@ -247,100 +286,98 @@ pub mod pallet { pub fn create_lock( origin: OriginFor, value: BalanceOf, - unlock_time: Timestamp, + unlock_time: T::BlockNumber, ) -> DispatchResult { let exchanger: AccountIdOf = ensure_signed(origin)?; - Self::_create_lock(&exchanger, value, unlock_time)?; - Self::deposit_event(Event::Created {}); - Ok(()) + Self::create_lock_inner(&exchanger, value, unlock_time) } #[pallet::call_index(2)] #[pallet::weight(T::WeightInfo::mint())] pub fn increase_amount(origin: OriginFor, value: BalanceOf) -> DispatchResult { let exchanger: AccountIdOf = ensure_signed(origin)?; - Self::_increase_amount(&exchanger, value)?; - Self::deposit_event(Event::Created {}); - Ok(()) + Self::increase_amount_inner(&exchanger, value) } #[pallet::call_index(3)] #[pallet::weight(T::WeightInfo::mint())] - pub fn increase_unlock_time(origin: OriginFor, time: Timestamp) -> DispatchResult { + pub fn increase_unlock_time(origin: OriginFor, time: T::BlockNumber) -> DispatchResult { let exchanger = ensure_signed(origin)?; - Self::_increase_unlock_time(&exchanger, time)?; - Self::deposit_event(Event::Created {}); - Ok(()) + Self::increase_unlock_time_inner(&exchanger, time) } #[pallet::call_index(4)] #[pallet::weight(T::WeightInfo::mint())] pub fn withdraw(origin: OriginFor) -> DispatchResult { let exchanger = ensure_signed(origin)?; - Self::_withdraw(&exchanger)?; - Self::deposit_event(Event::Created {}); - Ok(()) + Self::withdraw_inner(&exchanger) } #[pallet::call_index(5)] #[pallet::weight(T::WeightInfo::set_minimum_mint())] pub fn notify_rewards( origin: OriginFor, - rewards_duration: Option, + incentive_from: AccountIdOf, + rewards_duration: Option, rewards: Vec<(CurrencyIdOf, BalanceOf)>, ) -> DispatchResult { T::ControlOrigin::ensure_origin(origin)?; + Self::set_incentive(rewards_duration); + Self::notify_reward_amount(&incentive_from, rewards) + } - if let Some(rewards_duration) = rewards_duration { - let mut incentive_config = Self::incentive_configs(); - incentive_config.rewards_duration = rewards_duration; - IncentiveConfigs::::set(incentive_config); - }; - - Self::notify_reward_amount(rewards)?; - Self::deposit_event(Event::Created {}); - Ok(()) + #[pallet::call_index(6)] + #[pallet::weight(T::WeightInfo::mint())] + pub fn get_rewards(origin: OriginFor) -> DispatchResult { + let exchanger = ensure_signed(origin)?; + Self::get_rewards_inner(&exchanger) } } impl Pallet { pub fn _checkpoint( addr: &AccountIdOf, - old_locked: LockedBalance>, - new_locked: LockedBalance>, + old_locked: LockedBalance, T::BlockNumber>, + new_locked: LockedBalance, T::BlockNumber>, ) -> DispatchResult { - let mut u_old = Point::, BlockNumberFor>::default(); - let mut u_new = Point::, BlockNumberFor>::default(); - let mut old_dslope: i128; // 0_i128; + Self::update_reward(Some(addr))?; + + let mut u_old = Point::, T::BlockNumber>::default(); + let mut u_new = Point::, T::BlockNumber>::default(); let mut new_dslope = 0_i128; let mut g_epoch: U256 = Self::epoch(); - let ve_config = Self::ve_configs(); - let current_block_number: BlockNumberFor = - frame_system::Pallet::::block_number().into(); // BlockNumberFor - let current_timestamp: Timestamp = T::UnixTime::now().as_millis().saturated_into(); + let current_block_number: T::BlockNumber = frame_system::Pallet::::block_number(); - if old_locked.end > current_timestamp && old_locked.amount > BalanceOf::::zero() { - u_old.slope = old_locked - .amount - .checked_div(&Self::ve_configs().max_time.saturated_into::>()) - .ok_or(Error::::CalculationOverflow)?; + if old_locked.end > current_block_number && old_locked.amount > BalanceOf::::zero() { + u_old.slope = U256::from(old_locked.amount.saturated_into::()) + .checked_div(U256::from(T::MaxBlock::get().saturated_into::())) + .unwrap_or_default() + .as_u128() + .unique_saturated_into(); u_old.bias = u_old .slope - .saturating_mul((old_locked.end - current_timestamp).saturated_into()); + .checked_mul( + (old_locked.end.saturated_into::() as i128) - + (current_block_number.saturated_into::() as i128), + ) + .ok_or(ArithmeticError::Overflow)?; } - if new_locked.end > current_timestamp && new_locked.amount > BalanceOf::::zero() { + if new_locked.end > current_block_number && new_locked.amount > BalanceOf::::zero() { u_new.slope = U256::from(new_locked.amount.saturated_into::()) - .checked_div(U256::from(Self::ve_configs().max_time.saturated_into::())) + .checked_div(U256::from(T::MaxBlock::get().saturated_into::())) .unwrap_or_default() .as_u128() .unique_saturated_into(); u_new.bias = u_new .slope - .saturating_mul((new_locked.end - current_timestamp).saturated_into()); + .checked_mul( + (new_locked.end.saturated_into::() as i128) - + (current_block_number.saturated_into::() as i128), + ) + .ok_or(ArithmeticError::Overflow)?; } - - old_dslope = Self::slope_changes(old_locked.end); - if new_locked.end != 0 { + let mut old_dslope = Self::slope_changes(old_locked.end); + if new_locked.end != Zero::zero() { if new_locked.end == old_locked.end { new_dslope = old_dslope } else { @@ -348,70 +385,70 @@ pub mod pallet { } } - let mut last_point: Point, BlockNumberFor> = Point { - bias: Zero::zero(), - slope: Zero::zero(), - ts: current_timestamp, - blk: current_block_number, - fxs_amt: Zero::zero(), + let mut last_point: Point, T::BlockNumber> = Point { + bias: 0_i128, + slope: 0_i128, + block: current_block_number, + amount: Zero::zero(), }; if g_epoch > U256::zero() { last_point = Self::point_history(g_epoch); } else { - last_point.fxs_amt = Self::balance_of(addr, None)?; - } - let mut last_checkpoint = last_point.ts; - let initial_last_point = last_point; - let mut block_slope: u128 = Zero::zero(); - if current_timestamp > last_point.ts { - block_slope = ve_config.multiplier * - (current_block_number - last_point.blk).saturated_into::() / - (current_timestamp - last_point.ts).saturated_into::() + last_point.amount = T::MultiCurrency::free_balance( + T::TokenType::get(), + &T::VeMintingPalletId::get().into_account_truncating(), + ); } - let mut t_i: Timestamp = (last_checkpoint / ve_config.week) * ve_config.week; + let mut last_checkpoint = last_point.block; + let mut t_i: T::BlockNumber = last_checkpoint + .checked_div(&T::Week::get()) + .ok_or(ArithmeticError::Overflow)? + .checked_mul(&T::Week::get()) + .ok_or(ArithmeticError::Overflow)?; for _i in 0..255 { - t_i += ve_config.week; + t_i += T::Week::get(); let mut d_slope = Zero::zero(); - if t_i > current_timestamp { - t_i = current_timestamp + if t_i > current_block_number { + t_i = current_block_number } else { d_slope = Self::slope_changes(t_i) } - last_point.bias = U256::from(last_point.bias.saturated_into::()) + last_point.bias = last_point + .bias .checked_sub( - U256::from(last_point.slope.saturated_into::()).saturating_mul( - U256::from((t_i - last_checkpoint).saturated_into::()), - ), + last_point + .slope + .checked_mul( + t_i.checked_sub(&last_checkpoint) + .ok_or(ArithmeticError::Overflow)? + .saturated_into::() + .unique_saturated_into(), + ) + .ok_or(ArithmeticError::Overflow)?, ) - .unwrap_or_default() - .as_u128() - .unique_saturated_into(); + .ok_or(ArithmeticError::Overflow)?; - last_point.slope += (d_slope as u128).saturated_into(); - if last_point.bias < Zero::zero() { - // This can happen - last_point.bias = Zero::zero() - } - if last_point.slope < Zero::zero() { + last_point.slope = + last_point.slope.checked_add(d_slope).ok_or(ArithmeticError::Overflow)?; + if last_point.slope < 0_i128 { //This cannot happen - just in case - last_point.slope = Zero::zero() + last_point.slope = 0_i128 } + if last_point.bias < 0_i128 { + // This can happen + last_point.bias = 0_i128 + } + last_checkpoint = t_i; - last_point.ts = t_i; - last_point.blk = initial_last_point.blk + - (block_slope.saturating_mul( - (t_i - initial_last_point.ts) - .try_into() - .map_err(|_| ArithmeticError::Overflow)?, - ) / ve_config.multiplier) - .try_into() - .map_err(|_| ArithmeticError::Overflow)?; + last_point.block = t_i; g_epoch += U256::one(); // Fill for the current block, if applicable - if t_i == current_timestamp { - last_point.blk = current_block_number; - last_point.fxs_amt = Self::balance_of(addr, None)?; + if t_i == current_block_number { + last_point.amount = T::MultiCurrency::free_balance( + T::TokenType::get(), + &T::VeMintingPalletId::get().into_account_truncating(), + ); break; } else { PointHistory::::insert(g_epoch, last_point); @@ -419,30 +456,41 @@ pub mod pallet { } Epoch::::set(g_epoch); - last_point.slope += u_new.slope - u_old.slope; - last_point.bias += u_new.bias - u_old.bias; - if last_point.slope < Zero::zero() { - last_point.slope = Zero::zero() + last_point.slope = u_new + .slope + .checked_add(last_point.slope) + .ok_or(ArithmeticError::Overflow)? + .checked_sub(u_old.slope) + .ok_or(ArithmeticError::Overflow)?; + last_point.bias = last_point + .bias + .checked_add(u_new.bias) + .ok_or(ArithmeticError::Overflow)? + .checked_sub(u_old.bias) + .ok_or(ArithmeticError::Overflow)?; + if last_point.slope < 0_i128 { + last_point.slope = 0_i128 } - if last_point.bias < Zero::zero() { - last_point.bias = Zero::zero() + if last_point.bias < 0_i128 { + last_point.bias = 0_i128 } PointHistory::::insert(g_epoch, last_point); - if old_locked.end > current_timestamp { + if old_locked.end > current_block_number { // old_dslope was - u_old.slope, so we cancel that - old_dslope += u_old.slope.saturated_into::() as i128; + old_dslope = + old_dslope.checked_add(u_old.slope).ok_or(ArithmeticError::Overflow)?; if new_locked.end == old_locked.end { - old_dslope -= u_new.slope.saturated_into::() as i128; + old_dslope = + old_dslope.checked_sub(u_new.slope).ok_or(ArithmeticError::Overflow)?; } // It was a new deposit, not extension SlopeChanges::::insert(old_locked.end, old_dslope); } - if new_locked.end > current_timestamp { + if new_locked.end > current_block_number { if new_locked.end > old_locked.end { - new_dslope = new_dslope - .checked_sub(u_new.slope.saturated_into::() as i128) - .ok_or(ArithmeticError::Overflow)?; + new_dslope = + new_dslope.checked_sub(u_new.slope).ok_or(ArithmeticError::Overflow)?; SlopeChanges::::insert(new_locked.end, new_dslope); } // else: we recorded it already in old_dslope @@ -451,12 +499,9 @@ pub mod pallet { // Now handle user history let user_epoch = Self::user_point_epoch(addr) + U256::one(); UserPointEpoch::::insert(addr, user_epoch); - u_new.ts = current_timestamp; - u_new.blk = current_block_number; - u_new.fxs_amt = Self::locked(addr).amount; - + u_new.block = current_block_number; + u_new.amount = Self::locked(addr).amount; UserPointHistory::::insert(addr, user_epoch, u_new); - Self::update_reward(Some(addr))?; Ok(()) } @@ -464,39 +509,133 @@ pub mod pallet { pub fn _deposit_for( addr: &AccountIdOf, value: BalanceOf, - unlock_time: Timestamp, - locked_balance: LockedBalance>, + unlock_time: T::BlockNumber, + locked_balance: LockedBalance, T::BlockNumber>, ) -> DispatchResult { - let ve_config = Self::ve_configs(); - ensure!(value >= ve_config.min_mint, Error::::Expired); - - let current_timestamp: Timestamp = T::UnixTime::now().as_millis().saturated_into(); - + let current_block_number: T::BlockNumber = frame_system::Pallet::::block_number(); let mut _locked = locked_balance; let supply_before = Self::supply(); Supply::::set(supply_before + value); let old_locked = _locked.clone(); _locked.amount += value; - if unlock_time != 0 { + if unlock_time != Zero::zero() { _locked.end = unlock_time } Locked::::insert(addr, _locked.clone()); - Self::_checkpoint(addr, old_locked, _locked.clone())?; - if value != BalanceOf::::zero() { - T::MultiCurrency::extend_lock(COLLATOR_LOCK_ID, BNC, addr, value)?; + T::MultiCurrency::transfer( + T::TokenType::get(), + addr, + &T::VeMintingPalletId::get().into_account_truncating(), + value, + )?; } + Self::_checkpoint(addr, old_locked, _locked.clone())?; Self::deposit_event(Event::Minted { addr: addr.clone(), value, end: _locked.end, - timestamp: current_timestamp, + now: current_block_number, }); Self::deposit_event(Event::Supply { supply_before, supply: supply_before + value }); Ok(()) } + + // Get the current voting power for `addr` + pub(crate) fn balance_of_current_block( + addr: &AccountIdOf, + ) -> Result, DispatchError> { + let current_block_number: T::BlockNumber = frame_system::Pallet::::block_number(); + let u_epoch = Self::user_point_epoch(addr); + if u_epoch == U256::zero() { + return Ok(Zero::zero()); + } else { + let mut last_point: Point, T::BlockNumber> = + Self::user_point_history(addr, u_epoch); + + last_point.bias = last_point + .bias + .checked_sub( + last_point + .slope + .checked_mul( + (current_block_number.saturated_into::() as i128) + .checked_sub(last_point.block.saturated_into::() as i128) + .ok_or(ArithmeticError::Overflow)?, + ) + .ok_or(ArithmeticError::Overflow)?, + ) + .ok_or(ArithmeticError::Overflow)?; + + if last_point.bias < 0_i128 { + last_point.bias = 0_i128 + } + + Ok(last_point + .amount + .checked_add( + &T::VoteWeightMultiplier::get() + .checked_mul(&(last_point.bias as u128).unique_saturated_into()) + .ok_or(ArithmeticError::Overflow)?, + ) + .ok_or(ArithmeticError::Overflow)?) + } + } + + // Measure voting power of `addr` at block height `block` + pub(crate) fn balance_of_at( + addr: &AccountIdOf, + block: T::BlockNumber, + ) -> Result, DispatchError> { + let current_block_number: T::BlockNumber = frame_system::Pallet::::block_number(); + ensure!(block <= current_block_number, Error::::Expired); + + // Binary search + let mut _min = U256::zero(); + let mut _max = Self::user_point_epoch(addr); + for _i in 0..128 { + if _min >= _max { + break; + } + let _mid = (_min + _max + 1) / 2; + + if Self::user_point_history(addr, _mid).block <= block { + _min = _mid + } else { + _max = _mid - 1 + } + } + + let mut upoint: Point, T::BlockNumber> = + Self::user_point_history(addr, _min); + upoint.bias = upoint + .bias + .checked_sub( + upoint + .slope + .checked_mul( + (block.saturated_into::() as i128) + .checked_sub(upoint.block.saturated_into::() as i128) + .ok_or(ArithmeticError::Overflow)?, + ) + .ok_or(ArithmeticError::Overflow)?, + ) + .ok_or(ArithmeticError::Overflow)?; + + if upoint.bias < 0_i128 { + upoint.bias = 0_i128 + } + Ok(upoint + .amount + .checked_add( + &T::VoteWeightMultiplier::get() + .checked_mul(&(upoint.bias as u128).unique_saturated_into()) + .ok_or(ArithmeticError::Overflow)?, + ) + .ok_or(ArithmeticError::Overflow)?) + } } } diff --git a/pallets/ve-minting/src/mock.rs b/pallets/ve-minting/src/mock.rs index 1b60d5cc2..1fccefa87 100644 --- a/pallets/ve-minting/src/mock.rs +++ b/pallets/ve-minting/src/mock.rs @@ -22,7 +22,6 @@ #![allow(non_upper_case_globals)] use crate as bifrost_ve_minting; -use crate::BNC; use bifrost_asset_registry::AssetIdMaps; use bifrost_runtime_common::{micro, milli}; use bifrost_slp::{QueryId, QueryResponseManager}; @@ -37,11 +36,13 @@ use frame_support::{ }; use frame_system::EnsureSignedBy; use hex_literal::hex; -use node_primitives::{CurrencyId, CurrencyIdMapping, Moment, TokenSymbol}; +use node_primitives::{CurrencyId, CurrencyIdMapping, TokenSymbol}; use sp_core::{blake2_256, H256}; use sp_runtime::{ testing::Header, - traits::{AccountIdConversion, BlakeTwo256, Convert, IdentityLookup, TrailingZeroInput}, + traits::{ + AccountIdConversion, BlakeTwo256, Convert, ConvertInto, IdentityLookup, TrailingZeroInput, + }, AccountId32, }; use xcm::{ @@ -58,8 +59,8 @@ pub type Amount = i128; pub type Balance = u128; pub type AccountId = AccountId32; -// pub const BNC: CurrencyId = CurrencyId::Native(TokenSymbol::BNC); -// pub const vBNC: CurrencyId = CurrencyId::VToken(TokenSymbol::BNC); +pub const BNC: CurrencyId = CurrencyId::Native(TokenSymbol::BNC); +pub const vBNC: CurrencyId = CurrencyId::VToken(TokenSymbol::BNC); pub const KSM: CurrencyId = CurrencyId::Token(TokenSymbol::KSM); pub const vKSM: CurrencyId = CurrencyId::VToken(TokenSymbol::KSM); pub const MOVR: CurrencyId = CurrencyId::Token(TokenSymbol::MOVR); @@ -78,7 +79,6 @@ frame_support::construct_runtime!( Tokens: orml_tokens::{Pallet, Call, Storage, Config, Event}, Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, Currencies: orml_currencies::{Pallet, Call, Storage}, - Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent}, VtokenMinting: bifrost_vtoken_minting::{Pallet, Call, Storage, Event}, Slp: bifrost_slp::{Pallet, Call, Storage, Event}, AssetRegistry: bifrost_asset_registry::{Pallet, Call, Event, Storage}, @@ -186,19 +186,6 @@ impl orml_tokens::Config for Runtime { type CurrencyHooks = (); } -use bifrost_runtime_common::constants::time::SLOT_DURATION; -parameter_types! { - pub const MinimumPeriod: Moment = SLOT_DURATION / 2; -} - -impl pallet_timestamp::Config for Runtime { - type MinimumPeriod = MinimumPeriod; - /// A timestamp: milliseconds since the unix epoch. - type Moment = Moment; - type OnTimestampSet = (); - type WeightInfo = (); -} - parameter_types! { pub const MaximumUnlockIdOfUser: u32 = 1_000; pub const MaximumUnlockIdOfTimeUnit: u32 = 1_000; @@ -240,19 +227,28 @@ impl bifrost_asset_registry::Config for Runtime { } parameter_types! { + pub const VeMintingTokenType: CurrencyId = CurrencyId::VToken(TokenSymbol::BNC); pub VeMintingPalletId: PalletId = PalletId(*b"bf/vemnt"); + pub IncentivePalletId: PalletId = PalletId(*b"bf/veict"); + pub const Week: BlockNumber = 50400; // a week + pub const MaxBlock: BlockNumber = 10512000; // four years + pub const Multiplier: Balance = 10_u128.pow(12); + pub const VoteWeightMultiplier: Balance = 3; } impl bifrost_ve_minting::Config for Runtime { type RuntimeEvent = RuntimeEvent; type MultiCurrency = Currencies; - type Currency = Balances; type ControlOrigin = EnsureSignedBy; + type TokenType = VeMintingTokenType; type VeMintingPalletId = VeMintingPalletId; - // type CurrencyIdConversion = AssetIdMaps; - // type CurrencyIdRegister = AssetIdMaps; + type IncentivePalletId = IncentivePalletId; type WeightInfo = (); - type UnixTime = Timestamp; + type BlockNumberToBalance = ConvertInto; + type Week = Week; + type MaxBlock = MaxBlock; + type Multiplier = Multiplier; + type VoteWeightMultiplier = VoteWeightMultiplier; } pub struct SubAccountIndexMultiLocationConvertor; @@ -357,13 +353,15 @@ impl ExtBuilder { pub fn one_hundred_for_alice_n_bob(self) -> Self { self.balances(vec![ - (ALICE, BNC, 1000000000000000000000), - (BOB, BNC, 1000000000000), - (BOB, vKSM, 1000), - (BOB, KSM, 1000000000000), - (BOB, MOVR, 1000000000000000000000), - (CHARLIE, MOVR, 100000000000000000000000), - (VeMintingPalletId::get().into_account_truncating(), KSM, 10000), + (ALICE, BNC, 1_000_000_000_000), + (ALICE, vBNC, 1_000_000_000_000_000), + (ALICE, KSM, 1_000_000_000_000), + (BOB, BNC, 1_000_000_000_000), + (BOB, vBNC, 1_000_000_000_000_000), + (BOB, vKSM, 1_000_000_000_000), + (BOB, MOVR, 1_000_000_000_000), + (CHARLIE, BNC, 1_000_000_000_000), + (CHARLIE, vBNC, 1_000_000_000_000_000), ]) } diff --git a/pallets/ve-minting/src/tests.rs b/pallets/ve-minting/src/tests.rs index e2aa997e7..3f897372a 100644 --- a/pallets/ve-minting/src/tests.rs +++ b/pallets/ve-minting/src/tests.rs @@ -23,7 +23,7 @@ use crate::{mock::*, traits::VeMintingInterface, *}; use bifrost_asset_registry::AssetMetadata; use bifrost_runtime_common::milli; -use frame_support::assert_ok; +use frame_support::{assert_noop, assert_ok}; use node_primitives::TokenInfo; #[test] @@ -31,23 +31,20 @@ fn _checkpoint() { ExtBuilder::default().one_hundred_for_alice_n_bob().build().execute_with(|| { asset_registry(); System::set_block_number(System::block_number() + 20); - let current_timestamp: node_primitives::Timestamp = ::UnixTime::now(); let old_locked = LockedBalance { amount: 0, end: 0 }; - let new_locked = - LockedBalance { amount: 10000000000000, end: current_timestamp + 365 * 86400 * 1000 }; + let new_locked = LockedBalance { + amount: 10000000000000, + end: System::block_number() + 365 * 86400 / 12, + }; assert_ok!(VeMinting::set_config( RuntimeOrigin::signed(ALICE), Some(0), - Some(7 * 86400 * 1000), - Some(4 * 365 * 86400), - Some(10_u128.pow(18)), - Some(7 * 86400), - Some(0) + Some(7 * 86400 / 12) )); System::set_block_number(System::block_number() + 20); assert_ok!(VeMinting::_checkpoint(&BOB, old_locked, new_locked)); - assert_eq!(VeMinting::balance_of(&BOB, Some(current_timestamp)), Ok(0)); + assert_eq!(VeMinting::balance_of(&BOB, Some(System::block_number())), Ok(7499936934420)); }); } @@ -59,26 +56,21 @@ fn update_reward() { assert_ok!(VeMinting::set_config( RuntimeOrigin::signed(ALICE), Some(0), - Some(7 * 86400 * 1000), - Some(4 * 365 * 86400 * 1000), - Some(10_u128.pow(12)), - Some(7 * 86400), - Some(0) + Some(7 * 86400 / 12) )); - System::set_block_number(System::block_number() + 20); - let current_timestamp: node_primitives::Timestamp = ::UnixTime::now(); - System::set_block_number(System::block_number() + 20); - assert_ok!(VeMinting::_create_lock( + System::set_block_number(System::block_number() + 40); + assert_ok!(VeMinting::create_lock_inner( &BOB, - 10000000000000, - current_timestamp + 365 * 86400 * 1000, + 100_000_000_000, + System::block_number() + 365 * 86400 / 12, )); - assert_ok!(VeMinting::deposit_for(&BOB, 10000000000000)); + assert_eq!(VeMinting::balance_of(&BOB, None), Ok(174785436640)); + assert_ok!(VeMinting::deposit_for(&BOB, 100_000_000_000)); assert_ok!(VeMinting::update_reward(Some(&BOB))); - assert_eq!(VeMinting::balance_of(&BOB, None), Ok(20000000000000)); - assert_eq!(VeMinting::balance_of(&BOB, Some(current_timestamp)), Ok(20000000000000)); + assert_eq!(VeMinting::balance_of(&BOB, None), Ok(349578735500)); + assert_eq!(VeMinting::balance_of(&BOB, Some(System::block_number())), Ok(349578735500)); }); } @@ -107,29 +99,193 @@ fn notify_reward_amount() { assert_ok!(VeMinting::set_config( RuntimeOrigin::signed(ALICE), Some(0), - Some(7 * 86400 * 1000), - Some(4 * 365 * 86400 * 1000), - Some(10_u128.pow(12)), - Some(7 * 86400), - Some(3) + Some(7 * 86400 / 12) )); - System::set_block_number(System::block_number() + 20); - let current_timestamp: node_primitives::Timestamp = ::UnixTime::now(); - System::set_block_number(System::block_number() + 20); - assert_ok!(VeMinting::_create_lock( + System::set_block_number(System::block_number() + 40); + assert_noop!( + VeMinting::get_rewards(RuntimeOrigin::signed(BOB)), + Error::::NoRewards + ); + assert_ok!(VeMinting::create_lock_inner( &BOB, - 10000000000000, - current_timestamp + 365 * 86400 * 1000 + 20_000_000_000, + System::block_number() + 4 * 365 * 86400 / 12 + )); + assert_eq!(Tokens::free_balance(KSM, &BOB), 0); + assert_noop!( + VeMinting::get_rewards(RuntimeOrigin::signed(BOB)), + Error::::NoRewards + ); + assert_ok!(VeMinting::increase_amount(RuntimeOrigin::signed(BOB), 80_000_000_000)); + assert_eq!(VeMinting::balance_of(&BOB, None), Ok(399146883040)); + + let rewards = vec![(KSM, 1_000_000_000)]; + assert_ok!(VeMinting::notify_rewards( + RuntimeOrigin::signed(ALICE), + ALICE, + Some(7 * 86400 / 12), + rewards.clone() + )); + assert_eq!(Tokens::free_balance(KSM, &BOB), 0); + System::set_block_number(System::block_number() + 20); + assert_eq!(Tokens::free_balance(KSM, &BOB), 0); + assert_ok!(VeMinting::get_rewards(RuntimeOrigin::signed(BOB))); + assert_eq!(Tokens::free_balance(KSM, &BOB), 396819); + System::set_block_number(System::block_number() + 7 * 86400 / 12); + assert_ok!(VeMinting::get_rewards_inner(&BOB)); + assert_eq!(Tokens::free_balance(KSM, &BOB), 999986398); + assert_ok!(VeMinting::notify_rewards( + RuntimeOrigin::signed(ALICE), + ALICE, + Some(7 * 86400 / 12), + rewards + )); + assert_ok!(VeMinting::create_lock_inner( + &CHARLIE, + 100_000_000_000, + System::block_number() + 4 * 365 * 86400 / 12 + )); + System::set_block_number(System::block_number() + 1 * 86400 / 12); + assert_ok!(VeMinting::get_rewards_inner(&BOB)); + assert_eq!(Tokens::free_balance(KSM, &BOB), 1071285014); + assert_ok!(VeMinting::get_rewards_inner(&CHARLIE)); + assert_eq!(Tokens::free_balance(KSM, &CHARLIE), 71556583); + System::set_block_number(System::block_number() + 7 * 86400 / 12); + assert_ok!(VeMinting::get_rewards_inner(&CHARLIE)); + assert_eq!(Tokens::free_balance(KSM, &CHARLIE), 500898890); + assert_ok!(VeMinting::get_rewards_inner(&BOB)); + assert_eq!(Tokens::free_balance(KSM, &BOB), 1499073906); + }); +} + +#[test] +fn create_lock_to_withdraw() { + ExtBuilder::default().one_hundred_for_alice_n_bob().build().execute_with(|| { + asset_registry(); + System::set_block_number(System::block_number() + 7 * 86400 / 12); // a week + assert_ok!(VeMinting::set_config( + RuntimeOrigin::signed(ALICE), + Some(4 * 365 * 86400 / 12), + Some(7 * 86400 / 12) )); + log::debug!( + "1System::block_number():{:?} total_supply:{:?}", + System::block_number(), + VeMinting::total_supply(System::block_number()) + ); + let rewards = vec![(KSM, 1000)]; assert_ok!(VeMinting::notify_rewards( RuntimeOrigin::signed(ALICE), - Some(7 * 86400), + ALICE, + Some(7 * 86400 / 12), rewards )); - assert_ok!(VeMinting::deposit_for(&BOB, 10000000000000)); - assert_ok!(VeMinting::update_reward(Some(&BOB))); + log::debug!( + "2System::block_number():{:?} total_supply:{:?}", + System::block_number(), + VeMinting::total_supply(System::block_number()) + ); + assert_noop!( + VeMinting::increase_amount(RuntimeOrigin::signed(BOB), 50_000_000_000_000), + Error::::LockNotExist + ); + assert_noop!( + VeMinting::increase_unlock_time( + RuntimeOrigin::signed(BOB), + System::block_number() + 365 * 86400 / 12 + ), + Error::::LockNotExist + ); + assert_noop!( + VeMinting::create_lock( + RuntimeOrigin::signed(BOB), + 50_000_000_000_000, + System::block_number() + 5 * 365 * 86400 / 12 + ), + Error::::Expired + ); + assert_noop!( + VeMinting::create_lock( + RuntimeOrigin::signed(BOB), + 50_000_000_000_000, + System::block_number() + 7 * 86400 / 12 - 1 + ), + Error::::Expired + ); + assert_noop!( + VeMinting::create_lock( + RuntimeOrigin::signed(BOB), + 50_000, + System::block_number() + 7 * 86400 / 12 + ), + Error::::BelowMinimumMint + ); + assert_ok!(VeMinting::create_lock_inner( + &BOB, + 50_000_000_000_000, + System::block_number() + 365 * 86400 / 12 + )); + assert_noop!( + VeMinting::create_lock_inner( + &BOB, + 50_000_000_000_000, + System::block_number() + 365 * 86400 / 12 + ), + Error::::LockExist + ); + assert_noop!( + VeMinting::increase_unlock_time( + RuntimeOrigin::signed(BOB), + System::block_number() + 5 * 365 * 86400 / 12 + ), + Error::::Expired + ); + assert_eq!(VeMinting::balance_of_at(&BOB, System::block_number()), Ok(87397254003200)); + assert_eq!(VeMinting::balance_of_at(&BOB, System::block_number() - 10), Ok(0)); + assert_eq!(VeMinting::balance_of_at(&BOB, 0), Ok(0)); + assert_eq!(VeMinting::balance_of(&BOB, Some(System::block_number() - 10)), Ok(0)); + assert_eq!(VeMinting::total_supply(System::block_number()), Ok(87397254003200)); + assert_noop!( + VeMinting::increase_amount(RuntimeOrigin::signed(BOB), 50_000), + Error::::BelowMinimumMint + ); + assert_ok!(VeMinting::increase_amount(RuntimeOrigin::signed(BOB), 50_000_000_000_000)); + log::debug!( + "3System::block_number():{:?} total_supply:{:?}", + System::block_number(), + VeMinting::total_supply(System::block_number()) + ); + assert_eq!(VeMinting::balance_of(&BOB, None), Ok(174794515868800)); + assert_eq!(VeMinting::total_supply(System::block_number()), Ok(174794515868800)); + + assert_ok!(VeMinting::withdraw(RuntimeOrigin::signed(ALICE))); + assert_noop!(VeMinting::withdraw(RuntimeOrigin::signed(BOB)), Error::::Expired); + assert_eq!(VeMinting::total_supply(System::block_number()), Ok(174794515868800)); + System::set_block_number(System::block_number() + 2 * 365 * 86400 / 12); + assert_eq!(VeMinting::balance_of(&BOB, None), Ok(100_000_000_000_000)); + assert_eq!(VeMinting::total_supply(System::block_number()), Ok(100_000_000_000_000)); + assert_ok!(VeMinting::withdraw(RuntimeOrigin::signed(BOB))); + assert_ok!(VeMinting::withdraw_inner(&BOB)); + log::debug!( + "5System::block_number():{:?} total_supply:{:?}", + System::block_number(), + VeMinting::total_supply(System::block_number()) + ); + assert_eq!(VeMinting::balance_of(&BOB, None), Ok(0)); + assert_eq!(VeMinting::total_supply(System::block_number()), Ok(0)); + }); +} + +#[test] +fn overflow() { + ExtBuilder::default().one_hundred_for_alice_n_bob().build().execute_with(|| { + asset_registry(); + assert_ok!(VeMinting::create_lock_inner(&BOB, 100_000_000_000_000, 77000)); + System::set_block_number(77001); + assert_eq!(VeMinting::balance_of(&BOB, Some(77001)), Ok(100_000_000_000_000)); + assert_eq!(VeMinting::total_supply(System::block_number()), Ok(100_000_000_000_000)); }); } diff --git a/pallets/ve-minting/src/traits.rs b/pallets/ve-minting/src/traits.rs index 3668c0a8d..def508b1a 100644 --- a/pallets/ve-minting/src/traits.rs +++ b/pallets/ve-minting/src/traits.rs @@ -18,180 +18,155 @@ // Ensure we're `no_std` when compiling for Wasm. use crate::*; -// use node_primitives::BlockNumber; pub trait VeMintingInterface { fn deposit_for(addr: &AccountId, value: Balance) -> DispatchResult; - fn _withdraw(addr: &AccountId) -> DispatchResult; - fn balance_of(addr: &AccountId, time: Option) -> Result; - fn balance_of_at(addr: &AccountId, block: BlockNumber) -> Result; - fn total_supply(t: Timestamp) -> Balance; - fn supply_at(point: Point, t: Timestamp) -> Balance; + fn withdraw_inner(addr: &AccountId) -> DispatchResult; + fn balance_of(addr: &AccountId, time: Option) -> Result; + fn total_supply(t: BlockNumber) -> Result; + fn supply_at( + point: Point, + t: BlockNumber, + ) -> Result; fn find_block_epoch(_block: BlockNumber, max_epoch: U256) -> U256; - fn _create_lock(addr: &AccountId, _value: Balance, _unlock_time: Timestamp) -> DispatchResult; // Deposit `_value` BNC for `addr` and lock until `_unlock_time` - fn _increase_amount(addr: &AccountId, value: Balance) -> DispatchResult; // Deposit `_value` additional BNC for `addr` without modifying the unlock time - fn _increase_unlock_time(addr: &AccountId, _unlock_time: Timestamp) -> DispatchResult; // Extend the unlock time for `addr` to `_unlock_time` + fn create_lock_inner( + addr: &AccountId, + _value: Balance, + _unlock_time: BlockNumber, + ) -> DispatchResult; // Deposit `_value` BNC for `addr` and lock until `_unlock_time` + fn increase_amount_inner(addr: &AccountId, value: Balance) -> DispatchResult; // Deposit `_value` additional BNC for `addr` without modifying the unlock time + fn increase_unlock_time_inner(addr: &AccountId, _unlock_time: BlockNumber) -> DispatchResult; // Extend the unlock time for `addr` to `_unlock_time` } -impl VeMintingInterface, CurrencyIdOf, BalanceOf, BlockNumberFor> +impl VeMintingInterface, CurrencyIdOf, BalanceOf, T::BlockNumber> for Pallet { - fn _create_lock( + fn create_lock_inner( addr: &AccountIdOf, _value: BalanceOf, - _unlock_time: Timestamp, + _unlock_time: T::BlockNumber, ) -> DispatchResult { let ve_config = Self::ve_configs(); - let _locked: LockedBalance> = Self::locked(addr); - let unlock_time: Timestamp = (_unlock_time / ve_config.week) * ve_config.week; + ensure!(_value >= ve_config.min_mint, Error::::BelowMinimumMint); - let current_timestamp: Timestamp = T::UnixTime::now().as_millis().saturated_into(); + let _locked: LockedBalance, T::BlockNumber> = Self::locked(addr); + let unlock_time: T::BlockNumber = _unlock_time + .checked_div(&T::Week::get()) + .ok_or(ArithmeticError::Overflow)? + .checked_mul(&T::Week::get()) + .ok_or(ArithmeticError::Overflow)?; + + let current_block_number: T::BlockNumber = frame_system::Pallet::::block_number(); ensure!( - unlock_time > ve_config.min_time.saturating_add(current_timestamp), + unlock_time >= ve_config.min_block.saturating_add(current_block_number), Error::::Expired ); ensure!( - unlock_time <= ve_config.max_time.saturating_add(current_timestamp), + unlock_time <= T::MaxBlock::get().saturating_add(current_block_number), Error::::Expired ); - ensure!(_locked.amount == BalanceOf::::zero(), Error::::Expired); // Withdraw old tokens first - ensure!(_value >= ve_config.min_mint, Error::::Expired); // need non-zero value - - Self::_deposit_for(addr, _value, unlock_time, _locked) + ensure!(_locked.amount == BalanceOf::::zero(), Error::::LockExist); // Withdraw old tokens first + + Self::_deposit_for(addr, _value, unlock_time, _locked)?; + Self::deposit_event(Event::LockCreated { + addr: addr.to_owned(), + value: _value, + unlock_time: _unlock_time, + }); + Ok(()) } - fn _increase_unlock_time(addr: &AccountIdOf, _unlock_time: Timestamp) -> DispatchResult { + fn increase_unlock_time_inner( + addr: &AccountIdOf, + _unlock_time: T::BlockNumber, + ) -> DispatchResult { let ve_config = Self::ve_configs(); - let _locked: LockedBalance> = Self::locked(addr); - let unlock_time: Timestamp = (_unlock_time / ve_config.week) * ve_config.week; - - let current_timestamp: Timestamp = T::UnixTime::now().as_millis().saturated_into(); - ensure!(_locked.end > current_timestamp, Error::::Expired); - ensure!(unlock_time >= ve_config.min_time.saturating_add(_locked.end), Error::::Expired); + let _locked: LockedBalance, T::BlockNumber> = Self::locked(addr); + let unlock_time: T::BlockNumber = _unlock_time + .checked_div(&T::Week::get()) + .ok_or(ArithmeticError::Overflow)? + .checked_mul(&T::Week::get()) + .ok_or(ArithmeticError::Overflow)?; + + let current_block_number: T::BlockNumber = frame_system::Pallet::::block_number(); ensure!( - unlock_time <= ve_config.max_time.saturating_add(current_timestamp), + unlock_time >= ve_config.min_block.saturating_add(_locked.end), Error::::Expired ); - ensure!(_locked.amount > BalanceOf::::zero(), Error::::Expired); // Withdraw old tokens first - - Self::_deposit_for(addr, BalanceOf::::zero(), unlock_time, _locked) + ensure!( + unlock_time <= T::MaxBlock::get().saturating_add(current_block_number), + Error::::Expired + ); + ensure!(_locked.amount > BalanceOf::::zero(), Error::::LockNotExist); + ensure!(_locked.end > current_block_number, Error::::Expired); // Cannot add to expired/non-existent lock + + Self::_deposit_for(addr, BalanceOf::::zero(), unlock_time, _locked)?; + Self::deposit_event(Event::UnlockTimeIncreased { + addr: addr.to_owned(), + unlock_time: _unlock_time, + }); + Ok(()) } - fn _increase_amount(addr: &AccountIdOf, value: BalanceOf) -> DispatchResult { - let _locked: LockedBalance> = Self::locked(addr); - Self::_deposit_for(addr, value, 0, _locked) + fn increase_amount_inner(addr: &AccountIdOf, value: BalanceOf) -> DispatchResult { + let ve_config = Self::ve_configs(); + ensure!(value >= ve_config.min_mint, Error::::BelowMinimumMint); + let _locked: LockedBalance, T::BlockNumber> = Self::locked(addr); + ensure!(_locked.amount > Zero::zero(), Error::::LockNotExist); // Need to be executed after create_lock + let current_block_number: T::BlockNumber = frame_system::Pallet::::block_number(); + ensure!(_locked.end > current_block_number, Error::::Expired); // Cannot add to expired/non-existent lock + Self::_deposit_for(addr, value, Zero::zero(), _locked)?; + Self::deposit_event(Event::AmountIncreased { addr: addr.to_owned(), value }); + Ok(()) } fn deposit_for(addr: &AccountIdOf, value: BalanceOf) -> DispatchResult { - let _locked: LockedBalance> = Self::locked(addr); - Self::_deposit_for(addr, value, 0, _locked) + let _locked: LockedBalance, T::BlockNumber> = Self::locked(addr); + Self::_deposit_for(addr, value, Zero::zero(), _locked) } - fn _withdraw(addr: &AccountIdOf) -> DispatchResult { + fn withdraw_inner(addr: &AccountIdOf) -> DispatchResult { let mut _locked = Self::locked(addr); - let current_timestamp: Timestamp = T::UnixTime::now().as_millis().saturated_into(); - ensure!(current_timestamp > _locked.end, Error::::Expired); + let current_block_number: T::BlockNumber = frame_system::Pallet::::block_number(); + ensure!(current_block_number >= _locked.end, Error::::Expired); let value = _locked.amount; - let old_locked: LockedBalance> = _locked.clone(); + let old_locked: LockedBalance, T::BlockNumber> = _locked.clone(); _locked.end = Zero::zero(); _locked.amount = Zero::zero(); Locked::::insert(addr, _locked.clone()); let supply_before = Self::supply(); - Supply::::set(supply_before - value); + Supply::::set(supply_before.saturating_sub(value)); - Self::_checkpoint(addr, old_locked, _locked.clone())?; + // BNC should be transferred before checkpoint + T::MultiCurrency::transfer( + T::TokenType::get(), + &T::VeMintingPalletId::get().into_account_truncating(), + addr, + value, + )?; - // TODO: set_lock - T::Currency::set_lock(COLLATOR_LOCK_ID, addr, Zero::zero(), WithdrawReasons::all()); + Self::_checkpoint(addr, old_locked, _locked.clone())?; - Self::deposit_event(Event::Supply { supply_before, supply: supply_before - value }); + Self::deposit_event(Event::Withdrawn { addr: addr.to_owned(), value }); + Self::deposit_event(Event::Supply { + supply_before, + supply: supply_before.saturating_sub(value), + }); Ok(()) } fn balance_of( addr: &AccountIdOf, - time: Option, + time: Option, ) -> Result, DispatchError> { - let _t = match time { - Some(_t) => _t, - None => T::UnixTime::now().as_millis().saturated_into(), - }; - let u_epoch = Self::user_point_epoch(addr); - if u_epoch == U256::zero() { - return Ok(Zero::zero()); - } else { - let mut last_point: Point, BlockNumberFor> = - Self::user_point_history(addr, u_epoch); - - last_point.bias -= last_point - .slope - .saturating_mul((_t.saturating_sub(last_point.ts)).saturated_into()); - if last_point.bias < Zero::zero() { - last_point.bias = Zero::zero(); - } - Ok(last_point.fxs_amt + (Self::ve_configs().vote_weight_multiplier * last_point.bias)) + match time { + Some(_t) => Self::balance_of_at(addr, _t), + None => Self::balance_of_current_block(addr), } } - fn balance_of_at( - addr: &AccountIdOf, - _block: BlockNumberFor, - ) -> Result, DispatchError> { - let current_block_number: BlockNumberFor = - frame_system::Pallet::::block_number().into(); - ensure!(_block <= current_block_number, Error::::Expired); - let current_timestamp: Timestamp = T::UnixTime::now().as_millis().saturated_into(); - - // Binary search - let mut _min = U256::zero(); - let mut _max = Self::user_point_epoch(addr); - for _i in 0..128 { - if _min >= _max { - break; - } - let _mid = (_min + _max + 1) / 2; - - if Self::user_point_history(addr, _mid).blk <= _block { - _min = _mid - } else { - _max = _mid - 1 - } - } - - let mut upoint: Point, BlockNumberFor> = - Self::user_point_history(addr, _min); - - let max_epoch: U256 = Self::epoch(); - let _epoch: U256 = Self::find_block_epoch(_block, max_epoch); - let point_0: Point, BlockNumberFor> = Self::point_history(_epoch); - let d_block; - let d_t; - if _epoch < max_epoch { - let point_1 = Self::point_history(_epoch + 1); - d_block = point_1.blk - point_0.blk; - d_t = point_1.ts - point_0.ts; - } else { - d_block = current_block_number - point_0.blk; - d_t = current_timestamp - point_0.ts; - } - - let mut block_time = point_0.ts; - if d_block != Zero::zero() { - block_time += d_t - .saturating_mul((_block - point_0.blk).saturated_into()) - .saturating_div(d_block.saturated_into()); - } - upoint.bias -= upoint.slope.saturating_mul((block_time - upoint.ts).saturated_into()); - - if (upoint.bias >= Zero::zero()) || (upoint.fxs_amt >= Zero::zero()) { - Ok(upoint.fxs_amt + (Self::ve_configs().vote_weight_multiplier * upoint.bias)) - } else { - Ok(Zero::zero()) - } - } - - fn find_block_epoch(_block: BlockNumberFor, max_epoch: U256) -> U256 { + fn find_block_epoch(_block: T::BlockNumber, max_epoch: U256) -> U256 { let mut _min = U256::zero(); let mut _max = max_epoch; for _i in 0..128 { @@ -200,7 +175,7 @@ impl VeMintingInterface, CurrencyIdOf, BalanceOf } let _mid = (_min + _max + 1) / 2; - if Self::point_history(_mid).blk <= _block { + if Self::point_history(_mid).block <= _block { _min = _mid } else { _max = _mid - 1 @@ -209,19 +184,25 @@ impl VeMintingInterface, CurrencyIdOf, BalanceOf _min } - fn total_supply(t: Timestamp) -> BalanceOf { + fn total_supply(t: T::BlockNumber) -> Result, DispatchError> { let g_epoch: U256 = Self::epoch(); let last_point = Self::point_history(g_epoch); Self::supply_at(last_point, t) } - fn supply_at(point: Point, BlockNumberFor>, t: Timestamp) -> BalanceOf { - let ve_config = Self::ve_configs(); - + fn supply_at( + point: Point, T::BlockNumber>, + t: T::BlockNumber, + ) -> Result, DispatchError> { let mut last_point = point; - let mut t_i: Timestamp = (last_point.ts / ve_config.week) * ve_config.week; + let mut t_i: T::BlockNumber = last_point + .block + .checked_div(&T::Week::get()) + .ok_or(ArithmeticError::Overflow)? + .checked_mul(&T::Week::get()) + .ok_or(ArithmeticError::Overflow)?; for _i in 0..255 { - t_i += ve_config.week; + t_i += T::Week::get(); let mut d_slope = Zero::zero(); if t_i > t { t_i = t @@ -229,25 +210,105 @@ impl VeMintingInterface, CurrencyIdOf, BalanceOf d_slope = Self::slope_changes(t_i) } - last_point.bias = U256::from(last_point.bias.saturated_into::()) + last_point.bias = last_point + .bias .checked_sub( - U256::from(last_point.slope.saturated_into::()) - .saturating_mul(U256::from((t_i - last_point.ts).saturated_into::())), + last_point + .slope + .checked_mul( + t_i.checked_sub(&last_point.block) + .ok_or(ArithmeticError::Overflow)? + .saturated_into::() + .unique_saturated_into(), + ) + .ok_or(ArithmeticError::Overflow)?, ) - .unwrap_or_default() - .as_u128() - .unique_saturated_into(); + .ok_or(ArithmeticError::Overflow)?; if t_i == t { break; } - last_point.slope += (d_slope as u128).saturated_into(); - last_point.ts = t_i + last_point.slope += d_slope; + last_point.block = t_i } - if last_point.bias < Zero::zero() { - last_point.bias = Zero::zero() + if last_point.bias < 0_i128 { + last_point.bias = 0_i128 } - last_point.fxs_amt + Self::ve_configs().vote_weight_multiplier * last_point.bias + Ok(last_point + .amount + .checked_add( + &T::VoteWeightMultiplier::get() + .checked_mul(&(last_point.bias as u128).unique_saturated_into()) + .ok_or(ArithmeticError::Overflow)?, + ) + .ok_or(ArithmeticError::Overflow)?) + } +} + +pub trait Incentive { + fn set_incentive(rewards_duration: Option); + fn add_reward( + addr: &AccountId, + conf: &mut IncentiveConfig, + rewards: &Vec<(CurrencyId, Balance)>, + remaining: Balance, + ) -> DispatchResult; +} + +impl Incentive, CurrencyIdOf, BalanceOf, T::BlockNumber> + for Pallet +{ + fn set_incentive(rewards_duration: Option) { + if let Some(rewards_duration) = rewards_duration { + let mut incentive_config = Self::incentive_configs(); + incentive_config.rewards_duration = rewards_duration; + IncentiveConfigs::::set(incentive_config); + Self::deposit_event(Event::IncentiveSet { rewards_duration }); + }; + } + fn add_reward( + addr: &AccountIdOf, + conf: &mut IncentiveConfig, BalanceOf, T::BlockNumber>, + rewards: &Vec<(CurrencyIdOf, BalanceOf)>, + remaining: BalanceOf, + ) -> DispatchResult { + rewards.iter().try_for_each(|(currency, reward)| -> DispatchResult { + let mut total_reward: BalanceOf = *reward; + if remaining != Zero::zero() { + let leftover: BalanceOf = conf + .reward_rate + .get(currency) + .unwrap_or(&Zero::zero()) + .checked_mul(&remaining) + .ok_or(ArithmeticError::Overflow)?; + total_reward = total_reward.saturating_add(leftover); + } + let currency_amount = T::MultiCurrency::free_balance( + *currency, + &T::IncentivePalletId::get().into_account_truncating(), + ); + // Make sure the new reward is less than or equal to the reward owned by the + // IncentivePalletId + ensure!( + total_reward <= currency_amount.saturating_add(*reward), + Error::::NotEnoughBalance + ); + let new_reward = total_reward + .checked_div(&T::BlockNumberToBalance::convert(conf.rewards_duration)) + .ok_or(ArithmeticError::Overflow)?; + conf.reward_rate + .entry(*currency) + .and_modify(|total_reward| { + *total_reward = new_reward; + }) + .or_insert(new_reward); + T::MultiCurrency::transfer( + *currency, + addr, + &T::IncentivePalletId::get().into_account_truncating(), + *reward, + ) + }) } } diff --git a/runtime/bifrost-kusama/Cargo.toml b/runtime/bifrost-kusama/Cargo.toml index 7b5e51a78..4ad32760f 100644 --- a/runtime/bifrost-kusama/Cargo.toml +++ b/runtime/bifrost-kusama/Cargo.toml @@ -109,8 +109,6 @@ bifrost-farming = { path = "../../pallets/farming", default-features = false } bifrost-farming-rpc-runtime-api = { path = "../../pallets/farming/rpc/runtime-api", default-features = false } parachain-staking = { path = "../../pallets/parachain-staking", default-features = false } bifrost-fee-share = { path = "../../pallets/fee-share", default-features = false } -bifrost-ve-minting = { path = "../../pallets/ve-minting", default-features = false } -bifrost-ve-minting-rpc-runtime-api = { path = "../../pallets/ve-minting/rpc/runtime-api", default-features = false } # orml orml-currencies = { version = "0.4.1-dev", default-features = false } @@ -217,8 +215,6 @@ std = [ "bifrost-cross-in-out/std", "parachain-staking/std", "bifrost-fee-share/std", - "bifrost-ve-minting/std", - "bifrost-ve-minting-rpc-runtime-api/std", "zenlink-protocol/std", "zenlink-protocol-runtime-api/std", "zenlink-stable-amm/std", @@ -329,7 +325,6 @@ try-runtime = [ "bifrost-system-maker/try-runtime", "bifrost-fee-share/try-runtime", "bifrost-cross-in-out/try-runtime", - "bifrost-ve-minting/try-runtime", ] # When enabled, the runtime API will not be build. diff --git a/runtime/bifrost-kusama/src/lib.rs b/runtime/bifrost-kusama/src/lib.rs index 8a648a4b5..ee92252ad 100644 --- a/runtime/bifrost-kusama/src/lib.rs +++ b/runtime/bifrost-kusama/src/lib.rs @@ -50,7 +50,7 @@ pub use pallet_timestamp::Call as TimestampCall; pub use parachain_staking::{InflationInfo, Range}; use sp_api::impl_runtime_apis; use sp_arithmetic::Percent; -use sp_core::{OpaqueMetadata, U256}; +use sp_core::OpaqueMetadata; #[cfg(any(feature = "std", test))] pub use sp_runtime::BuildStorage; use sp_runtime::{ @@ -81,7 +81,6 @@ pub use bifrost_runtime_common::{ SlowAdjustingFeeUpdate, TechnicalCollective, }; use bifrost_slp::QueryId; -use bifrost_ve_minting::traits::VeMintingInterface; use codec::{Decode, Encode, MaxEncodedLen}; use constants::currency::*; use cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases; @@ -310,7 +309,6 @@ parameter_types! { pub const BuybackPalletId: PalletId = PalletId(*b"bf/salpc"); pub const SystemMakerPalletId: PalletId = PalletId(*b"bf/sysmk"); pub const FeeSharePalletId: PalletId = PalletId(*b"bf/feesh"); - pub const VeMintingPalletId: PalletId = PalletId(*b"bf/vemnt"); pub CheckingAccount: AccountId = PolkadotXcm::check_account(); } @@ -662,7 +660,7 @@ impl pallet_membership::Config for Runtime { } parameter_types! { - pub CandidacyBond: Balance = 100 * dollar::(NativeCurrencyId::get()); + pub CandidacyBond: Balance = 10_000 * dollar::(NativeCurrencyId::get()); // 1 storage item created, key size is 32 bytes, value size is 16+16. pub VotingBondBase: Balance = deposit::(1, 64); // additional data per vote is 32 bytes (account id). @@ -1486,6 +1484,7 @@ impl bifrost_cross_in_out::Config for Runtime { type RuntimeEvent = RuntimeEvent; type MultiCurrency = Currencies; type ControlOrigin = EitherOfDiverse; + type EntrancePalletId = SlpEntrancePalletId; type WeightInfo = bifrost_cross_in_out::weights::BifrostWeight; } @@ -1640,16 +1639,6 @@ impl bifrost_vtoken_minting::Config for Runtime { type CurrencyIdRegister = AssetIdMaps; } -impl bifrost_ve_minting::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type MultiCurrency = Currencies; - type Currency = Balances; - type ControlOrigin = EitherOfDiverse; - type VeMintingPalletId = VeMintingPalletId; - type WeightInfo = (); - type UnixTime = Timestamp; -} - // Below is the implementation of tokens manipulation functions other than native token. pub struct LocalAssetAdaptor(PhantomData); @@ -1829,7 +1818,6 @@ construct_runtime! { SystemMaker: bifrost_system_maker::{Pallet, Call, Storage, Event} = 121, FeeShare: bifrost_fee_share::{Pallet, Call, Storage, Event} = 122, CrossInOut: bifrost_cross_in_out::{Pallet, Call, Storage, Event} = 123, - VeMinting: bifrost_ve_minting::{Pallet, Call, Storage, Event} = 124, } } @@ -2175,28 +2163,6 @@ impl_runtime_apis! { } } - impl bifrost_ve_minting_rpc_runtime_api::VeMintingRuntimeApi for Runtime { - fn balance_of( - who: AccountId, - t: Option, - ) -> Balance{ - VeMinting::balance_of(&who, t).unwrap_or(Zero::zero()) - } - - fn total_supply( - t: node_primitives::Timestamp, - ) -> Balance{ - VeMinting::total_supply(t) - } - - fn find_block_epoch( - block: node_primitives::BlockNumber, - max_epoch: U256, - ) -> U256{ - VeMinting::find_block_epoch(block, max_epoch) - } - } - #[cfg(feature = "runtime-benchmarks")] impl frame_benchmarking::Benchmark for Runtime { fn benchmark_metadata(extra: bool) -> ( diff --git a/runtime/bifrost-polkadot/Cargo.toml b/runtime/bifrost-polkadot/Cargo.toml index 989d0de5f..060ecfed5 100644 --- a/runtime/bifrost-polkadot/Cargo.toml +++ b/runtime/bifrost-polkadot/Cargo.toml @@ -45,7 +45,7 @@ pallet-aura = { git = "https://github.com/paritytech/substrate", branch = "polka pallet-authorship = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.37", default-features = false } pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.37", default-features = false } pallet-bounties = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.37", default-features = false } -pallet-collective = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.37",default-features = false } +pallet-collective = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.37", default-features = false } pallet-democracy = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.37", default-features = false } pallet-elections-phragmen = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.37", default-features = false } pallet-identity = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.37", default-features = false } @@ -95,12 +95,14 @@ bifrost-slp = { path = "../../pallets/slp", default-features = false } bifrost-vtoken-minting = { path = "../../pallets/vtoken-minting", default-features = false } bifrost-system-staking = { path = "../../pallets/system-staking", default-features = false } bifrost-system-maker = { path = "../../pallets/system-maker", default-features = false } - +bifrost-cross-in-out = { path = "../../pallets/cross-in-out", default-features = false } bifrost-asset-registry = { path = "../../pallets/asset-registry", default-features = false } bifrost-vstoken-conversion = { path = "../../pallets/vstoken-conversion", default-features = false } bifrost-farming = { path = "../../pallets/farming", default-features = false } bifrost-farming-rpc-runtime-api = { path = "../../pallets/farming/rpc/runtime-api", default-features = false } bifrost-fee-share = { path = "../../pallets/fee-share", default-features = false } +bifrost-ve-minting = { path = "../../pallets/ve-minting", default-features = false } +bifrost-ve-minting-rpc-runtime-api = { path = "../../pallets/ve-minting/rpc/runtime-api", default-features = false } # orml orml-currencies = { version = "0.4.1-dev", default-features = false } @@ -196,9 +198,12 @@ std = [ "bifrost-system-staking/std", "bifrost-system-maker/std", "bifrost-fee-share/std", + "bifrost-ve-minting/std", + "bifrost-ve-minting-rpc-runtime-api/std", "zenlink-protocol/std", "zenlink-protocol-runtime-api/std", "merkle-distributor/std", + "bifrost-cross-in-out/std", ] with-tracing = ["frame-executive/with-tracing"] @@ -223,6 +228,7 @@ runtime-benchmarks = [ "bifrost-slp/runtime-benchmarks", "bifrost-salp/runtime-benchmarks", "bifrost-vtoken-minting/runtime-benchmarks", + "bifrost-cross-in-out/runtime-benchmarks", "sp-api/disable-logging", ] @@ -279,6 +285,8 @@ try-runtime = [ "bifrost-system-staking/try-runtime", "bifrost-system-maker/try-runtime", "bifrost-fee-share/try-runtime", + "bifrost-ve-minting/try-runtime", + "bifrost-cross-in-out/try-runtime", ] # When enabled, the runtime API will not be build. diff --git a/runtime/bifrost-polkadot/src/lib.rs b/runtime/bifrost-polkadot/src/lib.rs index dafeb8f38..e7fa54bce 100644 --- a/runtime/bifrost-polkadot/src/lib.rs +++ b/runtime/bifrost-polkadot/src/lib.rs @@ -35,8 +35,8 @@ pub use frame_support::{ construct_runtime, match_types, parameter_types, traits::{ ConstU32, ConstU64, ConstU8, Contains, EqualPrivilegeOnly, Everything, Imbalance, - InstanceFilter, IsInVec, LockIdentifier, NeverEnsureOrigin, Nothing, OnUnbalanced, - Randomness, + InstanceFilter, IsInVec, LockIdentifier, NeverEnsureOrigin, Nothing, OnRuntimeUpgrade, + OnUnbalanced, Randomness, }, weights::{ constants::{ @@ -51,7 +51,7 @@ pub use pallet_balances::Call as BalancesCall; pub use pallet_timestamp::Call as TimestampCall; use sp_api::impl_runtime_apis; use sp_arithmetic::Percent; -use sp_core::OpaqueMetadata; +use sp_core::{OpaqueMetadata, U256}; #[cfg(any(feature = "std", test))] pub use sp_runtime::BuildStorage; use sp_runtime::{ @@ -78,6 +78,7 @@ use bifrost_runtime_common::{ TechnicalCollective, }; use bifrost_slp::QueryId; +use bifrost_ve_minting::traits::VeMintingInterface; use codec::{Decode, Encode, MaxEncodedLen}; use constants::currency::*; use cumulus_primitives_core::ParaId as CumulusParaId; @@ -299,6 +300,8 @@ parameter_types! { pub const SystemMakerPalletId: PalletId = PalletId(*b"bf/sysmk"); pub const FeeSharePalletId: PalletId = PalletId(*b"bf/feesh"); pub CheckingAccount: AccountId = PolkadotXcm::check_account(); + pub const VeMintingPalletId: PalletId = PalletId(*b"bf/vemnt"); + pub const IncentivePalletId: PalletId = PalletId(*b"bf/veict"); } impl frame_system::Config for Runtime { @@ -649,7 +652,7 @@ impl pallet_membership::Config for Runtime { } parameter_types! { - pub const CandidacyBond: Balance = 100 * DOLLARS; + pub const CandidacyBond: Balance = 10_000 * DOLLARS; // 1 storage item created, key size is 32 bytes, value size is 16+16. pub const VotingBondBase: Balance = deposit(1, 64); // additional data per vote is 32 bytes (account id). @@ -1262,6 +1265,14 @@ impl bifrost_fee_share::Config for Runtime { type FeeSharePalletId = FeeSharePalletId; } +impl bifrost_cross_in_out::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type MultiCurrency = Currencies; + type ControlOrigin = EitherOfDiverse; + type EntrancePalletId = SlpEntrancePalletId; + type WeightInfo = bifrost_cross_in_out::weights::BifrostWeight; +} + // Bifrost modules end // zenlink runtime start @@ -1366,6 +1377,29 @@ impl bifrost_vtoken_minting::Config for Runtime { type CurrencyIdRegister = AssetIdMaps; } +parameter_types! { + pub const VeMintingTokenType: CurrencyId = CurrencyId::VToken(TokenSymbol::BNC); + pub const Week: BlockNumber = WEEKS; + pub const MaxBlock: BlockNumber = 4 * 365 * DAYS; + pub const Multiplier: Balance = 10_u128.pow(12); + pub const VoteWeightMultiplier: Balance = 3; +} + +impl bifrost_ve_minting::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type MultiCurrency = Currencies; + type ControlOrigin = EitherOfDiverse; + type TokenType = VeMintingTokenType; + type VeMintingPalletId = VeMintingPalletId; + type IncentivePalletId = IncentivePalletId; + type WeightInfo = (); + type BlockNumberToBalance = ConvertInto; + type Week = Week; + type MaxBlock = MaxBlock; + type Multiplier = Multiplier; + type VoteWeightMultiplier = VoteWeightMultiplier; +} + // Below is the implementation of tokens manipulation functions other than native token. pub struct LocalAssetAdaptor(PhantomData); @@ -1536,6 +1570,8 @@ construct_runtime! { SystemStaking: bifrost_system_staking::{Pallet, Call, Storage, Event} = 120, SystemMaker: bifrost_system_maker::{Pallet, Call, Storage, Event} = 121, FeeShare: bifrost_fee_share::{Pallet, Call, Storage, Event} = 122, + CrossInOut: bifrost_cross_in_out::{Pallet, Call, Storage, Event} = 123, + VeMinting: bifrost_ve_minting::{Pallet, Call, Storage, Event} = 124, } } @@ -1582,7 +1618,10 @@ pub type Executive = frame_executive::Executive< frame_system::ChainContext, Runtime, AllPalletsWithSystem, - pallet_balances::migration::MigrateToTrackInactive, + ( + pallet_balances::migration::MigrateToTrackInactive, + SalpOnRuntimeUpgrade, + ), >; #[cfg(feature = "runtime-benchmarks")] @@ -1799,6 +1838,28 @@ impl_runtime_apis! { } } + impl bifrost_ve_minting_rpc_runtime_api::VeMintingRuntimeApi for Runtime { + fn balance_of( + who: AccountId, + t: Option, + ) -> Balance{ + VeMinting::balance_of(&who, t).unwrap_or(Zero::zero()) + } + + fn total_supply( + t: node_primitives::BlockNumber, + ) -> Balance{ + VeMinting::total_supply(t).unwrap_or(Zero::zero()) + } + + fn find_block_epoch( + block: node_primitives::BlockNumber, + max_epoch: U256, + ) -> U256{ + VeMinting::find_block_epoch(block, max_epoch) + } + } + #[cfg(feature = "runtime-benchmarks")] impl frame_benchmarking::Benchmark for Runtime { fn benchmark_metadata(extra: bool) -> ( @@ -1855,6 +1916,43 @@ impl_runtime_apis! { } } +pub struct SalpOnRuntimeUpgrade(PhantomData); +impl OnRuntimeUpgrade for SalpOnRuntimeUpgrade { + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result, &'static str> { + #[allow(unused_imports)] + use frame_support::{migration, Identity}; + log::info!("Bifrost `pre_upgrade`..."); + + let redeem_pool: _ = bifrost_salp::RedeemPool::::get(); + log::info!("Old redeem_pool is {:?}", redeem_pool); + + Ok(vec![]) + } + + fn on_runtime_upgrade() -> Weight { + log::info!("Bifrost `on_runtime_upgrade`..."); + + let weight = bifrost_salp::migration::update_redeem_pool::(); + + log::info!("Bifrost `on_runtime_upgrade finished`"); + + weight + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade(_: sp_std::prelude::Vec) -> Result<(), &'static str> { + #[allow(unused_imports)] + use frame_support::{migration, Identity}; + log::info!("Bifrost `post_upgrade`..."); + + let redeem_pool: _ = bifrost_salp::RedeemPool::::get(); + log::info!("New redeem_pool is {:?}", redeem_pool); + + Ok(()) + } +} + struct CheckInherents; impl cumulus_pallet_parachain_system::CheckInherents for CheckInherents {