-
Notifications
You must be signed in to change notification settings - Fork 740
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Pools] fix derivation of pool account (#4999)
closes paritytech-secops/srlabs_findings#408. This fixes how ProxyDelegator accounts are derived but may cause issues in Westend since it would use the old derivative accounts. Does not affect Polkadot/Kusama as this pallet is not deployed to them yet. --------- Co-authored-by: Gonçalo Pestana <[email protected]>
- Loading branch information
Showing
6 changed files
with
152 additions
and
12 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# Schema: Polkadot SDK PRDoc Schema (prdoc) v1.0.0 | ||
# See doc at https://raw.githubusercontent.com/paritytech/polkadot-sdk/master/prdoc/schema_user.json | ||
|
||
title: Fixes entropy for derivation of proxy delegator account. | ||
|
||
doc: | ||
- audience: Runtime Dev | ||
description: | | ||
This fixes how ProxyDelegator accounts are derived but may cause issues in Westend since it would use the old | ||
derivative accounts. Does not affect Polkadot/Kusama as this pallet is not deployed to them yet. | ||
|
||
crates: | ||
- name: westend-runtime | ||
bump: patch | ||
- name: pallet-delegated-staking | ||
bump: patch | ||
- name: pallet-nomination-pools | ||
bump: patch |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
// 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. | ||
|
||
use super::*; | ||
use frame_support::traits::OnRuntimeUpgrade; | ||
|
||
#[cfg(feature = "try-runtime")] | ||
use sp_runtime::TryRuntimeError; | ||
|
||
pub mod unversioned { | ||
use super::*; | ||
#[cfg(feature = "try-runtime")] | ||
use alloc::vec::Vec; | ||
use sp_runtime::traits::AccountIdConversion; | ||
|
||
/// Migrates `ProxyDelegator` accounts with better entropy than the old logic which didn't take | ||
/// into account all the bytes of the agent account ID. | ||
pub struct ProxyDelegatorMigration<T, MaxAgents>(PhantomData<(T, MaxAgents)>); | ||
|
||
impl<T: Config, MaxAgents: Get<u32>> OnRuntimeUpgrade for ProxyDelegatorMigration<T, MaxAgents> { | ||
fn on_runtime_upgrade() -> Weight { | ||
let mut weight = Weight::zero(); | ||
let old_proxy_delegator = |agent: T::AccountId| { | ||
T::PalletId::get() | ||
.into_sub_account_truncating((AccountType::ProxyDelegator, agent.clone())) | ||
}; | ||
|
||
Agents::<T>::iter_keys().take(MaxAgents::get() as usize).for_each(|agent| { | ||
weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 0)); | ||
let old_proxy = old_proxy_delegator(agent.clone()); | ||
|
||
// if delegation does not exist, it does not need to be migrated. | ||
if let Some(delegation) = Delegation::<T>::get(&old_proxy) { | ||
weight.saturating_accrue(T::DbWeight::get().reads_writes(1, 0)); | ||
|
||
let new_proxy = | ||
Pallet::<T>::generate_proxy_delegator(Agent::from(agent.clone())); | ||
|
||
// accrue read writes for `do_migrate_delegation` | ||
weight.saturating_accrue(T::DbWeight::get().reads_writes(8, 8)); | ||
let _ = Pallet::<T>::do_migrate_delegation( | ||
Delegator::from(old_proxy.clone()), | ||
new_proxy.clone(), | ||
delegation.amount, | ||
) | ||
.map_err(|e| { | ||
log!( | ||
error, | ||
"Failed to migrate old proxy delegator {:?} to new proxy {:?} for agent {:?} with error: {:?}", | ||
old_proxy, | ||
new_proxy, | ||
agent, | ||
e, | ||
); | ||
}); | ||
}; | ||
}); | ||
|
||
log!(info, "Finished migrating old proxy delegator accounts to new ones"); | ||
weight | ||
} | ||
|
||
#[cfg(feature = "try-runtime")] | ||
fn post_upgrade(_data: Vec<u8>) -> Result<(), TryRuntimeError> { | ||
let mut unmigrated_count = 0; | ||
let old_proxy_delegator = |agent: T::AccountId| { | ||
T::PalletId::get() | ||
.into_sub_account_truncating((AccountType::ProxyDelegator, agent.clone())) | ||
}; | ||
|
||
Agents::<T>::iter_keys().take(MaxAgents::get() as usize).for_each(|agent| { | ||
let old_proxy: T::AccountId = old_proxy_delegator(agent.clone()); | ||
let held_balance = Pallet::<T>::held_balance_of(Delegator::from(old_proxy.clone())); | ||
let delegation = Delegation::<T>::get(&old_proxy); | ||
if delegation.is_some() || !held_balance.is_zero() { | ||
log!( | ||
error, | ||
"Old proxy delegator {:?} for agent {:?} is not migrated.", | ||
old_proxy, | ||
agent, | ||
); | ||
unmigrated_count += 1; | ||
} | ||
}); | ||
|
||
if unmigrated_count > 0 { | ||
Err(TryRuntimeError::Other("Some old proxy delegator accounts are not migrated.")) | ||
} else { | ||
Ok(()) | ||
} | ||
} | ||
} | ||
} |