From bfb32fbc6ecbc142c6e746ac97e0292104920702 Mon Sep 17 00:00:00 2001 From: b-yap <2826165+b-yap@users.noreply.github.com> Date: Wed, 21 Feb 2024 22:18:21 +0800 Subject: [PATCH 1/5] add the treasury-buyout-extension pallet --- runtime/amplitude/Cargo.toml | 20 ++++---- runtime/amplitude/src/lib.rs | 88 +++++++++++++++++++++++++++++++++++- 2 files changed, 98 insertions(+), 10 deletions(-) diff --git a/runtime/amplitude/Cargo.toml b/runtime/amplitude/Cargo.toml index cf776d086..639c0cbd3 100644 --- a/runtime/amplitude/Cargo.toml +++ b/runtime/amplitude/Cargo.toml @@ -104,8 +104,8 @@ orml-xcm-support = { git = "https://github.com/open-web3-stack/open-runtime-modu # KILT parachain-staking = { path = "../../pallets/parachain-staking", default-features = false } -orml-currencies-allowance-extension = { path = "../../pallets/orml-currencies-allowance-extension", default-features = false } - +orml-currencies-allowance-extension = {path = "../../pallets/orml-currencies-allowance-extension", default-features = false} +treasury-buyout-extension = {path = "../../pallets/treasury-buyout-extension", default-features = false} # Pendulum Pallets vesting-manager = { path = "../../pallets/vesting-manager", default-features = false } @@ -237,10 +237,12 @@ std = [ "module-pallet-staking-rpc-runtime-api/std", "module-vault-registry-rpc-runtime-api/std", "spacewalk-primitives/std", - # custom libraries from pendulum - "orml-currencies-allowance-extension/std", - "parachain-staking/std", - "vesting-manager/std", + # custom libraries from pendulum + "orml-currencies-allowance-extension/std", + "treasury-buyout-extension/std", + "parachain-staking/std", + "vesting-manager/std", + ] runtime-benchmarks = [ @@ -266,7 +268,8 @@ runtime-benchmarks = [ "cumulus-pallet-xcmp-queue/runtime-benchmarks", "pallet-collective/runtime-benchmarks", "runtime-common/runtime-benchmarks", - "orml-currencies-allowance-extension/runtime-benchmarks" + "orml-currencies-allowance-extension/runtime-benchmarks", + "treasury-buyout-extension/runtime-benchmarks" ] try-runtime = [ @@ -321,7 +324,8 @@ try-runtime = [ "reward-distribution/try-runtime", "dia-oracle/try-runtime", "orml-currencies-allowance-extension/try-runtime", + "treasury-buyout-extension/try-runtime", "vesting-manager/try-runtime", "bifrost-farming/try-runtime", "zenlink-protocol/try-runtime", -] \ No newline at end of file +] diff --git a/runtime/amplitude/src/lib.rs b/runtime/amplitude/src/lib.rs index 83fbd31d1..21d39271d 100644 --- a/runtime/amplitude/src/lib.rs +++ b/runtime/amplitude/src/lib.rs @@ -29,14 +29,16 @@ use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, traits::{ AccountIdConversion, AccountIdLookup, BlakeTwo256, Block as BlockT, Convert, ConvertInto, + One, Zero, }, transaction_validity::{TransactionSource, TransactionValidity}, - ApplyExtrinsicResult, DispatchError, FixedPointNumber, SaturatedConversion, + ApplyExtrinsicResult, DispatchError, FixedPointNumber, FixedU128, SaturatedConversion, }; const CONTRACTS_DEBUG_OUTPUT: bool = true; -use sp_std::{marker::PhantomData, prelude::*}; +use sp_std::{fmt::Debug, marker::PhantomData, prelude::*}; + #[cfg(feature = "std")] use sp_version::NativeVersion; use sp_version::RuntimeVersion; @@ -85,6 +87,7 @@ pub use nomination::Event as NominationEvent; use oracle::{ dia, dia::{DiaOracleAdapter, NativeCurrencyKey, XCMCurrencyConversion}, + OracleKey, }; pub use redeem::{Event as RedeemEvent, RedeemRequest}; pub use replace::{Event as ReplaceEvent, ReplaceRequest}; @@ -135,6 +138,7 @@ pub type SignedExtra = ( frame_system::CheckNonce, frame_system::CheckWeight, pallet_transaction_payment::ChargeTransactionPayment, + treasury_buyout_extension::CheckBuyout, ); /// Unchecked extrinsic type as expected by this runtime. @@ -371,6 +375,7 @@ impl Contains for BaseFilter { RuntimeCall::TokenAllowance(_) | RuntimeCall::AssetRegistry(_) | RuntimeCall::Proxy(_) | + RuntimeCall::TreasuryBuyoutExtension(_) | RuntimeCall::RewardDistribution(_) => true, // All pallets are allowed, but exhaustive match is defensive // in the case of adding new pallets. @@ -1056,6 +1061,7 @@ where frame_system::CheckNonce::::from(index), frame_system::CheckWeight::::new(), pallet_transaction_payment::ChargeTransactionPayment::::from(tip), + treasury_buyout_extension::CheckBuyout::::new(), ); let raw_payload = SignedPayload::new(call, extra).ok()?; @@ -1315,6 +1321,82 @@ impl orml_currencies_allowance_extension::Config for Runtime { type MaxAllowedCurrencies = ConstU32<256>; } +pub struct OraclePriceGetter(Oracle); + +impl treasury_buyout_extension::PriceGetter for OraclePriceGetter { + #[cfg(not(feature = "runtime-benchmarks"))] + fn get_price(currency_id: CurrencyId) -> Result + where + FixedNumber: FixedPointNumber + One + Zero + Debug + TryFrom, + { + let key = OracleKey::ExchangeRate(currency_id); + let asset_price = Oracle::get_price(key.clone())?; + + let converted_asset_price = FixedNumber::try_from(asset_price); + + match converted_asset_price { + Ok(price) => Ok(price), + Err(_) => Err(DispatchError::Other("Failed to convert price")), + } + } + + #[cfg(feature = "runtime-benchmarks")] + fn get_price(currency_id: CurrencyId) -> Result + where + FixedNumber: FixedPointNumber + One + Zero + Debug + TryFrom, + { + // Forcefully set chain status to running when benchmarking so that the oracle doesn't fail + Security::set_status(StatusCode::Running); + + let key = OracleKey::ExchangeRate(currency_id); + + // Attempt to get the price once and use the result to decide if feeding a value is necessary + match Oracle::get_price(key.clone()) { + Ok(asset_price) => { + // If the price is successfully retrieved, use it directly + let converted_asset_price = FixedNumber::try_from(asset_price) + .map_err(|_| DispatchError::Other("Failed to convert price"))?; + Ok(converted_asset_price) + }, + Err(_) => { + // Price not found, feed the default value + let rate = FixedU128::checked_from_rational(100, 1).expect("This is a valid ratio"); + // Account used for feeding values + let account = AccountId::from([0u8; 32]); + Oracle::feed_values(account, vec![(key.clone(), rate)])?; + + // If feeding was successful, just use the feeded price to spare a read + let converted_asset_price = FixedNumber::try_from(rate) + .map_err(|_| DispatchError::Other("Failed to convert price"))?; + Ok(converted_asset_price) + }, + } + } +} + +parameter_types! { + pub const SellFee: Permill = Permill::from_percent(1); + pub const MinAmountToBuyout: Balance = NANOUNIT; + // 24 hours in blocks (where average block time is 12 seconds) + pub const BuyoutPeriod: u32 = 7200; + // Maximum number of allowed currencies for buyout + pub const MaxAllowedBuyoutCurrencies: u32 = 20; +} + +impl treasury_buyout_extension::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Currency = Currencies; + type TreasuryAccount = AmplitudeTreasuryAccount; + type BuyoutPeriod = BuyoutPeriod; + type SellFee = SellFee; + type PriceGetter = OraclePriceGetter; + type MinAmountToBuyout = MinAmountToBuyout; + type MaxAllowedBuyoutCurrencies = MaxAllowedBuyoutCurrencies; + type WeightInfo = treasury_buyout_extension::default_weights::SubstrateWeight; + #[cfg(feature = "runtime-benchmarks")] + type RelayChainCurrencyId = RelayChainCurrencyId; +} + // Create the runtime by composing the FRAME pallets that were previously configured. construct_runtime!( pub enum Runtime where @@ -1391,6 +1473,7 @@ construct_runtime!( RewardDistribution: reward_distribution::{Pallet, Call, Storage, Event} = 73, TokenAllowance: orml_currencies_allowance_extension::{Pallet, Storage, Call, Event} = 80, + TreasuryBuyoutExtension: treasury_buyout_extension::{Pallet, Storage, Call, Event} = 82, Farming: farming::{Pallet, Call, Storage, Event} = 90, @@ -1429,6 +1512,7 @@ mod benches { [pallet_xcm, PolkadotXcm] [orml_currencies_allowance_extension, TokenAllowance] + [treasury_buyout_extension, TreasuryBuyoutExtension] ); } From 27819a5e3cb441597f86aaf1fea620b7ff8325ed Mon Sep 17 00:00:00 2001 From: b-yap <2826165+b-yap@users.noreply.github.com> Date: Thu, 22 Feb 2024 00:35:29 +0800 Subject: [PATCH 2/5] set the minamounttobuyout https://github.com/pendulum-chain/tasks/issues/198#issue-2070193524 --- runtime/amplitude/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/amplitude/src/lib.rs b/runtime/amplitude/src/lib.rs index 21d39271d..470272a00 100644 --- a/runtime/amplitude/src/lib.rs +++ b/runtime/amplitude/src/lib.rs @@ -1376,7 +1376,7 @@ impl treasury_buyout_extension::PriceGetter for OraclePriceGetter { parameter_types! { pub const SellFee: Permill = Permill::from_percent(1); - pub const MinAmountToBuyout: Balance = NANOUNIT; + pub const MinAmountToBuyout: Balance = 10 * MILLIUNIT; // 0.01 AMPE or 10_000_000_000 // 24 hours in blocks (where average block time is 12 seconds) pub const BuyoutPeriod: u32 = 7200; // Maximum number of allowed currencies for buyout From 52e38cd49d80ca8264a5c51efb29999a2b5e3a81 Mon Sep 17 00:00:00 2001 From: b-yap <2826165+b-yap@users.noreply.github.com> Date: Thu, 22 Feb 2024 17:15:07 +0800 Subject: [PATCH 3/5] add a mock `DataProviderImpl` --- runtime/amplitude/src/lib.rs | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/runtime/amplitude/src/lib.rs b/runtime/amplitude/src/lib.rs index 470272a00..7c0d6b3b8 100644 --- a/runtime/amplitude/src/lib.rs +++ b/runtime/amplitude/src/lib.rs @@ -187,14 +187,30 @@ impl XCMCurrencyConversion for AmplitudeDiaOracleKeyConverter { } } -type DataProviderImpl = DiaOracleAdapter< - DiaOracleModule, - UnsignedFixedPoint, - Moment, - dia::DiaOracleKeyConvertor, - ConvertPrice, - ConvertMoment, ->; +cfg_if::cfg_if! { + if #[cfg(feature = "runtime-benchmarks")] { + use oracle::testing_utils::{ + MockConvertMoment, MockConvertPrice, MockDiaOracle, MockOracleKeyConvertor, + }; + type DataProviderImpl = DiaOracleAdapter< + MockDiaOracle, + UnsignedFixedPoint, + Moment, + MockOracleKeyConvertor, + MockConvertPrice, + MockConvertMoment, + >; + } else { + type DataProviderImpl = DiaOracleAdapter< + DiaOracleModule, + UnsignedFixedPoint, + Moment, + dia::DiaOracleKeyConvertor, + ConvertPrice, + ConvertMoment, + >; + } +} pub struct ConvertPrice; From afb49a20fd39c3eb768989b094ed8f2ee47beef3 Mon Sep 17 00:00:00 2001 From: b-yap <2826165+b-yap@users.noreply.github.com> Date: Thu, 22 Feb 2024 23:12:53 +0800 Subject: [PATCH 4/5] set sellfee to 5% --- runtime/amplitude/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/amplitude/src/lib.rs b/runtime/amplitude/src/lib.rs index 7c0d6b3b8..eaf209655 100644 --- a/runtime/amplitude/src/lib.rs +++ b/runtime/amplitude/src/lib.rs @@ -1391,7 +1391,7 @@ impl treasury_buyout_extension::PriceGetter for OraclePriceGetter { } parameter_types! { - pub const SellFee: Permill = Permill::from_percent(1); + pub const SellFee: Permill = Permill::from_percent(5); pub const MinAmountToBuyout: Balance = 10 * MILLIUNIT; // 0.01 AMPE or 10_000_000_000 // 24 hours in blocks (where average block time is 12 seconds) pub const BuyoutPeriod: u32 = 7200; From e2e113d898e3b7943f03f93d21f344eef07b8fbd Mon Sep 17 00:00:00 2001 From: b-yap <2826165+b-yap@users.noreply.github.com> Date: Fri, 23 Feb 2024 22:33:27 +0800 Subject: [PATCH 5/5] https://github.com/pendulum-chain/pendulum/actions/runs/8006791620/job/21869341911?pr=424#step:8:1983 --- runtime/amplitude/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/runtime/amplitude/Cargo.toml b/runtime/amplitude/Cargo.toml index 639c0cbd3..c2c96240c 100644 --- a/runtime/amplitude/Cargo.toml +++ b/runtime/amplitude/Cargo.toml @@ -15,6 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.40" } [dependencies] +cfg-if = "1.0.0" codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } hex-literal = { version = "0.3.4", optional = true } log = { version = "0.4.17", default-features = false }