From 7cdd1ac5e47c6ee01bf2439beb25ac47d101da0e Mon Sep 17 00:00:00 2001 From: dylanVerstraete Date: Mon, 23 Jan 2023 11:40:47 +0100 Subject: [PATCH 1/2] fix: locked balances --- .../src/migrations/mod.rs | 3 +- .../src/migrations/v7.rs | 135 ++++++++++++++++++ .../pallet-smart-contract/src/types.rs | 1 + substrate-node/runtime/src/lib.rs | 1 + 4 files changed, 139 insertions(+), 1 deletion(-) create mode 100644 substrate-node/pallets/pallet-smart-contract/src/migrations/v7.rs diff --git a/substrate-node/pallets/pallet-smart-contract/src/migrations/mod.rs b/substrate-node/pallets/pallet-smart-contract/src/migrations/mod.rs index 6ec139373..bfd499d1e 100644 --- a/substrate-node/pallets/pallet-smart-contract/src/migrations/mod.rs +++ b/substrate-node/pallets/pallet-smart-contract/src/migrations/mod.rs @@ -1 +1,2 @@ -pub mod v6; \ No newline at end of file +pub mod v6; +pub mod v7; diff --git a/substrate-node/pallets/pallet-smart-contract/src/migrations/v7.rs b/substrate-node/pallets/pallet-smart-contract/src/migrations/v7.rs new file mode 100644 index 000000000..d53b484de --- /dev/null +++ b/substrate-node/pallets/pallet-smart-contract/src/migrations/v7.rs @@ -0,0 +1,135 @@ +use crate::*; +use frame_support::{traits::OnRuntimeUpgrade, weights::Weight}; +use sp_std::collections::btree_map::BTreeMap; +use sp_std::marker::PhantomData; + +#[cfg(feature = "try-runtime")] +use codec::{Decode, Encode}; +#[cfg(feature = "try-runtime")] +use sp_std::vec::Vec; + +pub struct FixTwinLockedBalances(PhantomData); + +impl OnRuntimeUpgrade for FixTwinLockedBalances { + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result, &'static str> { + info!("current pallet version: {:?}", PalletVersion::::get()); + assert!(PalletVersion::::get() >= types::StorageVersion::V6); + + info!("👥 Smart Contract pallet to V7 passes PRE migrate checks ✅",); + Ok(vec![]) + } + + fn on_runtime_upgrade() -> Weight { + if PalletVersion::::get() == types::StorageVersion::V6 { + migrate_to_version_7::() + } else { + info!(" >>> Unused Smart Contract pallet V7 migration"); + Weight::zero() + } + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade(pre_contracts_count: Vec) -> Result<(), &'static str> { + info!("current pallet version: {:?}", PalletVersion::::get()); + assert!(PalletVersion::::get() >= types::StorageVersion::V7); + + info!( + "👥 Smart Contract pallet to {:?} passes POST migrate checks ✅", + PalletVersion::::get() + ); + + Ok(()) + } +} + +pub fn migrate_to_version_7() -> frame_support::weights::Weight { + info!( + " >>> Starting contract pallet migration, pallet version: {:?}", + PalletVersion::::get() + ); + + let mut read_writes = 0; + + let mut twin_contract_locked_balances: BTreeMap> = BTreeMap::new(); + + for (ctr_id, l) in ContractLock::::iter() { + let ctr = Contracts::::get(ctr_id); + read_writes += 1; + match ctr { + Some(contract) => { + // l.amount_locked + twin_contract_locked_balances + .entry(contract.twin_id) + .and_modify(|v| *v += l.amount_locked) + .or_insert(BalanceOf::::saturated_from(0 as u128)); + } + None => (), + } + } + + for (t, total_contract_locked_balance) in twin_contract_locked_balances { + let twin = pallet_tfgrid::Twins::::get(t); + read_writes += 1; + match twin { + Some(twin) => { + let total_lock_balances = get_locked_balance::(&twin.account_id); + + if total_lock_balances != total_contract_locked_balance { + log::info!( + "total locked balance on twin {} account: {:?}", + t, + total_lock_balances + ); + log::info!( + "should have locked only: {:?}", + total_contract_locked_balance + ); + + let total_balance = ::Currency::total_balance(&twin.account_id) + - ::Currency::minimum_balance(); + + let amount_that_we_can_lock = total_balance.min(total_contract_locked_balance); + log::info!("we can lock up to: {:?}", amount_that_we_can_lock); + // Unlock all balance & relock real locked amount + ::Currency::remove_lock(GRID_LOCK_ID, &twin.account_id); + ::Currency::set_lock( + GRID_LOCK_ID, + &twin.account_id, + amount_that_we_can_lock, + WithdrawReasons::all(), + ); + read_writes += 2; + } + } + None => { + log::info!("twin {} not found", t); + } + } + } + + // Update pallet storage version + PalletVersion::::set(types::StorageVersion::V7); + info!(" <<< Storage version upgraded"); + + // Return the weight consumed by the migration. + T::DbWeight::get().reads(read_writes + 1) +} + +fn get_usable_balance(account_id: &T::AccountId) -> BalanceOf { + let balance = pallet_balances::pallet::Pallet::::usable_balance(account_id); + let b = balance.saturated_into::(); + BalanceOf::::saturated_from(b) +} + +pub fn get_locked_balance(account_id: &T::AccountId) -> BalanceOf { + let usable_balance = get_usable_balance::(account_id); + + let free_balance = ::Currency::free_balance(account_id); + + let locked_balance = free_balance.checked_sub(&usable_balance); + match locked_balance { + Some(balance) => balance, + None => BalanceOf::::saturated_from(0 as u128), + } +} diff --git a/substrate-node/pallets/pallet-smart-contract/src/types.rs b/substrate-node/pallets/pallet-smart-contract/src/types.rs index e7f2fb351..cfe59bb9c 100644 --- a/substrate-node/pallets/pallet-smart-contract/src/types.rs +++ b/substrate-node/pallets/pallet-smart-contract/src/types.rs @@ -18,6 +18,7 @@ pub enum StorageVersion { V4, V5, V6, + V7, } impl Default for StorageVersion { diff --git a/substrate-node/runtime/src/lib.rs b/substrate-node/runtime/src/lib.rs index 9c8042315..e2622440b 100644 --- a/substrate-node/runtime/src/lib.rs +++ b/substrate-node/runtime/src/lib.rs @@ -770,6 +770,7 @@ type Migrations = ( pallet_tfgrid::migrations::v11::FixFarmingPolicy, pallet_tfgrid::migrations::v12::InputValidation, pallet_tfgrid::migrations::v13::FixPublicIP, + pallet_smart_contract::migrations::v7::FixTwinLockedBalances, ); // follows Substrate's non destructive way of eliminating otherwise required From 976b23774b4bc8ad18fd8b90cec8208144b5d7c7 Mon Sep 17 00:00:00 2001 From: dylanVerstraete Date: Wed, 25 Jan 2023 11:00:16 +0100 Subject: [PATCH 2/2] chore: update migration --- .../src/migrations/v7.rs | 34 +++++++++++-------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/substrate-node/pallets/pallet-smart-contract/src/migrations/v7.rs b/substrate-node/pallets/pallet-smart-contract/src/migrations/v7.rs index d53b484de..94f2504d1 100644 --- a/substrate-node/pallets/pallet-smart-contract/src/migrations/v7.rs +++ b/substrate-node/pallets/pallet-smart-contract/src/migrations/v7.rs @@ -1,10 +1,11 @@ use crate::*; +#[cfg(feature = "try-runtime")] +use codec::{Decode, Encode}; use frame_support::{traits::OnRuntimeUpgrade, weights::Weight}; +use log::debug; use sp_std::collections::btree_map::BTreeMap; use sp_std::marker::PhantomData; -#[cfg(feature = "try-runtime")] -use codec::{Decode, Encode}; #[cfg(feature = "try-runtime")] use sp_std::vec::Vec; @@ -13,10 +14,10 @@ pub struct FixTwinLockedBalances(PhantomData); impl OnRuntimeUpgrade for FixTwinLockedBalances { #[cfg(feature = "try-runtime")] fn pre_upgrade() -> Result, &'static str> { - info!("current pallet version: {:?}", PalletVersion::::get()); + debug!("current pallet version: {:?}", PalletVersion::::get()); assert!(PalletVersion::::get() >= types::StorageVersion::V6); - info!("👥 Smart Contract pallet to V7 passes PRE migrate checks ✅",); + debug!("👥 Smart Contract pallet to V7 passes PRE migrate checks ✅",); Ok(vec![]) } @@ -24,17 +25,17 @@ impl OnRuntimeUpgrade for FixTwinLockedBalances { if PalletVersion::::get() == types::StorageVersion::V6 { migrate_to_version_7::() } else { - info!(" >>> Unused Smart Contract pallet V7 migration"); + debug!(" >>> Unused Smart Contract pallet V7 migration"); Weight::zero() } } #[cfg(feature = "try-runtime")] fn post_upgrade(pre_contracts_count: Vec) -> Result<(), &'static str> { - info!("current pallet version: {:?}", PalletVersion::::get()); + debug!("current pallet version: {:?}", PalletVersion::::get()); assert!(PalletVersion::::get() >= types::StorageVersion::V7); - info!( + debug!( "👥 Smart Contract pallet to {:?} passes POST migrate checks ✅", PalletVersion::::get() ); @@ -44,7 +45,7 @@ impl OnRuntimeUpgrade for FixTwinLockedBalances { } pub fn migrate_to_version_7() -> frame_support::weights::Weight { - info!( + debug!( " >>> Starting contract pallet migration, pallet version: {:?}", PalletVersion::::get() ); @@ -76,21 +77,24 @@ pub fn migrate_to_version_7() -> frame_support::weights::Weight { let total_lock_balances = get_locked_balance::(&twin.account_id); if total_lock_balances != total_contract_locked_balance { - log::info!( + debug!( "total locked balance on twin {} account: {:?}", - t, - total_lock_balances + t, total_lock_balances ); - log::info!( + debug!( "should have locked only: {:?}", total_contract_locked_balance ); + // get the total balance of the twin - minimum existence requirement let total_balance = ::Currency::total_balance(&twin.account_id) - ::Currency::minimum_balance(); + // lock only an amount up to the total balance + // this will make sure the locked balance will not exceed the total balance on the twin's account let amount_that_we_can_lock = total_balance.min(total_contract_locked_balance); - log::info!("we can lock up to: {:?}", amount_that_we_can_lock); + debug!("we can lock up to: {:?}", amount_that_we_can_lock); + // Unlock all balance & relock real locked amount ::Currency::remove_lock(GRID_LOCK_ID, &twin.account_id); ::Currency::set_lock( @@ -103,14 +107,14 @@ pub fn migrate_to_version_7() -> frame_support::weights::Weight { } } None => { - log::info!("twin {} not found", t); + debug!("twin {} not found", t); } } } // Update pallet storage version PalletVersion::::set(types::StorageVersion::V7); - info!(" <<< Storage version upgraded"); + debug!(" <<< Storage version upgraded"); // Return the weight consumed by the migration. T::DbWeight::get().reads(read_writes + 1)