diff --git a/Cargo.lock b/Cargo.lock index a11607534..01d821407 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2187,6 +2187,7 @@ dependencies = [ "pallet-offences", "pallet-offences-benchmarking", "pallet-origins", + "pallet-pool-withdrawal-fix", "pallet-preimage", "pallet-proxy", "pallet-recovery", @@ -2326,6 +2327,7 @@ dependencies = [ "pallet-offences", "pallet-offences-benchmarking", "pallet-origins", + "pallet-pool-withdrawal-fix", "pallet-preimage", "pallet-proxy", "pallet-recovery", @@ -10080,6 +10082,22 @@ dependencies = [ "sp-runtime", ] +[[package]] +name = "pallet-pool-withdrawal-fix" +version = "7.3.3" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "serde", + "sp-core", + "sp-runtime", + "sp-staking", + "sp-std", +] + [[package]] name = "pallet-preimage" version = "40.0.0" diff --git a/Cargo.toml b/Cargo.toml index 7f8615da7..933f57ba5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,6 +22,7 @@ members = [ "pallets/ddc-clusters-gov", "pallets/fee-handler", "pallets/origins", + "pallets/pool-withdrawal-fix", "runtime/cere", "runtime/cere-dev", "contracts/customer-deposit", @@ -193,6 +194,7 @@ pallet-ddc-staking = { path = "pallets/ddc-staking", default-features = false } pallet-erc20 = { path = "pallets/erc20", default-features = false } pallet-erc721 = { path = "pallets/erc721", default-features = false } pallet-origins = { path = "pallets/origins", default-features = false } +pallet-pool-withdrawal-fix = { path = "pallets/pool-withdrawal-fix", default-features = false } pallet-fee-handler = { path = "pallets/fee-handler", default-features = false } # Cere External Dependencies diff --git a/pallets/pool-withdrawal-fix/Cargo.toml b/pallets/pool-withdrawal-fix/Cargo.toml new file mode 100644 index 000000000..e2c8a15b5 --- /dev/null +++ b/pallets/pool-withdrawal-fix/Cargo.toml @@ -0,0 +1,49 @@ +[package] +name = "pallet-pool-withdrawal-fix" +version.workspace = true +authors.workspace = true +edition.workspace = true +homepage.workspace = true +license.workspace = true +readme.workspace = true +repository.workspace = true + +[dependencies] +# 3rd-party dependencies +codec = { workspace = true } +scale-info = { workspace = true } +serde = { workspace = true } + +# Substrate dependencies +frame-benchmarking = { workspace = true, optional = true } +frame-support = { workspace = true } +frame-system = { workspace = true } +sp-core = { workspace = true } +sp-runtime = { workspace = true } +sp-staking = { workspace = true } +sp-std = { workspace = true } + +[features] +default = ["std"] +std = [ + "codec/std", + "frame-benchmarking/std", + "frame-support/std", + "frame-system/std", + "scale-info/std", + "sp-runtime/std", + "sp-std/std", + "sp-core/std", + "serde/std", + "sp-staking/std", +] +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", +] diff --git a/pallets/pool-withdrawal-fix/src/lib.rs b/pallets/pool-withdrawal-fix/src/lib.rs new file mode 100644 index 000000000..322ea789b --- /dev/null +++ b/pallets/pool-withdrawal-fix/src/lib.rs @@ -0,0 +1,93 @@ +//! # Pool Withdrawal Fix Pallet +//! +//! A pallet for handling pool withdrawal operations through delegation pallet connector. +//! This pallet provides withdrawal functionality that can be called by root or governance. + +#![cfg_attr(not(feature = "std"), no_std)] + +use frame_support::pallet_prelude::Weight; +pub use pallet::*; + +#[frame_support::pallet] +pub mod pallet { + use crate::WeightInfo; + use frame_support::pallet_prelude::*; + use frame_support::traits::Currency; + use frame_support::traits::EnsureOrigin; + use frame_support::traits::LockableCurrency; + use frame_system::pallet_prelude::*; + use sp_staking::OnStakingUpdate; + + pub type BalanceOf = + <::Currency as Currency<::AccountId>>::Balance; + + #[pallet::pallet] + pub struct Pallet(_); + + /// Configure the pallet by specifying the parameters and types on which it depends. + #[pallet::config] + pub trait Config: frame_system::Config { + /// Because this pallet emits events, it depends on the runtime's definition of an event. + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + type Currency: LockableCurrency>; + /// Integrate Delegated Pallet + type DelegationPalletConnector: OnStakingUpdate>; + /// Governance origin for withdrawal calls + type GovernanceOrigin: EnsureOrigin; + /// Type representing the weight of this pallet + type WeightInfo: WeightInfo; + } + + /// Pallets use events to inform users when important changes are made. + /// https://docs.substrate.io/main-docs/build/events-errors/ + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + /// Withdrawal was called for a stash account. [stash_account, amount] + WithdrawCalled { stash_account: T::AccountId, amount: BalanceOf }, + } + + #[pallet::error] + pub enum Error { + /// Withdrawal failed due to insufficient balance or other staking constraints. + WithdrawalFailed, + } + + /// Dispatchable functions allows users to interact with the pallet and invoke state changes. + /// These functions materialize as "extrinsics", which are often compared to transactions. + /// Dispatchable functions must be annotated with a weight and must return a DispatchResult. + #[pallet::call] + impl Pallet { + /// Call withdrawal for a stash account through the delegation pallet connector. + /// This function can be called by root or governance. + #[pallet::call_index(0)] + #[pallet::weight(T::WeightInfo::call_withdraw())] + pub fn call_withdraw( + origin: OriginFor, + stash_account: T::AccountId, + amount: BalanceOf, + ) -> DispatchResult { + T::GovernanceOrigin::ensure_origin(origin)?; + + // Call the delegation pallet connector to handle withdrawal + T::DelegationPalletConnector::on_withdraw(&stash_account, amount); + + // Emit an event. + Self::deposit_event(Event::WithdrawCalled { stash_account, amount }); + + Ok(()) + } + } +} + +/// Weight functions needed for pallet_pool_withdrawal_fix. +pub trait WeightInfo { + fn call_withdraw() -> Weight; +} + +/// Default weight implementation for the pallet. +impl WeightInfo for () { + fn call_withdraw() -> Weight { + Weight::from_parts(10_000, 0) + } +} diff --git a/runtime/cere-dev/Cargo.toml b/runtime/cere-dev/Cargo.toml index 80fa269fb..8580d05fa 100644 --- a/runtime/cere-dev/Cargo.toml +++ b/runtime/cere-dev/Cargo.toml @@ -108,6 +108,7 @@ pallet-erc20 = { workspace = true } pallet-erc721 = { workspace = true } pallet-fee-handler = { workspace = true } pallet-origins = { workspace = true } +pallet-pool-withdrawal-fix = { workspace = true } # Hyperbridge Depedencies anyhow = { workspace = true } @@ -208,6 +209,7 @@ std = [ "pallet-ddc-clusters-gov/std", "sp-arithmetic/std", "pallet-origins/std", + "pallet-pool-withdrawal-fix/std", "pallet-hyperbridge/std", "ismp/std", "pallet-ismp/std", @@ -271,6 +273,7 @@ runtime-benchmarks = [ "pallet-preimage/runtime-benchmarks", "pallet-ddc-clusters-gov/runtime-benchmarks", "pallet-origins/runtime-benchmarks", + "pallet-pool-withdrawal-fix/runtime-benchmarks", "pallet-ddc-verification/runtime-benchmarks", "pallet-token-gateway/runtime-benchmarks", "pallet-migrations/runtime-benchmarks", @@ -329,6 +332,7 @@ try-runtime = [ "pallet-whitelist/try-runtime", "pallet-preimage/try-runtime", "pallet-origins/try-runtime", + "pallet-pool-withdrawal-fix/try-runtime", "pallet-ddc-clusters-gov/try-runtime", "pallet-ddc-verification/try-runtime", "pallet-ismp/try-runtime", diff --git a/runtime/cere-dev/src/lib.rs b/runtime/cere-dev/src/lib.rs index e2e41c3b9..cf4968198 100644 --- a/runtime/cere-dev/src/lib.rs +++ b/runtime/cere-dev/src/lib.rs @@ -173,7 +173,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // and set impl_version to 0. If only runtime // implementation changes and behavior does not, then leave spec_version as // is and increment impl_version. - spec_version: 73168, + spec_version: 73169, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 26, @@ -686,7 +686,7 @@ impl pallet_staking::Config for Runtime { type MaxUnlockingChunks = ConstU32<32>; type MaxControllersInDeprecationBatch = MaxControllersInDeprecationBatch; type HistoryDepth = frame_support::traits::ConstU32<84>; - type EventListeners = NominationPools; + type EventListeners = (NominationPools, DelegatedStaking); type WeightInfo = pallet_staking::weights::SubstrateWeight; type BenchmarkingConfig = StakingBenchmarkingConfig; type NominationsQuota = pallet_staking::FixedNominationsQuota<{ MaxNominations::get() }>; @@ -1564,6 +1564,14 @@ impl pallet_fee_handler::Config for Runtime { type WeightInfo = pallet_fee_handler::weights::SubstrateWeight; } +impl pallet_pool_withdrawal_fix::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + type DelegationPalletConnector = DelegatedStaking; + type GovernanceOrigin = EnsureRoot; + type WeightInfo = (); +} + #[frame_support::runtime] mod runtime { #[runtime::runtime] @@ -1746,6 +1754,9 @@ mod runtime { pub type FeeHandler = pallet_fee_handler::Pallet; #[runtime::pallet_index(53)] pub type DelegatedStaking = pallet_delegated_staking; + + #[runtime::pallet_index(54)] + pub type PoolWithdrawalFix = pallet_pool_withdrawal_fix::Pallet; } /// The address format for describing accounts. diff --git a/runtime/cere/Cargo.toml b/runtime/cere/Cargo.toml index 1280a229d..de1da69ee 100644 --- a/runtime/cere/Cargo.toml +++ b/runtime/cere/Cargo.toml @@ -106,6 +106,7 @@ pallet-erc20 = { workspace = true } pallet-erc721 = { workspace = true } pallet-fee-handler = { workspace = true } pallet-origins = { workspace = true } +pallet-pool-withdrawal-fix = { workspace = true } pallet-referenda = { workspace = true } pallet-whitelist = { workspace = true } @@ -205,6 +206,7 @@ std = [ "pallet-whitelist/std", "pallet-preimage/std", "pallet-origins/std", + "pallet-pool-withdrawal-fix/std", "pallet-hyperbridge/std", "ismp/std", "pallet-ismp/std", @@ -268,6 +270,7 @@ runtime-benchmarks = [ "pallet-preimage/runtime-benchmarks", "pallet-ddc-clusters-gov/runtime-benchmarks", "pallet-origins/runtime-benchmarks", + "pallet-pool-withdrawal-fix/runtime-benchmarks", "pallet-ddc-verification/runtime-benchmarks", "pallet-token-gateway/runtime-benchmarks", "pallet-migrations/runtime-benchmarks", @@ -327,6 +330,7 @@ try-runtime = [ "pallet-whitelist/try-runtime", "pallet-preimage/try-runtime", "pallet-origins/try-runtime", + "pallet-pool-withdrawal-fix/try-runtime", "pallet-ddc-clusters-gov/try-runtime", "pallet-ddc-verification/try-runtime", "pallet-ismp/try-runtime", diff --git a/runtime/cere/src/lib.rs b/runtime/cere/src/lib.rs index 492561155..09760b0f8 100644 --- a/runtime/cere/src/lib.rs +++ b/runtime/cere/src/lib.rs @@ -163,7 +163,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // and set impl_version to 0. If only runtime // implementation changes and behavior does not, then leave spec_version as // is and increment impl_version. - spec_version: 73168, + spec_version: 73169, impl_version: 0, apis: RUNTIME_API_VERSIONS, transaction_version: 26, @@ -696,7 +696,7 @@ impl pallet_staking::Config for Runtime { type MaxUnlockingChunks = ConstU32<32>; type MaxControllersInDeprecationBatch = MaxControllersInDeprecationBatch; type HistoryDepth = HistoryDepth; - type EventListeners = NominationPools; + type EventListeners = (NominationPools, DelegatedStaking); type WeightInfo = pallet_staking::weights::SubstrateWeight; type BenchmarkingConfig = StakingBenchmarkingConfig; type NominationsQuota = pallet_staking::FixedNominationsQuota<{ MaxNominations::get() }>; @@ -1553,6 +1553,14 @@ impl pallet_fee_handler::Config for Runtime { type WeightInfo = pallet_fee_handler::weights::SubstrateWeight; } +impl pallet_pool_withdrawal_fix::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + type DelegationPalletConnector = DelegatedStaking; + type GovernanceOrigin = EnsureRoot; + type WeightInfo = (); +} + #[frame_support::runtime] mod runtime { #[runtime::runtime] @@ -1734,6 +1742,9 @@ mod runtime { #[runtime::pallet_index(53)] pub type DelegatedStaking = pallet_delegated_staking; + + #[runtime::pallet_index(54)] + pub type PoolWithdrawalFix = pallet_pool_withdrawal_fix::Pallet; } /// The address format for describing accounts.