From f8a7bbff5b99f9db5ccf7b967fc91680799c4043 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Enrique=20Mu=C3=B1oz=20Mart=C3=ADn?= Date: Fri, 29 Dec 2023 23:30:50 +0100 Subject: [PATCH] Loans: Integration with OracleV2 (#1658) * loans using new oracle v2 system in runtimes * remove old orml oracles from runtimes and integration tests * simplify DataRegistry for benchmarking * fix loan benchmarks * fix loan benchmarks with runtimes * update integration tests * add new tests for updating oracle collections * remove pallet-data-collector * fix path --- Cargo.lock | 48 ---- Cargo.toml | 2 - libs/mocks/src/data.rs | 27 +- libs/traits/src/data.rs | 4 - libs/types/src/ids.rs | 1 - pallets/data-collector/Cargo.toml | 63 ----- pallets/data-collector/src/lib.rs | 243 ------------------ pallets/data-collector/src/mock.rs | 148 ----------- pallets/data-collector/src/tests.rs | 178 ------------- pallets/loans/src/benchmarking.rs | 27 +- pallets/loans/src/tests/mock.rs | 2 - pallets/loans/src/util.rs | 64 +---- pallets/oracle-data-collection/src/lib.rs | 62 ++++- runtime/altair/Cargo.toml | 7 - runtime/altair/src/lib.rs | 132 +++------- runtime/centrifuge/Cargo.toml | 7 - runtime/centrifuge/src/lib.rs | 78 +----- runtime/common/Cargo.toml | 8 - runtime/common/src/oracle.rs | 146 +---------- runtime/development/Cargo.toml | 7 - runtime/development/src/lib.rs | 76 +----- runtime/integration-tests/Cargo.toml | 2 - .../src/generic/cases/loans.rs | 85 +++++- .../integration-tests/src/generic/config.rs | 18 +- .../src/generic/utils/mod.rs | 66 ++++- 25 files changed, 285 insertions(+), 1216 deletions(-) delete mode 100644 pallets/data-collector/Cargo.toml delete mode 100644 pallets/data-collector/src/lib.rs delete mode 100644 pallets/data-collector/src/mock.rs delete mode 100644 pallets/data-collector/src/tests.rs diff --git a/Cargo.lock b/Cargo.lock index a0c25d0000..fb53867692 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -223,7 +223,6 @@ dependencies = [ "log", "moonbeam-relay-encoder", "orml-asset-registry", - "orml-oracle", "orml-tokens", "orml-traits", "orml-xcm", @@ -242,7 +241,6 @@ dependencies = [ "pallet-collective", "pallet-crowdloan-claim", "pallet-crowdloan-reward", - "pallet-data-collector", "pallet-democracy", "pallet-elections-phragmen", "pallet-ethereum", @@ -1160,7 +1158,6 @@ dependencies = [ "log", "moonbeam-relay-encoder", "orml-asset-registry", - "orml-oracle", "orml-tokens", "orml-traits", "orml-xcm", @@ -1179,7 +1176,6 @@ dependencies = [ "pallet-collective", "pallet-crowdloan-claim", "pallet-crowdloan-reward", - "pallet-data-collector", "pallet-democracy", "pallet-elections-phragmen", "pallet-ethereum", @@ -2769,7 +2765,6 @@ dependencies = [ "liquidity-pools-gateway-routers", "moonbeam-relay-encoder", "orml-asset-registry", - "orml-oracle", "orml-tokens", "orml-traits", "orml-xcm", @@ -2788,7 +2783,6 @@ dependencies = [ "pallet-collective", "pallet-crowdloan-claim", "pallet-crowdloan-reward", - "pallet-data-collector", "pallet-democracy", "pallet-elections-phragmen", "pallet-ethereum", @@ -6913,24 +6907,6 @@ dependencies = [ "xcm-executor", ] -[[package]] -name = "orml-oracle" -version = "0.4.1-dev" -source = "git+https://github.com/open-web3-stack/open-runtime-module-library?branch=polkadot-v0.9.43#28a2e6f0df9540d91db4018c7ecebb8bfc217a2a" -dependencies = [ - "frame-support", - "frame-system", - "orml-traits", - "orml-utilities", - "parity-scale-codec 3.6.5", - "scale-info", - "serde", - "sp-application-crypto", - "sp-io", - "sp-runtime", - "sp-std", -] - [[package]] name = "orml-tokens" version = "0.4.1-dev" @@ -7455,26 +7431,6 @@ dependencies = [ "sp-std", ] -[[package]] -name = "pallet-data-collector" -version = "1.0.0" -dependencies = [ - "cfg-traits", - "frame-benchmarking", - "frame-support", - "frame-system", - "orml-oracle", - "orml-traits", - "pallet-timestamp", - "parity-scale-codec 3.6.5", - "scale-info", - "sp-arithmetic", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", -] - [[package]] name = "pallet-democracy" version = "4.0.0-dev" @@ -11427,7 +11383,6 @@ dependencies = [ "hex-literal 0.3.4", "log", "orml-asset-registry", - "orml-oracle", "orml-tokens", "orml-traits", "orml-xcm", @@ -11445,7 +11400,6 @@ dependencies = [ "pallet-collective", "pallet-crowdloan-claim", "pallet-crowdloan-reward", - "pallet-data-collector", "pallet-democracy", "pallet-elections-phragmen", "pallet-ethereum", @@ -11549,7 +11503,6 @@ dependencies = [ "liquidity-pools-gateway-routers", "node-primitives", "orml-asset-registry", - "orml-oracle", "orml-tokens", "orml-traits", "orml-xcm", @@ -11568,7 +11521,6 @@ dependencies = [ "pallet-collective", "pallet-crowdloan-claim", "pallet-crowdloan-reward", - "pallet-data-collector", "pallet-democracy", "pallet-elections-phragmen", "pallet-ethereum", diff --git a/Cargo.toml b/Cargo.toml index 92f7037076..528399ae93 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,7 +37,6 @@ members = [ "pallets/permissions", "pallets/pool-system", "pallets/pool-registry", - "pallets/data-collector", "pallets/restricted-tokens", "pallets/restricted-xtokens", "pallets/transfer-allowlist", @@ -255,7 +254,6 @@ pallet-claims = { path = "pallets/claims", default-features = false } pallet-collator-allowlist = { path = "pallets/collator-allowlist", default-features = false } pallet-crowdloan-claim = { path = "pallets/crowdloan-claim", default-features = false } pallet-crowdloan-reward = { path = "pallets/crowdloan-reward", default-features = false } -pallet-data-collector = { path = "pallets/data-collector", default-features = false } pallet-ethereum-transaction = { path = "pallets/ethereum-transaction", default-features = false } pallet-fees = { path = "pallets/fees", default-features = false } pallet-foreign-investments = { path = "pallets/foreign-investments", default-features = false } diff --git a/libs/mocks/src/data.rs b/libs/mocks/src/data.rs index bf0019cf3f..53c85ed07a 100644 --- a/libs/mocks/src/data.rs +++ b/libs/mocks/src/data.rs @@ -3,7 +3,6 @@ pub mod pallet { use cfg_traits::data::{DataCollection, DataRegistry}; use frame_support::pallet_prelude::*; use mock_builder::{execute_call, register_call}; - use orml_traits::{DataFeeder, DataProvider}; #[pallet::config] pub trait Config: frame_system::Config { @@ -12,8 +11,6 @@ pub mod pallet { type Collection: DataCollection; type Data; type DataElem; - #[cfg(feature = "runtime-benchmarks")] - type MaxCollectionSize: Get; } #[pallet::pallet] @@ -49,19 +46,11 @@ pub mod pallet { ) { register_call!(move |(a, b)| f(a, b)); } - - pub fn mock_feed_value( - f: impl Fn(Option, T::DataId, T::DataElem) -> DispatchResult + 'static, - ) { - register_call!(move |(a, b, c)| f(a, b, c)); - } } impl DataRegistry for Pallet { type Collection = T::Collection; type Data = T::Data; - #[cfg(feature = "runtime-benchmarks")] - type MaxCollectionSize = T::MaxCollectionSize; fn get(a: &T::DataId, b: &T::CollectionId) -> Result { execute_call!((a, b)) @@ -80,15 +69,15 @@ pub mod pallet { } } - impl DataProvider for Pallet { - fn get(a: &T::DataId) -> Option { - execute_call!(a) - } - } + #[cfg(feature = "runtime-benchmarks")] + impl cfg_traits::ValueProvider<(u32, T::CollectionId), T::DataId> for Pallet { + type Value = T::Data; - impl DataFeeder for Pallet { - fn feed_value(a: Option, b: T::DataId, c: T::DataElem) -> DispatchResult { - execute_call!((a, b, c)) + fn get( + _: &(u32, T::CollectionId), + _: &T::DataId, + ) -> Result, DispatchError> { + unimplemented!() } } diff --git a/libs/traits/src/data.rs b/libs/traits/src/data.rs index 3a7df7469d..d0b6be6083 100644 --- a/libs/traits/src/data.rs +++ b/libs/traits/src/data.rs @@ -22,10 +22,6 @@ pub trait DataRegistry { /// Represents a data type Data; - /// Identify the max number a collection can reach. - #[cfg(feature = "runtime-benchmarks")] - type MaxCollectionSize: sp_runtime::traits::Get; - /// Return the last data value for a data id in a collection fn get(data_id: &DataId, collection_id: &CollectionId) -> Result; diff --git a/libs/types/src/ids.rs b/libs/types/src/ids.rs index b0e1c82c64..835b323465 100644 --- a/libs/types/src/ids.rs +++ b/libs/types/src/ids.rs @@ -36,7 +36,6 @@ pub const NFT_SALES_PALLET_ID: PalletId = PalletId(*b"pal/nfts"); pub const STAKE_POT_PALLET_ID: PalletId = PalletId(*b"PotStake"); pub const BLOCK_REWARDS_PALLET_ID: PalletId = PalletId(*b"cfg/blrw"); pub const LIQUIDITY_REWARDS_PALLET_ID: PalletId = PalletId(*b"cfg/lqrw"); -pub const PRICE_ORACLE_PALLET_ID: PalletId = PalletId(*b"or/price"); // Other ids pub const CHAIN_BRIDGE_HASH_ID: [u8; 13] = *b"cent_nft_hash"; diff --git a/pallets/data-collector/Cargo.toml b/pallets/data-collector/Cargo.toml deleted file mode 100644 index ac8ada72c3..0000000000 --- a/pallets/data-collector/Cargo.toml +++ /dev/null @@ -1,63 +0,0 @@ -[package] -authors = ["Centrifuge "] -description = "Pallet to collect data from a feeder entity" -edition = "2021" -license = "LGPL-3.0" -name = "pallet-data-collector" -repository = "https://github.com/centrifuge/centrifuge-chain" -version = "1.0.0" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - -[dependencies] -parity-scale-codec = { version = "3.0.0", features = ["derive"], default-features = false } -scale-info = { version = "2.3.0", default-features = false, features = ["derive"] } - -frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.43" } -frame-system = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.43" } -sp-arithmetic = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.43" } -sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.43" } -sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.43" } - -orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", default-features = false, branch = "polkadot-v0.9.43" } - -cfg-traits = { path = "../../libs/traits", default-features = false } - -# Optionals for benchmarking -frame-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true, branch = "polkadot-v0.9.43" } - -[dev-dependencies] -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.43" } -sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.43" } - -orml-oracle = { git = "https://github.com/open-web3-stack/open-runtime-module-library", branch = "polkadot-v0.9.43" } -pallet-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.43" } - -[features] -default = ["std"] -std = [ - "parity-scale-codec/std", - "scale-info/std", - "frame-support/std", - "frame-system/std", - "sp-arithmetic/std", - "sp-runtime/std", - "sp-std/std", - "cfg-traits/std", - "orml-traits/std", - "frame-benchmarking/std", -] -runtime-benchmarks = [ - "frame-benchmarking/runtime-benchmarks", - "cfg-traits/runtime-benchmarks", - "frame-support/runtime-benchmarks", - "frame-system/runtime-benchmarks", - "sp-runtime/runtime-benchmarks", -] -try-runtime = [ - "frame-support/try-runtime", - "frame-system/try-runtime", - "sp-runtime/try-runtime", - "cfg-traits/try-runtime", -] diff --git a/pallets/data-collector/src/lib.rs b/pallets/data-collector/src/lib.rs deleted file mode 100644 index 5c6a1d02dc..0000000000 --- a/pallets/data-collector/src/lib.rs +++ /dev/null @@ -1,243 +0,0 @@ -// Copyright 2023 Centrifuge Foundation (centrifuge.io). -// This file is part of Centrifuge chain project. - -// Centrifuge 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 (see http://www.gnu.org/licenses). - -// Centrifuge 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. - -//! Collects data from a feeder entity into collections to fastly read data in -//! one memory access. - -#![cfg_attr(not(feature = "std"), no_std)] - -pub use pallet::*; - -#[cfg(test)] -mod mock; - -#[cfg(test)] -mod tests; - -#[frame_support::pallet] -pub mod pallet { - use cfg_traits::data::{DataCollection, DataRegistry}; - use frame_support::{pallet_prelude::*, storage::bounded_btree_map::BoundedBTreeMap}; - use orml_traits::{DataProviderExtended, OnNewData}; - use sp_runtime::{ - traits::{EnsureAddAssign, EnsureSubAssign}, - DispatchError, DispatchResult, - }; - - type DataValueOf = (>::Data, >::Moment); - - const STORAGE_VERSION: StorageVersion = StorageVersion::new(0); - - #[pallet::pallet] - #[pallet::storage_version(STORAGE_VERSION)] - pub struct Pallet(_); - - #[pallet::config] - pub trait Config: frame_system::Config { - /// A data identification - type DataId: Parameter + MaxEncodedLen + Ord; - - /// A collection identification - type CollectionId: Parameter + MaxEncodedLen + Ord; - - /// Represents a data - type Data: Parameter + MaxEncodedLen + Ord; - - /// Represents a timestamp - type Moment: Parameter + MaxEncodedLen; - - /// Data provider for initializing data values - type DataProvider: DataProviderExtended< - (Self::DataId, Self::CollectionId), - (Self::Data, Self::Moment), - >; - - /// Max size of a data collection - #[pallet::constant] - type MaxCollectionSize: Get; - - /// Max number of collections - #[pallet::constant] - type MaxCollections: Get; - } - - /// Storage that contains the registering information - #[pallet::storage] - pub(crate) type Listening, I: 'static = ()> = StorageMap< - _, - Blake2_128Concat, - T::DataId, - BoundedBTreeMap, - ValueQuery, - >; - - /// Storage that contains the data values of a collection. - #[pallet::storage] - pub(crate) type Collection, I: 'static = ()> = StorageMap< - _, - Blake2_128Concat, - T::CollectionId, - BoundedBTreeMap, T::MaxCollectionSize>, - ValueQuery, - >; - - #[pallet::error] - pub enum Error { - /// The used data ID is not in the collection. - DataIdNotInCollection, - - /// The data ID doesn't have data associated to it. - /// The data was never set for the Id. - DataIdWithoutData, - - /// Max collection size exceeded - MaxCollectionSize, - - /// Max collection number exceeded - MaxCollectionNumber, - } - - impl, I: 'static> Pallet { - fn get_from_source( - data_id: &T::DataId, - collection_id: &T::CollectionId, - ) -> Result, DispatchError> { - T::DataProvider::get_no_op(&(data_id.clone(), collection_id.clone())) - .ok_or_else(|| Error::::DataIdWithoutData.into()) - } - } - - impl, I: 'static> DataRegistry for Pallet { - type Collection = CachedCollection; - type Data = DataValueOf; - #[cfg(feature = "runtime-benchmarks")] - type MaxCollectionSize = T::MaxCollectionSize; - - fn get( - data_id: &T::DataId, - collection_id: &T::CollectionId, - ) -> Result { - Collection::::get(collection_id) - .get(data_id) - .cloned() - .ok_or_else(|| Error::::DataIdNotInCollection.into()) - } - - fn collection(collection_id: &T::CollectionId) -> Self::Collection { - CachedCollection(Collection::::get(collection_id)) - } - - fn register_id(data_id: &T::DataId, collection_id: &T::CollectionId) -> DispatchResult { - Listening::::try_mutate(data_id, |counters| { - match counters.get_mut(collection_id) { - Some(counter) => counter.ensure_add_assign(1).map_err(|e| e.into()), - None => { - counters - .try_insert(collection_id.clone(), 1) - .map_err(|_| Error::::MaxCollectionNumber)?; - - Collection::::try_mutate(collection_id, |collection| { - let data = Self::get_from_source(data_id, collection_id)?; - - collection - .try_insert(data_id.clone(), data) - .map(|_| ()) - .map_err(|_| Error::::MaxCollectionSize.into()) - }) - } - } - }) - } - - fn unregister_id(data_id: &T::DataId, collection_id: &T::CollectionId) -> DispatchResult { - Listening::::try_mutate(data_id, |counters| { - let counter = counters - .get_mut(collection_id) - .ok_or(Error::::DataIdNotInCollection)?; - - counter.ensure_sub_assign(1)?; - if *counter == 0 { - counters.remove(collection_id); - Collection::::mutate(collection_id, |collection| { - collection.remove(data_id) - }); - } - - Ok(()) - }) - } - } - - impl, I: 'static> OnNewData for Pallet { - fn on_new_data(_: &T::AccountId, data_id: &T::DataId, _: &T::Data) { - // Input Data parameter could not correspond with the data comming from - // `DataProvider`. This implementation use `DataProvider` as a source of truth - // for Data values. - for collection_id in Listening::::get(data_id).keys() { - Collection::::mutate(collection_id, |collection| { - let data = Self::get_from_source(data_id, collection_id); - - if let (Some(value), Ok(new_value)) = (collection.get_mut(data_id), data) { - *value = new_value; - } - }); - } - } - } - - /// A collection cached in memory - pub struct CachedCollection, I: 'static = ()>( - BoundedBTreeMap, T::MaxCollectionSize>, - ); - - impl, I: 'static> DataCollection for CachedCollection { - type Data = DataValueOf; - - fn get(&self, data_id: &T::DataId) -> Result, DispatchError> { - self.0 - .get(data_id) - .cloned() - .ok_or_else(|| Error::::DataIdNotInCollection.into()) - } - } - - #[cfg(feature = "runtime-benchmarks")] - mod benchmark_impls { - use orml_traits::{DataFeeder, DataProvider}; - - use super::*; - // This implementation can be removed once: - // is merged. - impl, I: 'static> DataProvider for Pallet - where - T::DataProvider: DataProvider, - { - fn get(key: &T::DataId) -> Option { - T::DataProvider::get(key) - } - } - - impl, I: 'static> DataFeeder for Pallet - where - T::DataProvider: DataFeeder, - { - fn feed_value( - account_id: Option, - data_id: T::DataId, - data: T::Data, - ) -> DispatchResult { - T::DataProvider::feed_value(account_id, data_id, data) - } - } - } -} diff --git a/pallets/data-collector/src/mock.rs b/pallets/data-collector/src/mock.rs deleted file mode 100644 index d182cbcd0a..0000000000 --- a/pallets/data-collector/src/mock.rs +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright 2023 Centrifuge Foundation (centrifuge.io). -// This file is part of Centrifuge chain project. - -// Centrifuge 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 (see http://www.gnu.org/licenses). - -// Centrifuge 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. - -use frame_support::traits::{ConstU16, ConstU32, ConstU64, IsInVec}; -use orml_oracle::{CombineData, DataProviderExtended}; -use sp_core::H256; -use sp_runtime::{ - testing::Header, - traits::{BlakeTwo256, IdentityLookup}, -}; - -use crate::pallet as pallet_data_collector; - -type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; -type Block = frame_system::mocking::MockBlock; - -pub const BLOCK_TIME_MS: Moment = 10000; -pub const ORACLE_MEMBER: u64 = 42; - -pub type CollectionId = u16; -pub type DataId = u32; -pub type Data = u128; -pub type Moment = u64; -pub type AccountId = u64; - -frame_support::construct_runtime!( - pub enum Runtime where - Block = Block, - NodeBlock = Block, - UncheckedExtrinsic = UncheckedExtrinsic, - { - System: frame_system, - Timer: pallet_timestamp, - Oracle: orml_oracle, - DataCollector: pallet_data_collector, - } -); - -frame_support::parameter_types! { - pub const MaxCollectionSize: u32 = 5; - pub const MaxCollections: u32 = 3; - pub const RootMember: AccountId = 23; - pub static Members: Vec = vec![ORACLE_MEMBER]; - pub const MaxHasDispatchedSize: u32 = 1; -} - -impl frame_system::Config for Runtime { - type AccountData = (); - type AccountId = AccountId; - type BaseCallFilter = frame_support::traits::Everything; - type BlockHashCount = ConstU64<250>; - type BlockLength = (); - type BlockNumber = u64; - type BlockWeights = (); - type DbWeight = (); - type Hash = H256; - type Hashing = BlakeTwo256; - type Header = Header; - type Index = u64; - type Lookup = IdentityLookup; - type MaxConsumers = ConstU32<16>; - type OnKilledAccount = (); - type OnNewAccount = (); - type OnSetCode = (); - type PalletInfo = PalletInfo; - type RuntimeCall = RuntimeCall; - type RuntimeEvent = RuntimeEvent; - type RuntimeOrigin = RuntimeOrigin; - type SS58Prefix = ConstU16<42>; - type SystemWeightInfo = (); - type Version = (); -} - -impl pallet_timestamp::Config for Runtime { - type MinimumPeriod = ConstU64; - type Moment = Moment; - type OnTimestampSet = (); - type WeightInfo = (); -} - -type OracleValue = orml_oracle::TimestampedValue; - -pub struct LastData; -impl CombineData for LastData { - fn combine_data( - _: &DataId, - values: Vec, - _: Option, - ) -> Option { - values - .into_iter() - .max_by(|v1, v2| v1.timestamp.cmp(&v2.timestamp)) - } -} - -// This part is forced because of https://github.com/open-web3-stack/open-runtime-module-library/issues/904 -pub struct DataProviderBridge; -impl DataProviderExtended<(DataId, CollectionId), (Data, Moment)> for DataProviderBridge { - fn get_no_op(key: &(DataId, CollectionId)) -> Option<(Data, Moment)> { - Oracle::get_no_op(&key.0).map(|OracleValue { value, timestamp }| (value, timestamp)) - } - - fn get_all_values() -> Vec<((DataId, CollectionId), Option<(Data, Moment)>)> { - unimplemented!("unused by this pallet") - } -} - -impl orml_oracle::Config for Runtime { - type CombineData = LastData; - type MaxFeedValues = (); - type MaxHasDispatchedSize = MaxHasDispatchedSize; - type Members = IsInVec; - type OnNewData = DataCollector; - type OracleKey = DataId; - type OracleValue = Data; - type RootOperatorAccountId = RootMember; - type RuntimeEvent = RuntimeEvent; - type Time = Timer; - type WeightInfo = (); -} - -impl pallet_data_collector::Config for Runtime { - type CollectionId = CollectionId; - type Data = Data; - type DataId = DataId; - type DataProvider = DataProviderBridge; - type MaxCollectionSize = MaxCollectionSize; - type MaxCollections = MaxCollections; - type Moment = Moment; -} - -pub fn new_test_ext() -> sp_io::TestExternalities { - let storage = frame_system::GenesisConfig::default() - .build_storage::() - .unwrap(); - - sp_io::TestExternalities::new(storage) -} diff --git a/pallets/data-collector/src/tests.rs b/pallets/data-collector/src/tests.rs deleted file mode 100644 index 8bf2080b5c..0000000000 --- a/pallets/data-collector/src/tests.rs +++ /dev/null @@ -1,178 +0,0 @@ -// Copyright 2023 Centrifuge Foundation (centrifuge.io). -// This file is part of Centrifuge chain project. - -// Centrifuge 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 (see http://www.gnu.org/licenses). - -// Centrifuge 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. - -use cfg_traits::data::{DataCollection, DataRegistry}; -use frame_support::{assert_noop, assert_ok, pallet_prelude::Hooks}; -use orml_traits::DataFeeder; - -use super::{mock::*, pallet::Error}; - -const COLLECTION_ID: CollectionId = 1; -const DATA_ID: DataId = 10; - -fn advance_time(elapsed: u64) { - Timer::set_timestamp(Timer::get() + elapsed); -} - -fn feed(data_id: DataId, data: Data) { - // For testing we want to skip the limitiation of one feed call per block - Oracle::on_finalize(0); - Oracle::feed_value(Some(ORACLE_MEMBER), data_id, data).unwrap(); -} - -#[test] -fn feed_and_then_register() { - new_test_ext().execute_with(|| { - feed(DATA_ID, 100); - - assert_noop!( - DataCollector::get(&DATA_ID, &COLLECTION_ID), - Error::::DataIdNotInCollection - ); - - assert_ok!(DataCollector::register_id(&DATA_ID, &COLLECTION_ID)); - - assert_ok!( - DataCollector::collection(&COLLECTION_ID).get(&DATA_ID), - (100, Timer::now()) - ); - - assert_eq!( - DataCollector::get(&DATA_ID, &COLLECTION_ID), - Ok((100, Timer::now())) - ); - - advance_time(BLOCK_TIME_MS); - feed(DATA_ID, 200); - - assert_ok!( - DataCollector::collection(&COLLECTION_ID).get(&DATA_ID), - (200, Timer::now()) - ); - - assert_eq!( - DataCollector::get(&DATA_ID, &COLLECTION_ID), - Ok((200, Timer::now())) - ); - }); -} - -#[test] -fn register_without_feed() { - new_test_ext().execute_with(|| { - assert_noop!( - DataCollector::register_id(&DATA_ID, &COLLECTION_ID), - Error::::DataIdWithoutData - ); - }); -} - -#[test] -fn data_not_registered_in_collection() { - new_test_ext().execute_with(|| { - feed(DATA_ID, 100); - feed(DATA_ID + 1, 100); - - assert_ok!(DataCollector::register_id(&DATA_ID, &COLLECTION_ID)); - - let collection = DataCollector::collection(&COLLECTION_ID); - assert_noop!( - collection.get(&(DATA_ID + 1)), - Error::::DataIdNotInCollection - ); - }); -} - -#[test] -fn data_not_registered_after_unregister() { - new_test_ext().execute_with(|| { - feed(DATA_ID, 100); - - assert_ok!(DataCollector::register_id(&DATA_ID, &COLLECTION_ID)); - - assert_ok!(DataCollector::unregister_id(&DATA_ID, &COLLECTION_ID)); - - let collection = DataCollector::collection(&COLLECTION_ID); - assert_noop!( - collection.get(&DATA_ID), - Error::::DataIdNotInCollection - ); - }); -} - -#[test] -fn unregister_without_register() { - new_test_ext().execute_with(|| { - assert_noop!( - DataCollector::unregister_id(&DATA_ID, &COLLECTION_ID), - Error::::DataIdNotInCollection - ); - }); -} - -#[test] -fn register_twice() { - new_test_ext().execute_with(|| { - feed(DATA_ID, 100); - - assert_ok!(DataCollector::register_id(&DATA_ID, &COLLECTION_ID)); - - assert_ok!(DataCollector::register_id(&DATA_ID, &COLLECTION_ID)); - - assert_ok!(DataCollector::unregister_id(&DATA_ID, &COLLECTION_ID)); - - assert_ok!(DataCollector::unregister_id(&DATA_ID, &COLLECTION_ID)); - - assert_noop!( - DataCollector::unregister_id(&DATA_ID, &COLLECTION_ID), - Error::::DataIdNotInCollection - ); - }); -} - -#[test] -fn max_collection_number() { - new_test_ext().execute_with(|| { - feed(DATA_ID, 100); - - let max = MaxCollections::get() as CollectionId; - for i in 0..max { - assert_ok!(DataCollector::register_id(&DATA_ID, &(COLLECTION_ID + i))); - } - - assert_noop!( - DataCollector::register_id(&DATA_ID, &(COLLECTION_ID + max)), - Error::::MaxCollectionNumber - ); - }); -} - -#[test] -fn max_collection_size() { - new_test_ext().execute_with(|| { - let max = MaxCollectionSize::get(); - for i in 0..max { - feed(DATA_ID + i, 100); - assert_ok!(DataCollector::register_id(&(DATA_ID + i), &COLLECTION_ID)); - } - - feed(DATA_ID + max, 100); - assert_noop!( - DataCollector::register_id(&(DATA_ID + max), &COLLECTION_ID), - Error::::MaxCollectionSize - ); - - // Other collections can still be registered - assert_ok!(DataCollector::register_id(&DATA_ID, &(COLLECTION_ID + 1))); - }); -} diff --git a/pallets/loans/src/benchmarking.rs b/pallets/loans/src/benchmarking.rs index 4be8b228e3..34f30cbaab 100644 --- a/pallets/loans/src/benchmarking.rs +++ b/pallets/loans/src/benchmarking.rs @@ -15,9 +15,8 @@ use cfg_primitives::CFG; use cfg_traits::{ benchmarking::FundedPoolBenchmarkHelper, changes::ChangeGuard, - data::DataRegistry, interest::{CompoundingSchedule, InterestAccrual, InterestRate}, - Permissions, PoolWriteOffPolicyMutate, Seconds, TimeAsSecs, + Permissions, PoolWriteOffPolicyMutate, Seconds, TimeAsSecs, ValueProvider, }; use cfg_types::{ adjustments::Adjustment, @@ -26,7 +25,6 @@ use cfg_types::{ use frame_benchmarking::{account, benchmarks, impl_benchmark_test_suite}; use frame_support::traits::tokens::nonfungibles::{Create, Mutate}; use frame_system::RawOrigin; -use orml_traits::DataFeeder; use sp_arithmetic::FixedPointNumber; use sp_runtime::traits::{Bounded, Get, One, Zero}; @@ -59,11 +57,6 @@ type MaxRateCountOf = <::InterestAccrual as InterestAccrual< Adjustment<::Balance>, >>::MaxRateCount; -type MaxCollectionSizeOf = <::PriceRegistry as DataRegistry< - ::PriceId, - ::PoolId, ->>::MaxCollectionSize; - #[cfg(test)] fn config_mocks() { use cfg_mocks::pallet_mock_data::util::MockDataCollection; @@ -76,7 +69,6 @@ fn config_mocks() { MockPools::mock_account_for(|_| 0); MockPools::mock_withdraw(|_, _, _| Ok(())); MockPools::mock_deposit(|_, _, _| Ok(())); - MockPrices::mock_feed_value(|_, _, _| Ok(())); MockPrices::mock_register_id(|_, _| Ok(())); MockPrices::mock_collection(|_| MockDataCollection::new(|_| Ok(Default::default()))); MockChangeGuard::mock_note(|_, change| { @@ -98,7 +90,8 @@ where AccountId = T::AccountId, Balance = T::Balance, >, - T::PriceRegistry: DataFeeder, + T::Moment: Default, + T::PriceRegistry: ValueProvider<(u32, T::PoolId), T::PriceId, Value = PriceOf>, { fn prepare_benchmark() -> T::PoolId { #[cfg(test)] @@ -302,14 +295,9 @@ where .unwrap(); } - for i in 0..MaxCollectionSizeOf::::get() { - let price_id = i.into(); - // This account is different in each iteration because of how oracles works. - // This restriction no longer exists once - // https://github.com/open-web3-stack/open-runtime-module-library/pull/920 is merged - let feeder = account("feeder", i, 0); - T::PriceRegistry::feed_value(Some(feeder), price_id, Default::default()).unwrap(); - T::PriceRegistry::register_id(&price_id, &pool_id).unwrap(); + // Populate the price registry with prices + for i in 0..n { + T::PriceRegistry::set(&(0, pool_id), &T::PriceId::from(i), Default::default()); } for i in 0..n { @@ -335,7 +323,8 @@ benchmarks! { T::ItemId: From, T::PriceId: From, T::Pool: FundedPoolBenchmarkHelper, - T::PriceRegistry: DataFeeder, + T::Moment: Default, + T::PriceRegistry: ValueProvider<(u32, T::PoolId), T::PriceId, Value = PriceOf>, } create { diff --git a/pallets/loans/src/tests/mock.rs b/pallets/loans/src/tests/mock.rs index e6ea3e86cb..83787e3c45 100644 --- a/pallets/loans/src/tests/mock.rs +++ b/pallets/loans/src/tests/mock.rs @@ -218,8 +218,6 @@ impl pallet_mock_data::Config for Runtime { type Data = (Balance, Millis); type DataElem = Balance; type DataId = PriceId; - #[cfg(feature = "runtime-benchmarks")] - type MaxCollectionSize = MaxActiveLoansPerPool; } impl pallet_mock_change_guard::Config for Runtime { diff --git a/pallets/loans/src/util.rs b/pallets/loans/src/util.rs index 26a0b62566..0169d00ddf 100644 --- a/pallets/loans/src/util.rs +++ b/pallets/loans/src/util.rs @@ -11,69 +11,11 @@ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. -use cfg_traits::{ - changes::ChangeGuard, - data::{DataCollection, DataRegistry}, -}; -use orml_traits::{DataFeeder, DataProvider}; -use sp_runtime::{DispatchError, DispatchResult}; +use cfg_traits::changes::ChangeGuard; +use sp_runtime::DispatchError; use sp_std::marker::PhantomData; -use crate::{ - entities::changes::Change, - pallet::{Config, PriceOf}, -}; - -const DEFAULT_PRICE_ERR: DispatchError = - DispatchError::Other("No configured price registry for pallet-loans"); - -/// Type used to configure the pallet without a price registry -pub struct NoPriceRegistry(PhantomData); - -impl DataRegistry for NoPriceRegistry { - type Collection = NoPriceCollection; - type Data = PriceOf; - #[cfg(feature = "runtime-benchmarks")] - type MaxCollectionSize = sp_runtime::traits::ConstU32<0>; - - fn get(_: &T::PriceId, _: &T::PoolId) -> Result { - Err(DEFAULT_PRICE_ERR) - } - - fn collection(_: &T::PoolId) -> Self::Collection { - NoPriceCollection(PhantomData) - } - - fn register_id(_: &T::PriceId, _: &T::PoolId) -> DispatchResult { - Err(DEFAULT_PRICE_ERR) - } - - fn unregister_id(_: &T::PriceId, _: &T::PoolId) -> DispatchResult { - Err(DEFAULT_PRICE_ERR) - } -} - -impl DataProvider for NoPriceRegistry { - fn get(_: &T::PriceId) -> Option { - None - } -} - -impl DataFeeder for NoPriceRegistry { - fn feed_value(_: Option, _: T::PriceId, _: T::Rate) -> DispatchResult { - Err(DEFAULT_PRICE_ERR) - } -} - -pub struct NoPriceCollection(PhantomData); - -impl DataCollection for NoPriceCollection { - type Data = PriceOf; - - fn get(&self, _: &T::PriceId) -> Result { - Err(DEFAULT_PRICE_ERR) - } -} +use crate::{entities::changes::Change, pallet::Config}; const DEFAULT_CHANGE_ERR: DispatchError = DispatchError::Other("No configured change system for pallet-loans"); diff --git a/pallets/oracle-data-collection/src/lib.rs b/pallets/oracle-data-collection/src/lib.rs index 7bf132f128..da2b1886c3 100644 --- a/pallets/oracle-data-collection/src/lib.rs +++ b/pallets/oracle-data-collection/src/lib.rs @@ -263,10 +263,17 @@ pub mod pallet { ensure_signed(origin)?; let values = Keys::::iter_key_prefix(collection_id) - .filter_map(|key| match Self::get(&key, &collection_id) { - Ok(value) => Some(Ok((key, value))), - Err(err) if err == Error::::KeyNotInCollection.into() => None, - Err(err) => Some(Err(err)), + .filter_map(|key| { + let value = >::get( + &key, + &collection_id, + ); + + match value { + Ok(value) => Some(Ok((key, value))), + Err(err) if err == Error::::KeyNotInCollection.into() => None, + Err(err) => Some(Err(err)), + } }) .collect::, _>>()?; @@ -289,8 +296,6 @@ pub mod pallet { impl DataRegistry for Pallet { type Collection = CachedCollection; type Data = OracleValuePair; - #[cfg(feature = "runtime-benchmarks")] - type MaxCollectionSize = T::MaxCollectionSize; fn get( key: &T::OracleKey, @@ -328,7 +333,7 @@ pub mod pallet { } fn unregister_id(key: &T::OracleKey, collection_id: &T::CollectionId) -> DispatchResult { - Self::mutate_and_remove_if_clean(*collection_id, *key, |info| { + Self::mutate_and_remove_keys_if_clean(*collection_id, *key, |info| { info.usage_refs .ensure_sub_assign(1) .map_err(|_| Error::::KeyNotRegistered)?; @@ -346,7 +351,7 @@ pub mod pallet { } impl Pallet { - fn mutate_and_remove_if_clean( + fn mutate_and_remove_keys_if_clean( collection_id: T::CollectionId, key: T::OracleKey, f: impl FnOnce(&mut KeyInfo) -> DispatchResult, @@ -369,12 +374,51 @@ pub mod pallet { key: T::OracleKey, feeders: BoundedVec, ) -> DispatchResult { - Self::mutate_and_remove_if_clean(collection_id, key, |info| { + Self::mutate_and_remove_keys_if_clean(collection_id, key, |info| { info.feeders = feeders.clone(); Ok(()) }) } } + + #[cfg(feature = "runtime-benchmarks")] + impl ValueProvider<(u32, T::CollectionId), T::OracleKey> for Pallet + where + T::FeederId: From, + { + type Value = OracleValuePair; + + fn get( + &(id, collection_id): &(u32, T::CollectionId), + key: &T::OracleKey, + ) -> Result, DispatchError> { + T::OracleProvider::get(&(T::FeederId::from(id), collection_id), key) + } + + fn set( + &(id, collection_id): &(u32, T::CollectionId), + key: &T::OracleKey, + value: Self::Value, + ) { + let feeder = T::FeederId::from(id); + T::OracleProvider::set(&(feeder.clone(), collection_id), key, value); + + Keys::::mutate_exists(collection_id, key, |maybe_info| { + let info = maybe_info.get_or_insert(Default::default()); + if !info.feeders.contains(&feeder) { + info.feeders.try_push(feeder).unwrap(); + } + }); + + let aggregated_value = + >::get(key, &collection_id) + .unwrap(); + + Collection::::mutate(collection_id, |collection| { + collection.try_insert(*key, aggregated_value).unwrap(); + }); + } + } } pub mod types { diff --git a/runtime/altair/Cargo.toml b/runtime/altair/Cargo.toml index 89b743b885..d56d6a6292 100644 --- a/runtime/altair/Cargo.toml +++ b/runtime/altair/Cargo.toml @@ -78,7 +78,6 @@ cumulus-pallet-parachain-system = { workspace = true } cumulus-pallet-xcm = { workspace = true } cumulus-pallet-xcmp-queue = { workspace = true } orml-asset-registry = { workspace = true } -orml-oracle = { workspace = true } orml-tokens = { workspace = true } orml-xcm = { workspace = true } orml-xtokens = { workspace = true } @@ -95,7 +94,6 @@ pallet-collator-selection = { workspace = true } pallet-collective = { workspace = true } pallet-crowdloan-claim = { workspace = true } pallet-crowdloan-reward = { workspace = true } -pallet-data-collector = { workspace = true } pallet-democracy = { workspace = true } pallet-elections-phragmen = { workspace = true } pallet-ethereum = { workspace = true } @@ -209,7 +207,6 @@ std = [ "cumulus-pallet-xcm/std", "cumulus-pallet-xcmp-queue/std", "orml-asset-registry/std", - "orml-oracle/std", "orml-tokens/std", "orml-xcm/std", "orml-xtokens/std", @@ -226,7 +223,6 @@ std = [ "pallet-collective/std", "pallet-crowdloan-claim/std", "pallet-crowdloan-reward/std", - "pallet-data-collector/std", "pallet-democracy/std", "pallet-elections-phragmen/std", "pallet-ethereum/std", @@ -316,7 +312,6 @@ runtime-benchmarks = [ "pallet-collective/runtime-benchmarks", "pallet-crowdloan-claim/runtime-benchmarks", "pallet-crowdloan-reward/runtime-benchmarks", - "pallet-data-collector/runtime-benchmarks", "pallet-democracy/runtime-benchmarks", "pallet-elections-phragmen/runtime-benchmarks", "pallet-ethereum/runtime-benchmarks", @@ -388,7 +383,6 @@ try-runtime = [ "cumulus-pallet-xcm/try-runtime", "cumulus-pallet-xcmp-queue/try-runtime", "orml-asset-registry/try-runtime", - "orml-oracle/try-runtime", "orml-tokens/try-runtime", "orml-xcm/try-runtime", "orml-xtokens/try-runtime", @@ -405,7 +399,6 @@ try-runtime = [ "pallet-collective/try-runtime", "pallet-crowdloan-claim/try-runtime", "pallet-crowdloan-reward/try-runtime", - "pallet-data-collector/try-runtime", "pallet-democracy/try-runtime", "pallet-elections-phragmen/try-runtime", "pallet-ethereum/try-runtime", diff --git a/runtime/altair/src/lib.rs b/runtime/altair/src/lib.rs index 27262b1d24..c5fe79735b 100644 --- a/runtime/altair/src/lib.rs +++ b/runtime/altair/src/lib.rs @@ -30,7 +30,6 @@ use cfg_types::{ consts::pools::*, fee_keys::{Fee, FeeKey}, fixed_point::{Quantity, Rate, Ratio}, - ids::PRICE_ORACLE_PALLET_ID, investments::InvestmentPortfolio, oracles::OracleKey, permissions::{PermissionRoles, PermissionScope, PermissionedCurrencyRole, PoolRole, Role}, @@ -81,7 +80,6 @@ use runtime_common::{ fees::{DealWithFees, FeeToTreasury, WeightToFee}, oracle::{Feeder, OracleConverterBridge}, permissions::PoolAdminCheck, - production_or_benchmark, xcm::AccountIdToMultiLocation, xcm_transactor, AllowanceDeposit, CurrencyED, HoldId, NativeCurrency, }; @@ -1320,50 +1318,23 @@ impl pallet_rewards::Config for Runtime { type RuntimeEvent = RuntimeEvent; } -// PoolSystem & Loans - parameter_types! { pub const MaxActiveLoansPerPool: u32 = 300; - pub const MaxRateCount: u32 = MaxActiveLoansPerPool::get(); - pub const MaxCollectionSize: u32 = MaxActiveLoansPerPool::get(); + pub const MaxRateCount: u32 = 300; // See #1024 + pub const FirstValueFee: Fee = Fee::Balance(deposit(1, pallet_oracle_feed::util::size_of_feed::())); + #[derive(Clone, PartialEq, Eq, Debug, TypeInfo, Encode, Decode, MaxEncodedLen)] pub const MaxWriteOffPolicySize: u32 = 100; - pub const MaxPriceOracleMembers: u32 = 5; - pub const MaxHasDispatchedSize: u32 = production_or_benchmark!( - MaxPriceOracleMembers::get(), - // For benchmarking we need a number of members equal to the active loans. - // The benchmark distinction can be removed once - // is merged. - MaxActiveLoansPerPool::get() - ); - pub const MaxPoolsWithExternalPrices: u32 = 50; - pub RootOperatorOraclePrice: AccountId = PRICE_ORACLE_PALLET_ID.into_account_truncating(); -} - -impl pallet_membership::Config for Runtime { - type AddOrigin = EnsureRootOr; - type MaxMembers = MaxPriceOracleMembers; - type MembershipChanged = PriceOracle; - type MembershipInitialized = (); - type PrimeOrigin = EnsureRootOr; - type RemoveOrigin = EnsureRootOr; - type ResetOrigin = EnsureRootOr; - type RuntimeEvent = RuntimeEvent; - type SwapOrigin = EnsureRootOr; - type WeightInfo = pallet_membership::weights::SubstrateWeight; -} -parameter_types! { #[derive(Clone, PartialEq, Eq, Debug, TypeInfo, Encode, Decode, MaxEncodedLen)] pub const MaxFeedersPerKey: u32 = 10; - pub const FirstValueFee: Fee = Fee::Balance(deposit(1, pallet_oracle_feed::util::size_of_feed::())); } impl pallet_oracle_feed::Config for Runtime { type FeederOrigin = EitherOfDiverse, EnsureSigned>; type FirstValuePayFee = FeeToTreasury; type OracleKey = OracleKey; - type OracleValue = Quantity; + type OracleValue = Ratio; type RuntimeEvent = RuntimeEvent; type Time = Timestamp; type WeightInfo = weights::pallet_oracle_feed::WeightInfo; @@ -1387,38 +1358,39 @@ impl pallet_oracle_data_collection::Config for Runtime { type WeightInfo = weights::pallet_oracle_data_collection::WeightInfo; } -parameter_types! { - pub const MaxFeedValues: u32 = 500; -} - -impl orml_oracle::Config for Runtime { - type CombineData = runtime_common::oracle::LastOracleValue; - type MaxFeedValues = MaxFeedValues; - type MaxHasDispatchedSize = MaxHasDispatchedSize; - #[cfg(not(feature = "runtime-benchmarks"))] - type Members = PriceOracleMembership; - // This can be removed once - // is merged. - #[cfg(feature = "runtime-benchmarks")] - type Members = runtime_common::oracle::benchmarks_util::Members; - type OnNewData = runtime_common::oracle::OnNewPrice; - type OracleKey = OracleKey; - type OracleValue = Quantity; - type RootOperatorAccountId = RootOperatorOraclePrice; +impl pallet_interest_accrual::Config for Runtime { + type Balance = Balance; + type MaxRateCount = MaxRateCount; + type Rate = Rate; type RuntimeEvent = RuntimeEvent; type Time = Timestamp; - type WeightInfo = (); + type Weights = weights::pallet_interest_accrual::WeightInfo; } -impl pallet_data_collector::Config for Runtime { - type CollectionId = PoolId; - type Data = Balance; - type DataId = OracleKey; - type DataProvider = - runtime_common::oracle::DataProviderBridge; - type MaxCollectionSize = MaxCollectionSize; - type MaxCollections = MaxPoolsWithExternalPrices; +impl pallet_loans::Config for Runtime { + type Balance = Balance; + type ChangeGuard = PoolSystem; + type CollectionId = CollectionId; + type CurrencyId = CurrencyId; + type InterestAccrual = InterestAccrual; + type ItemId = ItemId; + type LoanId = LoanId; + type MaxActiveLoansPerPool = MaxActiveLoansPerPool; + type MaxWriteOffPolicySize = MaxWriteOffPolicySize; type Moment = Millis; + type NonFungible = Uniques; + type PerThing = Perquintill; + type Permissions = Permissions; + type Pool = PoolSystem; + type PoolId = PoolId; + type PriceId = OracleKey; + type PriceRegistry = OraclePriceCollection; + type Quantity = Quantity; + type Rate = Rate; + type RuntimeChange = runtime_common::changes::RuntimeChange; + type RuntimeEvent = RuntimeEvent; + type Time = Timestamp; + type WeightInfo = weights::pallet_loans::WeightInfo; } parameter_types! { @@ -1451,43 +1423,6 @@ impl pallet_xcm_transactor::Config for Runtime { type XcmSender = XcmRouter; } -impl pallet_interest_accrual::Config for Runtime { - type Balance = Balance; - // TODO: This is a stopgap value until we can calculate it correctly with - // updated benchmarks. See #1024 - type MaxRateCount = MaxActiveLoansPerPool; - type Rate = Rate; - type RuntimeEvent = RuntimeEvent; - type Time = Timestamp; - type Weights = weights::pallet_interest_accrual::WeightInfo; -} - -impl pallet_loans::Config for Runtime { - type Balance = Balance; - type ChangeGuard = PoolSystem; - type CollectionId = CollectionId; - type CurrencyId = CurrencyId; - type InterestAccrual = InterestAccrual; - type ItemId = ItemId; - type LoanId = LoanId; - type MaxActiveLoansPerPool = MaxActiveLoansPerPool; - type MaxWriteOffPolicySize = MaxWriteOffPolicySize; - type Moment = Millis; - type NonFungible = Uniques; - type PerThing = Perquintill; - type Permissions = Permissions; - type Pool = PoolSystem; - type PoolId = PoolId; - type PriceId = OracleKey; - type PriceRegistry = PriceCollector; - type Quantity = Quantity; - type Rate = Rate; - type RuntimeChange = runtime_common::changes::RuntimeChange; - type RuntimeEvent = RuntimeEvent; - type Time = Timestamp; - type WeightInfo = weights::pallet_loans::WeightInfo; -} - parameter_types! { pub const PoolPalletId: frame_support::PalletId = cfg_types::ids::POOLS_PALLET_ID; @@ -1847,7 +1782,6 @@ construct_runtime!( BlockRewardsBase: pallet_rewards::::{Pallet, Storage, Event, Config} = 104, BlockRewards: pallet_block_rewards::{Pallet, Call, Storage, Event, Config} = 105, Keystore: pallet_keystore::{Pallet, Call, Storage, Event} = 106, - PriceCollector: pallet_data_collector::{Pallet, Storage} = 107, LiquidityPools: pallet_liquidity_pools::{Pallet, Call, Storage, Event} = 108, LiquidityPoolsGateway: pallet_liquidity_pools_gateway::{Pallet, Call, Storage, Event, Origin } = 109, LiquidityRewardsBase: pallet_rewards::::{Pallet, Storage, Event, Config} = 110, @@ -1872,8 +1806,6 @@ construct_runtime!( OrmlTokens: orml_tokens::{Pallet, Storage, Event, Config} = 150, OrmlAssetRegistry: orml_asset_registry::{Pallet, Storage, Call, Event, Config} = 151, OrmlXcm: orml_xcm::{Pallet, Storage, Call, Event} = 152, - PriceOracle: orml_oracle::{Pallet, Call, Storage, Event} = 153, - PriceOracleMembership: pallet_membership::{Pallet, Call, Storage, Event} = 154, // EVM pallets EVM: pallet_evm::{Pallet, Config, Call, Storage, Event} = 160, diff --git a/runtime/centrifuge/Cargo.toml b/runtime/centrifuge/Cargo.toml index 8c80ee2329..d7b80cba4c 100644 --- a/runtime/centrifuge/Cargo.toml +++ b/runtime/centrifuge/Cargo.toml @@ -78,7 +78,6 @@ cumulus-pallet-parachain-system = { workspace = true } cumulus-pallet-xcm = { workspace = true } cumulus-pallet-xcmp-queue = { workspace = true } orml-asset-registry = { workspace = true } -orml-oracle = { workspace = true } orml-tokens = { workspace = true } orml-xcm = { workspace = true } orml-xtokens = { workspace = true } @@ -95,7 +94,6 @@ pallet-collator-selection = { workspace = true } pallet-collective = { workspace = true } pallet-crowdloan-claim = { workspace = true } pallet-crowdloan-reward = { workspace = true } -pallet-data-collector = { workspace = true } pallet-democracy = { workspace = true } pallet-elections-phragmen = { workspace = true } pallet-ethereum = { workspace = true } @@ -209,7 +207,6 @@ std = [ "cumulus-pallet-xcm/std", "cumulus-pallet-xcmp-queue/std", "orml-asset-registry/std", - "orml-oracle/std", "orml-tokens/std", "orml-xcm/std", "orml-xtokens/std", @@ -226,7 +223,6 @@ std = [ "pallet-collective/std", "pallet-crowdloan-claim/std", "pallet-crowdloan-reward/std", - "pallet-data-collector/std", "pallet-democracy/std", "pallet-elections-phragmen/std", "pallet-ethereum/std", @@ -315,7 +311,6 @@ runtime-benchmarks = [ "pallet-collective/runtime-benchmarks", "pallet-crowdloan-claim/runtime-benchmarks", "pallet-crowdloan-reward/runtime-benchmarks", - "pallet-data-collector/runtime-benchmarks", "pallet-democracy/runtime-benchmarks", "pallet-elections-phragmen/runtime-benchmarks", "pallet-ethereum/runtime-benchmarks", @@ -387,7 +382,6 @@ try-runtime = [ "cumulus-pallet-xcm/try-runtime", "cumulus-pallet-xcmp-queue/try-runtime", "orml-asset-registry/try-runtime", - "orml-oracle/try-runtime", "orml-tokens/try-runtime", "orml-xcm/try-runtime", "orml-xtokens/try-runtime", @@ -404,7 +398,6 @@ try-runtime = [ "pallet-collective/try-runtime", "pallet-crowdloan-claim/try-runtime", "pallet-crowdloan-reward/try-runtime", - "pallet-data-collector/try-runtime", "pallet-democracy/try-runtime", "pallet-elections-phragmen/try-runtime", "pallet-ethereum/try-runtime", diff --git a/runtime/centrifuge/src/lib.rs b/runtime/centrifuge/src/lib.rs index 37df6db791..a296c579e3 100644 --- a/runtime/centrifuge/src/lib.rs +++ b/runtime/centrifuge/src/lib.rs @@ -29,7 +29,6 @@ use cfg_types::{ consts::pools::{MaxTrancheNameLengthBytes, MaxTrancheSymbolLengthBytes}, fee_keys::{Fee, FeeKey}, fixed_point::{Quantity, Rate, Ratio}, - ids::PRICE_ORACLE_PALLET_ID, investments::InvestmentPortfolio, oracles::OracleKey, permissions::{ @@ -85,7 +84,6 @@ use runtime_common::{ fees::{DealWithFees, FeeToTreasury, WeightToFee}, oracle::{Feeder, OracleConverterBridge}, permissions::PoolAdminCheck, - production_or_benchmark, xcm::AccountIdToMultiLocation, xcm_transactor, AllowanceDeposit, CurrencyED, HoldId, NativeCurrency, }; @@ -1679,46 +1677,21 @@ impl pallet_investments::Config for Runtime { parameter_types! { pub const MaxActiveLoansPerPool: u32 = 1000; - pub const MaxRateCount: u32 = MaxActiveLoansPerPool::get(); - pub const MaxCollectionSize: u32 = MaxActiveLoansPerPool::get(); + pub const MaxRateCount: u32 = 1000; // See #1024 + pub const FirstValueFee: Fee = Fee::Balance(deposit(1, pallet_oracle_feed::util::size_of_feed::())); + #[derive(Clone, PartialEq, Eq, Debug, TypeInfo, Encode, Decode, MaxEncodedLen)] pub const MaxWriteOffPolicySize: u32 = 100; - pub const MaxPriceOracleMembers: u32 = 5; - pub const MaxHasDispatchedSize: u32 = production_or_benchmark!( - MaxPriceOracleMembers::get(), - // For benchmarking we need a number of members equal to the active loans. - // The benchmark distinction can be removed once - // is merged. - MaxActiveLoansPerPool::get() - ); - pub const MaxPoolsWithExternalPrices: u32 = 50; - pub RootOperatorOraclePrice: AccountId = PRICE_ORACLE_PALLET_ID.into_account_truncating(); -} - -impl pallet_membership::Config for Runtime { - type AddOrigin = EnsureRootOr; - type MaxMembers = MaxPriceOracleMembers; - type MembershipChanged = PriceOracle; - type MembershipInitialized = (); - type PrimeOrigin = EnsureRootOr; - type RemoveOrigin = EnsureRootOr; - type ResetOrigin = EnsureRootOr; - type RuntimeEvent = RuntimeEvent; - type SwapOrigin = EnsureRootOr; - type WeightInfo = pallet_membership::weights::SubstrateWeight; -} -parameter_types! { #[derive(Clone, PartialEq, Eq, Debug, TypeInfo, Encode, Decode, MaxEncodedLen)] pub const MaxFeedersPerKey: u32 = 10; - pub const FirstValueFee: Fee = Fee::Balance(deposit(1, pallet_oracle_feed::util::size_of_feed::())); } impl pallet_oracle_feed::Config for Runtime { type FeederOrigin = EitherOfDiverse, EnsureSigned>; type FirstValuePayFee = FeeToTreasury; type OracleKey = OracleKey; - type OracleValue = Quantity; + type OracleValue = Ratio; type RuntimeEvent = RuntimeEvent; type Time = Timestamp; type WeightInfo = weights::pallet_oracle_feed::WeightInfo; @@ -1742,45 +1715,9 @@ impl pallet_oracle_data_collection::Config for Runtime { type WeightInfo = weights::pallet_oracle_data_collection::WeightInfo; } -parameter_types! { - pub const MaxFeedValues: u32 = 500; -} - -impl orml_oracle::Config for Runtime { - type CombineData = runtime_common::oracle::LastOracleValue; - type MaxFeedValues = MaxFeedValues; - type MaxHasDispatchedSize = MaxHasDispatchedSize; - #[cfg(not(feature = "runtime-benchmarks"))] - type Members = PriceOracleMembership; - // This can be removed once - // is merged. - #[cfg(feature = "runtime-benchmarks")] - type Members = runtime_common::oracle::benchmarks_util::Members; - type OnNewData = runtime_common::oracle::OnNewPrice; - type OracleKey = OracleKey; - type OracleValue = Quantity; - type RootOperatorAccountId = RootOperatorOraclePrice; - type RuntimeEvent = RuntimeEvent; - type Time = Timestamp; - type WeightInfo = (); -} - -impl pallet_data_collector::Config for Runtime { - type CollectionId = PoolId; - type Data = Balance; - type DataId = OracleKey; - type DataProvider = - runtime_common::oracle::DataProviderBridge; - type MaxCollectionSize = MaxCollectionSize; - type MaxCollections = MaxPoolsWithExternalPrices; - type Moment = Millis; -} - impl pallet_interest_accrual::Config for Runtime { type Balance = Balance; - // TODO: This is a stopgap value until we can calculate it correctly with - // updated benchmarks. See #1024 - type MaxRateCount = MaxActiveLoansPerPool; + type MaxRateCount = MaxRateCount; type Rate = Rate; type RuntimeEvent = RuntimeEvent; type Time = Timestamp; @@ -1804,7 +1741,7 @@ impl pallet_loans::Config for Runtime { type Pool = PoolSystem; type PoolId = PoolId; type PriceId = OracleKey; - type PriceRegistry = PriceCollector; + type PriceRegistry = OraclePriceCollection; type Quantity = Quantity; type Rate = Rate; type RuntimeChange = runtime_common::changes::RuntimeChange; @@ -1951,7 +1888,6 @@ construct_runtime!( CollatorAllowlist: pallet_collator_allowlist::{Pallet, Call, Storage, Config, Event} = 99, BlockRewardsBase: pallet_rewards::::{Pallet, Storage, Event, Config} = 100, BlockRewards: pallet_block_rewards::{Pallet, Call, Storage, Event, Config} = 101, - PriceCollector: pallet_data_collector::{Pallet, Storage} = 102, LiquidityPools: pallet_liquidity_pools::{Pallet, Call, Storage, Event} = 103, LiquidityRewardsBase: pallet_rewards::::{Pallet, Storage, Event, Config} = 104, LiquidityRewards: pallet_liquidity_rewards::{Pallet, Call, Storage, Event} = 105, @@ -1977,8 +1913,6 @@ construct_runtime!( OrmlTokens: orml_tokens::{Pallet, Storage, Event, Config} = 151, OrmlAssetRegistry: orml_asset_registry::{Pallet, Storage, Call, Event, Config} = 152, OrmlXcm: orml_xcm::{Pallet, Storage, Call, Event} = 153, - PriceOracle: orml_oracle::{Pallet, Call, Storage, Event} = 154, - PriceOracleMembership: pallet_membership::{Pallet, Call, Storage, Event} = 155, // EVM pallets EVM: pallet_evm::{Pallet, Config, Call, Storage, Event} = 160, diff --git a/runtime/common/Cargo.toml b/runtime/common/Cargo.toml index 01b11ef07f..b8c6c7a2d5 100644 --- a/runtime/common/Cargo.toml +++ b/runtime/common/Cargo.toml @@ -56,7 +56,6 @@ cumulus-pallet-parachain-system = { workspace = true } cumulus-pallet-xcm = { workspace = true } cumulus-pallet-xcmp-queue = { workspace = true } orml-asset-registry = { workspace = true } -orml-oracle = { workspace = true } orml-tokens = { workspace = true } orml-xcm = { workspace = true } orml-xtokens = { workspace = true } @@ -73,7 +72,6 @@ pallet-collator-selection = { workspace = true } pallet-collective = { workspace = true } pallet-crowdloan-claim = { workspace = true } pallet-crowdloan-reward = { workspace = true } -pallet-data-collector = { workspace = true } pallet-democracy = { workspace = true } pallet-elections-phragmen = { workspace = true } pallet-ethereum = { workspace = true } @@ -142,7 +140,6 @@ std = [ "pallet-authorship/std", "pallet-balances/std", "pallet-base-fee/std", - "pallet-data-collector/std", "pallet-ethereum/std", "pallet-evm-chain-id/std", "pallet-evm-precompile-blake2/std", @@ -196,7 +193,6 @@ std = [ "cumulus-pallet-xcm/std", "cumulus-pallet-xcmp-queue/std", "orml-asset-registry/std", - "orml-oracle/std", "orml-tokens/std", "orml-xcm/std", "orml-xtokens/std", @@ -213,7 +209,6 @@ std = [ "pallet-collective/std", "pallet-crowdloan-claim/std", "pallet-crowdloan-reward/std", - "pallet-data-collector/std", "pallet-democracy/std", "pallet-elections-phragmen/std", "pallet-ethereum/std", @@ -295,7 +290,6 @@ runtime-benchmarks = [ "pallet-collective/runtime-benchmarks", "pallet-crowdloan-claim/runtime-benchmarks", "pallet-crowdloan-reward/runtime-benchmarks", - "pallet-data-collector/runtime-benchmarks", "pallet-democracy/runtime-benchmarks", "pallet-elections-phragmen/runtime-benchmarks", "pallet-ethereum/runtime-benchmarks", @@ -356,7 +350,6 @@ try-runtime = [ "cumulus-pallet-xcm/try-runtime", "cumulus-pallet-xcmp-queue/try-runtime", "orml-asset-registry/try-runtime", - "orml-oracle/try-runtime", "orml-tokens/try-runtime", "orml-xcm/try-runtime", "orml-xtokens/try-runtime", @@ -373,7 +366,6 @@ try-runtime = [ "pallet-collective/try-runtime", "pallet-crowdloan-claim/try-runtime", "pallet-crowdloan-reward/try-runtime", - "pallet-data-collector/try-runtime", "pallet-democracy/try-runtime", "pallet-elections-phragmen/try-runtime", "pallet-ethereum/try-runtime", diff --git a/runtime/common/src/oracle.rs b/runtime/common/src/oracle.rs index b567955ffc..7b561f6a03 100644 --- a/runtime/common/src/oracle.rs +++ b/runtime/common/src/oracle.rs @@ -9,150 +9,30 @@ use cfg_types::{ tokens::{CurrencyId, CustomMetadata}, }; use frame_support::{traits::OriginTrait, RuntimeDebugNoBound}; -use orml_traits::{asset_registry, CombineData, DataProviderExtended, OnNewData}; +use orml_traits::asset_registry; use parity_scale_codec::{Decode, Encode, MaxEncodedLen}; use scale_info::TypeInfo; -use sp_runtime::{ - traits::{EnsureInto, Zero}, - DispatchError, -}; -use sp_std::{marker::PhantomData, vec::Vec}; - -type TimestampedQuantity = orml_oracle::TimestampedValue; - -/// A provider that maps an `TimestampedQuantity` into a tuple -/// `(Balance, Millis)`. -pub struct DataProviderBridge( - PhantomData<(Oracle, AssetRegistry, Pools)>, -); - -impl DataProviderExtended<(OracleKey, PoolId), (Balance, Millis)> - for DataProviderBridge -where - Oracle: DataProviderExtended, - AssetRegistry: asset_registry::Inspect, - Pools: PoolInspect, -{ - fn get_no_op((key, pool_id): &(OracleKey, PoolId)) -> Option<(Balance, Millis)> { - let TimestampedQuantity { value, timestamp } = Oracle::get_no_op(key)?; - let currency = Pools::currency_for(*pool_id)?; - let decimals = AssetRegistry::metadata(¤cy)?.decimals; - - let balance = fixed_point_to_balance(value, decimals as usize).ok()?; - - Some((balance, timestamp)) - } - - fn get_all_values() -> Vec<((OracleKey, PoolId), Option<(Balance, Millis)>)> { - // Unimplemented. - // - // This method is not used by pallet-data-collector and there is no way to - // implementing it because `PoolId` is not known by the oracle. - sp_std::vec![] - } -} - -/// Trigger the new data event as a `Balance` type. -pub struct OnNewPrice(PhantomData); - -impl OnNewData for OnNewPrice -where - Collector: OnNewData, -{ - fn on_new_data(account_id: &AccountId, key: &OracleKey, _: &Quantity) { - // An expected user of `OnNewData` trait should never read/trust the `value` - // parameter of this call, and instead use a `DataProvider` as source of truth - // to get the real value, that could be modified by it. - // - // Tracking issue: https://github.com/open-web3-stack/open-runtime-module-library/issues/937 - // (4 point) - Collector::on_new_data(account_id, key, &Balance::zero()) - } -} +use sp_runtime::{traits::EnsureInto, DispatchError}; +use sp_std::marker::PhantomData; -/// Always choose the last updated value in case of several values. -pub struct LastOracleValue; - -#[cfg(not(feature = "runtime-benchmarks"))] -impl CombineData for LastOracleValue { - fn combine_data( - _: &OracleKey, - values: Vec, - _: Option, - ) -> Option { - values - .into_iter() - .max_by(|v1, v2| v1.timestamp.cmp(&v2.timestamp)) - } -} +#[derive(Clone, RuntimeDebugNoBound, TypeInfo, Encode, Decode, MaxEncodedLen)] +#[scale_info(skip_type_params(O))] +pub struct Feeder(pub O::PalletsOrigin); -/// This is used for feeding the oracle from the data-collector in -/// benchmarks. -/// It can be removed once is merged. -#[cfg(feature = "runtime-benchmarks")] -pub mod benchmarks_util { - use frame_support::traits::SortedMembers; - use orml_traits::{DataFeeder, DataProvider}; - use sp_runtime::DispatchResult; - use sp_std::vec::Vec; - - use super::*; - - // This implementation can be removed once: - // be merged. - impl DataProvider - for DataProviderBridge - where - Oracle: DataProvider, - { - fn get(_: &OracleKey) -> Option { - None - } +impl> Feeder { + pub fn signed(account: AccountId) -> Self { + Self(O::signed(account).into_caller()) } - impl DataFeeder - for DataProviderBridge - where - Oracle: DataFeeder, - { - fn feed_value(who: Option, key: OracleKey, _: Balance) -> DispatchResult { - Oracle::feed_value(who, key, Default::default()) - } + pub fn root() -> Self { + Self(O::root().into_caller()) } - impl CombineData for LastOracleValue { - fn combine_data( - _: &OracleKey, - _: Vec, - _: Option, - ) -> Option { - Some(TimestampedQuantity { - value: Default::default(), - timestamp: 0, - }) - } - } - - pub struct Members; - - impl SortedMembers for Members { - fn sorted_members() -> Vec { - // We do not want members for benchmarking - Vec::default() - } - - fn contains(_: &AccountId) -> bool { - // We want to mock the member permission for benchmark - // Allowing any member - true - } + pub fn none() -> Self { + Self(O::none().into_caller()) } } -#[derive(Clone, RuntimeDebugNoBound, TypeInfo, Encode, Decode, MaxEncodedLen)] -#[scale_info(skip_type_params(O))] -pub struct Feeder(O::PalletsOrigin); - impl PartialEq for Feeder { fn eq(&self, other: &Self) -> bool { self.0.eq(&other.0) diff --git a/runtime/development/Cargo.toml b/runtime/development/Cargo.toml index bb98e7c159..ba850273cc 100644 --- a/runtime/development/Cargo.toml +++ b/runtime/development/Cargo.toml @@ -77,7 +77,6 @@ cumulus-pallet-parachain-system = { workspace = true } cumulus-pallet-xcm = { workspace = true } cumulus-pallet-xcmp-queue = { workspace = true } orml-asset-registry = { workspace = true } -orml-oracle = { workspace = true } orml-tokens = { workspace = true } orml-xcm = { workspace = true } orml-xtokens = { workspace = true } @@ -94,7 +93,6 @@ pallet-collator-selection = { workspace = true } pallet-collective = { workspace = true } pallet-crowdloan-claim = { workspace = true } pallet-crowdloan-reward = { workspace = true } -pallet-data-collector = { workspace = true } pallet-democracy = { workspace = true } pallet-elections-phragmen = { workspace = true } pallet-ethereum = { workspace = true } @@ -207,7 +205,6 @@ std = [ "cumulus-pallet-xcm/std", "cumulus-pallet-xcmp-queue/std", "orml-asset-registry/std", - "orml-oracle/std", "orml-tokens/std", "orml-xcm/std", "orml-xtokens/std", @@ -224,7 +221,6 @@ std = [ "pallet-collective/std", "pallet-crowdloan-claim/std", "pallet-crowdloan-reward/std", - "pallet-data-collector/std", "pallet-democracy/std", "pallet-elections-phragmen/std", "pallet-ethereum/std", @@ -314,7 +310,6 @@ runtime-benchmarks = [ "pallet-collective/runtime-benchmarks", "pallet-crowdloan-claim/runtime-benchmarks", "pallet-crowdloan-reward/runtime-benchmarks", - "pallet-data-collector/runtime-benchmarks", "pallet-democracy/runtime-benchmarks", "pallet-elections-phragmen/runtime-benchmarks", "pallet-ethereum/runtime-benchmarks", @@ -386,7 +381,6 @@ try-runtime = [ "cumulus-pallet-xcm/try-runtime", "cumulus-pallet-xcmp-queue/try-runtime", "orml-asset-registry/try-runtime", - "orml-oracle/try-runtime", "orml-tokens/try-runtime", "orml-xcm/try-runtime", "orml-xtokens/try-runtime", @@ -403,7 +397,6 @@ try-runtime = [ "pallet-collective/try-runtime", "pallet-crowdloan-claim/try-runtime", "pallet-crowdloan-reward/try-runtime", - "pallet-data-collector/try-runtime", "pallet-democracy/try-runtime", "pallet-elections-phragmen/try-runtime", "pallet-ethereum/try-runtime", diff --git a/runtime/development/src/lib.rs b/runtime/development/src/lib.rs index 2d01c354b1..2f41e0ddd9 100644 --- a/runtime/development/src/lib.rs +++ b/runtime/development/src/lib.rs @@ -32,7 +32,6 @@ use cfg_types::{ consts::pools::*, fee_keys::{Fee, FeeKey}, fixed_point::{Quantity, Rate, Ratio}, - ids::PRICE_ORACLE_PALLET_ID, investments::InvestmentPortfolio, locations::Location, oracles::OracleKey, @@ -93,7 +92,6 @@ use runtime_common::{ fees::{DealWithFees, FeeToTreasury, WeightToFee}, oracle::{Feeder, OracleConverterBridge}, permissions::PoolAdminCheck, - production_or_benchmark, xcm::AccountIdToMultiLocation, xcm_transactor, AllowanceDeposit, CurrencyED, HoldId, NativeCurrency, }; @@ -1307,46 +1305,21 @@ impl pallet_xcm_transactor::Config for Runtime { parameter_types! { pub const MaxActiveLoansPerPool: u32 = 1000; - pub const MaxRateCount: u32 = MaxActiveLoansPerPool::get(); - pub const MaxCollectionSize: u32 = MaxActiveLoansPerPool::get(); + pub const MaxRateCount: u32 = 1000; // See #1024 + pub const FirstValueFee: Fee = Fee::Balance(deposit(1, pallet_oracle_feed::util::size_of_feed::())); + // #[derive(Clone, PartialEq, Eq, Debug, TypeInfo, Encode, Decode, MaxEncodedLen)] pub const MaxWriteOffPolicySize: u32 = 10; - pub const MaxPriceOracleMembers: u32 = 5; - pub const MaxHasDispatchedSize: u32 = production_or_benchmark!( - MaxPriceOracleMembers::get(), - // For benchmarking we need a number of members equal to the active loans. - // The benchmark distinction can be removed once - // is merged. - MaxActiveLoansPerPool::get() - ); - pub const MaxPoolsWithExternalPrices: u32 = 50; - pub RootOperatorOraclePrice: AccountId = PRICE_ORACLE_PALLET_ID.into_account_truncating(); -} - -impl pallet_membership::Config for Runtime { - type AddOrigin = EnsureRootOr; - type MaxMembers = MaxPriceOracleMembers; - type MembershipChanged = PriceOracle; - type MembershipInitialized = (); - type PrimeOrigin = EnsureRootOr; - type RemoveOrigin = EnsureRootOr; - type ResetOrigin = EnsureRootOr; - type RuntimeEvent = RuntimeEvent; - type SwapOrigin = EnsureRootOr; - type WeightInfo = pallet_membership::weights::SubstrateWeight; -} -parameter_types! { #[derive(Clone, PartialEq, Eq, Debug, TypeInfo, Encode, Decode, MaxEncodedLen)] pub const MaxFeedersPerKey: u32 = 10; - pub const FirstValueFee: Fee = Fee::Balance(deposit(1, pallet_oracle_feed::util::size_of_feed::())); } impl pallet_oracle_feed::Config for Runtime { type FeederOrigin = EitherOfDiverse, EnsureSigned>; type FirstValuePayFee = FeeToTreasury; type OracleKey = OracleKey; - type OracleValue = Quantity; + type OracleValue = Ratio; type RuntimeEvent = RuntimeEvent; type Time = Timestamp; type WeightInfo = weights::pallet_oracle_feed::WeightInfo; @@ -1370,44 +1343,8 @@ impl pallet_oracle_data_collection::Config for Runtime { type WeightInfo = weights::pallet_oracle_data_collection::WeightInfo; } -parameter_types! { - pub const MaxFeedValues: u32 = 500; -} - -impl orml_oracle::Config for Runtime { - type CombineData = runtime_common::oracle::LastOracleValue; - type MaxFeedValues = MaxFeedValues; - type MaxHasDispatchedSize = MaxHasDispatchedSize; - #[cfg(not(feature = "runtime-benchmarks"))] - type Members = PriceOracleMembership; - // This can be removed once - // is merged. - #[cfg(feature = "runtime-benchmarks")] - type Members = runtime_common::oracle::benchmarks_util::Members; - type OnNewData = runtime_common::oracle::OnNewPrice; - type OracleKey = OracleKey; - type OracleValue = Quantity; - type RootOperatorAccountId = RootOperatorOraclePrice; - type RuntimeEvent = RuntimeEvent; - type Time = Timestamp; - type WeightInfo = (); -} - -impl pallet_data_collector::Config for Runtime { - type CollectionId = PoolId; - type Data = Balance; - type DataId = OracleKey; - type DataProvider = - runtime_common::oracle::DataProviderBridge; - type MaxCollectionSize = MaxCollectionSize; - type MaxCollections = MaxPoolsWithExternalPrices; - type Moment = Millis; -} - impl pallet_interest_accrual::Config for Runtime { type Balance = Balance; - // TODO: This is a stopgap value until we can calculate it correctly with - // updated benchmarks. See #1024 type MaxRateCount = MaxRateCount; type Rate = Rate; type RuntimeEvent = RuntimeEvent; @@ -1432,7 +1369,7 @@ impl pallet_loans::Config for Runtime { type Pool = PoolSystem; type PoolId = PoolId; type PriceId = OracleKey; - type PriceRegistry = PriceCollector; + type PriceRegistry = OraclePriceCollection; type Quantity = Quantity; type Rate = Rate; type RuntimeChange = runtime_common::changes::RuntimeChange; @@ -1946,7 +1883,6 @@ construct_runtime!( BlockRewardsBase: pallet_rewards::::{Pallet, Storage, Event, Config} = 110, BlockRewards: pallet_block_rewards::{Pallet, Call, Storage, Event, Config} = 111, TransferAllowList: pallet_transfer_allowlist::{Pallet, Call, Storage, Event} = 112, - PriceCollector: pallet_data_collector::{Pallet, Storage} = 113, GapRewardMechanism: pallet_rewards::mechanism::gap = 114, LiquidityPoolsGateway: pallet_liquidity_pools_gateway::{Pallet, Call, Storage, Event, Origin } = 115, OrderBook: pallet_order_book::{Pallet, Call, Storage, Event} = 116, @@ -1968,8 +1904,6 @@ construct_runtime!( ChainBridge: chainbridge::{Pallet, Call, Storage, Event} = 151, OrmlAssetRegistry: orml_asset_registry::{Pallet, Storage, Call, Event, Config} = 152, OrmlXcm: orml_xcm::{Pallet, Storage, Call, Event} = 153, - PriceOracle: orml_oracle::{Pallet, Call, Storage, Event} = 154, - PriceOracleMembership: pallet_membership::{Pallet, Call, Storage, Event} = 155, // EVM pallets EVM: pallet_evm::{Pallet, Config, Call, Storage, Event} = 160, diff --git a/runtime/integration-tests/Cargo.toml b/runtime/integration-tests/Cargo.toml index 43a2d263ba..c572e775ad 100644 --- a/runtime/integration-tests/Cargo.toml +++ b/runtime/integration-tests/Cargo.toml @@ -91,7 +91,6 @@ cumulus-pallet-parachain-system = { workspace = true, features = ["std"] } cumulus-pallet-xcm = { workspace = true, features = ["std"] } cumulus-pallet-xcmp-queue = { workspace = true, features = ["std"] } orml-asset-registry = { workspace = true, features = ["std"] } -orml-oracle = { workspace = true, features = ["std"] } orml-tokens = { workspace = true, features = ["std"] } orml-xcm = { workspace = true, features = ["std"] } orml-xtokens = { workspace = true, features = ["std"] } @@ -108,7 +107,6 @@ pallet-collator-selection = { workspace = true, features = ["std"] } pallet-collective = { workspace = true, features = ["std"] } pallet-crowdloan-claim = { workspace = true, features = ["std"] } pallet-crowdloan-reward = { workspace = true, features = ["std"] } -pallet-data-collector = { workspace = true, features = ["std"] } pallet-democracy = { workspace = true, features = ["std"] } pallet-elections-phragmen = { workspace = true, features = ["std"] } pallet-ethereum = { workspace = true, features = ["std"] } diff --git a/runtime/integration-tests/src/generic/cases/loans.rs b/runtime/integration-tests/src/generic/cases/loans.rs index dbe0327ec7..ed65a5fdd2 100644 --- a/runtime/integration-tests/src/generic/cases/loans.rs +++ b/runtime/integration-tests/src/generic/cases/loans.rs @@ -25,8 +25,9 @@ use pallet_loans::{ LoanRestrictions, Maturity, PayDownSchedule, RepayRestrictions, RepaymentSchedule, }, }; -use runtime_common::apis::{ - runtime_decl_for_loans_api::LoansApiV1, runtime_decl_for_pools_api::PoolsApiV1, +use runtime_common::{ + apis::{runtime_decl_for_loans_api::LoansApiV1, runtime_decl_for_pools_api::PoolsApiV1}, + oracle::Feeder, }; use crate::{ @@ -248,6 +249,10 @@ mod call { change_id, } } + + pub fn update_portfolio_valuation() -> pallet_loans::Call { + pallet_loans::Call::update_portfolio_valuation { pool_id: POOL_A } + } } /// Test the basic loan flow, which consist in: @@ -292,7 +297,10 @@ fn internal_priced() { fn oracle_priced() { let mut env = common::initialize_state_for_loans::, T>(); - env.parachain_state_mut(|| utils::feed_oracle::(vec![(PRICE_A, PRICE_VALUE_A)])); + env.parachain_state_mut(|| { + utils::oracle::update_feeders::(POOL_ADMIN.id(), POOL_A, PRICE_A, &[Feeder::root()]); + utils::oracle::feed_from_root::(PRICE_A, PRICE_VALUE_A); + }); let info = env.parachain_state(|| { let now = as TimeAsSecs>::now(); @@ -308,15 +316,23 @@ fn oracle_priced() { env.pass(Blocks::BySeconds(SECONDS_PER_MINUTE / 2)); let loan_portfolio = env.parachain_state(|| T::Api::portfolio_loan(POOL_A, loan_id).unwrap()); + let present_value_price_a = loan_portfolio.present_value; + env.parachain_state_mut(|| { // Give required tokens to the borrower to be able to repay the interest accrued // until this moment utils::give_tokens::(BORROWER.id(), Usd6::ID, loan_portfolio.outstanding_interest); // Oracle modify the value - utils::feed_oracle::(vec![(PRICE_A, PRICE_VALUE_B)]) + utils::oracle::feed_from_root::(PRICE_A, PRICE_VALUE_B); }); + let loan_portfolio = env.parachain_state(|| T::Api::portfolio_loan(POOL_A, loan_id).unwrap()); + let present_value_price_b = loan_portfolio.present_value; + + // The valuation by the oracle has been changed + assert_ne!(present_value_price_a, present_value_price_b); + env.submit_now( BORROWER, call::repay_external(loan_id, loan_portfolio.outstanding_interest, PRICE_VALUE_B), @@ -327,6 +343,66 @@ fn oracle_priced() { env.submit_now(BORROWER, call::close(loan_id)).unwrap(); } +/// Test using oracles to valuate a portfolio. +/// The oracle values used by the portfilio comes from the oracle +/// collection +fn portfolio_valuated_by_oracle() { + let mut env = common::initialize_state_for_loans::, T>(); + + env.parachain_state_mut(|| { + utils::oracle::update_feeders::(POOL_ADMIN.id(), POOL_A, PRICE_A, &[Feeder::root()]); + }); + + let info = env.parachain_state(|| { + let now = as TimeAsSecs>::now(); + common::default_loan_info::(now, common::default_external_pricing()) + }); + env.submit_now(BORROWER, call::create(&info)).unwrap(); + + let loan_id = common::last_loan_id(&env); + + env.submit_now(BORROWER, call::borrow_external(loan_id)) + .unwrap(); + + // There is no price fed, so the price comes from the one used as settement + // price when borrowing + env.submit_now(ANY, call::update_portfolio_valuation()) + .unwrap(); + + env.parachain_state_mut(|| { + utils::oracle::feed_from_root::(PRICE_A, PRICE_VALUE_B); + }); + + let loan_portfolio = env.parachain_state(|| T::Api::portfolio_loan(POOL_A, loan_id).unwrap()); + let present_value_price_b = loan_portfolio.present_value; + + // There is a price fed, but the collection is not updated yet, + // so the price still comes from the one used as settement price when + // borrowing + env.submit_now(ANY, call::update_portfolio_valuation()) + .unwrap(); + + let total_portfolio_value = env.parachain_state(|| { + as cfg_traits::PoolNAV>::nav(POOL_A).unwrap() + }); + + assert_ne!(present_value_price_b, total_portfolio_value.0); + + // We finally update the collection + env.parachain_state_mut(|| { + utils::oracle::update_collection::(ANY.id(), POOL_A); + }); + + env.submit_now(ANY, call::update_portfolio_valuation()) + .unwrap(); + + let total_portfolio_value = env.parachain_state(|| { + as cfg_traits::PoolNAV>::nav(POOL_A).unwrap() + }); + + assert_eq!(present_value_price_b, total_portfolio_value.0); +} + fn update_maturity_extension() { let mut env = common::initialize_state_for_loans::, T>(); @@ -366,4 +442,5 @@ fn update_maturity_extension() { crate::test_for_runtimes!(all, internal_priced); crate::test_for_runtimes!(all, oracle_priced); +crate::test_for_runtimes!(all, portfolio_valuated_by_oracle); crate::test_for_runtimes!(all, update_maturity_extension); diff --git a/runtime/integration-tests/src/generic/config.rs b/runtime/integration-tests/src/generic/config.rs index 4670545415..e5d06451c8 100644 --- a/runtime/integration-tests/src/generic/config.rs +++ b/runtime/integration-tests/src/generic/config.rs @@ -27,6 +27,7 @@ use parity_scale_codec::Codec; use runtime_common::{ apis, fees::{DealWithFees, WeightToFee}, + oracle::Feeder, }; use sp_core::H256; use sp_runtime::{ @@ -102,8 +103,13 @@ pub trait Runtime: NativeFungible = pallet_balances::Pallet, > + cumulus_pallet_parachain_system::Config + parachain_info::Config - + orml_oracle::Config - + orml_xtokens::Config + + pallet_oracle_feed::Config + + pallet_oracle_data_collection::Config< + OracleKey = OracleKey, + OracleValue = Balance, + FeederId = Feeder, + CollectionId = PoolId, + > + orml_xtokens::Config + pallet_xcm::Config + pallet_restricted_tokens::Config + pallet_restricted_xtokens::Config @@ -151,7 +157,8 @@ pub trait Runtime: + From> + From> + From> - + From> + + From> + + From> + From> + From> + From> @@ -176,7 +183,8 @@ pub trait Runtime: + From> + From> + From> - + From> + + From> + + From> + From> + From> + From> @@ -189,7 +197,7 @@ pub trait Runtime: type RuntimeOriginExt: Into, ::RuntimeOrigin>> + From> + Clone - + OriginTrait::RuntimeCall> + + OriginTrait::RuntimeCall, AccountId = AccountId> + From + Into::RuntimeOrigin>> + From; diff --git a/runtime/integration-tests/src/generic/utils/mod.rs b/runtime/integration-tests/src/generic/utils/mod.rs index 907dc9f34b..75827556cf 100644 --- a/runtime/integration-tests/src/generic/utils/mod.rs +++ b/runtime/integration-tests/src/generic/utils/mod.rs @@ -15,7 +15,7 @@ pub mod genesis; use cfg_primitives::{AccountId, Balance, CollectionId, ItemId, PoolId, TrancheId}; use cfg_traits::{investments::TrancheCurrency as _, Seconds}; use cfg_types::{ - fixed_point::Quantity, + fixed_point::Ratio, oracles::OracleKey, permissions::{PermissionScope, PoolRole, Role}, pools::TrancheMetadata, @@ -24,6 +24,7 @@ use cfg_types::{ use frame_support::BoundedVec; use frame_system::RawOrigin; use pallet_pool_system::tranches::{TrancheInput, TrancheType}; +use runtime_common::oracle::Feeder; use sp_runtime::{ traits::{One, StaticLookup}, Perquintill, @@ -33,6 +34,17 @@ use crate::generic::config::{Runtime, RuntimeKind}; pub const POOL_MIN_EPOCH_TIME: Seconds = 24; +fn find_event(f: impl Fn(E) -> Option) -> Option +where + T::RuntimeEventExt: TryInto, +{ + frame_system::Pallet::::events() + .into_iter() + .rev() + .find_map(|record| record.event.try_into().map(|e| f(e)).ok()) + .flatten() +} + pub fn give_nft(dest: AccountId, (collection_id, item_id): (CollectionId, ItemId)) { pallet_uniques::Pallet::::force_create( RawOrigin::Root.into(), @@ -186,7 +198,55 @@ pub fn collect_redemptions( .unwrap(); } -pub fn feed_oracle(values: Vec<(OracleKey, Quantity)>) { - orml_oracle::Pallet::::feed_values(RawOrigin::Root.into(), values.try_into().unwrap()) +pub fn last_change_id() -> T::Hash { + find_event::(|e| match e { + pallet_pool_system::Event::::ProposedChange { change_id, .. } => Some(change_id), + _ => None, + }) + .unwrap() +} + +pub mod oracle { + use super::*; + + pub fn feed_from_root(key: OracleKey, value: Ratio) { + pallet_oracle_feed::Pallet::::feed(RawOrigin::Root.into(), key, value).unwrap(); + } + + pub fn update_feeders( + admin: AccountId, + pool_id: PoolId, + price_id: OracleKey, + feeders: &[Feeder], + ) { + pallet_oracle_data_collection::Pallet::::propose_update_feeders( + RawOrigin::Signed(admin.clone()).into(), + pool_id, + price_id, + feeders + .iter() + .cloned() + .collect::>() + .try_into() + .unwrap(), + ) + .unwrap(); + + let change_id = last_change_id::(); + + pallet_oracle_data_collection::Pallet::::apply_update_feeders( + RawOrigin::Signed(admin).into(), //or any account + pool_id, + change_id, + ) + .unwrap(); + } + + pub fn update_collection(any: AccountId, pool_id: PoolId) { + pallet_oracle_data_collection::Pallet::::update_collection( + RawOrigin::Signed(any).into(), + pool_id, + ) .unwrap(); + } }