diff --git a/crates/vault-registry/src/lib.rs b/crates/vault-registry/src/lib.rs index 78e54896da..78cb61d721 100644 --- a/crates/vault-registry/src/lib.rs +++ b/crates/vault-registry/src/lib.rs @@ -131,10 +131,6 @@ pub mod pallet { log::info!("Off-chain worker started on block {:?}", n); Self::_offchain_worker(); } - - fn on_runtime_upgrade() -> Weight { - crate::types::v2::migrate_v2_to_v3::() - } } #[pallet::validate_unsigned] diff --git a/crates/vault-registry/src/types.rs b/crates/vault-registry/src/types.rs index 0ab967d012..168b27c4e4 100644 --- a/crates/vault-registry/src/types.rs +++ b/crates/vault-registry/src/types.rs @@ -29,6 +29,8 @@ pub enum Version { V2, /// moved public_key out of the vault struct V3, + /// Fixed liquidation vault + V4, } #[derive(Debug, PartialEq)] @@ -104,229 +106,82 @@ pub type DefaultVaultId = VaultId<::AccountId, Cur pub type DefaultVaultCurrencyPair = VaultCurrencyPair>; -pub mod v2 { +pub mod liquidation_vault_fix { use super::*; + use primitives::{ + CurrencyId::Token, + TokenSymbol::{KBTC, KSM}, + VaultCurrencyPair, + }; - #[derive(Encode, Decode, Clone, PartialEq, Eq, Debug, Default, TypeInfo)] - struct WalletV2 { - // store all addresses for `report_vault_theft` checks - pub addresses: BTreeSet, - // we use this public key to generate new addresses - pub public_key: BtcPublicKey, - } - - #[derive(Encode, Decode, Clone, PartialEq, Eq, TypeInfo)] - #[cfg_attr(feature = "std", derive(Debug))] - struct VaultV2 { - /// Account identifier of the Vault - pub id: VaultId, - /// Bitcoin address of this Vault (P2PKH, P2SH, P2WPKH, P2WSH) - pub wallet: WalletV2, - /// Current status of the vault - pub status: super::VaultStatus, - /// Block height until which this Vault is banned from being used for - /// Issue, Redeem (except during automatic liquidation) and Replace. - pub banned_until: Option, - /// Number of tokens pending issue - pub to_be_issued_tokens: Balance, - /// Number of issued tokens - pub issued_tokens: Balance, - /// Number of tokens pending redeem - pub to_be_redeemed_tokens: Balance, - /// Number of tokens that have been requested for a replace through - /// `request_replace`, but that have not been accepted yet by a new_vault. - pub to_be_replaced_tokens: Balance, - /// Amount of collateral that is available as griefing collateral to vaults accepting - /// a replace request. It is to be payed out if the old_vault fails to call execute_replace. - pub replace_collateral: Balance, - /// Amount of collateral locked for accepted replace requests. - pub active_replace_collateral: Balance, - /// Amount of collateral that is locked for remaining to_be_redeemed - /// tokens upon liquidation. - pub liquidated_collateral: Balance, - } - - type DefaultVaultV2 = VaultV2< - ::AccountId, - ::BlockNumber, - BalanceOf, - CurrencyId, - >; - - pub fn migrate_v2_to_v3() -> frame_support::weights::Weight { + use crate::types::Version; + + const TO_BE_REDEEMED_DECREASE: u32 = 6_354_070; + + pub fn fix_liquidation_vault() -> Result { use sp_runtime::traits::Saturating; - if !matches!( - crate::StorageVersion::::get(), - Version::V0 | Version::V1 | Version::V2 - ) { - log::info!("Not running vault storage migration"); - return T::DbWeight::get().reads(1); // already upgraded; don't run migration + if !matches!(crate::StorageVersion::::get(), Version::V3) { + log::info!("Not running liquidation vault fix"); + return Err(()); } - let mut num_migrated_vaults = 0u64; - crate::Vaults::::translate::, _>(|_key, vault_v2| { - num_migrated_vaults.saturating_inc(); + let currency_pair = VaultCurrencyPair { + collateral: Token(KSM), + wrapped: Token(KBTC), + }; + >::try_mutate(¤cy_pair, |maybe_liquidation_vault| { + if let Some(ref mut liquidation_vault) = maybe_liquidation_vault { + liquidation_vault + .to_be_redeemed_tokens + .saturating_reduce(TO_BE_REDEEMED_DECREASE.into()); + Ok(()) + } else { + log::info!("Failed to fetch liquidation vault"); + Err(()) + } + })?; - crate::VaultBitcoinPublicKey::::insert( - vault_v2.id.account_id.clone(), - vault_v2.wallet.public_key.clone(), - ); - Some(Vault { - id: vault_v2.id, - wallet: Wallet { - addresses: vault_v2.wallet.addresses, - }, - status: vault_v2.status, - banned_until: vault_v2.banned_until, - to_be_issued_tokens: vault_v2.to_be_issued_tokens, - issued_tokens: vault_v2.issued_tokens, - to_be_redeemed_tokens: vault_v2.to_be_redeemed_tokens, - to_be_replaced_tokens: vault_v2.to_be_replaced_tokens, - replace_collateral: vault_v2.replace_collateral, - active_replace_collateral: vault_v2.active_replace_collateral, - liquidated_collateral: vault_v2.liquidated_collateral, - }) - }); - crate::StorageVersion::::put(Version::V3); + log::info!("LiquidationVault migration finished"); - log::info!("Migrated {num_migrated_vaults} vaults"); + crate::StorageVersion::::put(Version::V4); - T::DbWeight::get().reads_writes(num_migrated_vaults, num_migrated_vaults) + Ok(T::DbWeight::get().reads_writes(2, 2)) } #[cfg(test)] #[test] fn test_migration() { use crate::mock::Test; - use bitcoin::types::H160; - use frame_support::{storage::migration, Blake2_128Concat, StorageHasher}; - use primitives::{CurrencyId::Token, KBTC, KSM}; - use sp_runtime::traits::TrailingZeroInput; crate::mock::run_test(|| { - crate::StorageVersion::::put(Version::V2); - - let vault1: DefaultVaultV2 = VaultV2 { - id: VaultId { - account_id: Decode::decode(&mut TrailingZeroInput::new(&[1u8; 32])).unwrap(), - currencies: VaultCurrencyPair { - collateral: Token(KSM), - wrapped: Token(KBTC), - }, - }, - wallet: WalletV2 { - addresses: [ - BtcAddress::P2PKH(H160::from([1; 20])), - BtcAddress::P2PKH(H160::from([2; 20])), - ] - .into(), - public_key: BtcPublicKey::from([2u8; 33]), - }, - banned_until: None, - status: VaultStatus::Active(true), - issued_tokens: Default::default(), - liquidated_collateral: Default::default(), - replace_collateral: Default::default(), - to_be_issued_tokens: Default::default(), - to_be_redeemed_tokens: Default::default(), - to_be_replaced_tokens: Default::default(), - active_replace_collateral: Default::default(), - }; - let vault2: DefaultVaultV2 = VaultV2 { - id: VaultId { - account_id: Decode::decode(&mut TrailingZeroInput::new(&[2u8; 32])).unwrap(), - currencies: VaultCurrencyPair { - collateral: Token(KBTC), - wrapped: Token(KBTC), - }, - }, - wallet: WalletV2 { - addresses: [ - BtcAddress::P2PKH(H160::from([3; 20])), - BtcAddress::P2PKH(H160::from([4; 20])), - ] - .into(), - public_key: BtcPublicKey::from([3u8; 33]), - }, - banned_until: Some(123), - status: VaultStatus::Active(false), - issued_tokens: 1, - liquidated_collateral: 2, - replace_collateral: 3, - to_be_issued_tokens: 4, - to_be_redeemed_tokens: 5, - to_be_replaced_tokens: 6, - active_replace_collateral: 7, - }; - migration::put_storage_value( - b"VaultRegistry", - b"Vaults", - &Blake2_128Concat::hash(&vault1.id.encode()), - &vault1, - ); - migration::put_storage_value( - b"VaultRegistry", - b"Vaults", - &Blake2_128Concat::hash(&vault2.id.encode()), - &vault2, - ); + crate::StorageVersion::::put(Version::V3); - migrate_v2_to_v3::(); - - let expected_migrated_vault1 = Vault { - id: vault1.id.clone(), - wallet: Wallet { - addresses: vault1.wallet.addresses.clone(), - }, - status: vault1.status.clone(), - banned_until: vault1.banned_until, - to_be_issued_tokens: vault1.to_be_issued_tokens, - issued_tokens: vault1.issued_tokens, - to_be_redeemed_tokens: vault1.to_be_redeemed_tokens, - to_be_replaced_tokens: vault1.to_be_replaced_tokens, - replace_collateral: vault1.replace_collateral, - active_replace_collateral: vault1.active_replace_collateral, - liquidated_collateral: vault1.liquidated_collateral, + let currency_pair = VaultCurrencyPair { + collateral: Token(KSM), + wrapped: Token(KBTC), }; - let expected_migrated_vault2 = Vault { - id: vault2.id.clone(), - wallet: Wallet { - addresses: vault2.wallet.addresses.clone(), - }, - status: vault2.status.clone(), - banned_until: vault2.banned_until, - to_be_issued_tokens: vault2.to_be_issued_tokens, - issued_tokens: vault2.issued_tokens, - to_be_redeemed_tokens: vault2.to_be_redeemed_tokens, - to_be_replaced_tokens: vault2.to_be_replaced_tokens, - replace_collateral: vault2.replace_collateral, - active_replace_collateral: vault2.active_replace_collateral, - liquidated_collateral: vault2.liquidated_collateral, + let test_liquidaiton_vault = DefaultSystemVault:: { + to_be_issued_tokens: 123, + issued_tokens: 234, + to_be_redeemed_tokens: TO_BE_REDEEMED_DECREASE.into(), + collateral: 345, + currency_pair: currency_pair.clone(), }; - // check that vault struct was migrated correctly - assert_eq!( - crate::Vaults::::iter().collect::>(), - vec![ - (expected_migrated_vault2.id.clone(), expected_migrated_vault2), - (expected_migrated_vault1.id.clone(), expected_migrated_vault1), - ] - ); + crate::LiquidationVault::::insert(¤cy_pair, &test_liquidaiton_vault); + + fix_liquidation_vault::().unwrap(); - // check that public key is set assert_eq!( - crate::VaultBitcoinPublicKey::::iter().collect::>(), - vec![ - (vault2.id.account_id.clone(), vault2.wallet.public_key), - (vault1.id.account_id.clone(), vault1.wallet.public_key), - ] + crate::LiquidationVault::::get(¤cy_pair).unwrap(), + DefaultSystemVault:: { + to_be_redeemed_tokens: 0, + ..test_liquidaiton_vault + } ); - - // check that storage version is bumped - assert!(crate::StorageVersion::::get() == Version::V3); - }); + }) } } diff --git a/parachain/runtime/kintsugi/src/lib.rs b/parachain/runtime/kintsugi/src/lib.rs index 997e7293de..f5a2f18fdc 100644 --- a/parachain/runtime/kintsugi/src/lib.rs +++ b/parachain/runtime/kintsugi/src/lib.rs @@ -408,21 +408,20 @@ impl pallet_scheduler::Config for Runtime { type NoPreimagePostponement = NoPreimagePostponement; } -// Migration for scheduler pallet to move from a plain Call to a CallOrHash. -pub struct SchedulerMigrationV3; -impl frame_support::traits::OnRuntimeUpgrade for SchedulerMigrationV3 { +pub struct LiquidationVaultFixMigration; +impl frame_support::traits::OnRuntimeUpgrade for LiquidationVaultFixMigration { fn on_runtime_upgrade() -> frame_support::weights::Weight { - Scheduler::migrate_v2_to_v3() - } - - #[cfg(feature = "try-runtime")] - fn pre_upgrade() -> Result<(), &'static str> { - Scheduler::pre_migrate_to_v3() - } - - #[cfg(feature = "try-runtime")] - fn post_upgrade() -> Result<(), &'static str> { - Scheduler::post_migrate_to_v3() + use orml_traits::MultiReservableCurrency; + use sp_runtime::AccountId32; + if let Ok(weight) = vault_registry::types::liquidation_vault_fix::fix_liquidation_vault::() { + // a3b3EwCtmURY7K3d6aoWzouHriGfTsvCP2axuMVGpRpkPoxg8 + let account_raw = hex_literal::hex!("24ac7fb5407f270d807425ecc6352305c0a21b9e7a1ba9812a1785a2af9b955a"); + let account_id = AccountId32::from(account_raw); + Tokens::unreserve(Token(KSM), &account_id, 42335659763394); + weight + } else { + 0 + } } } @@ -1041,7 +1040,7 @@ pub type Executive = frame_executive::Executive< frame_system::ChainContext, Runtime, AllPalletsWithSystem, - SchedulerMigrationV3, + LiquidationVaultFixMigration, >; #[cfg(not(feature = "disable-runtime-api"))]