diff --git a/Cargo.lock b/Cargo.lock index 5d9122d9ab..9b04247ca5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1346,6 +1346,7 @@ dependencies = [ name = "bifrost-kusama-runtime" version = "0.8.0" dependencies = [ + "anyhow", "bifrost-asset-registry", "bifrost-channel-commission", "bifrost-cross-in-out", @@ -1391,6 +1392,7 @@ dependencies = [ "frame-system-rpc-runtime-api", "frame-try-runtime", "hex-literal 0.4.1", + "ismp", "lend-market", "lend-market-rpc-runtime-api", "leverage-staking", @@ -2204,6 +2206,7 @@ dependencies = [ name = "bifrost-slpx" version = "0.8.0" dependencies = [ + "anyhow", "bifrost-asset-registry", "bifrost-currencies", "bifrost-primitives", @@ -2222,13 +2225,16 @@ dependencies = [ "frame-system", "hex", "hex-literal 0.4.1", + "ismp", "log", "orml-tokens", "orml-traits", "orml-xtokens", "pallet-balances", "pallet-collective", + "pallet-ismp", "pallet-staking", + "pallet-timestamp", "pallet-xcm", "parity-scale-codec", "polkadot-parachain-primitives", @@ -2244,7 +2250,6 @@ dependencies = [ "staging-xcm-builder", "staging-xcm-executor", "tiny-keccak", - "xcm-simulator", "zenlink-protocol", ] diff --git a/pallets/slpx/Cargo.toml b/pallets/slpx/Cargo.toml index ff9bf3ee6b..9893db53c7 100644 --- a/pallets/slpx/Cargo.toml +++ b/pallets/slpx/Cargo.toml @@ -41,6 +41,9 @@ xcm-executor = { workspace = true } xcm-builder = { workspace = true } polkadot-primitives = { workspace = true } pallet-staking = { workspace = true } +pallet-ismp = { workspace = true, default-features = false } +ismp = { workspace = true, default-features = false } +anyhow = { workspace = true } [dev-dependencies] hex = { workspace = true } @@ -50,10 +53,11 @@ bifrost-vtoken-minting = { workspace = true } bifrost-slp = { workspace = true } cumulus-primitives-core = { workspace = true } bifrost-currencies = { workspace = true } -xcm-simulator = { workspace = true } bifrost-runtime-common = { workspace = true } pallet-collective = { workspace = true } parachain-info = { workspace = true } +pallet-timestamp = { workspace = true } +pallet-ismp = { workspace = true, default-features = false, features = [ "testing", "unsigned" ] } [features] @@ -85,6 +89,9 @@ std = [ "xcm-builder/std", "polkadot-primitives/std", "pallet-staking/std", + "pallet-ismp/std", + "ismp/std", + "anyhow/std", ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", @@ -96,4 +103,4 @@ runtime-benchmarks = [ "pallet-staking/runtime-benchmarks", ] try-runtime = ["frame-support/try-runtime"] -with-bifrost-polkadot-runtime = [] +polkadot = [] diff --git a/pallets/slpx/src/lib.rs b/pallets/slpx/src/lib.rs index bdbe9b5b5a..e96192d7ce 100644 --- a/pallets/slpx/src/lib.rs +++ b/pallets/slpx/src/lib.rs @@ -19,8 +19,8 @@ #![cfg_attr(not(feature = "std"), no_std)] use crate::types::{ AccountIdOf, BalanceOf, CurrencyIdOf, EthereumCallConfiguration, EthereumXcmCall, - EthereumXcmTransaction, EthereumXcmTransactionV2, MoonbeamCall, Order, OrderCaller, OrderType, - SupportChain, TargetChain, EVM_FUNCTION_SELECTOR, MAX_GAS_LIMIT, + EthereumXcmTransaction, EthereumXcmTransactionV2, MoonbeamCall, OracleConfig, Order, + OrderCaller, OrderType, SupportChain, TargetChain, EVM_FUNCTION_SELECTOR, MAX_GAS_LIMIT, }; use bifrost_asset_registry::AssetMetadata; use bifrost_primitives::{ @@ -37,14 +37,21 @@ use frame_support::{ pallet_prelude::ConstU32, sp_runtime::SaturatedConversion, traits::Get, - transactional, + transactional, PalletId, }; use frame_system::{ ensure_signed, pallet_prelude::{BlockNumberFor, OriginFor}, }; +use ismp::dispatcher::IsmpDispatcher; +#[cfg(feature = "polkadot")] +use ismp::{ + dispatcher::{DispatchPost, DispatchRequest, FeeMetadata}, + host::StateMachine, +}; use orml_traits::{MultiCurrency, XcmTransfer}; pub use pallet::*; +use pallet_ismp::ModuleId; use parity_scale_codec::{Decode, Encode}; use polkadot_parachain_primitives::primitives::{Id, Sibling}; use sp_core::{Hasher, H160, U256}; @@ -74,10 +81,12 @@ mod tests; #[cfg(feature = "runtime-benchmarks")] mod benchmarking; +/// [`PalletId`] where protocol fees will be collected +pub const PALLET_ID: ModuleId = ModuleId::Pallet(PalletId(*b"bif-slpx")); + #[frame_support::pallet] pub mod pallet { use super::*; - use crate::types::Order; use frame_support::{ pallet_prelude::{ValueQuery, *}, weights::WeightMeter, @@ -115,6 +124,9 @@ pub mod pallet { type XcmSender: SendXcm; /// Convert Location to `T::CurrencyId`. type CurrencyIdConvert: CurrencyIdMapping>>; + /// Ismp message disptacher + type IsmpHost: IsmpDispatcher, Balance = BalanceOf> + + Default; /// TreasuryAccount #[pallet::constant] type TreasuryAccount: Get>; @@ -218,6 +230,16 @@ pub mod pallet { XcmOracleFailed { error: DispatchError }, /// Withdraw xcm fee InsufficientAssets, + /// Set HyperBridge Oracle Config + SetHyperBridgeOracleConfig { + chain_id: u32, + to: H160, + timeout: u64, + payer: AccountIdOf, + fee: BalanceOf, + period: BlockNumberFor, + tokens: BoundedVec<(CurrencyId, H160), ConstU32<10>>, + }, } #[pallet::error] @@ -304,6 +326,16 @@ pub mod pallet { #[pallet::storage] pub type DelayBlock = StorageValue<_, BlockNumberFor, ValueQuery>; + /// HyperBridge Oracle Config + #[pallet::storage] + pub type HyperBridgeOracleConfig = StorageMap< + _, + Blake2_128Concat, + u32, + OracleConfig, BalanceOf, BlockNumberFor>, + OptionQuery, + >; + #[pallet::hooks] impl Hooks> for Pallet { fn on_idle(_: BlockNumberFor, limit: Weight) -> Weight { @@ -329,6 +361,11 @@ pub mod pallet { if !is_handle_xcm_oracle { let _ = Self::handle_order_queue(current_block_number, &mut weight); + }; + + #[cfg(feature = "polkadot")] + if !is_handle_xcm_oracle { + let _ = Self::handle_hyperbridge_oracle(current_block_number, &mut weight); } weight } @@ -781,6 +818,51 @@ pub mod pallet { // }; // Ok(().into()) // } + + // Set Hyperbridge oracle configuration + /// Parameters: + /// - `chain_id`: The chain id of destination chain + /// - `to`: The address of destination contract + /// - `timeout`: The timeout of the oracle + /// - `payer`: The payer of the oracle + /// - `fee`: The fee of the oracle + /// - `tokens`: The tokens of the oracle + #[pallet::call_index(15)] + #[pallet::weight(::WeightInfo::set_transfer_to_fee())] + pub fn set_hyperbridge_oracle( + origin: OriginFor, + chain_id: u32, + to: H160, + timeout: u64, + payer: T::AccountId, + fee: BalanceOf, + period: BlockNumberFor, + tokens: BoundedVec<(CurrencyId, H160), ConstU32<10>>, + ) -> DispatchResultWithPostInfo { + T::ControlOrigin::ensure_origin(origin)?; + HyperBridgeOracleConfig::::insert( + chain_id, + OracleConfig { + to, + timeout, + payer: payer.clone(), + fee, + period, + last_block: Default::default(), + tokens: tokens.clone(), + }, + ); + Self::deposit_event(Event::SetHyperBridgeOracleConfig { + chain_id, + to, + timeout, + payer, + fee, + period, + tokens, + }); + Ok(().into()) + } } } @@ -1331,6 +1413,79 @@ impl Pallet { return Ok(()); } } + + #[cfg(feature = "polkadot")] + #[transactional] + pub fn handle_hyperbridge_oracle( + current_block_number: BlockNumberFor, + weight: &mut Weight, + ) -> DispatchResult { + let dispatcher = T::IsmpHost::default(); + for ( + dest, + OracleConfig { + to, + timeout, + payer, + fee, + period, + last_block, + tokens, + }, + ) in HyperBridgeOracleConfig::::iter() + { + if last_block + period < current_block_number { + for (currency, token) in tokens.clone() { + let staking_currency_amount = + T::VtokenMintingInterface::get_token_pool(currency); + let v_currency_id = currency + .to_vtoken() + .map_err(|_| Error::::ErrorConvertVtoken)?; + + let v_currency_total_supply = T::MultiCurrency::total_issuance(v_currency_id); + let uint256_token_amount = + U256::from(staking_currency_amount.saturated_into::()); + let uint256_vtoken_amount = + U256::from(v_currency_total_supply.saturated_into::()); + + let body = ethabi::encode(&[ + ethabi::Token::Address(token), + ethabi::Token::Uint(uint256_token_amount), + ethabi::Token::Uint(uint256_vtoken_amount), + ]); + dispatcher + .dispatch_request( + DispatchRequest::Post(DispatchPost { + dest: StateMachine::Evm(dest), + from: PALLET_ID.to_bytes(), + to: to.0.to_vec(), + timeout, + body: body.to_vec(), + }), + FeeMetadata { + payer: payer.clone(), + fee, + }, + ) + .map_err(|_| Error::::Unsupported)?; + *weight = weight.saturating_add(T::DbWeight::get().reads_writes(6, 2)); + } + } + HyperBridgeOracleConfig::::insert( + dest, + OracleConfig { + to, + timeout, + payer, + fee, + tokens, + period, + last_block: current_block_number, + }, + ); + } + return Ok(()); + } } // Functions to be called by other pallets. diff --git a/pallets/slpx/src/mock.rs b/pallets/slpx/src/mock.rs index b1908b8a3e..9ffde7abd2 100644 --- a/pallets/slpx/src/mock.rs +++ b/pallets/slpx/src/mock.rs @@ -19,10 +19,8 @@ use crate as slpx; use bifrost_asset_registry::AssetIdMaps; -pub use bifrost_primitives::{ - CurrencyId, CurrencyIdMapping, MockXcmExecutor, SlpxOperator, TokenSymbol, BNC, KSM, -}; -use bifrost_primitives::{MockXcmTransfer, MoonbeamChainId, SlpOperator}; +pub use bifrost_primitives::{CurrencyId, MockXcmExecutor, SlpxOperator, TokenSymbol, BNC, KSM}; +use bifrost_primitives::{MockXcmTransfer, MoonbeamChainId}; use cumulus_primitives_core::ParaId; use frame_support::{ construct_runtime, derive_impl, ord_parameter_types, @@ -33,15 +31,15 @@ use frame_support::{ }; use frame_system::{EnsureRoot, EnsureSignedBy}; use hex_literal::hex; +use ismp::host::StateMachine; +use ismp::module::IsmpModule; +use ismp::router::IsmpRouter; use orml_traits::parameter_type_with_key; -use sp_runtime::{ - traits::{Convert, IdentityLookup}, - AccountId32, BuildStorage, -}; +use sp_core::ConstU64; +use sp_runtime::{traits::IdentityLookup, AccountId32, BuildStorage}; use sp_std::vec; pub use xcm::latest::prelude::*; use xcm::{latest::Location, opaque::latest::Junction::Parachain}; -use xcm_builder::FrameTransactionalProcessor; pub use xcm_builder::{EnsureXcmOrigin, FixedWeightBounds}; pub type Balance = u128; @@ -65,6 +63,8 @@ construct_runtime!( Slpx: slpx, PolkadotXcm: pallet_xcm, ParachainInfo: parachain_info, + Ismp: pallet_ismp, + Timestamp: pallet_timestamp, } ); @@ -73,6 +73,13 @@ parameter_types! { pub const BlockHashCount: u32 = 250; } +impl pallet_timestamp::Config for Test { + type Moment = u64; + type OnTimestampSet = (); + type MinimumPeriod = ConstU64<1>; + type WeightInfo = (); +} + #[derive_impl(frame_system::config_preludes::TestDefaultConfig as frame_system::DefaultConfig)] impl frame_system::Config for Test { type Block = Block; @@ -163,14 +170,6 @@ impl SlpxOperator for SlpxInterface { } } -pub struct MockSlp; - -impl SlpOperator for MockSlp { - fn all_delegation_requests_occupied(_: CurrencyId) -> bool { - false - } -} - impl bifrost_vtoken_minting::Config for Test { type RuntimeEvent = RuntimeEvent; type MultiCurrency = Currencies; @@ -201,39 +200,6 @@ parameter_types! { pub UniversalLocation: InteriorLocation = Parachain(2001).into(); } -pub struct XcmConfig; -impl xcm_executor::Config for XcmConfig { - type AssetClaims = (); - type AssetTransactor = (); - type AssetTrap = (); - type Barrier = (); - type RuntimeCall = RuntimeCall; - type IsReserve = (); - type IsTeleporter = (); - type UniversalLocation = UniversalLocation; - type OriginConverter = (); - type ResponseHandler = (); - type SubscriptionService = (); - type Trader = (); - type Weigher = FixedWeightBounds; - type XcmSender = (); - type PalletInstancesInfo = AllPalletsWithSystem; - type MaxAssetsIntoHolding = ConstU32<64>; - type FeeManager = (); - type MessageExporter = (); - type UniversalAliases = Nothing; - type CallDispatcher = RuntimeCall; - type SafeCallFilter = Everything; - type AssetLocker = (); - type Aliasers = Nothing; - type AssetExchanger = (); - type TransactionalProcessor = FrameTransactionalProcessor; - type HrmpNewChannelOpenRequestHandler = (); - type HrmpChannelAcceptedHandler = (); - type HrmpChannelClosingHandler = (); - type XcmRecorder = (); -} - parameter_type_with_key! { pub ParachainMinFee: |_location: Location| -> Option { None @@ -246,19 +212,6 @@ parameter_types! { pub const MaxAssetsForTransfer: usize = 2; } -pub struct CurrencyIdConvert(sp_std::marker::PhantomData); -impl> Convert> for CurrencyIdConvert { - fn convert(id: CurrencyId) -> Option { - AssetIdMaps::::get_location(&id) - } -} - -impl> Convert> for CurrencyIdConvert { - fn convert(location: Location) -> Option { - AssetIdMaps::::get_currency_id(&location) - } -} - impl parachain_info::Config for Test {} impl bifrost_asset_registry::Config for Test { @@ -306,6 +259,44 @@ impl pallet_xcm::Config for Test { type RemoteLockConsumerIdentifier = (); } +parameter_types! { + // The hyperbridge parachain on Polkadot + pub const Coprocessor: Option = Some(StateMachine::Kusama(4009)); + // The host state machine of this pallet, your state machine id goes here + pub const HostStateMachine: StateMachine = StateMachine::Kusama(2030); // polkadot +} + +#[derive(Default)] +pub struct Router; + +impl IsmpRouter for Router { + fn module_for_id(&self, id: Vec) -> Result, anyhow::Error> { + match id.as_slice() { + _ => Err(ismp::Error::ModuleNotFound(id))?, + } + } +} + +impl pallet_ismp::Config for Test { + type RuntimeEvent = RuntimeEvent; + // Modify the consensus client's permissions, for example, TechAdmin + type AdminOrigin = EnsureRoot; + // The state machine identifier of the chain -- parachain id + type HostStateMachine = HostStateMachine; + type TimestampProvider = Timestamp; + // The router provides the implementation for the IsmpModule as the module id. + type Router = Router; + type Balance = Balance; + // The token used to collect fees, only stablecoins are supported + type Currency = Balances; + // Co-processor + type Coprocessor = Coprocessor; + // A tuple of types implementing the ConsensusClient interface, which defines all consensus algorithms supported by this protocol deployment + type ConsensusClients = (); + type WeightProvider = (); + type OffchainDB = (); +} + impl slpx::Config for Test { type RuntimeEvent = RuntimeEvent; type RuntimeOrigin = RuntimeOrigin; @@ -320,6 +311,8 @@ impl slpx::Config for Test { type WeightInfo = (); type MaxOrderSize = ConstU32<500>; type BlockNumberProvider = System; + #[cfg(feature = "polkadot")] + type IsmpHost = Ismp; } // Build genesis storage according to the mock runtime. diff --git a/pallets/slpx/src/tests.rs b/pallets/slpx/src/tests.rs index a9e83fcba2..c63955717e 100644 --- a/pallets/slpx/src/tests.rs +++ b/pallets/slpx/src/tests.rs @@ -493,3 +493,56 @@ fn test_hook() { println!("{}", Currencies::free_balance(VDOT, &BOB)); }) } + +#[test] +fn test_abi_encode() { + new_test_ext().execute_with(|| { + let expect_hex_string = "000000000000000000000000000000000000000000000000000000000000500400000000000000000000000000000000000000000000000000000000000007d00000000000000000000000000000000000000000000000000000000000000bb8"; + let expect_address = H160::from_slice(&hex!["0000000000000000000000000000000000005004"]); + let expect_toke_pool = 2000u128; + let expect_vtoken_supply = 3000u128; + let data = ethabi::encode(&[ + ethabi::Token::Address(expect_address), + ethabi::Token::Uint(U256::from(expect_toke_pool)), + ethabi::Token::Uint(U256::from(expect_vtoken_supply)), + ]); + assert_eq!(expect_hex_string, hex::encode(data)); + }) +} + +#[test] +fn test_set_hyperbridge_oracle_config() { + new_test_ext().execute_with(|| { + assert_ok!(Slpx::set_hyperbridge_oracle( + RuntimeOrigin::root(), + 1, + H160::from(hex!["ae0daa9bfc50f03ce23d30c796709a58470b5f42"]), + 60, + ALICE, + 5u32.into(), + 5u32.into(), + BoundedVec::try_from(vec![( + BNC, + H160::from(hex!["ae0daa9bfc50f03ce23d30c796709a58470b5f42"]) + )]) + .unwrap() + )); + + assert_eq!( + HyperBridgeOracleConfig::::get(1).unwrap(), + OracleConfig { + to: H160::from(hex!["ae0daa9bfc50f03ce23d30c796709a58470b5f42"]), + timeout: 60, + payer: ALICE, + fee: 5u32.into(), + period: 5u32.into(), + last_block: 0u32.into(), + tokens: BoundedVec::try_from(vec![( + BNC, + H160::from(hex!["ae0daa9bfc50f03ce23d30c796709a58470b5f42"]) + )]) + .unwrap(), + } + ); + }) +} diff --git a/pallets/slpx/src/types.rs b/pallets/slpx/src/types.rs index 082ffa3b32..399a1431f5 100644 --- a/pallets/slpx/src/types.rs +++ b/pallets/slpx/src/types.rs @@ -17,6 +17,7 @@ // along with this program. If not, see . use crate::pallet; +use bifrost_primitives::CurrencyId; use ethereum::TransactionAction; use orml_traits::MultiCurrency; use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; @@ -146,3 +147,22 @@ pub struct Order { pub target_chain: TargetChain, pub channel_id: u32, } + +/// HyperBridge Oracle Config +#[derive(Encode, Decode, PartialEq, Clone, RuntimeDebug, TypeInfo, MaxEncodedLen)] +pub struct OracleConfig { + /// Destination chain contract address + pub to: H160, + /// Time out + pub timeout: u64, + /// The AccountId of the sender + pub payer: AccountId, + /// The fee paid by the sender + pub fee: Balance, + /// Wait for the period to call XCM once + pub period: BlockNumber, + /// Block number of the last call + pub last_block: BlockNumber, + /// Token list + pub tokens: BoundedVec<(CurrencyId, H160), ConstU32<10>>, +} diff --git a/runtime/bifrost-kusama/Cargo.toml b/runtime/bifrost-kusama/Cargo.toml index a7d78e9a58..e8a5e2682a 100644 --- a/runtime/bifrost-kusama/Cargo.toml +++ b/runtime/bifrost-kusama/Cargo.toml @@ -147,6 +147,8 @@ leverage-staking = { workspace = true } bifrost-channel-commission = { workspace = true } bifrost-vtoken-minting-rpc-runtime-api = { workspace = true } bifrost-vbnc-convert = { workspace = true } +ismp = { workspace = true } +anyhow = { workspace = true } [build-dependencies] substrate-wasm-builder = { workspace = true, optional = true } @@ -274,6 +276,7 @@ std = [ "bifrost-xcm-interface/std", "bifrost-channel-commission/std", "bifrost-vbnc-convert/std", + "ismp/std", "substrate-wasm-builder" ] diff --git a/runtime/bifrost-kusama/src/lib.rs b/runtime/bifrost-kusama/src/lib.rs index 1ef55acd9a..233c4f217c 100644 --- a/runtime/bifrost-kusama/src/lib.rs +++ b/runtime/bifrost-kusama/src/lib.rs @@ -137,7 +137,10 @@ use governance::{ pub mod xcm_config; use bifrost_primitives::{MoonriverChainId, OraclePriceProvider}; use bifrost_runtime_common::currency_converter::CurrencyIdConvert; +use ismp::dispatcher::FeeMetadata; +use ismp::dispatcher::IsmpDispatcher; use pallet_xcm::{EnsureResponse, QueryStatus}; +use sp_core::H256; use sp_runtime::traits::{IdentityLookup, Verify}; use xcm::{ v3::MultiLocation, v4::prelude::*, IntoVersion, VersionedAssetId, VersionedAssets, @@ -1411,6 +1414,27 @@ impl bifrost_vtoken_minting::Config for Runtime { type BlockNumberProvider = System; } +#[derive(Default)] +pub struct MockIsmpHost; +impl ismp::dispatcher::IsmpDispatcher for MockIsmpHost { + type Account = AccountId; + type Balance = Balance; + fn dispatch_request( + &self, + _: ismp::dispatcher::DispatchRequest, + _: FeeMetadata<::Account, ::Balance>, + ) -> Result { + unreachable!() + } + fn dispatch_response( + &self, + _: ismp::router::PostResponse, + _: FeeMetadata<::Account, ::Balance>, + ) -> Result { + unreachable!() + } +} + impl bifrost_slpx::Config for Runtime { type RuntimeEvent = RuntimeEvent; type RuntimeOrigin = RuntimeOrigin; @@ -1425,6 +1449,7 @@ impl bifrost_slpx::Config for Runtime { type WeightInfo = weights::bifrost_slpx::BifrostWeight; type MaxOrderSize = ConstU32<500>; type BlockNumberProvider = System; + type IsmpHost = MockIsmpHost; } pub struct EnsurePoolAssetId; diff --git a/runtime/bifrost-paseo/Cargo.toml b/runtime/bifrost-paseo/Cargo.toml index 9bc61addfd..6163f97a65 100644 --- a/runtime/bifrost-paseo/Cargo.toml +++ b/runtime/bifrost-paseo/Cargo.toml @@ -152,7 +152,7 @@ bifrost-salp = { workspace = true } bifrost-salp-rpc-runtime-api = { workspace = true } bifrost-slp = { workspace = true } bifrost-slp-v2 = { workspace = true, features = ["polkadot"] } -bifrost-slpx = { workspace = true } +bifrost-slpx = { workspace = true, features = ["polkadot"]} bifrost-stable-pool = { workspace = true } bifrost-stable-pool-rpc-runtime-api = { workspace = true } bifrost-system-staking = { workspace = true } diff --git a/runtime/bifrost-paseo/src/lib.rs b/runtime/bifrost-paseo/src/lib.rs index ec1ef21844..d0b608a588 100644 --- a/runtime/bifrost-paseo/src/lib.rs +++ b/runtime/bifrost-paseo/src/lib.rs @@ -1111,6 +1111,7 @@ impl bifrost_slpx::Config for Runtime { type WeightInfo = weights::bifrost_slpx::BifrostWeight; type MaxOrderSize = ConstU32<500>; type BlockNumberProvider = System; + type IsmpHost = Ismp; } pub struct EnsurePoolAssetId; diff --git a/runtime/bifrost-polkadot/Cargo.toml b/runtime/bifrost-polkadot/Cargo.toml index e09ae669ad..7aa85760cd 100644 --- a/runtime/bifrost-polkadot/Cargo.toml +++ b/runtime/bifrost-polkadot/Cargo.toml @@ -153,7 +153,7 @@ bifrost-salp = { workspace = true } bifrost-salp-rpc-runtime-api = { workspace = true } bifrost-slp = { workspace = true } bifrost-slp-v2 = { workspace = true, features = ["polkadot"] } -bifrost-slpx = { workspace = true } +bifrost-slpx = { workspace = true, features = ["polkadot"] } bifrost-stable-pool = { workspace = true } bifrost-stable-pool-rpc-runtime-api = { workspace = true } bifrost-system-staking = { workspace = true } diff --git a/runtime/bifrost-polkadot/src/lib.rs b/runtime/bifrost-polkadot/src/lib.rs index ad7bc28704..86d8b8428c 100644 --- a/runtime/bifrost-polkadot/src/lib.rs +++ b/runtime/bifrost-polkadot/src/lib.rs @@ -1112,6 +1112,7 @@ impl bifrost_slpx::Config for Runtime { type WeightInfo = weights::bifrost_slpx::BifrostWeight; type MaxOrderSize = ConstU32<500>; type BlockNumberProvider = System; + type IsmpHost = Ismp; } pub struct EnsurePoolAssetId;