Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: locked balances #590

Merged
merged 3 commits into from
Jan 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
pub mod v6;
pub mod v6;
pub mod v7;
139 changes: 139 additions & 0 deletions substrate-node/pallets/pallet-smart-contract/src/migrations/v7.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
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 sp_std::vec::Vec;

pub struct FixTwinLockedBalances<T: Config>(PhantomData<T>);

impl<T: Config> OnRuntimeUpgrade for FixTwinLockedBalances<T> {
#[cfg(feature = "try-runtime")]
fn pre_upgrade() -> Result<Vec<u8>, &'static str> {
debug!("current pallet version: {:?}", PalletVersion::<T>::get());
assert!(PalletVersion::<T>::get() >= types::StorageVersion::V6);

debug!("👥 Smart Contract pallet to V7 passes PRE migrate checks ✅",);
Ok(vec![])
}

fn on_runtime_upgrade() -> Weight {
if PalletVersion::<T>::get() == types::StorageVersion::V6 {
migrate_to_version_7::<T>()
} else {
debug!(" >>> Unused Smart Contract pallet V7 migration");
Weight::zero()
}
}

#[cfg(feature = "try-runtime")]
fn post_upgrade(pre_contracts_count: Vec<u8>) -> Result<(), &'static str> {
debug!("current pallet version: {:?}", PalletVersion::<T>::get());
assert!(PalletVersion::<T>::get() >= types::StorageVersion::V7);

debug!(
"👥 Smart Contract pallet to {:?} passes POST migrate checks ✅",
PalletVersion::<T>::get()
);

Ok(())
}
}

pub fn migrate_to_version_7<T: Config>() -> frame_support::weights::Weight {
debug!(
" >>> Starting contract pallet migration, pallet version: {:?}",
PalletVersion::<T>::get()
);

let mut read_writes = 0;

let mut twin_contract_locked_balances: BTreeMap<u32, BalanceOf<T>> = BTreeMap::new();

for (ctr_id, l) in ContractLock::<T>::iter() {
let ctr = Contracts::<T>::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::<T>::saturated_from(0 as u128));
}
None => (),
}
}

for (t, total_contract_locked_balance) in twin_contract_locked_balances {
let twin = pallet_tfgrid::Twins::<T>::get(t);
read_writes += 1;
match twin {
Some(twin) => {
let total_lock_balances = get_locked_balance::<T>(&twin.account_id);

if total_lock_balances != total_contract_locked_balance {
debug!(
"total locked balance on twin {} account: {:?}",
t, total_lock_balances
);
debug!(
"should have locked only: {:?}",
total_contract_locked_balance
);

// get the total balance of the twin - minimum existence requirement
let total_balance = <T as Config>::Currency::total_balance(&twin.account_id)
DylanVerstraete marked this conversation as resolved.
Show resolved Hide resolved
- <T as Config>::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);
debug!("we can lock up to: {:?}", amount_that_we_can_lock);

// Unlock all balance & relock real locked amount
<T as Config>::Currency::remove_lock(GRID_LOCK_ID, &twin.account_id);
<T as Config>::Currency::set_lock(
GRID_LOCK_ID,
&twin.account_id,
amount_that_we_can_lock,
WithdrawReasons::all(),
);
read_writes += 2;
}
}
None => {
debug!("twin {} not found", t);
}
}
}

// Update pallet storage version
PalletVersion::<T>::set(types::StorageVersion::V7);
debug!(" <<< Storage version upgraded");

// Return the weight consumed by the migration.
T::DbWeight::get().reads(read_writes + 1)
}

fn get_usable_balance<T: Config>(account_id: &T::AccountId) -> BalanceOf<T> {
let balance = pallet_balances::pallet::Pallet::<T>::usable_balance(account_id);
let b = balance.saturated_into::<u128>();
BalanceOf::<T>::saturated_from(b)
}

pub fn get_locked_balance<T: Config>(account_id: &T::AccountId) -> BalanceOf<T> {
let usable_balance = get_usable_balance::<T>(account_id);

let free_balance = <T as Config>::Currency::free_balance(account_id);

let locked_balance = free_balance.checked_sub(&usable_balance);
match locked_balance {
Some(balance) => balance,
None => BalanceOf::<T>::saturated_from(0 as u128),
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ pub enum StorageVersion {
V4,
V5,
V6,
V7,
}

impl Default for StorageVersion {
Expand Down
7 changes: 4 additions & 3 deletions substrate-node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -762,9 +762,10 @@ pub type Executive = frame_executive::Executive<
Migrations,
>;

// All migrations executed on runtime upgrade as a nested tuple of types implementing
// `OnRuntimeUpgrade`.
type Migrations = pallet_tfgrid::migrations::v14::FixFarmingPoliciesMap<Runtime>;
type Migrations = (
pallet_smart_contract::migrations::v7::FixTwinLockedBalances<Runtime>,
pallet_tfgrid::migrations::v14::FixFarmingPoliciesMap<Runtime>,
);

// follows Substrate's non destructive way of eliminating otherwise required
// repetion: https://github.com/paritytech/substrate/pull/10592
Expand Down