From 8996e051af84c151160cbb1a60234e4d5d0899e9 Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Wed, 15 Mar 2023 13:18:31 +0000 Subject: [PATCH 01/18] poc --- Cargo.lock | 14 +++ Cargo.toml | 1 + frame/treasury-oracle/Cargo.toml | 40 +++++++ frame/treasury-oracle/src/lib.rs | 198 +++++++++++++++++++++++++++++++ 4 files changed, 253 insertions(+) create mode 100644 frame/treasury-oracle/Cargo.toml create mode 100644 frame/treasury-oracle/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index d0aea7729bd2d..0b903bd82b81c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6852,6 +6852,20 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-treasury-oracle" +version = "4.0.0-dev" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", +] + [[package]] name = "pallet-uniques" version = "4.0.0-dev" diff --git a/Cargo.toml b/Cargo.toml index de562ad79e47e..55916e42beb25 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -166,6 +166,7 @@ members = [ "frame/transaction-payment/rpc/runtime-api", "frame/transaction-storage", "frame/treasury", + "frame/treasury-oracle", "frame/tips", "frame/uniques", "frame/utility", diff --git a/frame/treasury-oracle/Cargo.toml b/frame/treasury-oracle/Cargo.toml new file mode 100644 index 0000000000000..3599955391ca3 --- /dev/null +++ b/frame/treasury-oracle/Cargo.toml @@ -0,0 +1,40 @@ +[package] +name = "pallet-treasury-oracle" +version = "4.0.0-dev" +description = "Convert whitelisted assets to native balance" +authors = ["Centrifuge "] +homepage = "https://substrate.io" +edition = "2021" +license = "Unlicense" +publish = false +repository = "https://github.com/paritytech/substrate/" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.2.2", default-features = false, features = [ + "derive", +] } +scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } +frame-benchmarking = { version = "4.0.0-dev", default-features = false, optional = true, path = "../benchmarking" } +frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } +frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } +sp-runtime = { version = "7.0.0", path = "../../primitives/runtime" } + +[dev-dependencies] +sp-core = { version = "7.0.0", path = "../../primitives/core" } +sp-io = { version = "7.0.0", path = "../../primitives/io" } + +[features] +default = ["std"] +std = [ + "codec/std", + "frame-benchmarking?/std", + "frame-support/std", + "frame-system/std", + "scale-info/std", + "sp-runtime/std", +] +runtime-benchmarks = ["frame-benchmarking/runtime-benchmarks"] +try-runtime = ["frame-support/try-runtime"] diff --git a/frame/treasury-oracle/src/lib.rs b/frame/treasury-oracle/src/lib.rs new file mode 100644 index 0000000000000..b80205d76fb05 --- /dev/null +++ b/frame/treasury-oracle/src/lib.rs @@ -0,0 +1,198 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#![cfg_attr(not(feature = "std"), no_std)] + +use frame_support::traits::{ + fungible::Inspect, + tokens::{Balance, BalanceConversion}, +}; +use frame_system::WeightInfo; +use sp_runtime::{traits::Zero, FixedPointNumber, FixedPointOperand, FixedU128}; + +pub use pallet::*; + +// #[cfg(test)] +// mod mock; + +// #[cfg(test)] +// mod tests; + +// #[cfg(feature = "runtime-benchmarks")] +// mod benchmarking; + +// Type alias for `frame_system`'s account id. +type AccountIdOf = ::AccountId; +// This pallet's asset id and balance type. +type AssetIdOf = ::AssetId; +// Generic fungible balance type. +type BalanceOf = <::Currency as Inspect>>::Balance; + +// TODO: Pallet description + +// #[frame_support::pallet] +// TODO: Remove +#[frame_support::pallet(dev_mode)] +pub mod pallet { + use super::*; + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::config] + pub trait Config: frame_system::Config { + /// The Weight information for extrinsics in this pallet. + type WeightInfo: WeightInfo; + + /// The runtime event type. + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + + /// The origin permissioned to create a conversion rate for an asset. + type CreateOrigin: EnsureOrigin; + + /// The origin permissioned to remove an existing conversion rate for an asset. + type RemoveOrigin: EnsureOrigin; + + /// The origin permissioned to update an existiing conversion rate for an asset. + type UpdateOrigin: EnsureOrigin; + + /// The units in which we record balances. + type Balance: Balance + FixedPointOperand; + + /// The currency mechanism for this pallet. + type Currency: Inspect; + + /// The identifier for the class of asset. + type AssetId: Member + Parameter + Copy + MaybeSerializeDeserialize + MaxEncodedLen; + + /// Wrapper around `Self::AssetId` to use in dispatchable call signatures. Allows the use + /// of compact encoding in instances of the pallet, which will prevent breaking changes + /// resulting from the removal of `HasCompact` from `Self::AssetId`. + /// + /// This type includes the `From` bound, since tightly coupled pallets may + /// want to convert an `AssetId` into a parameter for calling dispatchable functions + /// directly. + type AssetIdParameter: Parameter + + Copy + + From + + Into + + MaxEncodedLen; + } + + #[pallet::storage] + #[pallet::getter(fn conversion_rate_to_native)] + /// Maps an asset to its fixed point representation in the native balance. + pub(super) type ConversionRateToNative = + StorageMap<_, Blake2_128Concat, T::AssetId, FixedU128, OptionQuery>; + + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + // Some `asset_id` conversion rate was created. + Created { asset_id: T::AssetId, rate: FixedU128 }, + // Some `asset_id` conversion rate was removed. + Removed { asset_id: T::AssetId, rate: FixedU128 }, + // Some existing `asset_id` conversion rate was updated from `old` to `new`. + Updated { asset_id: T::AssetId, old: FixedU128, new: FixedU128 }, + } + + #[pallet::error] + pub enum Error { + /// The given asset ID is unknown. + Unknown, + Conversion, + } + + #[pallet::call] + impl Pallet { + #[pallet::call_index(0)] + pub fn create( + origin: OriginFor, + id: T::AssetIdParameter, + rate: FixedU128, + ) -> DispatchResult { + T::CreateOrigin::ensure_origin(origin)?; + + let asset_id: T::AssetId = id.into(); + ConversionRateToNative::::set(asset_id, Some(rate)); + + Self::deposit_event(Event::Created { asset_id, rate }); + Ok(()) + } + + #[pallet::call_index(1)] + pub fn update( + origin: OriginFor, + id: T::AssetIdParameter, + rate: FixedU128, + ) -> DispatchResult { + T::UpdateOrigin::ensure_origin(origin)?; + + let asset_id: T::AssetId = id.into(); + let mut old = FixedU128::zero(); + ConversionRateToNative::::mutate(asset_id, |maybe_rate| { + if let Some(r) = maybe_rate { + old = *r; + *r = rate; + + Ok(()) + } else { + Err(Error::::Unknown) + } + })?; + + Self::deposit_event(Event::Updated { asset_id, old, new: rate }); + Ok(()) + } + + #[pallet::call_index(2)] + pub fn remove( + origin: OriginFor, + id: T::AssetIdParameter, + rate: FixedU128, + ) -> DispatchResult { + T::RemoveOrigin::ensure_origin(origin)?; + + let asset_id: T::AssetId = id.into(); + ensure!(ConversionRateToNative::::contains_key(asset_id), Error::::Unknown); + + ConversionRateToNative::::remove(asset_id); + + Self::deposit_event(Event::Removed { asset_id, rate }); + Ok(()) + } + } +} + +impl BalanceConversion, AssetIdOf, BalanceOf> for Pallet +where + T: Config, + BalanceOf: FixedPointOperand + Zero, +{ + type Error = pallet::Error; + + fn to_asset_balance( + balance: BalanceOf, + asset_id: AssetIdOf, + ) -> Result, pallet::Error> { + let rate = Pallet::::conversion_rate_to_native(asset_id) + .ok_or(pallet::Error::::Unknown.into())?; + Ok(rate.saturating_mul_int(balance)) + } +} From 8a07bc038a3f123f7b4860284b7646d56d1b9a2e Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Wed, 15 Mar 2023 15:26:38 +0000 Subject: [PATCH 02/18] fix: remove AssetIdParameter --- frame/treasury-oracle/src/lib.rs | 24 +++--------------------- 1 file changed, 3 insertions(+), 21 deletions(-) diff --git a/frame/treasury-oracle/src/lib.rs b/frame/treasury-oracle/src/lib.rs index b80205d76fb05..c92222084aa31 100644 --- a/frame/treasury-oracle/src/lib.rs +++ b/frame/treasury-oracle/src/lib.rs @@ -80,19 +80,6 @@ pub mod pallet { /// The identifier for the class of asset. type AssetId: Member + Parameter + Copy + MaybeSerializeDeserialize + MaxEncodedLen; - - /// Wrapper around `Self::AssetId` to use in dispatchable call signatures. Allows the use - /// of compact encoding in instances of the pallet, which will prevent breaking changes - /// resulting from the removal of `HasCompact` from `Self::AssetId`. - /// - /// This type includes the `From` bound, since tightly coupled pallets may - /// want to convert an `AssetId` into a parameter for calling dispatchable functions - /// directly. - type AssetIdParameter: Parameter - + Copy - + From - + Into - + MaxEncodedLen; } #[pallet::storage] @@ -116,7 +103,6 @@ pub mod pallet { pub enum Error { /// The given asset ID is unknown. Unknown, - Conversion, } #[pallet::call] @@ -124,12 +110,11 @@ pub mod pallet { #[pallet::call_index(0)] pub fn create( origin: OriginFor, - id: T::AssetIdParameter, + asset_id: T::AssetId, rate: FixedU128, ) -> DispatchResult { T::CreateOrigin::ensure_origin(origin)?; - let asset_id: T::AssetId = id.into(); ConversionRateToNative::::set(asset_id, Some(rate)); Self::deposit_event(Event::Created { asset_id, rate }); @@ -139,12 +124,11 @@ pub mod pallet { #[pallet::call_index(1)] pub fn update( origin: OriginFor, - id: T::AssetIdParameter, + asset_id: T::AssetId, rate: FixedU128, ) -> DispatchResult { T::UpdateOrigin::ensure_origin(origin)?; - let asset_id: T::AssetId = id.into(); let mut old = FixedU128::zero(); ConversionRateToNative::::mutate(asset_id, |maybe_rate| { if let Some(r) = maybe_rate { @@ -164,14 +148,12 @@ pub mod pallet { #[pallet::call_index(2)] pub fn remove( origin: OriginFor, - id: T::AssetIdParameter, + asset_id: T::AssetId, rate: FixedU128, ) -> DispatchResult { T::RemoveOrigin::ensure_origin(origin)?; - let asset_id: T::AssetId = id.into(); ensure!(ConversionRateToNative::::contains_key(asset_id), Error::::Unknown); - ConversionRateToNative::::remove(asset_id); Self::deposit_event(Event::Removed { asset_id, rate }); From 47443ec7f97505657c777cc23180c96ed45d1db0 Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Wed, 15 Mar 2023 17:46:52 +0000 Subject: [PATCH 03/18] tests: add --- Cargo.lock | 1 + frame/treasury-oracle/Cargo.toml | 2 + frame/treasury-oracle/src/lib.rs | 18 ++-- frame/treasury-oracle/src/mock.rs | 96 ++++++++++++++++++++++ frame/treasury-oracle/src/tests.rs | 128 +++++++++++++++++++++++++++++ 5 files changed, 234 insertions(+), 11 deletions(-) create mode 100644 frame/treasury-oracle/src/mock.rs create mode 100644 frame/treasury-oracle/src/tests.rs diff --git a/Cargo.lock b/Cargo.lock index 0b903bd82b81c..d6448139165cf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6859,6 +6859,7 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", + "pallet-balances", "parity-scale-codec", "scale-info", "sp-core", diff --git a/frame/treasury-oracle/Cargo.toml b/frame/treasury-oracle/Cargo.toml index 3599955391ca3..2f4f974c5c425 100644 --- a/frame/treasury-oracle/Cargo.toml +++ b/frame/treasury-oracle/Cargo.toml @@ -23,6 +23,7 @@ frame-system = { version = "4.0.0-dev", default-features = false, path = "../sys sp-runtime = { version = "7.0.0", path = "../../primitives/runtime" } [dev-dependencies] +pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../balances" } sp-core = { version = "7.0.0", path = "../../primitives/core" } sp-io = { version = "7.0.0", path = "../../primitives/io" } @@ -33,6 +34,7 @@ std = [ "frame-benchmarking?/std", "frame-support/std", "frame-system/std", + "pallet-balances/std", "scale-info/std", "sp-runtime/std", ] diff --git a/frame/treasury-oracle/src/lib.rs b/frame/treasury-oracle/src/lib.rs index c92222084aa31..298a5b7be0636 100644 --- a/frame/treasury-oracle/src/lib.rs +++ b/frame/treasury-oracle/src/lib.rs @@ -26,11 +26,11 @@ use sp_runtime::{traits::Zero, FixedPointNumber, FixedPointOperand, FixedU128}; pub use pallet::*; -// #[cfg(test)] -// mod mock; +#[cfg(test)] +mod mock; -// #[cfg(test)] -// mod tests; +#[cfg(test)] +mod tests; // #[cfg(feature = "runtime-benchmarks")] // mod benchmarking; @@ -94,7 +94,7 @@ pub mod pallet { // Some `asset_id` conversion rate was created. Created { asset_id: T::AssetId, rate: FixedU128 }, // Some `asset_id` conversion rate was removed. - Removed { asset_id: T::AssetId, rate: FixedU128 }, + Removed { asset_id: T::AssetId }, // Some existing `asset_id` conversion rate was updated from `old` to `new`. Updated { asset_id: T::AssetId, old: FixedU128, new: FixedU128 }, } @@ -146,17 +146,13 @@ pub mod pallet { } #[pallet::call_index(2)] - pub fn remove( - origin: OriginFor, - asset_id: T::AssetId, - rate: FixedU128, - ) -> DispatchResult { + pub fn remove(origin: OriginFor, asset_id: T::AssetId) -> DispatchResult { T::RemoveOrigin::ensure_origin(origin)?; ensure!(ConversionRateToNative::::contains_key(asset_id), Error::::Unknown); ConversionRateToNative::::remove(asset_id); - Self::deposit_event(Event::Removed { asset_id, rate }); + Self::deposit_event(Event::Removed { asset_id }); Ok(()) } } diff --git a/frame/treasury-oracle/src/mock.rs b/frame/treasury-oracle/src/mock.rs new file mode 100644 index 0000000000000..ca5426f3d7cab --- /dev/null +++ b/frame/treasury-oracle/src/mock.rs @@ -0,0 +1,96 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! The crate's mock. + +use crate as pallet_treasury_oracle; +use frame_support::traits::{ConstU16, ConstU64}; +use sp_core::H256; +use sp_runtime::{ + testing::Header, + traits::{BlakeTwo256, IdentityLookup}, +}; + +type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; +type Block = frame_system::mocking::MockBlock; + +frame_support::construct_runtime!( + pub enum Test where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system, + TreasuryOracle: pallet_treasury_oracle, + Balances: pallet_balances, + } +); + +impl frame_system::Config for Test { + type BaseCallFilter = frame_support::traits::Everything; + type BlockWeights = (); + type BlockLength = (); + type DbWeight = (); + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = u64; + type Lookup = IdentityLookup; + type Header = Header; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = ConstU64<250>; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = ConstU16<42>; + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; +} + +impl pallet_balances::Config for Test { + type Balance = u64; + type DustRemoval = (); + type RuntimeEvent = RuntimeEvent; + type ExistentialDeposit = ConstU64<1>; + type AccountStore = System; + type WeightInfo = (); + type MaxLocks = (); + type MaxReserves = (); + type ReserveIdentifier = [u8; 8]; +} + +impl pallet_treasury_oracle::Config for Test { + type WeightInfo = (); + type RuntimeEvent = RuntimeEvent; + type CreateOrigin = frame_system::EnsureRoot; + type RemoveOrigin = frame_system::EnsureSigned; + type UpdateOrigin = frame_system::EnsureSigned; + type Balance = u64; + type Currency = Balances; + type AssetId = u32; +} + +// Build genesis storage according to the mock runtime. +pub fn new_test_ext() -> sp_io::TestExternalities { + frame_system::GenesisConfig::default().build_storage::().unwrap().into() +} diff --git a/frame/treasury-oracle/src/tests.rs b/frame/treasury-oracle/src/tests.rs new file mode 100644 index 0000000000000..2549ff3218fcd --- /dev/null +++ b/frame/treasury-oracle/src/tests.rs @@ -0,0 +1,128 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! The crate's tests. + +use super::*; +use crate::pallet as pallet_treasury_oracle; +use frame_support::{assert_noop, assert_ok}; +use mock::{new_test_ext, RuntimeOrigin, Test, TreasuryOracle}; +use sp_runtime::FixedU128; + +const ASSET_ID: u32 = 42; + +#[test] +fn create_works() { + new_test_ext().execute_with(|| { + assert!(TreasuryOracle::conversion_rate_to_native(ASSET_ID).is_none()); + assert_ok!(TreasuryOracle::create( + RuntimeOrigin::root(), + ASSET_ID, + FixedU128::from_float(0.1) + )); + + assert_eq!( + TreasuryOracle::conversion_rate_to_native(ASSET_ID), + Some(FixedU128::from_float(0.1)) + ); + }); +} + +#[test] +fn remove_works() { + new_test_ext().execute_with(|| { + assert_ok!(TreasuryOracle::create( + RuntimeOrigin::root(), + ASSET_ID, + FixedU128::from_float(0.1) + )); + + assert_ok!(TreasuryOracle::remove(RuntimeOrigin::signed(1), ASSET_ID,)); + assert!(TreasuryOracle::conversion_rate_to_native(ASSET_ID).is_none()); + }); +} + +#[test] +fn remove_unknown_throws() { + new_test_ext().execute_with(|| { + assert_noop!( + TreasuryOracle::remove(RuntimeOrigin::signed(1), ASSET_ID,), + Error::::Unknown + ); + }); +} + +#[test] +fn update_works() { + new_test_ext().execute_with(|| { + assert_ok!(TreasuryOracle::create( + RuntimeOrigin::root(), + ASSET_ID, + FixedU128::from_float(0.1) + )); + assert_ok!(TreasuryOracle::update( + RuntimeOrigin::signed(1), + ASSET_ID, + FixedU128::from_float(0.5) + )); + + assert_eq!( + TreasuryOracle::conversion_rate_to_native(ASSET_ID), + Some(FixedU128::from_float(0.5)) + ); + }); +} + +#[test] +fn update_unknown_throws() { + new_test_ext().execute_with(|| { + assert_noop!( + TreasuryOracle::update(RuntimeOrigin::signed(1), ASSET_ID, FixedU128::from_float(0.5)), + Error::::Unknown + ); + }); +} + +#[test] +fn convert_works() { + new_test_ext().execute_with(|| { + assert_ok!(TreasuryOracle::create( + RuntimeOrigin::root(), + ASSET_ID, + FixedU128::from_float(2.51) + )); + + let conversion = , + ::AssetId, + BalanceOf, + >>::to_asset_balance(10, ASSET_ID); + assert_eq!(conversion.expect("Conversion rate exists for asset"), 25); + }); +} + +#[test] +fn convert_unknown_works() { + new_test_ext().execute_with(|| { + let conversion = , + ::AssetId, + BalanceOf, + >>::to_asset_balance(10, ASSET_ID); + assert!(conversion.is_err()); + }); +} From 8d3ddee0d409c1930218224cb259cb9ef57f2c05 Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Wed, 15 Mar 2023 18:14:12 +0000 Subject: [PATCH 04/18] docs: add pallet description --- frame/treasury-oracle/src/lib.rs | 54 ++++++++++++++++++++++++++++-- frame/treasury-oracle/src/tests.rs | 19 ++++++++++- 2 files changed, 70 insertions(+), 3 deletions(-) diff --git a/frame/treasury-oracle/src/lib.rs b/frame/treasury-oracle/src/lib.rs index 298a5b7be0636..972b5ad21aeb8 100644 --- a/frame/treasury-oracle/src/lib.rs +++ b/frame/treasury-oracle/src/lib.rs @@ -15,6 +15,52 @@ // See the License for the specific language governing permissions and // limitations under the License. +//! A simple oracle pallet for the treasury. +//! +//! ## Overview +//! +//! The TreasuryOracle pallet provides means of setting conversion rates +//! for some asset to native balance. +//! +//! The supported dispatchable functions are documented in the [`Call`] enum. +//! +//! ### Terminology +//! +//! * **Asset balance**: The balance type of an arbitrary asset. The network might only know about +//! identifier of the asset and nothing more. +//! * **Native balance**: The balance type of the network's native currency. +//! * **Treasury spend**: A payment from the treasury after the corresponding proposal has been +//! approved. +//! +//! ### Goals +//! +//! The treasury-oracle system in Substrate is designed to make the following possible: +//! +//! * Whitelisting assets other than the native currency which can be accepted for Treasury spends. +//! * Providing a soft conversion for the balance of whitelisted assets to native. +//! * Updating existing conversion rates. +//! +//! ## Interface +//! +//! ### Permissioned Functions +//! +//! * `create`: Creates a new asset conversion rate. +//! * `remove`: Removes an existing asset conversion rate. +//! * `update`: Overwrites an existing assert conversion rate. +//! +//! Please refer to the [`Call`] enum and its associated variants for documentation on each +//! function. +//! +//! ### Assumptions +//! +//! * Conversion rates will not be used to determine the payment amount in another asset. +//! * Conversion rates will be used to determine the tier of the spender status, e.g. +//! `SmallSpender`, `MediumSpender` or `BigSpender`. +//! * Conversion rates are only required from some asset to native. +//! +//! ## Related Modules +//! * [`Treasury`](../treasury/index.html) + #![cfg_attr(not(feature = "std"), no_std)] use frame_support::traits::{ @@ -42,8 +88,6 @@ type AssetIdOf = ::AssetId; // Generic fungible balance type. type BalanceOf = <::Currency as Inspect>>::Balance; -// TODO: Pallet description - // #[frame_support::pallet] // TODO: Remove #[frame_support::pallet(dev_mode)] @@ -103,6 +147,8 @@ pub mod pallet { pub enum Error { /// The given asset ID is unknown. Unknown, + /// The given asset ID already has an assigned conversion rate and cannot be re-created. + AlreadyExists, } #[pallet::call] @@ -115,6 +161,10 @@ pub mod pallet { ) -> DispatchResult { T::CreateOrigin::ensure_origin(origin)?; + ensure!( + !ConversionRateToNative::::contains_key(asset_id), + Error::::AlreadyExists + ); ConversionRateToNative::::set(asset_id, Some(rate)); Self::deposit_event(Event::Created { asset_id, rate }); diff --git a/frame/treasury-oracle/src/tests.rs b/frame/treasury-oracle/src/tests.rs index 2549ff3218fcd..b61d9d048dd1a 100644 --- a/frame/treasury-oracle/src/tests.rs +++ b/frame/treasury-oracle/src/tests.rs @@ -42,6 +42,23 @@ fn create_works() { }); } +#[test] +fn create_existing_throws() { + new_test_ext().execute_with(|| { + assert!(TreasuryOracle::conversion_rate_to_native(ASSET_ID).is_none()); + assert_ok!(TreasuryOracle::create( + RuntimeOrigin::root(), + ASSET_ID, + FixedU128::from_float(0.1) + )); + + assert_noop!( + TreasuryOracle::create(RuntimeOrigin::root(), ASSET_ID, FixedU128::from_float(0.1)), + Error::::AlreadyExists + ); + }); +} + #[test] fn remove_works() { new_test_ext().execute_with(|| { @@ -116,7 +133,7 @@ fn convert_works() { } #[test] -fn convert_unknown_works() { +fn convert_unknown_throws() { new_test_ext().execute_with(|| { let conversion = , From 109a321bfafd2b377d80bb40d92b65f613e8812e Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Thu, 16 Mar 2023 10:43:53 +0000 Subject: [PATCH 05/18] feat: add benches --- Cargo.lock | 1 + bin/node/runtime/Cargo.toml | 4 + bin/node/runtime/src/lib.rs | 13 ++++ frame/treasury-oracle/Cargo.toml | 17 ++++- frame/treasury-oracle/src/benchmarking.rs | 91 +++++++++++++++++++++++ frame/treasury-oracle/src/lib.rs | 12 +-- 6 files changed, 129 insertions(+), 9 deletions(-) create mode 100644 frame/treasury-oracle/src/benchmarking.rs diff --git a/Cargo.lock b/Cargo.lock index d6448139165cf..0429e597e52c7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3589,6 +3589,7 @@ dependencies = [ "pallet-transaction-payment-rpc-runtime-api", "pallet-transaction-storage", "pallet-treasury", + "pallet-treasury-oracle", "pallet-uniques", "pallet-utility", "pallet-vesting", diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 16f1d0a4cb532..9d36ebf9da37f 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -110,6 +110,7 @@ pallet-sudo = { version = "4.0.0-dev", default-features = false, path = "../../. pallet-timestamp = { version = "4.0.0-dev", default-features = false, path = "../../../frame/timestamp" } pallet-tips = { version = "4.0.0-dev", default-features = false, path = "../../../frame/tips" } pallet-treasury = { version = "4.0.0-dev", default-features = false, path = "../../../frame/treasury" } +pallet-treasury-oracle = { version = "4.0.0-dev", default-features = false, path = "../../../frame/treasury-oracle" } pallet-utility = { version = "4.0.0-dev", default-features = false, path = "../../../frame/utility" } pallet-transaction-payment = { version = "4.0.0-dev", default-features = false, path = "../../../frame/transaction-payment" } pallet-transaction-payment-rpc-runtime-api = { version = "4.0.0-dev", default-features = false, path = "../../../frame/transaction-payment/rpc/runtime-api/" } @@ -201,6 +202,7 @@ std = [ "pallet-transaction-payment/std", "pallet-transaction-storage/std", "pallet-treasury/std", + "pallet-treasury-oracle/std", "sp-transaction-pool/std", "pallet-utility/std", "sp-version/std", @@ -272,6 +274,7 @@ runtime-benchmarks = [ "pallet-tips/runtime-benchmarks", "pallet-transaction-storage/runtime-benchmarks", "pallet-treasury/runtime-benchmarks", + "pallet-treasury-oracle/runtime-benchmarks", "pallet-utility/runtime-benchmarks", "pallet-uniques/runtime-benchmarks", "pallet-nfts/runtime-benchmarks", @@ -333,6 +336,7 @@ try-runtime = [ "pallet-timestamp/try-runtime", "pallet-tips/try-runtime", "pallet-treasury/try-runtime", + "pallet-treasury-oracle/try-runtime", "pallet-utility/try-runtime", "pallet-transaction-payment/try-runtime", "pallet-asset-tx-payment/try-runtime", diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index d8426d3b35e15..9df7342a9e07e 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -1114,6 +1114,17 @@ impl pallet_treasury::Config for Runtime { type SpendOrigin = EnsureWithSuccess, AccountId, MaxBalance>; } +impl pallet_treasury_oracle::Config for Runtime { + type CreateOrigin = EnsureRoot; + type RemoveOrigin = EnsureRoot; + type UpdateOrigin = EnsureRoot; + type Balance = Balance; + type Currency = Balances; + type AssetId = u32; + type RuntimeEvent = RuntimeEvent; + type WeightInfo = (); +} + parameter_types! { pub const BountyCuratorDeposit: Permill = Permill::from_percent(50); pub const BountyValueMinimum: Balance = 5 * DOLLARS; @@ -1758,6 +1769,7 @@ construct_runtime!( TechnicalMembership: pallet_membership::, Grandpa: pallet_grandpa, Treasury: pallet_treasury, + TreasuryOracle: pallet_treasury_oracle, Contracts: pallet_contracts, Sudo: pallet_sudo, ImOnline: pallet_im_online, @@ -1915,6 +1927,7 @@ mod benches { [pallet_tips, Tips] [pallet_transaction_storage, TransactionStorage] [pallet_treasury, Treasury] + [pallet_treasury_oracle, TreasuryOracle] [pallet_uniques, Uniques] [pallet_nfts, Nfts] [pallet_utility, Utility] diff --git a/frame/treasury-oracle/Cargo.toml b/frame/treasury-oracle/Cargo.toml index 2f4f974c5c425..a3193304b4edb 100644 --- a/frame/treasury-oracle/Cargo.toml +++ b/frame/treasury-oracle/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "pallet-treasury-oracle" version = "4.0.0-dev" -description = "Convert whitelisted assets to native balance" -authors = ["Centrifuge "] +description = "Whitelist non-native assets for treasury spending and provide conversion to native balance" +authors = ["William Freudenberger "] homepage = "https://substrate.io" edition = "2021" license = "Unlicense" @@ -38,5 +38,14 @@ std = [ "scale-info/std", "sp-runtime/std", ] -runtime-benchmarks = ["frame-benchmarking/runtime-benchmarks"] -try-runtime = ["frame-support/try-runtime"] +runtime-benchmarks = [ + "frame-benchmarking/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", +] diff --git a/frame/treasury-oracle/src/benchmarking.rs b/frame/treasury-oracle/src/benchmarking.rs new file mode 100644 index 0000000000000..a5aca433abd35 --- /dev/null +++ b/frame/treasury-oracle/src/benchmarking.rs @@ -0,0 +1,91 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! The crate's benchmarks. + +#![cfg(feature = "runtime-benchmarks")] + +use super::*; +use crate::Pallet as TreasuryOracle; +use frame_benchmarking::v2::*; +use frame_support::assert_ok; +use frame_system::RawOrigin; + +const ASSET_ID: u32 = 1; + +fn default_conversion_rate() -> FixedU128 { + FixedU128::from_float(0.1) +} + +#[benchmarks(where ::AssetId: From)] +mod benchmarks { + use super::*; + + #[benchmark] + fn create() -> Result<(), BenchmarkError> { + #[extrinsic_call] + _(RawOrigin::Root, ASSET_ID.into(), default_conversion_rate()); + + assert_eq!( + TreasuryOracle::::conversion_rate_to_native::<::AssetId>( + ASSET_ID.into() + ), + Some(default_conversion_rate()) + ); + Ok(()) + } + + #[benchmark] + fn update() -> Result<(), BenchmarkError> { + assert_ok!(TreasuryOracle::::create( + RawOrigin::Root.into(), + ASSET_ID.into(), + default_conversion_rate() + )); + + #[extrinsic_call] + _(RawOrigin::Root, ASSET_ID.into(), FixedU128::from_float(1.5)); + + assert_eq!( + TreasuryOracle::::conversion_rate_to_native::<::AssetId>( + ASSET_ID.into() + ), + Some(FixedU128::from_float(1.5)) + ); + Ok(()) + } + + #[benchmark] + fn remove() -> Result<(), BenchmarkError> { + assert_ok!(TreasuryOracle::::create( + RawOrigin::Root.into(), + ASSET_ID.into(), + default_conversion_rate() + )); + + #[extrinsic_call] + _(RawOrigin::Root, ASSET_ID.into()); + + assert!(TreasuryOracle::::conversion_rate_to_native::<::AssetId>( + ASSET_ID.into() + ) + .is_none()); + Ok(()) + } + + impl_benchmark_test_suite! { TreasuryOracle, crate::mock::new_test_ext(), crate::mock::Test } +} diff --git a/frame/treasury-oracle/src/lib.rs b/frame/treasury-oracle/src/lib.rs index 972b5ad21aeb8..cc37fc44c386e 100644 --- a/frame/treasury-oracle/src/lib.rs +++ b/frame/treasury-oracle/src/lib.rs @@ -27,7 +27,7 @@ //! ### Terminology //! //! * **Asset balance**: The balance type of an arbitrary asset. The network might only know about -//! identifier of the asset and nothing more. +//! the identifier of the asset and nothing more. //! * **Native balance**: The balance type of the network's native currency. //! * **Treasury spend**: A payment from the treasury after the corresponding proposal has been //! approved. @@ -55,8 +55,8 @@ //! //! * Conversion rates will not be used to determine the payment amount in another asset. //! * Conversion rates will be used to determine the tier of the spender status, e.g. -//! `SmallSpender`, `MediumSpender` or `BigSpender`. -//! * Conversion rates are only required from some asset to native. +//! `SmallSpender`, `MediumSpender`, `BigSpender` or `Treasurer`. +//! * All conversion rates reflect the ration of some asset to native, e.g. native = asset * rate. //! //! ## Related Modules //! * [`Treasury`](../treasury/index.html) @@ -78,8 +78,8 @@ mod mock; #[cfg(test)] mod tests; -// #[cfg(feature = "runtime-benchmarks")] -// mod benchmarking; +#[cfg(feature = "runtime-benchmarks")] +mod benchmarking; // Type alias for `frame_system`'s account id. type AccountIdOf = ::AccountId; @@ -129,6 +129,8 @@ pub mod pallet { #[pallet::storage] #[pallet::getter(fn conversion_rate_to_native)] /// Maps an asset to its fixed point representation in the native balance. + /// + /// E.g. `native_amount = asset_amount * ConversionRateToNative::::get(asset_id)` pub(super) type ConversionRateToNative = StorageMap<_, Blake2_128Concat, T::AssetId, FixedU128, OptionQuery>; From 4a0fca4d18af9cfd9a7d74a4f11fa248ba4d7428 Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Thu, 16 Mar 2023 15:24:35 +0000 Subject: [PATCH 06/18] refactor: UnknownAssetId --- frame/treasury-oracle/Cargo.toml | 3 +-- frame/treasury-oracle/src/lib.rs | 18 +++++++++++------- frame/treasury-oracle/src/tests.rs | 4 ++-- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/frame/treasury-oracle/Cargo.toml b/frame/treasury-oracle/Cargo.toml index a3193304b4edb..e1d724ddcac0e 100644 --- a/frame/treasury-oracle/Cargo.toml +++ b/frame/treasury-oracle/Cargo.toml @@ -23,7 +23,7 @@ frame-system = { version = "4.0.0-dev", default-features = false, path = "../sys sp-runtime = { version = "7.0.0", path = "../../primitives/runtime" } [dev-dependencies] -pallet-balances = { version = "4.0.0-dev", default-features = false, path = "../balances" } +pallet-balances = { version = "4.0.0-dev", path = "../balances" } sp-core = { version = "7.0.0", path = "../../primitives/core" } sp-io = { version = "7.0.0", path = "../../primitives/io" } @@ -34,7 +34,6 @@ std = [ "frame-benchmarking?/std", "frame-support/std", "frame-system/std", - "pallet-balances/std", "scale-info/std", "sp-runtime/std", ] diff --git a/frame/treasury-oracle/src/lib.rs b/frame/treasury-oracle/src/lib.rs index cc37fc44c386e..c61058f9fe0aa 100644 --- a/frame/treasury-oracle/src/lib.rs +++ b/frame/treasury-oracle/src/lib.rs @@ -88,9 +88,7 @@ type AssetIdOf = ::AssetId; // Generic fungible balance type. type BalanceOf = <::Currency as Inspect>>::Balance; -// #[frame_support::pallet] -// TODO: Remove -#[frame_support::pallet(dev_mode)] +#[frame_support::pallet] pub mod pallet { use super::*; use frame_support::pallet_prelude::*; @@ -148,12 +146,13 @@ pub mod pallet { #[pallet::error] pub enum Error { /// The given asset ID is unknown. - Unknown, + UnknownAssetId, /// The given asset ID already has an assigned conversion rate and cannot be re-created. AlreadyExists, } #[pallet::call] + #[pallet::weight(10_000 + T::DbWeight::get().writes(1).ref_time())] impl Pallet { #[pallet::call_index(0)] pub fn create( @@ -174,6 +173,7 @@ pub mod pallet { } #[pallet::call_index(1)] + #[pallet::weight(10_000 + T::DbWeight::get().writes(1).ref_time())] pub fn update( origin: OriginFor, asset_id: T::AssetId, @@ -189,7 +189,7 @@ pub mod pallet { Ok(()) } else { - Err(Error::::Unknown) + Err(Error::::UnknownAssetId) } })?; @@ -198,10 +198,14 @@ pub mod pallet { } #[pallet::call_index(2)] + #[pallet::weight(10_000 + T::DbWeight::get().writes(1).ref_time())] pub fn remove(origin: OriginFor, asset_id: T::AssetId) -> DispatchResult { T::RemoveOrigin::ensure_origin(origin)?; - ensure!(ConversionRateToNative::::contains_key(asset_id), Error::::Unknown); + ensure!( + ConversionRateToNative::::contains_key(asset_id), + Error::::UnknownAssetId + ); ConversionRateToNative::::remove(asset_id); Self::deposit_event(Event::Removed { asset_id }); @@ -222,7 +226,7 @@ where asset_id: AssetIdOf, ) -> Result, pallet::Error> { let rate = Pallet::::conversion_rate_to_native(asset_id) - .ok_or(pallet::Error::::Unknown.into())?; + .ok_or(pallet::Error::::UnknownAssetId.into())?; Ok(rate.saturating_mul_int(balance)) } } diff --git a/frame/treasury-oracle/src/tests.rs b/frame/treasury-oracle/src/tests.rs index b61d9d048dd1a..74eea79a0b76d 100644 --- a/frame/treasury-oracle/src/tests.rs +++ b/frame/treasury-oracle/src/tests.rs @@ -78,7 +78,7 @@ fn remove_unknown_throws() { new_test_ext().execute_with(|| { assert_noop!( TreasuryOracle::remove(RuntimeOrigin::signed(1), ASSET_ID,), - Error::::Unknown + Error::::UnknownAssetId ); }); } @@ -109,7 +109,7 @@ fn update_unknown_throws() { new_test_ext().execute_with(|| { assert_noop!( TreasuryOracle::update(RuntimeOrigin::signed(1), ASSET_ID, FixedU128::from_float(0.5)), - Error::::Unknown + Error::::UnknownAssetId ); }); } From 719364f26fd6af9154d4e44018111ae4a907e635 Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Thu, 16 Mar 2023 16:08:41 +0000 Subject: [PATCH 07/18] fix: normalize mock cfg --- frame/treasury-oracle/src/lib.rs | 2 +- frame/treasury-oracle/src/mock.rs | 4 ++-- frame/treasury-oracle/src/tests.rs | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/frame/treasury-oracle/src/lib.rs b/frame/treasury-oracle/src/lib.rs index c61058f9fe0aa..5be780c0be6c9 100644 --- a/frame/treasury-oracle/src/lib.rs +++ b/frame/treasury-oracle/src/lib.rs @@ -152,9 +152,9 @@ pub mod pallet { } #[pallet::call] - #[pallet::weight(10_000 + T::DbWeight::get().writes(1).ref_time())] impl Pallet { #[pallet::call_index(0)] + #[pallet::weight(10_000 + T::DbWeight::get().writes(1).ref_time())] pub fn create( origin: OriginFor, asset_id: T::AssetId, diff --git a/frame/treasury-oracle/src/mock.rs b/frame/treasury-oracle/src/mock.rs index ca5426f3d7cab..fe93190fad4ff 100644 --- a/frame/treasury-oracle/src/mock.rs +++ b/frame/treasury-oracle/src/mock.rs @@ -83,8 +83,8 @@ impl pallet_treasury_oracle::Config for Test { type WeightInfo = (); type RuntimeEvent = RuntimeEvent; type CreateOrigin = frame_system::EnsureRoot; - type RemoveOrigin = frame_system::EnsureSigned; - type UpdateOrigin = frame_system::EnsureSigned; + type RemoveOrigin = frame_system::EnsureRoot; + type UpdateOrigin = frame_system::EnsureRoot; type Balance = u64; type Currency = Balances; type AssetId = u32; diff --git a/frame/treasury-oracle/src/tests.rs b/frame/treasury-oracle/src/tests.rs index 74eea79a0b76d..8db2baf777819 100644 --- a/frame/treasury-oracle/src/tests.rs +++ b/frame/treasury-oracle/src/tests.rs @@ -68,7 +68,7 @@ fn remove_works() { FixedU128::from_float(0.1) )); - assert_ok!(TreasuryOracle::remove(RuntimeOrigin::signed(1), ASSET_ID,)); + assert_ok!(TreasuryOracle::remove(RuntimeOrigin::root(), ASSET_ID,)); assert!(TreasuryOracle::conversion_rate_to_native(ASSET_ID).is_none()); }); } @@ -77,7 +77,7 @@ fn remove_works() { fn remove_unknown_throws() { new_test_ext().execute_with(|| { assert_noop!( - TreasuryOracle::remove(RuntimeOrigin::signed(1), ASSET_ID,), + TreasuryOracle::remove(RuntimeOrigin::root(), ASSET_ID,), Error::::UnknownAssetId ); }); @@ -92,7 +92,7 @@ fn update_works() { FixedU128::from_float(0.1) )); assert_ok!(TreasuryOracle::update( - RuntimeOrigin::signed(1), + RuntimeOrigin::root(), ASSET_ID, FixedU128::from_float(0.5) )); @@ -108,7 +108,7 @@ fn update_works() { fn update_unknown_throws() { new_test_ext().execute_with(|| { assert_noop!( - TreasuryOracle::update(RuntimeOrigin::signed(1), ASSET_ID, FixedU128::from_float(0.5)), + TreasuryOracle::update(RuntimeOrigin::root(), ASSET_ID, FixedU128::from_float(0.5)), Error::::UnknownAssetId ); }); From 0adf9519fc1a85b8323caaa2e5dec7662d3a0151 Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Thu, 16 Mar 2023 18:50:21 +0000 Subject: [PATCH 08/18] fix: benchmarks --- frame/treasury-oracle/Cargo.toml | 3 +-- frame/treasury-oracle/src/benchmarking.rs | 9 ++++--- frame/treasury-oracle/src/lib.rs | 29 ++++++++++++++++++----- 3 files changed, 28 insertions(+), 13 deletions(-) diff --git a/frame/treasury-oracle/Cargo.toml b/frame/treasury-oracle/Cargo.toml index e1d724ddcac0e..a46d4f3cff5e4 100644 --- a/frame/treasury-oracle/Cargo.toml +++ b/frame/treasury-oracle/Cargo.toml @@ -6,7 +6,6 @@ authors = ["William Freudenberger "] homepage = "https://substrate.io" edition = "2021" license = "Unlicense" -publish = false repository = "https://github.com/paritytech/substrate/" [package.metadata.docs.rs] @@ -20,7 +19,7 @@ scale-info = { version = "2.1.1", default-features = false, features = ["derive" frame-benchmarking = { version = "4.0.0-dev", default-features = false, optional = true, path = "../benchmarking" } frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } -sp-runtime = { version = "7.0.0", path = "../../primitives/runtime" } +sp-runtime = { version = "7.0.0", default-features = false, path = "../../primitives/runtime" } [dev-dependencies] pallet-balances = { version = "4.0.0-dev", path = "../balances" } diff --git a/frame/treasury-oracle/src/benchmarking.rs b/frame/treasury-oracle/src/benchmarking.rs index a5aca433abd35..b1c3f7c739b21 100644 --- a/frame/treasury-oracle/src/benchmarking.rs +++ b/frame/treasury-oracle/src/benchmarking.rs @@ -17,10 +17,9 @@ //! The crate's benchmarks. -#![cfg(feature = "runtime-benchmarks")] - use super::*; use crate::Pallet as TreasuryOracle; + use frame_benchmarking::v2::*; use frame_support::assert_ok; use frame_system::RawOrigin; @@ -28,7 +27,7 @@ use frame_system::RawOrigin; const ASSET_ID: u32 = 1; fn default_conversion_rate() -> FixedU128 { - FixedU128::from_float(0.1) + FixedU128::from_u32(1u32) } #[benchmarks(where ::AssetId: From)] @@ -58,13 +57,13 @@ mod benchmarks { )); #[extrinsic_call] - _(RawOrigin::Root, ASSET_ID.into(), FixedU128::from_float(1.5)); + _(RawOrigin::Root, ASSET_ID.into(), FixedU128::from_u32(2)); assert_eq!( TreasuryOracle::::conversion_rate_to_native::<::AssetId>( ASSET_ID.into() ), - Some(FixedU128::from_float(1.5)) + Some(FixedU128::from_u32(2)) ); Ok(()) } diff --git a/frame/treasury-oracle/src/lib.rs b/frame/treasury-oracle/src/lib.rs index 5be780c0be6c9..305db8edb025e 100644 --- a/frame/treasury-oracle/src/lib.rs +++ b/frame/treasury-oracle/src/lib.rs @@ -15,8 +15,13 @@ // See the License for the specific language governing permissions and // limitations under the License. +//! # Treasury Oracle Pallet +//! //! A simple oracle pallet for the treasury. //! +//! - [`Config`] +//! - [`Call`] +//! //! ## Overview //! //! The TreasuryOracle pallet provides means of setting conversion rates @@ -72,15 +77,14 @@ use sp_runtime::{traits::Zero, FixedPointNumber, FixedPointOperand, FixedU128}; pub use pallet::*; +#[cfg(feature = "runtime-benchmarks")] +pub mod benchmarking; #[cfg(test)] mod mock; #[cfg(test)] mod tests; -#[cfg(feature = "runtime-benchmarks")] -mod benchmarking; - // Type alias for `frame_system`'s account id. type AccountIdOf = ::AccountId; // This pallet's asset id and balance type. @@ -124,12 +128,12 @@ pub mod pallet { type AssetId: Member + Parameter + Copy + MaybeSerializeDeserialize + MaxEncodedLen; } - #[pallet::storage] - #[pallet::getter(fn conversion_rate_to_native)] /// Maps an asset to its fixed point representation in the native balance. /// /// E.g. `native_amount = asset_amount * ConversionRateToNative::::get(asset_id)` - pub(super) type ConversionRateToNative = + #[pallet::storage] + #[pallet::getter(fn conversion_rate_to_native)] + pub type ConversionRateToNative = StorageMap<_, Blake2_128Concat, T::AssetId, FixedU128, OptionQuery>; #[pallet::event] @@ -153,6 +157,10 @@ pub mod pallet { #[pallet::call] impl Pallet { + /// Initialize a conversion rate for the given asset. + /// + /// ## Complexity + /// - O(1) #[pallet::call_index(0)] #[pallet::weight(10_000 + T::DbWeight::get().writes(1).ref_time())] pub fn create( @@ -172,6 +180,10 @@ pub mod pallet { Ok(()) } + /// Remove the conversion rate for the given asset. + /// + /// ## Complexity + /// - O(1) #[pallet::call_index(1)] #[pallet::weight(10_000 + T::DbWeight::get().writes(1).ref_time())] pub fn update( @@ -197,6 +209,10 @@ pub mod pallet { Ok(()) } + /// Update an existing conversion rate for the given asset. + /// + /// ## Complexity + /// - O(1) #[pallet::call_index(2)] #[pallet::weight(10_000 + T::DbWeight::get().writes(1).ref_time())] pub fn remove(origin: OriginFor, asset_id: T::AssetId) -> DispatchResult { @@ -214,6 +230,7 @@ pub mod pallet { } } +// Exposes conversion of an arbitrary balance of an asset to native balance. impl BalanceConversion, AssetIdOf, BalanceOf> for Pallet where T: Config, From ffb6d95e8b30774a7acd740fef33768a69b41f40 Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Thu, 16 Mar 2023 19:27:40 +0000 Subject: [PATCH 09/18] chore: add weights --- Cargo.lock | 1 + bin/node/runtime/src/lib.rs | 2 +- frame/treasury-oracle/Cargo.toml | 2 + frame/treasury-oracle/src/lib.rs | 10 +-- frame/treasury-oracle/src/weights.rs | 129 +++++++++++++++++++++++++++ 5 files changed, 138 insertions(+), 6 deletions(-) create mode 100644 frame/treasury-oracle/src/weights.rs diff --git a/Cargo.lock b/Cargo.lock index 0429e597e52c7..4e9bee85904cf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6866,6 +6866,7 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", + "sp-std", ] [[package]] diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 9f1eb4f644d25..70348667ee7ba 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -1122,7 +1122,7 @@ impl pallet_treasury_oracle::Config for Runtime { type Currency = Balances; type AssetId = u32; type RuntimeEvent = RuntimeEvent; - type WeightInfo = (); + type WeightInfo = pallet_treasury_oracle::weights::SubstrateWeight; } parameter_types! { diff --git a/frame/treasury-oracle/Cargo.toml b/frame/treasury-oracle/Cargo.toml index a46d4f3cff5e4..45dc3a355c1b1 100644 --- a/frame/treasury-oracle/Cargo.toml +++ b/frame/treasury-oracle/Cargo.toml @@ -20,6 +20,7 @@ frame-benchmarking = { version = "4.0.0-dev", default-features = false, optional frame-support = { version = "4.0.0-dev", default-features = false, path = "../support" } frame-system = { version = "4.0.0-dev", default-features = false, path = "../system" } sp-runtime = { version = "7.0.0", default-features = false, path = "../../primitives/runtime" } +sp-std = { version = "5.0.0", default-features = false, path = "../../primitives/std" } [dev-dependencies] pallet-balances = { version = "4.0.0-dev", path = "../balances" } @@ -35,6 +36,7 @@ std = [ "frame-system/std", "scale-info/std", "sp-runtime/std", + "sp-std/std", ] runtime-benchmarks = [ "frame-benchmarking/runtime-benchmarks", diff --git a/frame/treasury-oracle/src/lib.rs b/frame/treasury-oracle/src/lib.rs index 305db8edb025e..6f4e16eb92fde 100644 --- a/frame/treasury-oracle/src/lib.rs +++ b/frame/treasury-oracle/src/lib.rs @@ -72,18 +72,18 @@ use frame_support::traits::{ fungible::Inspect, tokens::{Balance, BalanceConversion}, }; -use frame_system::WeightInfo; use sp_runtime::{traits::Zero, FixedPointNumber, FixedPointOperand, FixedU128}; pub use pallet::*; +pub use weights::WeightInfo; #[cfg(feature = "runtime-benchmarks")] pub mod benchmarking; #[cfg(test)] mod mock; - #[cfg(test)] mod tests; +pub mod weights; // Type alias for `frame_system`'s account id. type AccountIdOf = ::AccountId; @@ -162,7 +162,7 @@ pub mod pallet { /// ## Complexity /// - O(1) #[pallet::call_index(0)] - #[pallet::weight(10_000 + T::DbWeight::get().writes(1).ref_time())] + #[pallet::weight(T::WeightInfo::create())] pub fn create( origin: OriginFor, asset_id: T::AssetId, @@ -185,7 +185,7 @@ pub mod pallet { /// ## Complexity /// - O(1) #[pallet::call_index(1)] - #[pallet::weight(10_000 + T::DbWeight::get().writes(1).ref_time())] + #[pallet::weight(T::WeightInfo::update())] pub fn update( origin: OriginFor, asset_id: T::AssetId, @@ -214,7 +214,7 @@ pub mod pallet { /// ## Complexity /// - O(1) #[pallet::call_index(2)] - #[pallet::weight(10_000 + T::DbWeight::get().writes(1).ref_time())] + #[pallet::weight(T::WeightInfo::remove())] pub fn remove(origin: OriginFor, asset_id: T::AssetId) -> DispatchResult { T::RemoveOrigin::ensure_origin(origin)?; diff --git a/frame/treasury-oracle/src/weights.rs b/frame/treasury-oracle/src/weights.rs new file mode 100644 index 0000000000000..7dee1d84441a2 --- /dev/null +++ b/frame/treasury-oracle/src/weights.rs @@ -0,0 +1,129 @@ +// This file is part of Substrate. + +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Autogenerated weights for pallet_treasury_oracle +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-03-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `local`, CPU: `` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/production/substrate +// benchmark +// pallet +// --chain=dev +// --steps=50 +// --repeat=20 +// --pallet=pallet_treasury_oracle +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --heap-pages=4096 +// --output=./frame/treasury-oracle/src/weights.rs +// --header=./HEADER-APACHE2 +// --template=./.maintain/frame-weight-template.hbs + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; +use sp_std::marker::PhantomData; + +/// Weight functions needed for pallet_treasury_oracle. +pub trait WeightInfo { + fn create() -> Weight; + fn update() -> Weight; + fn remove() -> Weight; +} + +/// Weights for pallet_treasury_oracle using the Substrate node and recommended hardware. +pub struct SubstrateWeight(PhantomData); +impl WeightInfo for SubstrateWeight { + /// Storage: TreasuryOracle ConversionRateToNative (r:1 w:1) + /// Proof: TreasuryOracle ConversionRateToNative (max_values: None, max_size: Some(36), added: 2511, mode: MaxEncodedLen) + fn create() -> Weight { + // Proof Size summary in bytes: + // Measured: `76` + // Estimated: `3501` + // Minimum execution time: 6_000_000 picoseconds. + Weight::from_parts(7_000_000, 3501) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: TreasuryOracle ConversionRateToNative (r:1 w:1) + /// Proof: TreasuryOracle ConversionRateToNative (max_values: None, max_size: Some(36), added: 2511, mode: MaxEncodedLen) + fn update() -> Weight { + // Proof Size summary in bytes: + // Measured: `137` + // Estimated: `3501` + // Minimum execution time: 7_000_000 picoseconds. + Weight::from_parts(8_000_000, 3501) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } + /// Storage: TreasuryOracle ConversionRateToNative (r:1 w:1) + /// Proof: TreasuryOracle ConversionRateToNative (max_values: None, max_size: Some(36), added: 2511, mode: MaxEncodedLen) + fn remove() -> Weight { + // Proof Size summary in bytes: + // Measured: `137` + // Estimated: `3501` + // Minimum execution time: 7_000_000 picoseconds. + Weight::from_parts(8_000_000, 3501) + .saturating_add(T::DbWeight::get().reads(1_u64)) + .saturating_add(T::DbWeight::get().writes(1_u64)) + } +} + +// For backwards compatibility and tests +impl WeightInfo for () { + /// Storage: TreasuryOracle ConversionRateToNative (r:1 w:1) + /// Proof: TreasuryOracle ConversionRateToNative (max_values: None, max_size: Some(36), added: 2511, mode: MaxEncodedLen) + fn create() -> Weight { + // Proof Size summary in bytes: + // Measured: `76` + // Estimated: `3501` + // Minimum execution time: 6_000_000 picoseconds. + Weight::from_parts(7_000_000, 3501) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: TreasuryOracle ConversionRateToNative (r:1 w:1) + /// Proof: TreasuryOracle ConversionRateToNative (max_values: None, max_size: Some(36), added: 2511, mode: MaxEncodedLen) + fn update() -> Weight { + // Proof Size summary in bytes: + // Measured: `137` + // Estimated: `3501` + // Minimum execution time: 7_000_000 picoseconds. + Weight::from_parts(8_000_000, 3501) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } + /// Storage: TreasuryOracle ConversionRateToNative (r:1 w:1) + /// Proof: TreasuryOracle ConversionRateToNative (max_values: None, max_size: Some(36), added: 2511, mode: MaxEncodedLen) + fn remove() -> Weight { + // Proof Size summary in bytes: + // Measured: `137` + // Estimated: `3501` + // Minimum execution time: 7_000_000 picoseconds. + Weight::from_parts(8_000_000, 3501) + .saturating_add(RocksDbWeight::get().reads(1_u64)) + .saturating_add(RocksDbWeight::get().writes(1_u64)) + } +} From 301ddb2bd207ee33e848d71c31c7d7107bccb015 Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Fri, 17 Mar 2023 09:00:45 +0000 Subject: [PATCH 10/18] refactor: remove storage getter --- frame/treasury-oracle/src/benchmarking.rs | 26 ++++++++++------------- frame/treasury-oracle/src/lib.rs | 3 +-- frame/treasury-oracle/src/tests.rs | 10 ++++----- 3 files changed, 17 insertions(+), 22 deletions(-) diff --git a/frame/treasury-oracle/src/benchmarking.rs b/frame/treasury-oracle/src/benchmarking.rs index b1c3f7c739b21..5bb212a3ae01e 100644 --- a/frame/treasury-oracle/src/benchmarking.rs +++ b/frame/treasury-oracle/src/benchmarking.rs @@ -18,7 +18,7 @@ //! The crate's benchmarks. use super::*; -use crate::Pallet as TreasuryOracle; +use crate::{pallet as pallet_treasury_oracle, Pallet as TreasuryOracle}; use frame_benchmarking::v2::*; use frame_support::assert_ok; @@ -36,13 +36,12 @@ mod benchmarks { #[benchmark] fn create() -> Result<(), BenchmarkError> { + let asset_id: T::AssetId = ASSET_ID.into(); #[extrinsic_call] - _(RawOrigin::Root, ASSET_ID.into(), default_conversion_rate()); + _(RawOrigin::Root, asset_id, default_conversion_rate()); assert_eq!( - TreasuryOracle::::conversion_rate_to_native::<::AssetId>( - ASSET_ID.into() - ), + pallet_treasury_oracle::ConversionRateToNative::::get(asset_id), Some(default_conversion_rate()) ); Ok(()) @@ -50,19 +49,18 @@ mod benchmarks { #[benchmark] fn update() -> Result<(), BenchmarkError> { + let asset_id: T::AssetId = ASSET_ID.into(); assert_ok!(TreasuryOracle::::create( RawOrigin::Root.into(), - ASSET_ID.into(), + asset_id, default_conversion_rate() )); #[extrinsic_call] - _(RawOrigin::Root, ASSET_ID.into(), FixedU128::from_u32(2)); + _(RawOrigin::Root, asset_id, FixedU128::from_u32(2)); assert_eq!( - TreasuryOracle::::conversion_rate_to_native::<::AssetId>( - ASSET_ID.into() - ), + pallet_treasury_oracle::ConversionRateToNative::::get(asset_id), Some(FixedU128::from_u32(2)) ); Ok(()) @@ -70,6 +68,7 @@ mod benchmarks { #[benchmark] fn remove() -> Result<(), BenchmarkError> { + let asset_id: T::AssetId = ASSET_ID.into(); assert_ok!(TreasuryOracle::::create( RawOrigin::Root.into(), ASSET_ID.into(), @@ -77,12 +76,9 @@ mod benchmarks { )); #[extrinsic_call] - _(RawOrigin::Root, ASSET_ID.into()); + _(RawOrigin::Root, asset_id); - assert!(TreasuryOracle::::conversion_rate_to_native::<::AssetId>( - ASSET_ID.into() - ) - .is_none()); + assert!(pallet_treasury_oracle::ConversionRateToNative::::get(asset_id).is_none()); Ok(()) } diff --git a/frame/treasury-oracle/src/lib.rs b/frame/treasury-oracle/src/lib.rs index 6f4e16eb92fde..1a85fe6aa1100 100644 --- a/frame/treasury-oracle/src/lib.rs +++ b/frame/treasury-oracle/src/lib.rs @@ -132,7 +132,6 @@ pub mod pallet { /// /// E.g. `native_amount = asset_amount * ConversionRateToNative::::get(asset_id)` #[pallet::storage] - #[pallet::getter(fn conversion_rate_to_native)] pub type ConversionRateToNative = StorageMap<_, Blake2_128Concat, T::AssetId, FixedU128, OptionQuery>; @@ -242,7 +241,7 @@ where balance: BalanceOf, asset_id: AssetIdOf, ) -> Result, pallet::Error> { - let rate = Pallet::::conversion_rate_to_native(asset_id) + let rate = pallet::ConversionRateToNative::::get(asset_id) .ok_or(pallet::Error::::UnknownAssetId.into())?; Ok(rate.saturating_mul_int(balance)) } diff --git a/frame/treasury-oracle/src/tests.rs b/frame/treasury-oracle/src/tests.rs index 8db2baf777819..8e5dd3e037ff0 100644 --- a/frame/treasury-oracle/src/tests.rs +++ b/frame/treasury-oracle/src/tests.rs @@ -28,7 +28,7 @@ const ASSET_ID: u32 = 42; #[test] fn create_works() { new_test_ext().execute_with(|| { - assert!(TreasuryOracle::conversion_rate_to_native(ASSET_ID).is_none()); + assert!(pallet_treasury_oracle::ConversionRateToNative::::get(ASSET_ID).is_none()); assert_ok!(TreasuryOracle::create( RuntimeOrigin::root(), ASSET_ID, @@ -36,7 +36,7 @@ fn create_works() { )); assert_eq!( - TreasuryOracle::conversion_rate_to_native(ASSET_ID), + pallet_treasury_oracle::ConversionRateToNative::::get(ASSET_ID), Some(FixedU128::from_float(0.1)) ); }); @@ -45,7 +45,7 @@ fn create_works() { #[test] fn create_existing_throws() { new_test_ext().execute_with(|| { - assert!(TreasuryOracle::conversion_rate_to_native(ASSET_ID).is_none()); + assert!(pallet_treasury_oracle::ConversionRateToNative::::get(ASSET_ID).is_none()); assert_ok!(TreasuryOracle::create( RuntimeOrigin::root(), ASSET_ID, @@ -69,7 +69,7 @@ fn remove_works() { )); assert_ok!(TreasuryOracle::remove(RuntimeOrigin::root(), ASSET_ID,)); - assert!(TreasuryOracle::conversion_rate_to_native(ASSET_ID).is_none()); + assert!(pallet_treasury_oracle::ConversionRateToNative::::get(ASSET_ID).is_none()); }); } @@ -98,7 +98,7 @@ fn update_works() { )); assert_eq!( - TreasuryOracle::conversion_rate_to_native(ASSET_ID), + pallet_treasury_oracle::ConversionRateToNative::::get(ASSET_ID), Some(FixedU128::from_float(0.5)) ); }); From 7153a2c98f37fe8588c4863bd3ff1b37978ba202 Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Mon, 3 Apr 2023 14:41:04 +0200 Subject: [PATCH 11/18] chore: apply suggestions from code review --- Cargo.lock | 34 +++++----- Cargo.toml | 2 +- bin/node/runtime/Cargo.toml | 8 +-- bin/node/runtime/src/lib.rs | 8 +-- .../Cargo.toml | 2 +- .../src/benchmarking.rs | 14 ++-- .../src/lib.rs | 25 ++++--- .../src/mock.rs | 6 +- .../src/tests.rs | 68 ++++++------------- .../src/weights.rs | 34 +++++----- rust-toolchain.toml | 5 ++ 11 files changed, 93 insertions(+), 113 deletions(-) rename frame/{treasury-oracle => asset-rate}/Cargo.toml (98%) rename frame/{treasury-oracle => asset-rate}/src/benchmarking.rs (79%) rename frame/{treasury-oracle => asset-rate}/src/lib.rs (90%) rename frame/{treasury-oracle => asset-rate}/src/mock.rs (95%) rename frame/{treasury-oracle => asset-rate}/src/tests.rs (52%) rename frame/{treasury-oracle => asset-rate}/src/weights.rs (72%) create mode 100644 rust-toolchain.toml diff --git a/Cargo.lock b/Cargo.lock index 4e9bee85904cf..a240e1c386aab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3528,6 +3528,7 @@ dependencies = [ "log", "node-primitives", "pallet-alliance", + "pallet-asset-rate", "pallet-asset-tx-payment", "pallet-assets", "pallet-authority-discovery", @@ -3589,7 +3590,6 @@ dependencies = [ "pallet-transaction-payment-rpc-runtime-api", "pallet-transaction-storage", "pallet-treasury", - "pallet-treasury-oracle", "pallet-uniques", "pallet-utility", "pallet-vesting", @@ -5420,6 +5420,22 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-asset-rate" +version = "4.0.0-dev" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "pallet-balances", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", +] + [[package]] name = "pallet-asset-tx-payment" version = "4.0.0-dev" @@ -6853,22 +6869,6 @@ dependencies = [ "sp-std", ] -[[package]] -name = "pallet-treasury-oracle" -version = "4.0.0-dev" -dependencies = [ - "frame-benchmarking", - "frame-support", - "frame-system", - "pallet-balances", - "parity-scale-codec", - "scale-info", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", -] - [[package]] name = "pallet-uniques" version = "4.0.0-dev" diff --git a/Cargo.toml b/Cargo.toml index 55916e42beb25..de9a3179edb17 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -166,7 +166,7 @@ members = [ "frame/transaction-payment/rpc/runtime-api", "frame/transaction-storage", "frame/treasury", - "frame/treasury-oracle", + "frame/asset-rate", "frame/tips", "frame/uniques", "frame/utility", diff --git a/bin/node/runtime/Cargo.toml b/bin/node/runtime/Cargo.toml index 9d36ebf9da37f..2889ccefc6df7 100644 --- a/bin/node/runtime/Cargo.toml +++ b/bin/node/runtime/Cargo.toml @@ -53,6 +53,7 @@ frame-election-provider-support = { version = "4.0.0-dev", default-features = fa frame-system-rpc-runtime-api = { version = "4.0.0-dev", default-features = false, path = "../../../frame/system/rpc/runtime-api/" } frame-try-runtime = { version = "0.10.0-dev", default-features = false, path = "../../../frame/try-runtime", optional = true } pallet-alliance = { version = "4.0.0-dev", default-features = false, path = "../../../frame/alliance" } +pallet-asset-rate = { version = "4.0.0-dev", default-features = false, path = "../../../frame/asset-rate" } pallet-assets = { version = "4.0.0-dev", default-features = false, path = "../../../frame/assets" } pallet-authority-discovery = { version = "4.0.0-dev", default-features = false, path = "../../../frame/authority-discovery" } pallet-authorship = { version = "4.0.0-dev", default-features = false, path = "../../../frame/authorship" } @@ -110,7 +111,6 @@ pallet-sudo = { version = "4.0.0-dev", default-features = false, path = "../../. pallet-timestamp = { version = "4.0.0-dev", default-features = false, path = "../../../frame/timestamp" } pallet-tips = { version = "4.0.0-dev", default-features = false, path = "../../../frame/tips" } pallet-treasury = { version = "4.0.0-dev", default-features = false, path = "../../../frame/treasury" } -pallet-treasury-oracle = { version = "4.0.0-dev", default-features = false, path = "../../../frame/treasury-oracle" } pallet-utility = { version = "4.0.0-dev", default-features = false, path = "../../../frame/utility" } pallet-transaction-payment = { version = "4.0.0-dev", default-features = false, path = "../../../frame/transaction-payment" } pallet-transaction-payment-rpc-runtime-api = { version = "4.0.0-dev", default-features = false, path = "../../../frame/transaction-payment/rpc/runtime-api/" } @@ -202,7 +202,7 @@ std = [ "pallet-transaction-payment/std", "pallet-transaction-storage/std", "pallet-treasury/std", - "pallet-treasury-oracle/std", + "pallet-asset-rate/std", "sp-transaction-pool/std", "pallet-utility/std", "sp-version/std", @@ -274,7 +274,7 @@ runtime-benchmarks = [ "pallet-tips/runtime-benchmarks", "pallet-transaction-storage/runtime-benchmarks", "pallet-treasury/runtime-benchmarks", - "pallet-treasury-oracle/runtime-benchmarks", + "pallet-asset-rate/runtime-benchmarks", "pallet-utility/runtime-benchmarks", "pallet-uniques/runtime-benchmarks", "pallet-nfts/runtime-benchmarks", @@ -336,7 +336,7 @@ try-runtime = [ "pallet-timestamp/try-runtime", "pallet-tips/try-runtime", "pallet-treasury/try-runtime", - "pallet-treasury-oracle/try-runtime", + "pallet-asset-rate/try-runtime", "pallet-utility/try-runtime", "pallet-transaction-payment/try-runtime", "pallet-asset-tx-payment/try-runtime", diff --git a/bin/node/runtime/src/lib.rs b/bin/node/runtime/src/lib.rs index 70348667ee7ba..d27fcb478d42a 100644 --- a/bin/node/runtime/src/lib.rs +++ b/bin/node/runtime/src/lib.rs @@ -1114,7 +1114,7 @@ impl pallet_treasury::Config for Runtime { type SpendOrigin = EnsureWithSuccess, AccountId, MaxBalance>; } -impl pallet_treasury_oracle::Config for Runtime { +impl pallet_asset_rate::Config for Runtime { type CreateOrigin = EnsureRoot; type RemoveOrigin = EnsureRoot; type UpdateOrigin = EnsureRoot; @@ -1122,7 +1122,7 @@ impl pallet_treasury_oracle::Config for Runtime { type Currency = Balances; type AssetId = u32; type RuntimeEvent = RuntimeEvent; - type WeightInfo = pallet_treasury_oracle::weights::SubstrateWeight; + type WeightInfo = pallet_asset_rate::weights::SubstrateWeight; } parameter_types! { @@ -1769,7 +1769,7 @@ construct_runtime!( TechnicalMembership: pallet_membership::, Grandpa: pallet_grandpa, Treasury: pallet_treasury, - TreasuryOracle: pallet_treasury_oracle, + AssetRate: pallet_asset_rate, Contracts: pallet_contracts, Sudo: pallet_sudo, ImOnline: pallet_im_online, @@ -1927,7 +1927,7 @@ mod benches { [pallet_tips, Tips] [pallet_transaction_storage, TransactionStorage] [pallet_treasury, Treasury] - [pallet_treasury_oracle, TreasuryOracle] + [pallet_asset_rate, AssetRate] [pallet_uniques, Uniques] [pallet_nfts, Nfts] [pallet_utility, Utility] diff --git a/frame/treasury-oracle/Cargo.toml b/frame/asset-rate/Cargo.toml similarity index 98% rename from frame/treasury-oracle/Cargo.toml rename to frame/asset-rate/Cargo.toml index 45dc3a355c1b1..83b20944cc881 100644 --- a/frame/treasury-oracle/Cargo.toml +++ b/frame/asset-rate/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "pallet-treasury-oracle" +name = "pallet-asset-rate" version = "4.0.0-dev" description = "Whitelist non-native assets for treasury spending and provide conversion to native balance" authors = ["William Freudenberger "] diff --git a/frame/treasury-oracle/src/benchmarking.rs b/frame/asset-rate/src/benchmarking.rs similarity index 79% rename from frame/treasury-oracle/src/benchmarking.rs rename to frame/asset-rate/src/benchmarking.rs index 5bb212a3ae01e..dde0d764affb2 100644 --- a/frame/treasury-oracle/src/benchmarking.rs +++ b/frame/asset-rate/src/benchmarking.rs @@ -18,7 +18,7 @@ //! The crate's benchmarks. use super::*; -use crate::{pallet as pallet_treasury_oracle, Pallet as TreasuryOracle}; +use crate::{pallet as pallet_asset_rate, Pallet as AssetRate}; use frame_benchmarking::v2::*; use frame_support::assert_ok; @@ -41,7 +41,7 @@ mod benchmarks { _(RawOrigin::Root, asset_id, default_conversion_rate()); assert_eq!( - pallet_treasury_oracle::ConversionRateToNative::::get(asset_id), + pallet_asset_rate::ConversionRateToNative::::get(asset_id), Some(default_conversion_rate()) ); Ok(()) @@ -50,7 +50,7 @@ mod benchmarks { #[benchmark] fn update() -> Result<(), BenchmarkError> { let asset_id: T::AssetId = ASSET_ID.into(); - assert_ok!(TreasuryOracle::::create( + assert_ok!(AssetRate::::create( RawOrigin::Root.into(), asset_id, default_conversion_rate() @@ -60,7 +60,7 @@ mod benchmarks { _(RawOrigin::Root, asset_id, FixedU128::from_u32(2)); assert_eq!( - pallet_treasury_oracle::ConversionRateToNative::::get(asset_id), + pallet_asset_rate::ConversionRateToNative::::get(asset_id), Some(FixedU128::from_u32(2)) ); Ok(()) @@ -69,7 +69,7 @@ mod benchmarks { #[benchmark] fn remove() -> Result<(), BenchmarkError> { let asset_id: T::AssetId = ASSET_ID.into(); - assert_ok!(TreasuryOracle::::create( + assert_ok!(AssetRate::::create( RawOrigin::Root.into(), ASSET_ID.into(), default_conversion_rate() @@ -78,9 +78,9 @@ mod benchmarks { #[extrinsic_call] _(RawOrigin::Root, asset_id); - assert!(pallet_treasury_oracle::ConversionRateToNative::::get(asset_id).is_none()); + assert!(pallet_asset_rate::ConversionRateToNative::::get(asset_id).is_none()); Ok(()) } - impl_benchmark_test_suite! { TreasuryOracle, crate::mock::new_test_ext(), crate::mock::Test } + impl_benchmark_test_suite! { AssetRate, crate::mock::new_test_ext(), crate::mock::Test } } diff --git a/frame/treasury-oracle/src/lib.rs b/frame/asset-rate/src/lib.rs similarity index 90% rename from frame/treasury-oracle/src/lib.rs rename to frame/asset-rate/src/lib.rs index 1a85fe6aa1100..f2c144392ada9 100644 --- a/frame/treasury-oracle/src/lib.rs +++ b/frame/asset-rate/src/lib.rs @@ -15,16 +15,14 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! # Treasury Oracle Pallet -//! -//! A simple oracle pallet for the treasury. +//! # Asset Rate Pallet //! //! - [`Config`] //! - [`Call`] //! //! ## Overview //! -//! The TreasuryOracle pallet provides means of setting conversion rates +//! The AssetRate pallet provides means of setting conversion rates //! for some asset to native balance. //! //! The supported dispatchable functions are documented in the [`Call`] enum. @@ -39,7 +37,7 @@ //! //! ### Goals //! -//! The treasury-oracle system in Substrate is designed to make the following possible: +//! The asset-rate system in Substrate is designed to make the following possible: //! //! * Whitelisting assets other than the native currency which can be accepted for Treasury spends. //! * Providing a soft conversion for the balance of whitelisted assets to native. @@ -139,11 +137,11 @@ pub mod pallet { #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { // Some `asset_id` conversion rate was created. - Created { asset_id: T::AssetId, rate: FixedU128 }, + AssetRateCreated { asset_id: T::AssetId, rate: FixedU128 }, // Some `asset_id` conversion rate was removed. - Removed { asset_id: T::AssetId }, + AssetRateRemoved { asset_id: T::AssetId }, // Some existing `asset_id` conversion rate was updated from `old` to `new`. - Updated { asset_id: T::AssetId, old: FixedU128, new: FixedU128 }, + AssetRateUpdated { asset_id: T::AssetId, old: FixedU128, new: FixedU128 }, } #[pallet::error] @@ -175,11 +173,11 @@ pub mod pallet { ); ConversionRateToNative::::set(asset_id, Some(rate)); - Self::deposit_event(Event::Created { asset_id, rate }); + Self::deposit_event(Event::AssetRateCreated { asset_id, rate }); Ok(()) } - /// Remove the conversion rate for the given asset. + /// Update the conversion rate for the given asset. /// /// ## Complexity /// - O(1) @@ -204,11 +202,11 @@ pub mod pallet { } })?; - Self::deposit_event(Event::Updated { asset_id, old, new: rate }); + Self::deposit_event(Event::AssetRateUpdated { asset_id, old, new: rate }); Ok(()) } - /// Update an existing conversion rate for the given asset. + /// Remove an existing conversion rate for the given asset. /// /// ## Complexity /// - O(1) @@ -223,13 +221,14 @@ pub mod pallet { ); ConversionRateToNative::::remove(asset_id); - Self::deposit_event(Event::Removed { asset_id }); + Self::deposit_event(Event::AssetRateRemoved { asset_id }); Ok(()) } } } // Exposes conversion of an arbitrary balance of an asset to native balance. +// TODO: Switch to `AssetBalanceToBalance` after merging Substrate #13610 impl BalanceConversion, AssetIdOf, BalanceOf> for Pallet where T: Config, diff --git a/frame/treasury-oracle/src/mock.rs b/frame/asset-rate/src/mock.rs similarity index 95% rename from frame/treasury-oracle/src/mock.rs rename to frame/asset-rate/src/mock.rs index fe93190fad4ff..198007be6cc29 100644 --- a/frame/treasury-oracle/src/mock.rs +++ b/frame/asset-rate/src/mock.rs @@ -17,7 +17,7 @@ //! The crate's mock. -use crate as pallet_treasury_oracle; +use crate as pallet_asset_rate; use frame_support::traits::{ConstU16, ConstU64}; use sp_core::H256; use sp_runtime::{ @@ -35,7 +35,7 @@ frame_support::construct_runtime!( UncheckedExtrinsic = UncheckedExtrinsic, { System: frame_system, - TreasuryOracle: pallet_treasury_oracle, + AssetRate: pallet_asset_rate, Balances: pallet_balances, } ); @@ -79,7 +79,7 @@ impl pallet_balances::Config for Test { type ReserveIdentifier = [u8; 8]; } -impl pallet_treasury_oracle::Config for Test { +impl pallet_asset_rate::Config for Test { type WeightInfo = (); type RuntimeEvent = RuntimeEvent; type CreateOrigin = frame_system::EnsureRoot; diff --git a/frame/treasury-oracle/src/tests.rs b/frame/asset-rate/src/tests.rs similarity index 52% rename from frame/treasury-oracle/src/tests.rs rename to frame/asset-rate/src/tests.rs index 8e5dd3e037ff0..0c4c29519a4de 100644 --- a/frame/treasury-oracle/src/tests.rs +++ b/frame/asset-rate/src/tests.rs @@ -18,9 +18,9 @@ //! The crate's tests. use super::*; -use crate::pallet as pallet_treasury_oracle; +use crate::pallet as pallet_asset_rate; use frame_support::{assert_noop, assert_ok}; -use mock::{new_test_ext, RuntimeOrigin, Test, TreasuryOracle}; +use mock::{new_test_ext, AssetRate, RuntimeOrigin, Test}; use sp_runtime::FixedU128; const ASSET_ID: u32 = 42; @@ -28,15 +28,11 @@ const ASSET_ID: u32 = 42; #[test] fn create_works() { new_test_ext().execute_with(|| { - assert!(pallet_treasury_oracle::ConversionRateToNative::::get(ASSET_ID).is_none()); - assert_ok!(TreasuryOracle::create( - RuntimeOrigin::root(), - ASSET_ID, - FixedU128::from_float(0.1) - )); + assert!(pallet_asset_rate::ConversionRateToNative::::get(ASSET_ID).is_none()); + assert_ok!(AssetRate::create(RuntimeOrigin::root(), ASSET_ID, FixedU128::from_float(0.1))); assert_eq!( - pallet_treasury_oracle::ConversionRateToNative::::get(ASSET_ID), + pallet_asset_rate::ConversionRateToNative::::get(ASSET_ID), Some(FixedU128::from_float(0.1)) ); }); @@ -45,15 +41,11 @@ fn create_works() { #[test] fn create_existing_throws() { new_test_ext().execute_with(|| { - assert!(pallet_treasury_oracle::ConversionRateToNative::::get(ASSET_ID).is_none()); - assert_ok!(TreasuryOracle::create( - RuntimeOrigin::root(), - ASSET_ID, - FixedU128::from_float(0.1) - )); + assert!(pallet_asset_rate::ConversionRateToNative::::get(ASSET_ID).is_none()); + assert_ok!(AssetRate::create(RuntimeOrigin::root(), ASSET_ID, FixedU128::from_float(0.1))); assert_noop!( - TreasuryOracle::create(RuntimeOrigin::root(), ASSET_ID, FixedU128::from_float(0.1)), + AssetRate::create(RuntimeOrigin::root(), ASSET_ID, FixedU128::from_float(0.1)), Error::::AlreadyExists ); }); @@ -62,14 +54,10 @@ fn create_existing_throws() { #[test] fn remove_works() { new_test_ext().execute_with(|| { - assert_ok!(TreasuryOracle::create( - RuntimeOrigin::root(), - ASSET_ID, - FixedU128::from_float(0.1) - )); - - assert_ok!(TreasuryOracle::remove(RuntimeOrigin::root(), ASSET_ID,)); - assert!(pallet_treasury_oracle::ConversionRateToNative::::get(ASSET_ID).is_none()); + assert_ok!(AssetRate::create(RuntimeOrigin::root(), ASSET_ID, FixedU128::from_float(0.1))); + + assert_ok!(AssetRate::remove(RuntimeOrigin::root(), ASSET_ID,)); + assert!(pallet_asset_rate::ConversionRateToNative::::get(ASSET_ID).is_none()); }); } @@ -77,7 +65,7 @@ fn remove_works() { fn remove_unknown_throws() { new_test_ext().execute_with(|| { assert_noop!( - TreasuryOracle::remove(RuntimeOrigin::root(), ASSET_ID,), + AssetRate::remove(RuntimeOrigin::root(), ASSET_ID,), Error::::UnknownAssetId ); }); @@ -86,19 +74,11 @@ fn remove_unknown_throws() { #[test] fn update_works() { new_test_ext().execute_with(|| { - assert_ok!(TreasuryOracle::create( - RuntimeOrigin::root(), - ASSET_ID, - FixedU128::from_float(0.1) - )); - assert_ok!(TreasuryOracle::update( - RuntimeOrigin::root(), - ASSET_ID, - FixedU128::from_float(0.5) - )); + assert_ok!(AssetRate::create(RuntimeOrigin::root(), ASSET_ID, FixedU128::from_float(0.1))); + assert_ok!(AssetRate::update(RuntimeOrigin::root(), ASSET_ID, FixedU128::from_float(0.5))); assert_eq!( - pallet_treasury_oracle::ConversionRateToNative::::get(ASSET_ID), + pallet_asset_rate::ConversionRateToNative::::get(ASSET_ID), Some(FixedU128::from_float(0.5)) ); }); @@ -108,7 +88,7 @@ fn update_works() { fn update_unknown_throws() { new_test_ext().execute_with(|| { assert_noop!( - TreasuryOracle::update(RuntimeOrigin::root(), ASSET_ID, FixedU128::from_float(0.5)), + AssetRate::update(RuntimeOrigin::root(), ASSET_ID, FixedU128::from_float(0.5)), Error::::UnknownAssetId ); }); @@ -117,15 +97,11 @@ fn update_unknown_throws() { #[test] fn convert_works() { new_test_ext().execute_with(|| { - assert_ok!(TreasuryOracle::create( - RuntimeOrigin::root(), - ASSET_ID, - FixedU128::from_float(2.51) - )); + assert_ok!(AssetRate::create(RuntimeOrigin::root(), ASSET_ID, FixedU128::from_float(2.51))); - let conversion = , - ::AssetId, + ::AssetId, BalanceOf, >>::to_asset_balance(10, ASSET_ID); assert_eq!(conversion.expect("Conversion rate exists for asset"), 25); @@ -135,9 +111,9 @@ fn convert_works() { #[test] fn convert_unknown_throws() { new_test_ext().execute_with(|| { - let conversion = , - ::AssetId, + ::AssetId, BalanceOf, >>::to_asset_balance(10, ASSET_ID); assert!(conversion.is_err()); diff --git a/frame/treasury-oracle/src/weights.rs b/frame/asset-rate/src/weights.rs similarity index 72% rename from frame/treasury-oracle/src/weights.rs rename to frame/asset-rate/src/weights.rs index 7dee1d84441a2..4fae62634ef13 100644 --- a/frame/treasury-oracle/src/weights.rs +++ b/frame/asset-rate/src/weights.rs @@ -15,7 +15,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Autogenerated weights for pallet_treasury_oracle +//! Autogenerated weights for pallet_asset_rate //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev //! DATE: 2023-03-16, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` @@ -30,12 +30,12 @@ // --chain=dev // --steps=50 // --repeat=20 -// --pallet=pallet_treasury_oracle +// --pallet=pallet_asset_rate // --extrinsic=* // --execution=wasm // --wasm-execution=compiled // --heap-pages=4096 -// --output=./frame/treasury-oracle/src/weights.rs +// --output=./frame/asset-rate/src/weights.rs // --header=./HEADER-APACHE2 // --template=./.maintain/frame-weight-template.hbs @@ -46,18 +46,18 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use sp_std::marker::PhantomData; -/// Weight functions needed for pallet_treasury_oracle. +/// Weight functions needed for pallet_asset_rate. pub trait WeightInfo { fn create() -> Weight; fn update() -> Weight; fn remove() -> Weight; } -/// Weights for pallet_treasury_oracle using the Substrate node and recommended hardware. +/// Weights for pallet_asset_rate using the Substrate node and recommended hardware. pub struct SubstrateWeight(PhantomData); impl WeightInfo for SubstrateWeight { - /// Storage: TreasuryOracle ConversionRateToNative (r:1 w:1) - /// Proof: TreasuryOracle ConversionRateToNative (max_values: None, max_size: Some(36), added: 2511, mode: MaxEncodedLen) + /// Storage: AssetRate ConversionRateToNative (r:1 w:1) + /// Proof: AssetRate ConversionRateToNative (max_values: None, max_size: Some(36), added: 2511, mode: MaxEncodedLen) fn create() -> Weight { // Proof Size summary in bytes: // Measured: `76` @@ -67,8 +67,8 @@ impl WeightInfo for SubstrateWeight { .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: TreasuryOracle ConversionRateToNative (r:1 w:1) - /// Proof: TreasuryOracle ConversionRateToNative (max_values: None, max_size: Some(36), added: 2511, mode: MaxEncodedLen) + /// Storage: AssetRate ConversionRateToNative (r:1 w:1) + /// Proof: AssetRate ConversionRateToNative (max_values: None, max_size: Some(36), added: 2511, mode: MaxEncodedLen) fn update() -> Weight { // Proof Size summary in bytes: // Measured: `137` @@ -78,8 +78,8 @@ impl WeightInfo for SubstrateWeight { .saturating_add(T::DbWeight::get().reads(1_u64)) .saturating_add(T::DbWeight::get().writes(1_u64)) } - /// Storage: TreasuryOracle ConversionRateToNative (r:1 w:1) - /// Proof: TreasuryOracle ConversionRateToNative (max_values: None, max_size: Some(36), added: 2511, mode: MaxEncodedLen) + /// Storage: AssetRate ConversionRateToNative (r:1 w:1) + /// Proof: AssetRate ConversionRateToNative (max_values: None, max_size: Some(36), added: 2511, mode: MaxEncodedLen) fn remove() -> Weight { // Proof Size summary in bytes: // Measured: `137` @@ -93,8 +93,8 @@ impl WeightInfo for SubstrateWeight { // For backwards compatibility and tests impl WeightInfo for () { - /// Storage: TreasuryOracle ConversionRateToNative (r:1 w:1) - /// Proof: TreasuryOracle ConversionRateToNative (max_values: None, max_size: Some(36), added: 2511, mode: MaxEncodedLen) + /// Storage: AssetRate ConversionRateToNative (r:1 w:1) + /// Proof: AssetRate ConversionRateToNative (max_values: None, max_size: Some(36), added: 2511, mode: MaxEncodedLen) fn create() -> Weight { // Proof Size summary in bytes: // Measured: `76` @@ -104,8 +104,8 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: TreasuryOracle ConversionRateToNative (r:1 w:1) - /// Proof: TreasuryOracle ConversionRateToNative (max_values: None, max_size: Some(36), added: 2511, mode: MaxEncodedLen) + /// Storage: AssetRate ConversionRateToNative (r:1 w:1) + /// Proof: AssetRate ConversionRateToNative (max_values: None, max_size: Some(36), added: 2511, mode: MaxEncodedLen) fn update() -> Weight { // Proof Size summary in bytes: // Measured: `137` @@ -115,8 +115,8 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().reads(1_u64)) .saturating_add(RocksDbWeight::get().writes(1_u64)) } - /// Storage: TreasuryOracle ConversionRateToNative (r:1 w:1) - /// Proof: TreasuryOracle ConversionRateToNative (max_values: None, max_size: Some(36), added: 2511, mode: MaxEncodedLen) + /// Storage: AssetRate ConversionRateToNative (r:1 w:1) + /// Proof: AssetRate ConversionRateToNative (max_values: None, max_size: Some(36), added: 2511, mode: MaxEncodedLen) fn remove() -> Weight { // Proof Size summary in bytes: // Measured: `137` diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000000000..45d3fb304bb99 --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,5 @@ +[toolchain] +channel = "nightly-2022-11-15" +components = [ "rustfmt", "clippy" ] +targets = [ "wasm32-unknown-unknown" ] +profile = "minimal" From fdeefbda884fb5373311e734218b92b8e83be7c6 Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Mon, 3 Apr 2023 14:43:14 +0200 Subject: [PATCH 12/18] docs: add native balance to calls --- frame/asset-rate/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frame/asset-rate/src/lib.rs b/frame/asset-rate/src/lib.rs index f2c144392ada9..6587fc10dd132 100644 --- a/frame/asset-rate/src/lib.rs +++ b/frame/asset-rate/src/lib.rs @@ -154,7 +154,7 @@ pub mod pallet { #[pallet::call] impl Pallet { - /// Initialize a conversion rate for the given asset. + /// Initialize a conversion rate to native balance for the given asset. /// /// ## Complexity /// - O(1) @@ -177,7 +177,7 @@ pub mod pallet { Ok(()) } - /// Update the conversion rate for the given asset. + /// Update the conversion rate to native balance for the given asset. /// /// ## Complexity /// - O(1) @@ -206,7 +206,7 @@ pub mod pallet { Ok(()) } - /// Remove an existing conversion rate for the given asset. + /// Remove an existing conversion rate to native balance for the given asset. /// /// ## Complexity /// - O(1) From 65df23eb1833dbb70198b0e64de58cc1a52d8b59 Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Tue, 4 Apr 2023 08:19:05 +0200 Subject: [PATCH 13/18] chore: apply suggestions from code review --- frame/asset-rate/src/lib.rs | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/frame/asset-rate/src/lib.rs b/frame/asset-rate/src/lib.rs index 6587fc10dd132..7f245393d120c 100644 --- a/frame/asset-rate/src/lib.rs +++ b/frame/asset-rate/src/lib.rs @@ -32,15 +32,12 @@ //! * **Asset balance**: The balance type of an arbitrary asset. The network might only know about //! the identifier of the asset and nothing more. //! * **Native balance**: The balance type of the network's native currency. -//! * **Treasury spend**: A payment from the treasury after the corresponding proposal has been -//! approved. //! //! ### Goals //! //! The asset-rate system in Substrate is designed to make the following possible: //! -//! * Whitelisting assets other than the native currency which can be accepted for Treasury spends. -//! * Providing a soft conversion for the balance of whitelisted assets to native. +//! * Providing a soft conversion for the balance of supported assets to a default asset class. //! * Updating existing conversion rates. //! //! ## Interface @@ -56,13 +53,9 @@ //! //! ### Assumptions //! -//! * Conversion rates will not be used to determine the payment amount in another asset. -//! * Conversion rates will be used to determine the tier of the spender status, e.g. -//! `SmallSpender`, `MediumSpender`, `BigSpender` or `Treasurer`. +//! * Conversion rates are only used as estimates, and are not designed to be precise or closely +//! tracking real world values. //! * All conversion rates reflect the ration of some asset to native, e.g. native = asset * rate. -//! -//! ## Related Modules -//! * [`Treasury`](../treasury/index.html) #![cfg_attr(not(feature = "std"), no_std)] @@ -123,7 +116,7 @@ pub mod pallet { type Currency: Inspect; /// The identifier for the class of asset. - type AssetId: Member + Parameter + Copy + MaybeSerializeDeserialize + MaxEncodedLen; + type AssetId: frame_support::traits::tokens::AssetId; } /// Maps an asset to its fixed point representation in the native balance. From 58cc428c9a06a3edb803195f945f7b669e0b9583 Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Wed, 12 Apr 2023 08:22:01 +0200 Subject: [PATCH 14/18] chore: apply ConversionFromAssetBalance --- frame/asset-rate/src/lib.rs | 11 +++++------ frame/asset-rate/src/tests.rs | 8 ++++---- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/frame/asset-rate/src/lib.rs b/frame/asset-rate/src/lib.rs index 7f245393d120c..3b117fea8af74 100644 --- a/frame/asset-rate/src/lib.rs +++ b/frame/asset-rate/src/lib.rs @@ -22,8 +22,8 @@ //! //! ## Overview //! -//! The AssetRate pallet provides means of setting conversion rates -//! for some asset to native balance. +//! The AssetRate pallet provides means of setting conversion rates for some asset to native +//! balance. //! //! The supported dispatchable functions are documented in the [`Call`] enum. //! @@ -61,7 +61,7 @@ use frame_support::traits::{ fungible::Inspect, - tokens::{Balance, BalanceConversion}, + tokens::{Balance, ConversionFromAssetBalance}, }; use sp_runtime::{traits::Zero, FixedPointNumber, FixedPointOperand, FixedU128}; @@ -221,15 +221,14 @@ pub mod pallet { } // Exposes conversion of an arbitrary balance of an asset to native balance. -// TODO: Switch to `AssetBalanceToBalance` after merging Substrate #13610 -impl BalanceConversion, AssetIdOf, BalanceOf> for Pallet +impl ConversionFromAssetBalance, AssetIdOf, BalanceOf> for Pallet where T: Config, BalanceOf: FixedPointOperand + Zero, { type Error = pallet::Error; - fn to_asset_balance( + fn from_asset_balance( balance: BalanceOf, asset_id: AssetIdOf, ) -> Result, pallet::Error> { diff --git a/frame/asset-rate/src/tests.rs b/frame/asset-rate/src/tests.rs index 0c4c29519a4de..4e5a3167bef21 100644 --- a/frame/asset-rate/src/tests.rs +++ b/frame/asset-rate/src/tests.rs @@ -99,11 +99,11 @@ fn convert_works() { new_test_ext().execute_with(|| { assert_ok!(AssetRate::create(RuntimeOrigin::root(), ASSET_ID, FixedU128::from_float(2.51))); - let conversion = , ::AssetId, BalanceOf, - >>::to_asset_balance(10, ASSET_ID); + >>::from_asset_balance(10, ASSET_ID); assert_eq!(conversion.expect("Conversion rate exists for asset"), 25); }); } @@ -111,11 +111,11 @@ fn convert_works() { #[test] fn convert_unknown_throws() { new_test_ext().execute_with(|| { - let conversion = , ::AssetId, BalanceOf, - >>::to_asset_balance(10, ASSET_ID); + >>::from_asset_balance(10, ASSET_ID); assert!(conversion.is_err()); }); } From 44a9f6af98e59b05600f42901d6578eb30a3bfa3 Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Wed, 12 Apr 2023 08:22:23 +0200 Subject: [PATCH 15/18] tests: update balance mock --- frame/asset-rate/src/mock.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/frame/asset-rate/src/mock.rs b/frame/asset-rate/src/mock.rs index 198007be6cc29..9775b7a747926 100644 --- a/frame/asset-rate/src/mock.rs +++ b/frame/asset-rate/src/mock.rs @@ -77,6 +77,10 @@ impl pallet_balances::Config for Test { type MaxLocks = (); type MaxReserves = (); type ReserveIdentifier = [u8; 8]; + type HoldIdentifier = (); + type FreezeIdentifier = (); + type MaxHolds = (); + type MaxFreezes = (); } impl pallet_asset_rate::Config for Test { From 03acddbd7d7096ebbdc74bd44545c257277f820d Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Wed, 12 Apr 2023 09:26:32 +0200 Subject: [PATCH 16/18] chore: apply suggestions from code review --- frame/asset-rate/Cargo.toml | 2 +- rust-toolchain.toml | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) delete mode 100644 rust-toolchain.toml diff --git a/frame/asset-rate/Cargo.toml b/frame/asset-rate/Cargo.toml index 83b20944cc881..646d68e5b0fc7 100644 --- a/frame/asset-rate/Cargo.toml +++ b/frame/asset-rate/Cargo.toml @@ -5,7 +5,7 @@ description = "Whitelist non-native assets for treasury spending and provide con authors = ["William Freudenberger "] homepage = "https://substrate.io" edition = "2021" -license = "Unlicense" +license = "Apache-2.0" repository = "https://github.com/paritytech/substrate/" [package.metadata.docs.rs] diff --git a/rust-toolchain.toml b/rust-toolchain.toml deleted file mode 100644 index 45d3fb304bb99..0000000000000 --- a/rust-toolchain.toml +++ /dev/null @@ -1,5 +0,0 @@ -[toolchain] -channel = "nightly-2022-11-15" -components = [ "rustfmt", "clippy" ] -targets = [ "wasm32-unknown-unknown" ] -profile = "minimal" From 1f14c39b3b63f46e447af6750a5e677f77a32e2c Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Tue, 18 Apr 2023 11:40:28 +0200 Subject: [PATCH 17/18] ci: set publish to false --- frame/asset-rate/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/frame/asset-rate/Cargo.toml b/frame/asset-rate/Cargo.toml index 646d68e5b0fc7..36aabb12bcbbd 100644 --- a/frame/asset-rate/Cargo.toml +++ b/frame/asset-rate/Cargo.toml @@ -7,6 +7,7 @@ homepage = "https://substrate.io" edition = "2021" license = "Apache-2.0" repository = "https://github.com/paritytech/substrate/" +publish = false [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] From 329b846b1b10d477830fe63703f35e4fdebdba69 Mon Sep 17 00:00:00 2001 From: William Freudenberger Date: Tue, 18 Apr 2023 11:40:41 +0200 Subject: [PATCH 18/18] docs: fix missing rustdoc --- frame/asset-rate/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frame/asset-rate/src/lib.rs b/frame/asset-rate/src/lib.rs index 3b117fea8af74..8c6597a389833 100644 --- a/frame/asset-rate/src/lib.rs +++ b/frame/asset-rate/src/lib.rs @@ -220,7 +220,7 @@ pub mod pallet { } } -// Exposes conversion of an arbitrary balance of an asset to native balance. +/// Exposes conversion of an arbitrary balance of an asset to native balance. impl ConversionFromAssetBalance, AssetIdOf, BalanceOf> for Pallet where T: Config,