From bca632c3eaf7f533600eed7b4940445293418000 Mon Sep 17 00:00:00 2001 From: Dmitry Lavrenov Date: Mon, 7 Aug 2023 13:01:24 +0300 Subject: [PATCH 01/38] Initial basic implementation --- Cargo.lock | 14 ++ .../Cargo.toml | 36 +++ .../src/lib.rs | 182 ++++++++++++++++ .../src/mock.rs | 206 ++++++++++++++++++ .../src/tests.rs | 35 +++ 5 files changed, 473 insertions(+) create mode 100644 crates/pallet-bridges-initializer-currency-swap/Cargo.toml create mode 100644 crates/pallet-bridges-initializer-currency-swap/src/lib.rs create mode 100644 crates/pallet-bridges-initializer-currency-swap/src/mock.rs create mode 100644 crates/pallet-bridges-initializer-currency-swap/src/tests.rs diff --git a/Cargo.lock b/Cargo.lock index 15812a4db..18ef362a6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5900,6 +5900,20 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-bridges-initializer-currency-swap" +version = "0.1.0" +dependencies = [ + "frame-support", + "frame-system", + "pallet-balances", + "pallet-pot", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-std", +] + [[package]] name = "pallet-chain-properties" version = "0.1.0" diff --git a/crates/pallet-bridges-initializer-currency-swap/Cargo.toml b/crates/pallet-bridges-initializer-currency-swap/Cargo.toml new file mode 100644 index 000000000..3214ebc2b --- /dev/null +++ b/crates/pallet-bridges-initializer-currency-swap/Cargo.toml @@ -0,0 +1,36 @@ +[package] +name = "pallet-bridges-initializer-currency-swap" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.2.2", default-features = false, features = ["derive"] } +frame-support = { default-features = false, git = "https://github.com/humanode-network/substrate", branch = "locked/polkadot-v0.9.38" } +frame-system = { default-features = false, git = "https://github.com/humanode-network/substrate", branch = "locked/polkadot-v0.9.38" } +scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } +sp-std = { default-features = false, git = "https://github.com/humanode-network/substrate", branch = "locked/polkadot-v0.9.38" } + +[dev-dependencies] +pallet-pot = { version = "0.1", path = "../pallet-pot", default-features = false } + +pallet-balances = { git = "https://github.com/humanode-network/substrate", branch = "locked/polkadot-v0.9.38" } +sp-core = { git = "https://github.com/humanode-network/substrate", branch = "locked/polkadot-v0.9.38" } + +[features] +default = ["std"] +std = [ + "codec/std", + "frame-support/std", + "frame-system/std", + "pallet-balances/std", + "pallet-pot/std", + "scale-info/std", + "sp-std/std", +] +try-runtime = [ + "frame-support/try-runtime", + "frame-system/try-runtime", + "pallet-balances/try-runtime", + "pallet-pot/try-runtime", +] diff --git a/crates/pallet-bridges-initializer-currency-swap/src/lib.rs b/crates/pallet-bridges-initializer-currency-swap/src/lib.rs new file mode 100644 index 000000000..0269c414a --- /dev/null +++ b/crates/pallet-bridges-initializer-currency-swap/src/lib.rs @@ -0,0 +1,182 @@ +//! A substrate pallet for bridge pot currency swap initialization implementation. + +// Either generate code at stadard mode, or `no_std`, based on the `std` feature presence. +#![cfg_attr(not(feature = "std"), no_std)] + +use frame_support::{ + sp_runtime::{ + traits::{CheckedAdd, CheckedSub, Convert, Get}, + ArithmeticError, DispatchError, + }, + traits::{fungible, Currency}, +}; +pub use pallet::*; + +#[cfg(test)] +mod mock; + +#[cfg(test)] +mod tests; + +pub trait BalanceMaker> { + const IS_SWAPPABLE_CHANGED: bool; + + fn make_balance(amount: C::Balance) -> Result<(), DispatchError>; +} + +// We have to temporarily allow some clippy lints. Later on we'll send patches to substrate to +// fix them at their end. +#[allow(clippy::missing_docs_in_private_items)] +#[frame_support::pallet] +pub mod pallet { + use frame_support::{pallet_prelude::*, sp_runtime::traits::MaybeDisplay}; + use sp_std::fmt::Debug; + + use super::*; + + /// The Bridge Pot Currency Swap Pallet. + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + pub struct Pallet(_); + + /// Configuration trait of this pallet. + #[pallet::config] + pub trait Config: frame_system::Config { + type EvmAccountId: Parameter + + Member + + MaybeSerializeDeserialize + + Debug + + MaybeDisplay + + Ord + + MaxEncodedLen; + + type NativeCurrency: Currency + + fungible::Inspect< + Self::AccountId, + Balance = >::Balance, + >; + + type EvmCurrency: Currency + + fungible::Inspect< + Self::EvmAccountId, + Balance = >::Balance, + >; + + type BalanceConverterNativeToEvm: Convert< + >::Balance, + >::Balance, + >; + + type BalanceConverterEvmToNative: Convert< + >::Balance, + >::Balance, + >; + + type NativeEvmBridgePot: Get; + type NativeBridgeBalanceMaker: BalanceMaker; + + type EvmNativeBridgePot: Get; + type EvmBridgeBalanceMaker: BalanceMaker; + } + + #[pallet::genesis_config] + pub struct GenesisConfig(PhantomData); + + // The default value for the genesis config type. + #[cfg(feature = "std")] + impl Default for GenesisConfig { + fn default() -> Self { + Self(PhantomData) + } + } + + // The build of genesis for the pallet. + #[pallet::genesis_build] + impl GenesisBuild for GenesisConfig { + fn build(&self) { + match Pallet::::init() { + Ok(_) => {} + Err(err) => panic!("error during bridges initialization: {err:?}",), + } + } + } +} + +impl Pallet { + pub fn init() -> Result<(), DispatchError> { + assert!( + !T::EvmBridgeBalanceMaker::IS_SWAPPABLE_CHANGED, + "not supported" + ); + + let evm_total_issuance = T::EvmCurrency::total_issuance(); + let evm_swappable = evm_total_issuance; + + let native_swap_reserved = T::BalanceConverterEvmToNative::convert(evm_swappable); + let native_bridge_balance = native_swap_reserved + .checked_add(&T::NativeCurrency::minimum_balance()) + .ok_or(ArithmeticError::Overflow)?; + + T::NativeBridgeBalanceMaker::make_balance(native_bridge_balance)?; + + let native_total_issuance = T::NativeCurrency::total_issuance(); + let native_swappable = native_total_issuance + .checked_sub(&native_bridge_balance) + .ok_or(ArithmeticError::Underflow)?; + + let evm_swap_reserved = T::BalanceConverterNativeToEvm::convert(native_swappable); + let evm_bridge_balance = evm_swap_reserved + .checked_add(&T::EvmCurrency::minimum_balance()) + .ok_or(ArithmeticError::Overflow)?; + + T::EvmBridgeBalanceMaker::make_balance(evm_bridge_balance)?; + + assert!(Self::verify_balanced()?, "not balanced"); + + Ok(()) + } + + fn verify_balanced() -> Result { + let is_balanced_native_evm = swap_reserved_balance::< + T::AccountId, + T::NativeCurrency, + T::NativeEvmBridgePot, + >()? == T::BalanceConverterEvmToNative::convert( + swappable_balance::()?, + ); + + let is_balanced_evm_native = + T::BalanceConverterNativeToEvm::convert(swap_reserved_balance::< + T::AccountId, + T::NativeCurrency, + T::NativeEvmBridgePot, + >()?) + == swappable_balance::()?; + + Ok(is_balanced_native_evm && is_balanced_evm_native) + } +} + +/// Swappable balance. +fn swappable_balance, B: Get>( +) -> Result { + let total = C::total_issuance(); + let bridge = C::total_balance(&B::get()); + + let swappable = total + .checked_sub(&bridge) + .ok_or(ArithmeticError::Underflow)?; + + Ok(swappable) +} + +/// Swap reserved balance. +fn swap_reserved_balance, B: Get>( +) -> Result { + let bridge = C::total_balance(&B::get()); + let ed = C::minimum_balance(); + + let reserved = bridge.checked_sub(&ed).ok_or(ArithmeticError::Underflow)?; + + Ok(reserved) +} diff --git a/crates/pallet-bridges-initializer-currency-swap/src/mock.rs b/crates/pallet-bridges-initializer-currency-swap/src/mock.rs new file mode 100644 index 000000000..674170a4a --- /dev/null +++ b/crates/pallet-bridges-initializer-currency-swap/src/mock.rs @@ -0,0 +1,206 @@ +//! The mock for the pallet. + +// Allow simple integer arithmetic in tests. +#![allow(clippy::integer_arithmetic)] + +use frame_support::{ + parameter_types, sp_io, + sp_runtime::{ + testing::Header, + traits::{BlakeTwo256, Identity, IdentityLookup}, + BuildStorage, DispatchError, + }, + traits::{ConstU32, ConstU64, Currency, StorageMapShim}, + PalletId, +}; +use sp_core::H256; + +use crate::{self as pallet_bridges_init_currency_swap, BalanceMaker}; + +pub(crate) const EXISTENTIAL_DEPOSIT_NATIVE: u64 = 10; +pub(crate) const EXISTENTIAL_DEPOSIT_EVM: u64 = 20; + +type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; +type Block = frame_system::mocking::MockBlock; + +pub(crate) type AccountId = u64; +pub(crate) type EvmAccountId = u64; +type Balance = u64; + +frame_support::construct_runtime!( + pub enum Test where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system, + Balances: pallet_balances::, + EvmBalances: pallet_balances::, + SwapBridgeNativeToEvmPot: pallet_pot::, + SwapBridgeEvmToNativePot: pallet_pot::, + EvmNativeBridgesInitializer: pallet_bridges_init_currency_swap, + } +); + +impl frame_system::Config for Test { + type BaseCallFilter = frame_support::traits::Everything; + type BlockWeights = (); + type BlockLength = (); + type DbWeight = (); + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + type Header = Header; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = ConstU64<250>; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = (); + type OnSetCode = (); + type MaxConsumers = ConstU32<16>; +} + +type BalancesInstanceNative = pallet_balances::Instance1; +type BalancesInstanceEvm = pallet_balances::Instance2; + +impl pallet_balances::Config for Test { + type Balance = u64; + type RuntimeEvent = RuntimeEvent; + type DustRemoval = (); + type ExistentialDeposit = ConstU64; + type AccountStore = System; + type MaxLocks = (); + type MaxReserves = (); + type ReserveIdentifier = [u8; 8]; + type WeightInfo = (); +} + +impl pallet_balances::Config for Test { + type Balance = u64; + type RuntimeEvent = RuntimeEvent; + type DustRemoval = (); + type ExistentialDeposit = ConstU64; + type AccountStore = StorageMapShim< + pallet_balances::Account, + frame_system::Provider, + AccountId, + pallet_balances::AccountData, + >; + type MaxLocks = (); + type MaxReserves = (); + type ReserveIdentifier = [u8; 8]; + type WeightInfo = (); +} + +parameter_types! { + pub const SwapBridgeNativeToEvmPotPalletId: PalletId = PalletId(*b"humanoNE"); + pub const SwapBridgeEvmToNativePotPalletId: PalletId = PalletId(*b"humanoEN"); +} + +type PotInstanceSwapBridgeNativeToEvm = pallet_pot::Instance1; +type PotInstanceSwapBridgeEvmToNative = pallet_pot::Instance2; + +impl pallet_pot::Config for Test { + type RuntimeEvent = RuntimeEvent; + type AccountId = AccountId; + type PalletId = SwapBridgeNativeToEvmPotPalletId; + type Currency = Balances; +} + +impl pallet_pot::Config for Test { + type RuntimeEvent = RuntimeEvent; + type AccountId = EvmAccountId; + type PalletId = SwapBridgeEvmToNativePotPalletId; + type Currency = EvmBalances; +} + +parameter_types! { + pub const SwapBridgeNativeToEvmPalletId: PalletId = PalletId(*b"hmsb/ne1"); + pub const SwapBridgeEvmToNativePalletId: PalletId = PalletId(*b"hmsb/en1"); +} + +parameter_types! { + pub SwapBridgeNativeToEvmPotAccountId: AccountId = SwapBridgeNativeToEvmPot::account_id(); + pub SwapBridgeEvmToNativePotAccountId: AccountId = SwapBridgeEvmToNativePot::account_id(); +} + +parameter_types! { + pub NativeTreasury: AccountId = 4200; +} + +pub struct NativeBridgeBalanceMaker; + +impl BalanceMaker for NativeBridgeBalanceMaker { + const IS_SWAPPABLE_CHANGED: bool = true; + + fn make_balance(amount: Balance) -> Result<(), DispatchError> { + let imbalance = Balances::withdraw( + &NativeTreasury::get(), + amount, + frame_support::traits::WithdrawReasons::TRANSFER, + frame_support::traits::ExistenceRequirement::KeepAlive, + )?; + + Balances::resolve_creating(&SwapBridgeNativeToEvmPotAccountId::get(), imbalance); + Ok(()) + } +} + +pub struct EvmBridgeBalanceMaker; + +impl BalanceMaker for EvmBridgeBalanceMaker { + const IS_SWAPPABLE_CHANGED: bool = false; + + fn make_balance(amount: Balance) -> Result<(), DispatchError> { + let imbalance = EvmBalances::issue(amount); + + EvmBalances::resolve_creating(&SwapBridgeNativeToEvmPotAccountId::get(), imbalance); + Ok(()) + } +} + +impl pallet_bridges_init_currency_swap::Config for Test { + type EvmAccountId = EvmAccountId; + type NativeCurrency = Balances; + type EvmCurrency = EvmBalances; + type BalanceConverterEvmToNative = Identity; + type BalanceConverterNativeToEvm = Identity; + type NativeEvmBridgePot = SwapBridgeNativeToEvmPotAccountId; + type NativeBridgeBalanceMaker = NativeBridgeBalanceMaker; + type EvmNativeBridgePot = SwapBridgeEvmToNativePotAccountId; + type EvmBridgeBalanceMaker = EvmBridgeBalanceMaker; +} + +// This function basically just builds a genesis storage key/value store according to +// our desired mockup. +pub fn new_test_ext_with(genesis_config: GenesisConfig) -> sp_io::TestExternalities { + let storage = genesis_config.build_storage().unwrap(); + storage.into() +} + +pub fn runtime_lock() -> std::sync::MutexGuard<'static, ()> { + static MOCK_RUNTIME_MUTEX: std::sync::Mutex<()> = std::sync::Mutex::new(()); + + // Ignore the poisoning for the tests that panic. + // We only care about concurrency here, not about the poisoning. + match MOCK_RUNTIME_MUTEX.lock() { + Ok(guard) => guard, + Err(poisoned) => poisoned.into_inner(), + } +} + +pub fn with_runtime_lock(f: impl FnOnce() -> R) -> R { + let lock = runtime_lock(); + let res = f(); + drop(lock); + res +} diff --git a/crates/pallet-bridges-initializer-currency-swap/src/tests.rs b/crates/pallet-bridges-initializer-currency-swap/src/tests.rs new file mode 100644 index 000000000..e4c0f5a14 --- /dev/null +++ b/crates/pallet-bridges-initializer-currency-swap/src/tests.rs @@ -0,0 +1,35 @@ +use frame_support::traits::Currency; + +use crate::mock::*; + +#[test] +fn works() { + with_runtime_lock(|| { + let config = GenesisConfig { + balances: pallet_balances::GenesisConfig { + balances: vec![(4200, 1450), (4201, 20), (4203, 30)], + }, + evm_balances: pallet_balances::GenesisConfig { + balances: vec![(4211, 200), (4212, 300), (4213, 400), (4214, 500)], + }, + swap_bridge_native_to_evm_pot: pallet_pot::GenesisConfig { + initial_state: pallet_pot::InitialState::Unchecked, + }, + swap_bridge_evm_to_native_pot: pallet_pot::GenesisConfig { + initial_state: pallet_pot::InitialState::Unchecked, + }, + ..Default::default() + }; + new_test_ext_with(config).execute_with(move || { + assert_eq!( + Balances::total_balance(&SwapBridgeNativeToEvmPot::account_id()), + 1410 + ); + assert_eq!(Balances::total_balance(&4200), 40); + assert_eq!( + EvmBalances::total_balance(&SwapBridgeNativeToEvmPot::account_id(),), + 40 + 20 + 30 + EXISTENTIAL_DEPOSIT_EVM + ); + }); + }) +} From 8c0c96be4f200560e1ea9fb782a324213b54689c Mon Sep 17 00:00:00 2001 From: Dmitry Lavrenov Date: Tue, 8 Aug 2023 12:55:18 +0300 Subject: [PATCH 02/38] Inline implementations --- .../src/lib.rs | 26 +++++------- .../src/mock.rs | 40 ++----------------- 2 files changed, 15 insertions(+), 51 deletions(-) diff --git a/crates/pallet-bridges-initializer-currency-swap/src/lib.rs b/crates/pallet-bridges-initializer-currency-swap/src/lib.rs index 0269c414a..9b3e2d982 100644 --- a/crates/pallet-bridges-initializer-currency-swap/src/lib.rs +++ b/crates/pallet-bridges-initializer-currency-swap/src/lib.rs @@ -18,12 +18,6 @@ mod mock; #[cfg(test)] mod tests; -pub trait BalanceMaker> { - const IS_SWAPPABLE_CHANGED: bool; - - fn make_balance(amount: C::Balance) -> Result<(), DispatchError>; -} - // We have to temporarily allow some clippy lints. Later on we'll send patches to substrate to // fix them at their end. #[allow(clippy::missing_docs_in_private_items)] @@ -73,10 +67,10 @@ pub mod pallet { >; type NativeEvmBridgePot: Get; - type NativeBridgeBalanceMaker: BalanceMaker; + + type NativeTreasuryPot: Get; type EvmNativeBridgePot: Get; - type EvmBridgeBalanceMaker: BalanceMaker; } #[pallet::genesis_config] @@ -104,11 +98,6 @@ pub mod pallet { impl Pallet { pub fn init() -> Result<(), DispatchError> { - assert!( - !T::EvmBridgeBalanceMaker::IS_SWAPPABLE_CHANGED, - "not supported" - ); - let evm_total_issuance = T::EvmCurrency::total_issuance(); let evm_swappable = evm_total_issuance; @@ -117,7 +106,13 @@ impl Pallet { .checked_add(&T::NativeCurrency::minimum_balance()) .ok_or(ArithmeticError::Overflow)?; - T::NativeBridgeBalanceMaker::make_balance(native_bridge_balance)?; + let imbalance = T::NativeCurrency::withdraw( + &T::NativeTreasuryPot::get(), + native_bridge_balance, + frame_support::traits::WithdrawReasons::TRANSFER, + frame_support::traits::ExistenceRequirement::KeepAlive, + )?; + T::NativeCurrency::resolve_creating(&T::NativeEvmBridgePot::get(), imbalance); let native_total_issuance = T::NativeCurrency::total_issuance(); let native_swappable = native_total_issuance @@ -129,7 +124,8 @@ impl Pallet { .checked_add(&T::EvmCurrency::minimum_balance()) .ok_or(ArithmeticError::Overflow)?; - T::EvmBridgeBalanceMaker::make_balance(evm_bridge_balance)?; + let imbalance = T::EvmCurrency::issue(evm_bridge_balance); + T::EvmCurrency::resolve_creating(&T::EvmNativeBridgePot::get(), imbalance); assert!(Self::verify_balanced()?, "not balanced"); diff --git a/crates/pallet-bridges-initializer-currency-swap/src/mock.rs b/crates/pallet-bridges-initializer-currency-swap/src/mock.rs index 674170a4a..3996030d5 100644 --- a/crates/pallet-bridges-initializer-currency-swap/src/mock.rs +++ b/crates/pallet-bridges-initializer-currency-swap/src/mock.rs @@ -8,14 +8,14 @@ use frame_support::{ sp_runtime::{ testing::Header, traits::{BlakeTwo256, Identity, IdentityLookup}, - BuildStorage, DispatchError, + BuildStorage, }, - traits::{ConstU32, ConstU64, Currency, StorageMapShim}, + traits::{ConstU32, ConstU64, StorageMapShim}, PalletId, }; use sp_core::H256; -use crate::{self as pallet_bridges_init_currency_swap, BalanceMaker}; +use crate::{self as pallet_bridges_init_currency_swap}; pub(crate) const EXISTENTIAL_DEPOSIT_NATIVE: u64 = 10; pub(crate) const EXISTENTIAL_DEPOSIT_EVM: u64 = 20; @@ -137,37 +137,6 @@ parameter_types! { pub NativeTreasury: AccountId = 4200; } -pub struct NativeBridgeBalanceMaker; - -impl BalanceMaker for NativeBridgeBalanceMaker { - const IS_SWAPPABLE_CHANGED: bool = true; - - fn make_balance(amount: Balance) -> Result<(), DispatchError> { - let imbalance = Balances::withdraw( - &NativeTreasury::get(), - amount, - frame_support::traits::WithdrawReasons::TRANSFER, - frame_support::traits::ExistenceRequirement::KeepAlive, - )?; - - Balances::resolve_creating(&SwapBridgeNativeToEvmPotAccountId::get(), imbalance); - Ok(()) - } -} - -pub struct EvmBridgeBalanceMaker; - -impl BalanceMaker for EvmBridgeBalanceMaker { - const IS_SWAPPABLE_CHANGED: bool = false; - - fn make_balance(amount: Balance) -> Result<(), DispatchError> { - let imbalance = EvmBalances::issue(amount); - - EvmBalances::resolve_creating(&SwapBridgeNativeToEvmPotAccountId::get(), imbalance); - Ok(()) - } -} - impl pallet_bridges_init_currency_swap::Config for Test { type EvmAccountId = EvmAccountId; type NativeCurrency = Balances; @@ -175,9 +144,8 @@ impl pallet_bridges_init_currency_swap::Config for Test { type BalanceConverterEvmToNative = Identity; type BalanceConverterNativeToEvm = Identity; type NativeEvmBridgePot = SwapBridgeNativeToEvmPotAccountId; - type NativeBridgeBalanceMaker = NativeBridgeBalanceMaker; + type NativeTreasuryPot = NativeTreasury; type EvmNativeBridgePot = SwapBridgeEvmToNativePotAccountId; - type EvmBridgeBalanceMaker = EvmBridgeBalanceMaker; } // This function basically just builds a genesis storage key/value store according to From 14e2bf0073be64726336bf270e84ed0b6230e7d5 Mon Sep 17 00:00:00 2001 From: Dmitry Lavrenov Date: Tue, 8 Aug 2023 13:26:24 +0300 Subject: [PATCH 03/38] Docs and refactoring --- .../src/lib.rs | 34 +++++++++++++++---- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/crates/pallet-bridges-initializer-currency-swap/src/lib.rs b/crates/pallet-bridges-initializer-currency-swap/src/lib.rs index 9b3e2d982..dbe2f6eff 100644 --- a/crates/pallet-bridges-initializer-currency-swap/src/lib.rs +++ b/crates/pallet-bridges-initializer-currency-swap/src/lib.rs @@ -1,4 +1,4 @@ -//! A substrate pallet for bridge pot currency swap initialization implementation. +//! A substrate pallet for bridges pot currency swap initialization logic. // Either generate code at stadard mode, or `no_std`, based on the `std` feature presence. #![cfg_attr(not(feature = "std"), no_std)] @@ -36,6 +36,7 @@ pub mod pallet { /// Configuration trait of this pallet. #[pallet::config] pub trait Config: frame_system::Config { + /// The evm user account identifier type. type EvmAccountId: Parameter + Member + MaybeSerializeDeserialize @@ -44,32 +45,41 @@ pub mod pallet { + Ord + MaxEncodedLen; + /// The interface into native currency implementation. type NativeCurrency: Currency + fungible::Inspect< Self::AccountId, Balance = >::Balance, >; + /// The interface into evm currency implementation. type EvmCurrency: Currency + fungible::Inspect< Self::EvmAccountId, Balance = >::Balance, >; + /// The converter to determine how the balance amount should be converted from + /// native currency to evm currency. type BalanceConverterNativeToEvm: Convert< >::Balance, >::Balance, >; + /// The converter to determine how the balance amount should be converted from + /// evm currency to native currency. type BalanceConverterEvmToNative: Convert< >::Balance, >::Balance, >; + /// The native-evm bridge pot account. type NativeEvmBridgePot: Get; + /// The native treasury pot account. type NativeTreasuryPot: Get; + /// The evm-native bridge pot account. type EvmNativeBridgePot: Get; } @@ -88,16 +98,23 @@ pub mod pallet { #[pallet::genesis_build] impl GenesisBuild for GenesisConfig { fn build(&self) { - match Pallet::::init() { + match Pallet::::initialize() { Ok(_) => {} Err(err) => panic!("error during bridges initialization: {err:?}",), } } } + + #[pallet::error] + pub enum Error { + /// The currencies are not balanced. + NotBalanced, + } } impl Pallet { - pub fn init() -> Result<(), DispatchError> { + /// Initialize bridges pot accounts. + pub fn initialize() -> Result<(), DispatchError> { let evm_total_issuance = T::EvmCurrency::total_issuance(); let evm_swappable = evm_total_issuance; @@ -127,12 +144,15 @@ impl Pallet { let imbalance = T::EvmCurrency::issue(evm_bridge_balance); T::EvmCurrency::resolve_creating(&T::EvmNativeBridgePot::get(), imbalance); - assert!(Self::verify_balanced()?, "not balanced"); + if !Self::is_balanced()? { + return Err(Error::::NotBalanced.into()); + } Ok(()) } - fn verify_balanced() -> Result { + /// Verify currencies balanced requirements. + fn is_balanced() -> Result { let is_balanced_native_evm = swap_reserved_balance::< T::AccountId, T::NativeCurrency, @@ -153,7 +173,7 @@ impl Pallet { } } -/// Swappable balance. +/// A helper function to calculate swappable balance. fn swappable_balance, B: Get>( ) -> Result { let total = C::total_issuance(); @@ -166,7 +186,7 @@ fn swappable_balance, B: Get>( Ok(swappable) } -/// Swap reserved balance. +/// A helper function to calculate swap reserved balance. fn swap_reserved_balance, B: Get>( ) -> Result { let bridge = C::total_balance(&B::get()); From a71541ec74d935509ebccfe7ccf27193b72cccc6 Mon Sep 17 00:00:00 2001 From: Dmitry Lavrenov Date: Tue, 8 Aug 2023 14:33:15 +0300 Subject: [PATCH 04/38] Handle all bridges initial balances cases --- .../src/lib.rs | 109 ++++++++++++++++-- 1 file changed, 98 insertions(+), 11 deletions(-) diff --git a/crates/pallet-bridges-initializer-currency-swap/src/lib.rs b/crates/pallet-bridges-initializer-currency-swap/src/lib.rs index dbe2f6eff..ab1e2e5dc 100644 --- a/crates/pallet-bridges-initializer-currency-swap/src/lib.rs +++ b/crates/pallet-bridges-initializer-currency-swap/src/lib.rs @@ -5,12 +5,13 @@ use frame_support::{ sp_runtime::{ - traits::{CheckedAdd, CheckedSub, Convert, Get}, + traits::{CheckedAdd, CheckedSub, Convert, Get, Zero}, ArithmeticError, DispatchError, }, traits::{fungible, Currency}, }; pub use pallet::*; +use sp_std::cmp::Ordering; #[cfg(test)] mod mock; @@ -28,7 +29,7 @@ pub mod pallet { use super::*; - /// The Bridge Pot Currency Swap Pallet. + /// The Bridge Pot Currency Swap Initializer Pallet. #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] pub struct Pallet(_); @@ -109,6 +110,10 @@ pub mod pallet { pub enum Error { /// The currencies are not balanced. NotBalanced, + /// Native-evm bridge pot balance is too high. + NativeEvmBridgePotOverflow, + /// Evm-native bridge pot balance is too low. + EvmNativeBridgePotUnderflow, } } @@ -123,13 +128,7 @@ impl Pallet { .checked_add(&T::NativeCurrency::minimum_balance()) .ok_or(ArithmeticError::Overflow)?; - let imbalance = T::NativeCurrency::withdraw( - &T::NativeTreasuryPot::get(), - native_bridge_balance, - frame_support::traits::WithdrawReasons::TRANSFER, - frame_support::traits::ExistenceRequirement::KeepAlive, - )?; - T::NativeCurrency::resolve_creating(&T::NativeEvmBridgePot::get(), imbalance); + Self::make_native_bridge_balance_be(native_bridge_balance)?; let native_total_issuance = T::NativeCurrency::total_issuance(); let native_swappable = native_total_issuance @@ -141,8 +140,7 @@ impl Pallet { .checked_add(&T::EvmCurrency::minimum_balance()) .ok_or(ArithmeticError::Overflow)?; - let imbalance = T::EvmCurrency::issue(evm_bridge_balance); - T::EvmCurrency::resolve_creating(&T::EvmNativeBridgePot::get(), imbalance); + Self::make_evm_bridge_balance_be(evm_bridge_balance)?; if !Self::is_balanced()? { return Err(Error::::NotBalanced.into()); @@ -151,6 +149,95 @@ impl Pallet { Ok(()) } + /// Make native bridge balance be provided amount value. + /// + /// The logic can change native swappable balance value. + fn make_native_bridge_balance_be( + amount: >::Balance, + ) -> Result<(), DispatchError> { + let current_native_bridge_balance = + T::NativeCurrency::total_balance(&T::NativeEvmBridgePot::get()); + + if current_native_bridge_balance == Zero::zero() { + let imbalance = T::NativeCurrency::withdraw( + &T::NativeTreasuryPot::get(), + amount, + frame_support::traits::WithdrawReasons::TRANSFER, + frame_support::traits::ExistenceRequirement::KeepAlive, + )?; + T::NativeCurrency::resolve_creating(&T::NativeEvmBridgePot::get(), imbalance); + + return Ok(()); + } + + match current_native_bridge_balance.cmp(&amount) { + Ordering::Less => { + let imbalance = T::NativeCurrency::withdraw( + &T::NativeTreasuryPot::get(), + amount + .checked_sub(¤t_native_bridge_balance) + .ok_or(ArithmeticError::Underflow)?, + frame_support::traits::WithdrawReasons::TRANSFER, + frame_support::traits::ExistenceRequirement::KeepAlive, + )?; + T::NativeCurrency::resolve_into_existing(&T::NativeEvmBridgePot::get(), imbalance) + .map_err(|_| Error::::NativeEvmBridgePotOverflow)?; + } + Ordering::Greater => { + let imbalance = T::NativeCurrency::withdraw( + &T::NativeEvmBridgePot::get(), + current_native_bridge_balance + .checked_sub(&amount) + .ok_or(ArithmeticError::Underflow)?, + frame_support::traits::WithdrawReasons::TRANSFER, + frame_support::traits::ExistenceRequirement::KeepAlive, + )?; + T::NativeCurrency::resolve_into_existing(&T::NativeEvmBridgePot::get(), imbalance) + .map_err(|_| Error::::NativeEvmBridgePotOverflow)?; + } + Ordering::Equal => {} + } + + Ok(()) + } + + /// Make evm bridge balance be provided amount value. + /// + /// The logic shouldn't change evm swappable balance value. + fn make_evm_bridge_balance_be( + amount: >::Balance, + ) -> Result<(), DispatchError> { + let current_evm_bridge_balance = + T::EvmCurrency::total_balance(&T::EvmNativeBridgePot::get()); + + match current_evm_bridge_balance.cmp(&amount) { + Ordering::Less => { + let imbalance = T::EvmCurrency::issue( + amount + .checked_sub(¤t_evm_bridge_balance) + .ok_or(ArithmeticError::Underflow)?, + ); + T::EvmCurrency::resolve_creating(&T::EvmNativeBridgePot::get(), imbalance); + } + Ordering::Greater => { + let imbalance = T::EvmCurrency::burn( + current_evm_bridge_balance + .checked_sub(&amount) + .ok_or(ArithmeticError::Underflow)?, + ); + T::EvmCurrency::settle( + &T::EvmNativeBridgePot::get(), + imbalance, + frame_support::traits::WithdrawReasons::RESERVE, + frame_support::traits::ExistenceRequirement::KeepAlive, + ) + .map_err(|_| Error::::NativeEvmBridgePotOverflow)?; + } + Ordering::Equal => {} + } + Ok(()) + } + /// Verify currencies balanced requirements. fn is_balanced() -> Result { let is_balanced_native_evm = swap_reserved_balance::< From a976d20241299a29c55dca84733a266d7204584b Mon Sep 17 00:00:00 2001 From: Dmitry Lavrenov Date: Tue, 8 Aug 2023 15:18:01 +0300 Subject: [PATCH 05/38] Fix basic test --- .../src/lib.rs | 5 ++- .../src/tests.rs | 35 ++++++++++++++----- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/crates/pallet-bridges-initializer-currency-swap/src/lib.rs b/crates/pallet-bridges-initializer-currency-swap/src/lib.rs index ab1e2e5dc..639a082f6 100644 --- a/crates/pallet-bridges-initializer-currency-swap/src/lib.rs +++ b/crates/pallet-bridges-initializer-currency-swap/src/lib.rs @@ -121,7 +121,10 @@ impl Pallet { /// Initialize bridges pot accounts. pub fn initialize() -> Result<(), DispatchError> { let evm_total_issuance = T::EvmCurrency::total_issuance(); - let evm_swappable = evm_total_issuance; + let evm_bridge_balance = T::EvmCurrency::total_balance(&T::EvmNativeBridgePot::get()); + let evm_swappable = evm_total_issuance + .checked_sub(&evm_bridge_balance) + .ok_or(ArithmeticError::Underflow)?; let native_swap_reserved = T::BalanceConverterEvmToNative::convert(evm_swappable); let native_bridge_balance = native_swap_reserved diff --git a/crates/pallet-bridges-initializer-currency-swap/src/tests.rs b/crates/pallet-bridges-initializer-currency-swap/src/tests.rs index e4c0f5a14..eacde66e6 100644 --- a/crates/pallet-bridges-initializer-currency-swap/src/tests.rs +++ b/crates/pallet-bridges-initializer-currency-swap/src/tests.rs @@ -3,32 +3,49 @@ use frame_support::traits::Currency; use crate::mock::*; #[test] -fn works() { +fn initialization_works() { with_runtime_lock(|| { let config = GenesisConfig { balances: pallet_balances::GenesisConfig { - balances: vec![(4200, 1450), (4201, 20), (4203, 30)], + balances: vec![ + (NativeTreasury::get(), 1450), + (4201, 20), + (4203, 30), + ( + SwapBridgeNativeToEvmPot::account_id(), + EXISTENTIAL_DEPOSIT_NATIVE, + ), + ], }, evm_balances: pallet_balances::GenesisConfig { - balances: vec![(4211, 200), (4212, 300), (4213, 400), (4214, 500)], + balances: vec![ + (4211, 200), + (4212, 300), + (4213, 400), + (4214, 500), + ( + SwapBridgeEvmToNativePot::account_id(), + EXISTENTIAL_DEPOSIT_EVM, + ), + ], }, swap_bridge_native_to_evm_pot: pallet_pot::GenesisConfig { - initial_state: pallet_pot::InitialState::Unchecked, + initial_state: pallet_pot::InitialState::Initialized, }, swap_bridge_evm_to_native_pot: pallet_pot::GenesisConfig { - initial_state: pallet_pot::InitialState::Unchecked, + initial_state: pallet_pot::InitialState::Initialized, }, ..Default::default() }; new_test_ext_with(config).execute_with(move || { assert_eq!( Balances::total_balance(&SwapBridgeNativeToEvmPot::account_id()), - 1410 + 200 + 300 + 400 + 500 + EXISTENTIAL_DEPOSIT_NATIVE ); - assert_eq!(Balances::total_balance(&4200), 40); + assert_eq!(Balances::total_balance(&NativeTreasury::get()), 50); assert_eq!( - EvmBalances::total_balance(&SwapBridgeNativeToEvmPot::account_id(),), - 40 + 20 + 30 + EXISTENTIAL_DEPOSIT_EVM + EvmBalances::total_balance(&SwapBridgeEvmToNativePot::account_id(),), + 50 + 20 + 30 + EXISTENTIAL_DEPOSIT_EVM ); }); }) From 6a09b509168d7e8e326f41f05686a8dba9d5a695 Mon Sep 17 00:00:00 2001 From: Dmitry Lavrenov Date: Tue, 8 Aug 2023 16:52:40 +0300 Subject: [PATCH 06/38] Properly handle edge cases --- .../src/lib.rs | 54 ++++++++++++------- 1 file changed, 35 insertions(+), 19 deletions(-) diff --git a/crates/pallet-bridges-initializer-currency-swap/src/lib.rs b/crates/pallet-bridges-initializer-currency-swap/src/lib.rs index 639a082f6..befac082f 100644 --- a/crates/pallet-bridges-initializer-currency-swap/src/lib.rs +++ b/crates/pallet-bridges-initializer-currency-swap/src/lib.rs @@ -110,10 +110,6 @@ pub mod pallet { pub enum Error { /// The currencies are not balanced. NotBalanced, - /// Native-evm bridge pot balance is too high. - NativeEvmBridgePotOverflow, - /// Evm-native bridge pot balance is too low. - EvmNativeBridgePotUnderflow, } } @@ -124,7 +120,7 @@ impl Pallet { let evm_bridge_balance = T::EvmCurrency::total_balance(&T::EvmNativeBridgePot::get()); let evm_swappable = evm_total_issuance .checked_sub(&evm_bridge_balance) - .ok_or(ArithmeticError::Underflow)?; + .expect("evm_total_issuance is greater than evm_bridge_balance; qed."); let native_swap_reserved = T::BalanceConverterEvmToNative::convert(evm_swappable); let native_bridge_balance = native_swap_reserved @@ -136,7 +132,7 @@ impl Pallet { let native_total_issuance = T::NativeCurrency::total_issuance(); let native_swappable = native_total_issuance .checked_sub(&native_bridge_balance) - .ok_or(ArithmeticError::Underflow)?; + .expect("native_total_issuance is greater than native_bridge_balance; qed."); let evm_swap_reserved = T::BalanceConverterNativeToEvm::convert(native_swappable); let evm_bridge_balance = evm_swap_reserved @@ -154,7 +150,7 @@ impl Pallet { /// Make native bridge balance be provided amount value. /// - /// The logic can change native swappable balance value. + /// The logic can change native swappable balance value. fn make_native_bridge_balance_be( amount: >::Balance, ) -> Result<(), DispatchError> { @@ -179,24 +175,33 @@ impl Pallet { &T::NativeTreasuryPot::get(), amount .checked_sub(¤t_native_bridge_balance) - .ok_or(ArithmeticError::Underflow)?, + .expect("current_native_bridge_balance is less than amount; qed."), frame_support::traits::WithdrawReasons::TRANSFER, frame_support::traits::ExistenceRequirement::KeepAlive, )?; - T::NativeCurrency::resolve_into_existing(&T::NativeEvmBridgePot::get(), imbalance) - .map_err(|_| Error::::NativeEvmBridgePotOverflow)?; + // We can safely ignore the result as overflow cann't be reached. + // current_native_bridge_balance < amount. The resulted balance is equal to amount. + let _ = T::NativeCurrency::resolve_into_existing( + &T::NativeEvmBridgePot::get(), + imbalance, + ); } Ordering::Greater => { let imbalance = T::NativeCurrency::withdraw( &T::NativeEvmBridgePot::get(), current_native_bridge_balance .checked_sub(&amount) - .ok_or(ArithmeticError::Underflow)?, + .expect("current_native_bridge_balance is greater than amount; qed."), frame_support::traits::WithdrawReasons::TRANSFER, frame_support::traits::ExistenceRequirement::KeepAlive, )?; - T::NativeCurrency::resolve_into_existing(&T::NativeEvmBridgePot::get(), imbalance) - .map_err(|_| Error::::NativeEvmBridgePotOverflow)?; + // We can safely ignore the result as overflow cann't be reached. + // current_native_bridge_balance + current_native_treasury < total_issuance. + // So, imbalance + current_native_treasury < total_issuance. + let _ = T::NativeCurrency::resolve_into_existing( + &T::NativeTreasuryPot::get(), + imbalance, + ); } Ordering::Equal => {} } @@ -213,28 +218,39 @@ impl Pallet { let current_evm_bridge_balance = T::EvmCurrency::total_balance(&T::EvmNativeBridgePot::get()); + if current_evm_bridge_balance == Zero::zero() { + let imbalance = T::EvmCurrency::issue(amount); + T::EvmCurrency::resolve_creating(&T::EvmNativeBridgePot::get(), imbalance); + + return Ok(()); + } + match current_evm_bridge_balance.cmp(&amount) { Ordering::Less => { let imbalance = T::EvmCurrency::issue( amount .checked_sub(¤t_evm_bridge_balance) - .ok_or(ArithmeticError::Underflow)?, + .expect("current_evm_bridge_balance is less than amount; qed."), ); - T::EvmCurrency::resolve_creating(&T::EvmNativeBridgePot::get(), imbalance); + // We can safely ignore the result as overflow cann't be reached. + // current_evm_bridge_balance < amount. The resulted balance is equal to amount. + let _ = + T::EvmCurrency::resolve_into_existing(&T::EvmNativeBridgePot::get(), imbalance); } Ordering::Greater => { let imbalance = T::EvmCurrency::burn( current_evm_bridge_balance .checked_sub(&amount) - .ok_or(ArithmeticError::Underflow)?, + .expect("current_evm_bridge_balance is greater than amount; qed."), ); - T::EvmCurrency::settle( + // We can safely ignore the result as underflow cann't be reached. + // current_evm_bridge_balance > amount => imbalance < current_evm_bridge_balance. + let _ = T::EvmCurrency::settle( &T::EvmNativeBridgePot::get(), imbalance, frame_support::traits::WithdrawReasons::RESERVE, frame_support::traits::ExistenceRequirement::KeepAlive, - ) - .map_err(|_| Error::::NativeEvmBridgePotOverflow)?; + ); } Ordering::Equal => {} } From 33f69568f2ba877fe56a42e2a3cf9dbc46d081ae Mon Sep 17 00:00:00 2001 From: Dmitry Lavrenov Date: Tue, 8 Aug 2023 16:59:08 +0300 Subject: [PATCH 07/38] Improve tests --- .../src/tests.rs | 143 +++++++++++++++--- 1 file changed, 120 insertions(+), 23 deletions(-) diff --git a/crates/pallet-bridges-initializer-currency-swap/src/tests.rs b/crates/pallet-bridges-initializer-currency-swap/src/tests.rs index eacde66e6..6e01bebc4 100644 --- a/crates/pallet-bridges-initializer-currency-swap/src/tests.rs +++ b/crates/pallet-bridges-initializer-currency-swap/src/tests.rs @@ -3,31 +3,88 @@ use frame_support::traits::Currency; use crate::mock::*; #[test] -fn initialization_works() { +fn initialization_bridges_ed_works() { with_runtime_lock(|| { + let treasury = (NativeTreasury::get(), 1450); + let alice = (4201, 20); + let bob = (4203, 30); + let swap_bridge_native_evm = ( + SwapBridgeNativeToEvmPot::account_id(), + EXISTENTIAL_DEPOSIT_NATIVE, + ); + + let lion = (4211, 200); + let dog = (4212, 300); + let cat = (4213, 400); + let fish = (4214, 500); + let swap_bridge_evm_native = ( + SwapBridgeEvmToNativePot::account_id(), + EXISTENTIAL_DEPOSIT_EVM, + ); + + let config = GenesisConfig { + balances: pallet_balances::GenesisConfig { + balances: vec![treasury, alice, bob, swap_bridge_native_evm], + }, + evm_balances: pallet_balances::GenesisConfig { + balances: vec![lion, dog, cat, fish, swap_bridge_evm_native], + }, + swap_bridge_native_to_evm_pot: pallet_pot::GenesisConfig { + initial_state: pallet_pot::InitialState::Initialized, + }, + swap_bridge_evm_to_native_pot: pallet_pot::GenesisConfig { + initial_state: pallet_pot::InitialState::Initialized, + }, + ..Default::default() + }; + new_test_ext_with(config).execute_with(move || { + assert_eq!( + Balances::total_balance(&SwapBridgeNativeToEvmPot::account_id()), + lion.1 + dog.1 + cat.1 + fish.1 + EXISTENTIAL_DEPOSIT_NATIVE + ); + assert_eq!( + Balances::total_balance(&NativeTreasury::get()), + treasury.1 - (lion.1 + dog.1 + cat.1 + fish.1) + ); + assert_eq!( + EvmBalances::total_balance(&SwapBridgeEvmToNativePot::account_id(),), + Balances::total_balance(&NativeTreasury::get()) + + alice.1 + + bob.1 + + EXISTENTIAL_DEPOSIT_EVM + ); + }); + }) +} + +#[test] +fn initialization_bridges_ed_delta_works() { + with_runtime_lock(|| { + let treasury = (NativeTreasury::get(), 1450); + let alice = (4201, 20); + let bob = (4203, 30); + let native_bridge_delta = 100; + let swap_bridge_native_evm = ( + SwapBridgeNativeToEvmPot::account_id(), + EXISTENTIAL_DEPOSIT_NATIVE + native_bridge_delta, + ); + + let lion = (4211, 200); + let dog = (4212, 300); + let cat = (4213, 400); + let fish = (4214, 500); + let evm_bridge_delta = 50; + let swap_bridge_evm_native = ( + SwapBridgeEvmToNativePot::account_id(), + EXISTENTIAL_DEPOSIT_EVM + evm_bridge_delta, + ); + let config = GenesisConfig { balances: pallet_balances::GenesisConfig { - balances: vec![ - (NativeTreasury::get(), 1450), - (4201, 20), - (4203, 30), - ( - SwapBridgeNativeToEvmPot::account_id(), - EXISTENTIAL_DEPOSIT_NATIVE, - ), - ], + balances: vec![treasury, alice, bob, swap_bridge_native_evm], }, evm_balances: pallet_balances::GenesisConfig { - balances: vec![ - (4211, 200), - (4212, 300), - (4213, 400), - (4214, 500), - ( - SwapBridgeEvmToNativePot::account_id(), - EXISTENTIAL_DEPOSIT_EVM, - ), - ], + balances: vec![lion, dog, cat, fish, swap_bridge_evm_native], }, swap_bridge_native_to_evm_pot: pallet_pot::GenesisConfig { initial_state: pallet_pot::InitialState::Initialized, @@ -40,13 +97,53 @@ fn initialization_works() { new_test_ext_with(config).execute_with(move || { assert_eq!( Balances::total_balance(&SwapBridgeNativeToEvmPot::account_id()), - 200 + 300 + 400 + 500 + EXISTENTIAL_DEPOSIT_NATIVE + lion.1 + dog.1 + cat.1 + fish.1 + EXISTENTIAL_DEPOSIT_NATIVE + ); + assert_eq!( + Balances::total_balance(&NativeTreasury::get()), + treasury.1 - (lion.1 + dog.1 + cat.1 + fish.1) + native_bridge_delta ); - assert_eq!(Balances::total_balance(&NativeTreasury::get()), 50); assert_eq!( EvmBalances::total_balance(&SwapBridgeEvmToNativePot::account_id(),), - 50 + 20 + 30 + EXISTENTIAL_DEPOSIT_EVM + Balances::total_balance(&NativeTreasury::get()) + + alice.1 + + bob.1 + + EXISTENTIAL_DEPOSIT_EVM ); }); }) } + +#[test] +#[should_panic = "error during bridges initialization: Arithmetic(Overflow)"] +fn initialization_fails_overflow() { + with_runtime_lock(|| { + let treasury = (NativeTreasury::get(), EXISTENTIAL_DEPOSIT_NATIVE); + let swap_bridge_native_evm = ( + SwapBridgeNativeToEvmPot::account_id(), + u64::MAX - EXISTENTIAL_DEPOSIT_NATIVE, + ); + + let swap_bridge_evm_native = ( + SwapBridgeEvmToNativePot::account_id(), + EXISTENTIAL_DEPOSIT_EVM, + ); + + let config = GenesisConfig { + balances: pallet_balances::GenesisConfig { + balances: vec![treasury, swap_bridge_native_evm], + }, + evm_balances: pallet_balances::GenesisConfig { + balances: vec![swap_bridge_evm_native], + }, + swap_bridge_native_to_evm_pot: pallet_pot::GenesisConfig { + initial_state: pallet_pot::InitialState::Initialized, + }, + swap_bridge_evm_to_native_pot: pallet_pot::GenesisConfig { + initial_state: pallet_pot::InitialState::Initialized, + }, + ..Default::default() + }; + new_test_ext_with(config).execute_with(move || {}); + }) +} From 96102f35555c6cab5ee17027da8c884040277654 Mon Sep 17 00:00:00 2001 From: Dmitry Lavrenov Date: Tue, 8 Aug 2023 17:55:54 +0300 Subject: [PATCH 08/38] Add initialization_fails_treasury_insufficient_balance test --- .../src/lib.rs | 1 + .../src/tests.rs | 39 +++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/crates/pallet-bridges-initializer-currency-swap/src/lib.rs b/crates/pallet-bridges-initializer-currency-swap/src/lib.rs index befac082f..60b7dbffd 100644 --- a/crates/pallet-bridges-initializer-currency-swap/src/lib.rs +++ b/crates/pallet-bridges-initializer-currency-swap/src/lib.rs @@ -195,6 +195,7 @@ impl Pallet { frame_support::traits::WithdrawReasons::TRANSFER, frame_support::traits::ExistenceRequirement::KeepAlive, )?; + // We can safely ignore the result as overflow cann't be reached. // current_native_bridge_balance + current_native_treasury < total_issuance. // So, imbalance + current_native_treasury < total_issuance. diff --git a/crates/pallet-bridges-initializer-currency-swap/src/tests.rs b/crates/pallet-bridges-initializer-currency-swap/src/tests.rs index 6e01bebc4..704ccd079 100644 --- a/crates/pallet-bridges-initializer-currency-swap/src/tests.rs +++ b/crates/pallet-bridges-initializer-currency-swap/src/tests.rs @@ -147,3 +147,42 @@ fn initialization_fails_overflow() { new_test_ext_with(config).execute_with(move || {}); }) } + +#[test] +#[should_panic = "error during bridges initialization: Module(ModuleError { index: 1, error: [2, 0, 0, 0], message: Some(\"InsufficientBalance\") })"] +fn initialization_fails_treasury_insufficient_balance() { + with_runtime_lock(|| { + let treasury = (NativeTreasury::get(), EXISTENTIAL_DEPOSIT_NATIVE + 10); + let swap_bridge_native_evm = ( + SwapBridgeNativeToEvmPot::account_id(), + EXISTENTIAL_DEPOSIT_NATIVE, + ); + + let lion = (4211, 200); + let dog = (4212, 300); + let cat = (4213, 400); + let fish = (4214, 500); + let evm_bridge_delta = 50; + let swap_bridge_evm_native = ( + SwapBridgeEvmToNativePot::account_id(), + EXISTENTIAL_DEPOSIT_EVM + evm_bridge_delta, + ); + + let config = GenesisConfig { + balances: pallet_balances::GenesisConfig { + balances: vec![treasury, swap_bridge_native_evm], + }, + evm_balances: pallet_balances::GenesisConfig { + balances: vec![lion, dog, cat, fish, swap_bridge_evm_native], + }, + swap_bridge_native_to_evm_pot: pallet_pot::GenesisConfig { + initial_state: pallet_pot::InitialState::Initialized, + }, + swap_bridge_evm_to_native_pot: pallet_pot::GenesisConfig { + initial_state: pallet_pot::InitialState::Initialized, + }, + ..Default::default() + }; + new_test_ext_with(config).execute_with(move || {}); + }) +} From b7f58c073cb2c6ba6a847f65982b2ed7e8923a6f Mon Sep 17 00:00:00 2001 From: Dmitry Lavrenov Date: Tue, 8 Aug 2023 19:10:02 +0300 Subject: [PATCH 09/38] Update features snapshot --- utils/checks/snapshots/features.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/utils/checks/snapshots/features.yaml b/utils/checks/snapshots/features.yaml index 49ad2eca8..9fd6b6cb1 100644 --- a/utils/checks/snapshots/features.yaml +++ b/utils/checks/snapshots/features.yaml @@ -1988,6 +1988,10 @@ features: - default - std +- name: pallet-bridges-initializer-currency-swap 0.1.0 + features: + - default + - std - name: pallet-chain-properties 0.1.0 features: - default From 8c25bf4bae62a4efae4202298e984ccb97e622af Mon Sep 17 00:00:00 2001 From: Dmitry Lavrenov Date: Tue, 8 Aug 2023 19:41:54 +0300 Subject: [PATCH 10/38] Add weight value calculation --- .../src/lib.rs | 47 +++++++++++++++---- 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/crates/pallet-bridges-initializer-currency-swap/src/lib.rs b/crates/pallet-bridges-initializer-currency-swap/src/lib.rs index 60b7dbffd..665d8370e 100644 --- a/crates/pallet-bridges-initializer-currency-swap/src/lib.rs +++ b/crates/pallet-bridges-initializer-currency-swap/src/lib.rs @@ -9,6 +9,7 @@ use frame_support::{ ArithmeticError, DispatchError, }, traits::{fungible, Currency}, + weights::Weight, }; pub use pallet::*; use sp_std::cmp::Ordering; @@ -115,9 +116,11 @@ pub mod pallet { impl Pallet { /// Initialize bridges pot accounts. - pub fn initialize() -> Result<(), DispatchError> { + pub fn initialize() -> Result { let evm_total_issuance = T::EvmCurrency::total_issuance(); let evm_bridge_balance = T::EvmCurrency::total_balance(&T::EvmNativeBridgePot::get()); + let mut weight = T::DbWeight::get().reads(2); + let evm_swappable = evm_total_issuance .checked_sub(&evm_bridge_balance) .expect("evm_total_issuance is greater than evm_bridge_balance; qed."); @@ -126,10 +129,13 @@ impl Pallet { let native_bridge_balance = native_swap_reserved .checked_add(&T::NativeCurrency::minimum_balance()) .ok_or(ArithmeticError::Overflow)?; + weight += T::DbWeight::get().reads(1); - Self::make_native_bridge_balance_be(native_bridge_balance)?; + weight += Self::make_native_bridge_balance_be(native_bridge_balance)?; let native_total_issuance = T::NativeCurrency::total_issuance(); + weight += T::DbWeight::get().reads(1); + let native_swappable = native_total_issuance .checked_sub(&native_bridge_balance) .expect("native_total_issuance is greater than native_bridge_balance; qed."); @@ -138,14 +144,16 @@ impl Pallet { let evm_bridge_balance = evm_swap_reserved .checked_add(&T::EvmCurrency::minimum_balance()) .ok_or(ArithmeticError::Overflow)?; + weight += T::DbWeight::get().reads(1); - Self::make_evm_bridge_balance_be(evm_bridge_balance)?; + weight += Self::make_evm_bridge_balance_be(evm_bridge_balance)?; if !Self::is_balanced()? { return Err(Error::::NotBalanced.into()); } + weight += T::DbWeight::get().reads(8); - Ok(()) + Ok(weight) } /// Make native bridge balance be provided amount value. @@ -153,9 +161,10 @@ impl Pallet { /// The logic can change native swappable balance value. fn make_native_bridge_balance_be( amount: >::Balance, - ) -> Result<(), DispatchError> { + ) -> Result { let current_native_bridge_balance = T::NativeCurrency::total_balance(&T::NativeEvmBridgePot::get()); + let mut weight = T::DbWeight::get().reads(1); if current_native_bridge_balance == Zero::zero() { let imbalance = T::NativeCurrency::withdraw( @@ -164,9 +173,12 @@ impl Pallet { frame_support::traits::WithdrawReasons::TRANSFER, frame_support::traits::ExistenceRequirement::KeepAlive, )?; + weight += T::DbWeight::get().writes(1); + T::NativeCurrency::resolve_creating(&T::NativeEvmBridgePot::get(), imbalance); + weight += T::DbWeight::get().writes(1); - return Ok(()); + return Ok(weight); } match current_native_bridge_balance.cmp(&amount) { @@ -179,12 +191,15 @@ impl Pallet { frame_support::traits::WithdrawReasons::TRANSFER, frame_support::traits::ExistenceRequirement::KeepAlive, )?; + weight += T::DbWeight::get().writes(1); + // We can safely ignore the result as overflow cann't be reached. // current_native_bridge_balance < amount. The resulted balance is equal to amount. let _ = T::NativeCurrency::resolve_into_existing( &T::NativeEvmBridgePot::get(), imbalance, ); + weight += T::DbWeight::get().writes(1); } Ordering::Greater => { let imbalance = T::NativeCurrency::withdraw( @@ -195,6 +210,7 @@ impl Pallet { frame_support::traits::WithdrawReasons::TRANSFER, frame_support::traits::ExistenceRequirement::KeepAlive, )?; + weight += T::DbWeight::get().writes(1); // We can safely ignore the result as overflow cann't be reached. // current_native_bridge_balance + current_native_treasury < total_issuance. @@ -203,11 +219,12 @@ impl Pallet { &T::NativeTreasuryPot::get(), imbalance, ); + weight += T::DbWeight::get().writes(1); } Ordering::Equal => {} } - Ok(()) + Ok(weight) } /// Make evm bridge balance be provided amount value. @@ -215,15 +232,19 @@ impl Pallet { /// The logic shouldn't change evm swappable balance value. fn make_evm_bridge_balance_be( amount: >::Balance, - ) -> Result<(), DispatchError> { + ) -> Result { let current_evm_bridge_balance = T::EvmCurrency::total_balance(&T::EvmNativeBridgePot::get()); + let mut weight = T::DbWeight::get().reads(1); if current_evm_bridge_balance == Zero::zero() { let imbalance = T::EvmCurrency::issue(amount); + weight += T::DbWeight::get().writes(1); + T::EvmCurrency::resolve_creating(&T::EvmNativeBridgePot::get(), imbalance); + weight += T::DbWeight::get().writes(1); - return Ok(()); + return Ok(weight); } match current_evm_bridge_balance.cmp(&amount) { @@ -233,10 +254,13 @@ impl Pallet { .checked_sub(¤t_evm_bridge_balance) .expect("current_evm_bridge_balance is less than amount; qed."), ); + weight += T::DbWeight::get().writes(1); + // We can safely ignore the result as overflow cann't be reached. // current_evm_bridge_balance < amount. The resulted balance is equal to amount. let _ = T::EvmCurrency::resolve_into_existing(&T::EvmNativeBridgePot::get(), imbalance); + weight += T::DbWeight::get().writes(1); } Ordering::Greater => { let imbalance = T::EvmCurrency::burn( @@ -244,6 +268,8 @@ impl Pallet { .checked_sub(&amount) .expect("current_evm_bridge_balance is greater than amount; qed."), ); + weight += T::DbWeight::get().writes(1); + // We can safely ignore the result as underflow cann't be reached. // current_evm_bridge_balance > amount => imbalance < current_evm_bridge_balance. let _ = T::EvmCurrency::settle( @@ -252,10 +278,11 @@ impl Pallet { frame_support::traits::WithdrawReasons::RESERVE, frame_support::traits::ExistenceRequirement::KeepAlive, ); + weight += T::DbWeight::get().writes(1); } Ordering::Equal => {} } - Ok(()) + Ok(weight) } /// Verify currencies balanced requirements. From 71c31786fef83eeb0d3eaf7b59d9f0f97a8dd666 Mon Sep 17 00:00:00 2001 From: Dmitry Lavrenov Date: Tue, 8 Aug 2023 20:08:28 +0300 Subject: [PATCH 11/38] Add runtime-upgrade logic --- .../src/lib.rs | 87 +++++++++++++------ .../src/upgrade_init.rs | 33 +++++++ 2 files changed, 92 insertions(+), 28 deletions(-) create mode 100644 crates/pallet-bridges-initializer-currency-swap/src/upgrade_init.rs diff --git a/crates/pallet-bridges-initializer-currency-swap/src/lib.rs b/crates/pallet-bridges-initializer-currency-swap/src/lib.rs index 665d8370e..6b1434782 100644 --- a/crates/pallet-bridges-initializer-currency-swap/src/lib.rs +++ b/crates/pallet-bridges-initializer-currency-swap/src/lib.rs @@ -8,30 +8,38 @@ use frame_support::{ traits::{CheckedAdd, CheckedSub, Convert, Get, Zero}, ArithmeticError, DispatchError, }, - traits::{fungible, Currency}, + storage::with_storage_layer, + traits::{fungible, Currency, StorageVersion}, weights::Weight, }; pub use pallet::*; use sp_std::cmp::Ordering; +mod upgrade_init; + #[cfg(test)] mod mock; #[cfg(test)] mod tests; +/// The current storage version. +const STORAGE_VERSION: StorageVersion = StorageVersion::new(1); + // We have to temporarily allow some clippy lints. Later on we'll send patches to substrate to // fix them at their end. #[allow(clippy::missing_docs_in_private_items)] #[frame_support::pallet] pub mod pallet { use frame_support::{pallet_prelude::*, sp_runtime::traits::MaybeDisplay}; + use frame_system::pallet_prelude::*; use sp_std::fmt::Debug; use super::*; /// The Bridge Pot Currency Swap Initializer Pallet. #[pallet::pallet] + #[pallet::storage_version(STORAGE_VERSION)] #[pallet::generate_store(pub(super) trait Store)] pub struct Pallet(_); @@ -112,46 +120,69 @@ pub mod pallet { /// The currencies are not balanced. NotBalanced, } + + #[pallet::hooks] + impl Hooks> for Pallet { + fn on_runtime_upgrade() -> Weight { + upgrade_init::on_runtime_upgrade::() + } + + #[cfg(feature = "try-runtime")] + fn pre_upgrade() -> Result, &'static str> { + upgrade_init::pre_upgrade::() + } + + #[cfg(feature = "try-runtime")] + fn post_upgrade(state: Vec) -> Result<(), &'static str> { + upgrade_init::post_upgrade::() + } + } } impl Pallet { /// Initialize bridges pot accounts. pub fn initialize() -> Result { - let evm_total_issuance = T::EvmCurrency::total_issuance(); - let evm_bridge_balance = T::EvmCurrency::total_balance(&T::EvmNativeBridgePot::get()); - let mut weight = T::DbWeight::get().reads(2); + let mut weight = T::DbWeight::get().reads(0); - let evm_swappable = evm_total_issuance - .checked_sub(&evm_bridge_balance) - .expect("evm_total_issuance is greater than evm_bridge_balance; qed."); + with_storage_layer(move || { + let evm_total_issuance = T::EvmCurrency::total_issuance(); + let evm_bridge_balance = T::EvmCurrency::total_balance(&T::EvmNativeBridgePot::get()); + weight += T::DbWeight::get().reads(2); - let native_swap_reserved = T::BalanceConverterEvmToNative::convert(evm_swappable); - let native_bridge_balance = native_swap_reserved - .checked_add(&T::NativeCurrency::minimum_balance()) - .ok_or(ArithmeticError::Overflow)?; - weight += T::DbWeight::get().reads(1); + let evm_swappable = evm_total_issuance + .checked_sub(&evm_bridge_balance) + .expect("evm_total_issuance is greater than evm_bridge_balance; qed."); - weight += Self::make_native_bridge_balance_be(native_bridge_balance)?; + let native_swap_reserved = T::BalanceConverterEvmToNative::convert(evm_swappable); + let native_bridge_balance = native_swap_reserved + .checked_add(&T::NativeCurrency::minimum_balance()) + .ok_or(ArithmeticError::Overflow)?; + weight += T::DbWeight::get().reads(1); - let native_total_issuance = T::NativeCurrency::total_issuance(); - weight += T::DbWeight::get().reads(1); + weight += Self::make_native_bridge_balance_be(native_bridge_balance)?; - let native_swappable = native_total_issuance - .checked_sub(&native_bridge_balance) - .expect("native_total_issuance is greater than native_bridge_balance; qed."); + let native_total_issuance = T::NativeCurrency::total_issuance(); + weight += T::DbWeight::get().reads(1); - let evm_swap_reserved = T::BalanceConverterNativeToEvm::convert(native_swappable); - let evm_bridge_balance = evm_swap_reserved - .checked_add(&T::EvmCurrency::minimum_balance()) - .ok_or(ArithmeticError::Overflow)?; - weight += T::DbWeight::get().reads(1); + let native_swappable = native_total_issuance + .checked_sub(&native_bridge_balance) + .expect("native_total_issuance is greater than native_bridge_balance; qed."); - weight += Self::make_evm_bridge_balance_be(evm_bridge_balance)?; + let evm_swap_reserved = T::BalanceConverterNativeToEvm::convert(native_swappable); + let evm_bridge_balance = evm_swap_reserved + .checked_add(&T::EvmCurrency::minimum_balance()) + .ok_or(ArithmeticError::Overflow)?; + weight += T::DbWeight::get().reads(1); - if !Self::is_balanced()? { - return Err(Error::::NotBalanced.into()); - } - weight += T::DbWeight::get().reads(8); + weight += Self::make_evm_bridge_balance_be(evm_bridge_balance)?; + + if !Self::is_balanced()? { + return Err::<(), DispatchError>(Error::::NotBalanced.into()); + } + weight += T::DbWeight::get().reads(8); + + Ok(()) + })?; Ok(weight) } diff --git a/crates/pallet-bridges-initializer-currency-swap/src/upgrade_init.rs b/crates/pallet-bridges-initializer-currency-swap/src/upgrade_init.rs new file mode 100644 index 000000000..157e856d2 --- /dev/null +++ b/crates/pallet-bridges-initializer-currency-swap/src/upgrade_init.rs @@ -0,0 +1,33 @@ +//! Initialization of the bridge pot accounts on runtime upgrade. + +use frame_support::pallet_prelude::*; + +use crate::Pallet; + +/// Initialize the bridges pot accounts. +pub fn on_runtime_upgrade() -> Weight { + match Pallet::::initialize() { + Ok(weight) => weight, + Err(err) => panic!("error during bridges initialization: {err:?}"), + } +} + +/// Check the state before the bridges initialization. +/// +/// Panics if anything goes wrong. +#[cfg(feature = "try-runtime")] +pub fn pre_upgrade, I: 'static>() -> Result, &'static str> { + // do nothing +} + +/// Check the state after the bridges initialization. +/// +/// Panics if anything goes wrong. +#[cfg(feature = "try-runtime")] +pub fn post_upgrade, I: 'static>(state: Vec) -> Result<(), &'static str> { + if !Pallet::::is_balanced() { + return Err("currencies are not balanced"); + } + + Ok(()) +} From 2d04e2a2333b4d6196ffde1a00281cfca402ef68 Mon Sep 17 00:00:00 2001 From: Dmitry Lavrenov Date: Wed, 9 Aug 2023 11:32:11 +0300 Subject: [PATCH 12/38] Add runtime upgrade test --- .../src/mock/mod.rs | 4 + .../src/mock/v1.rs | 126 ++++++++++++++++++ .../src/{mock.rs => mock/v2.rs} | 4 +- .../src/tests.rs | 54 +++++++- 4 files changed, 184 insertions(+), 4 deletions(-) create mode 100644 crates/pallet-bridges-initializer-currency-swap/src/mock/mod.rs create mode 100644 crates/pallet-bridges-initializer-currency-swap/src/mock/v1.rs rename crates/pallet-bridges-initializer-currency-swap/src/{mock.rs => mock/v2.rs} (98%) diff --git a/crates/pallet-bridges-initializer-currency-swap/src/mock/mod.rs b/crates/pallet-bridges-initializer-currency-swap/src/mock/mod.rs new file mode 100644 index 000000000..38cf45c47 --- /dev/null +++ b/crates/pallet-bridges-initializer-currency-swap/src/mock/mod.rs @@ -0,0 +1,4 @@ +//! The mocks for the pallet testing. + +pub mod v1; +pub mod v2; diff --git a/crates/pallet-bridges-initializer-currency-swap/src/mock/v1.rs b/crates/pallet-bridges-initializer-currency-swap/src/mock/v1.rs new file mode 100644 index 000000000..b9bb48995 --- /dev/null +++ b/crates/pallet-bridges-initializer-currency-swap/src/mock/v1.rs @@ -0,0 +1,126 @@ +//! The v1 mock that represents just a case with two separate accounts system +//! without bridges initialization logic at runtime. + +// Allow simple integer arithmetic in tests. +#![allow(clippy::integer_arithmetic)] + +use frame_support::{ + parameter_types, sp_io, + sp_runtime::{ + testing::Header, + traits::{BlakeTwo256, IdentityLookup}, + BuildStorage, + }, + traits::{ConstU32, ConstU64, StorageMapShim}, +}; +use sp_core::H256; + +pub(crate) const EXISTENTIAL_DEPOSIT_NATIVE: u64 = 10; +pub(crate) const EXISTENTIAL_DEPOSIT_EVM: u64 = 20; + +type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; +type Block = frame_system::mocking::MockBlock; + +pub(crate) type AccountId = u64; +pub(crate) type EvmAccountId = u64; +type Balance = u64; + +frame_support::construct_runtime!( + pub enum Test where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system, + Balances: pallet_balances::, + EvmBalances: pallet_balances::, + } +); + +impl frame_system::Config for Test { + type BaseCallFilter = frame_support::traits::Everything; + type BlockWeights = (); + type BlockLength = (); + type DbWeight = (); + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + type Header = Header; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = ConstU64<250>; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = (); + type OnSetCode = (); + type MaxConsumers = ConstU32<16>; +} + +type BalancesInstanceNative = pallet_balances::Instance1; +type BalancesInstanceEvm = pallet_balances::Instance2; + +impl pallet_balances::Config for Test { + type Balance = u64; + type RuntimeEvent = RuntimeEvent; + type DustRemoval = (); + type ExistentialDeposit = ConstU64; + type AccountStore = System; + type MaxLocks = (); + type MaxReserves = (); + type ReserveIdentifier = [u8; 8]; + type WeightInfo = (); +} + +impl pallet_balances::Config for Test { + type Balance = u64; + type RuntimeEvent = RuntimeEvent; + type DustRemoval = (); + type ExistentialDeposit = ConstU64; + type AccountStore = StorageMapShim< + pallet_balances::Account, + frame_system::Provider, + EvmAccountId, + pallet_balances::AccountData, + >; + type MaxLocks = (); + type MaxReserves = (); + type ReserveIdentifier = [u8; 8]; + type WeightInfo = (); +} + +parameter_types! { + pub NativeTreasury: AccountId = 4200; +} + +// This function basically just builds a genesis storage key/value store according to +// our desired mockup. +pub fn new_test_ext_with(genesis_config: GenesisConfig) -> sp_io::TestExternalities { + let storage = genesis_config.build_storage().unwrap(); + storage.into() +} + +pub fn runtime_lock() -> std::sync::MutexGuard<'static, ()> { + static MOCK_RUNTIME_MUTEX: std::sync::Mutex<()> = std::sync::Mutex::new(()); + + // Ignore the poisoning for the tests that panic. + // We only care about concurrency here, not about the poisoning. + match MOCK_RUNTIME_MUTEX.lock() { + Ok(guard) => guard, + Err(poisoned) => poisoned.into_inner(), + } +} + +pub fn with_runtime_lock(f: impl FnOnce() -> R) -> R { + let lock = runtime_lock(); + let res = f(); + drop(lock); + res +} diff --git a/crates/pallet-bridges-initializer-currency-swap/src/mock.rs b/crates/pallet-bridges-initializer-currency-swap/src/mock/v2.rs similarity index 98% rename from crates/pallet-bridges-initializer-currency-swap/src/mock.rs rename to crates/pallet-bridges-initializer-currency-swap/src/mock/v2.rs index 3996030d5..6e9a69b23 100644 --- a/crates/pallet-bridges-initializer-currency-swap/src/mock.rs +++ b/crates/pallet-bridges-initializer-currency-swap/src/mock/v2.rs @@ -1,4 +1,4 @@ -//! The mock for the pallet. +//! The v2 mock that includes bridges initialization logic at runtime. // Allow simple integer arithmetic in tests. #![allow(clippy::integer_arithmetic)] @@ -92,7 +92,7 @@ impl pallet_balances::Config for Test { type AccountStore = StorageMapShim< pallet_balances::Account, frame_system::Provider, - AccountId, + EvmAccountId, pallet_balances::AccountData, >; type MaxLocks = (); diff --git a/crates/pallet-bridges-initializer-currency-swap/src/tests.rs b/crates/pallet-bridges-initializer-currency-swap/src/tests.rs index 704ccd079..719a5b6d3 100644 --- a/crates/pallet-bridges-initializer-currency-swap/src/tests.rs +++ b/crates/pallet-bridges-initializer-currency-swap/src/tests.rs @@ -1,6 +1,6 @@ -use frame_support::traits::Currency; +use frame_support::traits::{Currency, OnRuntimeUpgrade}; -use crate::mock::*; +use crate::mock::{v1, v2::*}; #[test] fn initialization_bridges_ed_works() { @@ -186,3 +186,53 @@ fn initialization_fails_treasury_insufficient_balance() { new_test_ext_with(config).execute_with(move || {}); }) } + +#[test] +fn runtime_upgrade() { + with_runtime_lock(|| { + v1::with_runtime_lock(|| { + let treasury = (NativeTreasury::get(), 1450); + let alice = (4201, 20); + let bob = (4203, 30); + + let lion = (4211, 200); + let dog = (4212, 300); + let cat = (4213, 400); + let fish = (4214, 500); + + let config = v1::GenesisConfig { + balances: pallet_balances::GenesisConfig { + balances: vec![treasury, alice, bob], + }, + evm_balances: pallet_balances::GenesisConfig { + balances: vec![lion, dog, cat, fish], + }, + ..Default::default() + }; + + let mut v1_ext = v1::new_test_ext_with(config); + v1_ext.execute_with(move || { + // Do runtime upgrade hook. + AllPalletsWithoutSystem::on_runtime_upgrade(); + + // Verify bridges initialization result. + assert!(EvmNativeBridgesInitializer::is_balanced().unwrap()); + assert_eq!( + Balances::total_balance(&SwapBridgeNativeToEvmPot::account_id()), + lion.1 + dog.1 + cat.1 + fish.1 + EXISTENTIAL_DEPOSIT_NATIVE + ); + assert_eq!( + Balances::total_balance(&NativeTreasury::get()), + treasury.1 - (lion.1 + dog.1 + cat.1 + fish.1 + EXISTENTIAL_DEPOSIT_NATIVE) + ); + assert_eq!( + EvmBalances::total_balance(&SwapBridgeEvmToNativePot::account_id(),), + Balances::total_balance(&NativeTreasury::get()) + + alice.1 + + bob.1 + + EXISTENTIAL_DEPOSIT_EVM + ); + }); + }) + }) +} From a80bb29f3e19794ce39bbe7b91bc037249604db6 Mon Sep 17 00:00:00 2001 From: Dmitry Lavrenov Date: Wed, 9 Aug 2023 11:47:49 +0300 Subject: [PATCH 13/38] Check is balanced before applying initialization --- Cargo.lock | 1 + .../Cargo.toml | 2 ++ .../src/lib.rs | 10 +++++++--- .../src/upgrade_init.rs | 13 ++++++++++--- 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 18ef362a6..d22821f5c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5912,6 +5912,7 @@ dependencies = [ "scale-info", "sp-core", "sp-std", + "sp-tracing", ] [[package]] diff --git a/crates/pallet-bridges-initializer-currency-swap/Cargo.toml b/crates/pallet-bridges-initializer-currency-swap/Cargo.toml index 3214ebc2b..9d4091cd0 100644 --- a/crates/pallet-bridges-initializer-currency-swap/Cargo.toml +++ b/crates/pallet-bridges-initializer-currency-swap/Cargo.toml @@ -10,6 +10,7 @@ frame-support = { default-features = false, git = "https://github.com/humanode-n frame-system = { default-features = false, git = "https://github.com/humanode-network/substrate", branch = "locked/polkadot-v0.9.38" } scale-info = { version = "2.5.0", default-features = false, features = ["derive"] } sp-std = { default-features = false, git = "https://github.com/humanode-network/substrate", branch = "locked/polkadot-v0.9.38" } +sp-tracing = { default-features = false, git = "https://github.com/humanode-network/substrate", branch = "locked/polkadot-v0.9.38" } [dev-dependencies] pallet-pot = { version = "0.1", path = "../pallet-pot", default-features = false } @@ -27,6 +28,7 @@ std = [ "pallet-pot/std", "scale-info/std", "sp-std/std", + "sp-tracing/std", ] try-runtime = [ "frame-support/try-runtime", diff --git a/crates/pallet-bridges-initializer-currency-swap/src/lib.rs b/crates/pallet-bridges-initializer-currency-swap/src/lib.rs index 6b1434782..5ea26119e 100644 --- a/crates/pallet-bridges-initializer-currency-swap/src/lib.rs +++ b/crates/pallet-bridges-initializer-currency-swap/src/lib.rs @@ -108,9 +108,13 @@ pub mod pallet { #[pallet::genesis_build] impl GenesisBuild for GenesisConfig { fn build(&self) { - match Pallet::::initialize() { - Ok(_) => {} - Err(err) => panic!("error during bridges initialization: {err:?}",), + let is_balanced = Pallet::::is_balanced().unwrap_or_default(); + + if !is_balanced { + match Pallet::::initialize() { + Ok(_) => {} + Err(err) => panic!("error during bridges initialization: {err:?}",), + } } } } diff --git a/crates/pallet-bridges-initializer-currency-swap/src/upgrade_init.rs b/crates/pallet-bridges-initializer-currency-swap/src/upgrade_init.rs index 157e856d2..0a021efbb 100644 --- a/crates/pallet-bridges-initializer-currency-swap/src/upgrade_init.rs +++ b/crates/pallet-bridges-initializer-currency-swap/src/upgrade_init.rs @@ -6,10 +6,17 @@ use crate::Pallet; /// Initialize the bridges pot accounts. pub fn on_runtime_upgrade() -> Weight { - match Pallet::::initialize() { - Ok(weight) => weight, - Err(err) => panic!("error during bridges initialization: {err:?}"), + let is_balanced = Pallet::::is_balanced().unwrap_or_default(); + let mut weight = T::DbWeight::get().reads(8); + + if !is_balanced { + match Pallet::::initialize() { + Ok(w) => weight += w, + Err(err) => sp_tracing::error!("error during bridges initialization: {err:?}"), + } } + + weight } /// Check the state before the bridges initialization. From 00cf8fca010529f5da7255f88be9b3e9c52770b7 Mon Sep 17 00:00:00 2001 From: Dmitry Lavrenov Date: Wed, 9 Aug 2023 12:01:14 +0300 Subject: [PATCH 14/38] Fix try-runtime feature related code --- .../src/lib.rs | 4 ++-- .../src/upgrade_init.rs | 13 +++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/crates/pallet-bridges-initializer-currency-swap/src/lib.rs b/crates/pallet-bridges-initializer-currency-swap/src/lib.rs index 5ea26119e..f845862b2 100644 --- a/crates/pallet-bridges-initializer-currency-swap/src/lib.rs +++ b/crates/pallet-bridges-initializer-currency-swap/src/lib.rs @@ -133,12 +133,12 @@ pub mod pallet { #[cfg(feature = "try-runtime")] fn pre_upgrade() -> Result, &'static str> { - upgrade_init::pre_upgrade::() + upgrade_init::pre_upgrade::() } #[cfg(feature = "try-runtime")] fn post_upgrade(state: Vec) -> Result<(), &'static str> { - upgrade_init::post_upgrade::() + upgrade_init::post_upgrade::(state) } } } diff --git a/crates/pallet-bridges-initializer-currency-swap/src/upgrade_init.rs b/crates/pallet-bridges-initializer-currency-swap/src/upgrade_init.rs index 0a021efbb..ea4d49cd5 100644 --- a/crates/pallet-bridges-initializer-currency-swap/src/upgrade_init.rs +++ b/crates/pallet-bridges-initializer-currency-swap/src/upgrade_init.rs @@ -2,10 +2,10 @@ use frame_support::pallet_prelude::*; -use crate::Pallet; +use crate::{Config, Pallet}; /// Initialize the bridges pot accounts. -pub fn on_runtime_upgrade() -> Weight { +pub fn on_runtime_upgrade() -> Weight { let is_balanced = Pallet::::is_balanced().unwrap_or_default(); let mut weight = T::DbWeight::get().reads(8); @@ -23,16 +23,17 @@ pub fn on_runtime_upgrade() -> Weight { /// /// Panics if anything goes wrong. #[cfg(feature = "try-runtime")] -pub fn pre_upgrade, I: 'static>() -> Result, &'static str> { - // do nothing +pub fn pre_upgrade() -> Result, &'static str> { + // Do nothing. + Ok(Vec::new()) } /// Check the state after the bridges initialization. /// /// Panics if anything goes wrong. #[cfg(feature = "try-runtime")] -pub fn post_upgrade, I: 'static>(state: Vec) -> Result<(), &'static str> { - if !Pallet::::is_balanced() { +pub fn post_upgrade(_state: Vec) -> Result<(), &'static str> { + if !Pallet::::is_balanced()? { return Err("currencies are not balanced"); } From 1ad81528f7473616c5d4eb07be38317ca50c6904 Mon Sep 17 00:00:00 2001 From: Dmitry Lavrenov Date: Wed, 9 Aug 2023 12:30:21 +0300 Subject: [PATCH 15/38] Rename pallet in mock --- .../pallet-bridges-initializer-currency-swap/src/mock/v2.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/pallet-bridges-initializer-currency-swap/src/mock/v2.rs b/crates/pallet-bridges-initializer-currency-swap/src/mock/v2.rs index 6e9a69b23..fef28f17e 100644 --- a/crates/pallet-bridges-initializer-currency-swap/src/mock/v2.rs +++ b/crates/pallet-bridges-initializer-currency-swap/src/mock/v2.rs @@ -15,7 +15,7 @@ use frame_support::{ }; use sp_core::H256; -use crate::{self as pallet_bridges_init_currency_swap}; +use crate::{self as pallet_bridges_initializer_currency_swap}; pub(crate) const EXISTENTIAL_DEPOSIT_NATIVE: u64 = 10; pub(crate) const EXISTENTIAL_DEPOSIT_EVM: u64 = 20; @@ -38,7 +38,7 @@ frame_support::construct_runtime!( EvmBalances: pallet_balances::, SwapBridgeNativeToEvmPot: pallet_pot::, SwapBridgeEvmToNativePot: pallet_pot::, - EvmNativeBridgesInitializer: pallet_bridges_init_currency_swap, + EvmNativeBridgesInitializer: pallet_bridges_initializer_currency_swap, } ); @@ -137,7 +137,7 @@ parameter_types! { pub NativeTreasury: AccountId = 4200; } -impl pallet_bridges_init_currency_swap::Config for Test { +impl pallet_bridges_initializer_currency_swap::Config for Test { type EvmAccountId = EvmAccountId; type NativeCurrency = Balances; type EvmCurrency = EvmBalances; From 55ad986186808aad0dc49816ce9b07638f84329e Mon Sep 17 00:00:00 2001 From: Dmitry Lavrenov Date: Wed, 9 Aug 2023 20:19:38 +0300 Subject: [PATCH 16/38] Use runtime_lock and externalities logic as shared components --- .../src/mock/mod.rs | 44 ++++++++++ .../src/mock/v1.rs | 41 +-------- .../src/mock/v2.rs | 44 +--------- .../src/tests.rs | 88 +++++++++---------- 4 files changed, 90 insertions(+), 127 deletions(-) diff --git a/crates/pallet-bridges-initializer-currency-swap/src/mock/mod.rs b/crates/pallet-bridges-initializer-currency-swap/src/mock/mod.rs index 38cf45c47..3f1c97627 100644 --- a/crates/pallet-bridges-initializer-currency-swap/src/mock/mod.rs +++ b/crates/pallet-bridges-initializer-currency-swap/src/mock/mod.rs @@ -1,4 +1,48 @@ //! The mocks for the pallet testing. +use frame_support::{parameter_types, sp_io, sp_runtime::BuildStorage}; + +use crate::{self as pallet_bridges_initializer_currency_swap}; + pub mod v1; pub mod v2; + +pub(crate) const EXISTENTIAL_DEPOSIT_NATIVE: u64 = 10; +pub(crate) const EXISTENTIAL_DEPOSIT_EVM: u64 = 20; + +pub(crate) type AccountId = u64; +pub(crate) type EvmAccountId = u64; + +type Balance = u64; + +type BalancesInstanceNative = pallet_balances::Instance1; +type BalancesInstanceEvm = pallet_balances::Instance2; + +parameter_types! { + pub NativeTreasury: AccountId = 4200; +} + +// This function basically just builds a genesis storage key/value store according to +// our desired mockup. +pub fn new_test_ext_with(genesis_config: impl BuildStorage) -> sp_io::TestExternalities { + let storage = genesis_config.build_storage().unwrap(); + storage.into() +} + +pub fn runtime_lock() -> std::sync::MutexGuard<'static, ()> { + static MOCK_RUNTIME_MUTEX: std::sync::Mutex<()> = std::sync::Mutex::new(()); + + // Ignore the poisoning for the tests that panic. + // We only care about concurrency here, not about the poisoning. + match MOCK_RUNTIME_MUTEX.lock() { + Ok(guard) => guard, + Err(poisoned) => poisoned.into_inner(), + } +} + +pub fn with_runtime_lock(f: impl FnOnce() -> R) -> R { + let lock = runtime_lock(); + let res = f(); + drop(lock); + res +} diff --git a/crates/pallet-bridges-initializer-currency-swap/src/mock/v1.rs b/crates/pallet-bridges-initializer-currency-swap/src/mock/v1.rs index b9bb48995..4a065e679 100644 --- a/crates/pallet-bridges-initializer-currency-swap/src/mock/v1.rs +++ b/crates/pallet-bridges-initializer-currency-swap/src/mock/v1.rs @@ -5,26 +5,19 @@ #![allow(clippy::integer_arithmetic)] use frame_support::{ - parameter_types, sp_io, sp_runtime::{ testing::Header, traits::{BlakeTwo256, IdentityLookup}, - BuildStorage, }, traits::{ConstU32, ConstU64, StorageMapShim}, }; use sp_core::H256; -pub(crate) const EXISTENTIAL_DEPOSIT_NATIVE: u64 = 10; -pub(crate) const EXISTENTIAL_DEPOSIT_EVM: u64 = 20; +use super::*; type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; type Block = frame_system::mocking::MockBlock; -pub(crate) type AccountId = u64; -pub(crate) type EvmAccountId = u64; -type Balance = u64; - frame_support::construct_runtime!( pub enum Test where Block = Block, @@ -64,9 +57,6 @@ impl frame_system::Config for Test { type MaxConsumers = ConstU32<16>; } -type BalancesInstanceNative = pallet_balances::Instance1; -type BalancesInstanceEvm = pallet_balances::Instance2; - impl pallet_balances::Config for Test { type Balance = u64; type RuntimeEvent = RuntimeEvent; @@ -95,32 +85,3 @@ impl pallet_balances::Config for Test { type ReserveIdentifier = [u8; 8]; type WeightInfo = (); } - -parameter_types! { - pub NativeTreasury: AccountId = 4200; -} - -// This function basically just builds a genesis storage key/value store according to -// our desired mockup. -pub fn new_test_ext_with(genesis_config: GenesisConfig) -> sp_io::TestExternalities { - let storage = genesis_config.build_storage().unwrap(); - storage.into() -} - -pub fn runtime_lock() -> std::sync::MutexGuard<'static, ()> { - static MOCK_RUNTIME_MUTEX: std::sync::Mutex<()> = std::sync::Mutex::new(()); - - // Ignore the poisoning for the tests that panic. - // We only care about concurrency here, not about the poisoning. - match MOCK_RUNTIME_MUTEX.lock() { - Ok(guard) => guard, - Err(poisoned) => poisoned.into_inner(), - } -} - -pub fn with_runtime_lock(f: impl FnOnce() -> R) -> R { - let lock = runtime_lock(); - let res = f(); - drop(lock); - res -} diff --git a/crates/pallet-bridges-initializer-currency-swap/src/mock/v2.rs b/crates/pallet-bridges-initializer-currency-swap/src/mock/v2.rs index fef28f17e..2d8aaa4bf 100644 --- a/crates/pallet-bridges-initializer-currency-swap/src/mock/v2.rs +++ b/crates/pallet-bridges-initializer-currency-swap/src/mock/v2.rs @@ -4,29 +4,21 @@ #![allow(clippy::integer_arithmetic)] use frame_support::{ - parameter_types, sp_io, + parameter_types, sp_runtime::{ testing::Header, traits::{BlakeTwo256, Identity, IdentityLookup}, - BuildStorage, }, traits::{ConstU32, ConstU64, StorageMapShim}, PalletId, }; use sp_core::H256; -use crate::{self as pallet_bridges_initializer_currency_swap}; - -pub(crate) const EXISTENTIAL_DEPOSIT_NATIVE: u64 = 10; -pub(crate) const EXISTENTIAL_DEPOSIT_EVM: u64 = 20; +use super::*; type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; type Block = frame_system::mocking::MockBlock; -pub(crate) type AccountId = u64; -pub(crate) type EvmAccountId = u64; -type Balance = u64; - frame_support::construct_runtime!( pub enum Test where Block = Block, @@ -69,9 +61,6 @@ impl frame_system::Config for Test { type MaxConsumers = ConstU32<16>; } -type BalancesInstanceNative = pallet_balances::Instance1; -type BalancesInstanceEvm = pallet_balances::Instance2; - impl pallet_balances::Config for Test { type Balance = u64; type RuntimeEvent = RuntimeEvent; @@ -133,10 +122,6 @@ parameter_types! { pub SwapBridgeEvmToNativePotAccountId: AccountId = SwapBridgeEvmToNativePot::account_id(); } -parameter_types! { - pub NativeTreasury: AccountId = 4200; -} - impl pallet_bridges_initializer_currency_swap::Config for Test { type EvmAccountId = EvmAccountId; type NativeCurrency = Balances; @@ -147,28 +132,3 @@ impl pallet_bridges_initializer_currency_swap::Config for Test { type NativeTreasuryPot = NativeTreasury; type EvmNativeBridgePot = SwapBridgeEvmToNativePotAccountId; } - -// This function basically just builds a genesis storage key/value store according to -// our desired mockup. -pub fn new_test_ext_with(genesis_config: GenesisConfig) -> sp_io::TestExternalities { - let storage = genesis_config.build_storage().unwrap(); - storage.into() -} - -pub fn runtime_lock() -> std::sync::MutexGuard<'static, ()> { - static MOCK_RUNTIME_MUTEX: std::sync::Mutex<()> = std::sync::Mutex::new(()); - - // Ignore the poisoning for the tests that panic. - // We only care about concurrency here, not about the poisoning. - match MOCK_RUNTIME_MUTEX.lock() { - Ok(guard) => guard, - Err(poisoned) => poisoned.into_inner(), - } -} - -pub fn with_runtime_lock(f: impl FnOnce() -> R) -> R { - let lock = runtime_lock(); - let res = f(); - drop(lock); - res -} diff --git a/crates/pallet-bridges-initializer-currency-swap/src/tests.rs b/crates/pallet-bridges-initializer-currency-swap/src/tests.rs index 719a5b6d3..829a35b47 100644 --- a/crates/pallet-bridges-initializer-currency-swap/src/tests.rs +++ b/crates/pallet-bridges-initializer-currency-swap/src/tests.rs @@ -1,6 +1,6 @@ use frame_support::traits::{Currency, OnRuntimeUpgrade}; -use crate::mock::{v1, v2::*}; +use crate::mock::{new_test_ext_with, v1, v2::*, with_runtime_lock, *}; #[test] fn initialization_bridges_ed_works() { @@ -190,49 +190,47 @@ fn initialization_fails_treasury_insufficient_balance() { #[test] fn runtime_upgrade() { with_runtime_lock(|| { - v1::with_runtime_lock(|| { - let treasury = (NativeTreasury::get(), 1450); - let alice = (4201, 20); - let bob = (4203, 30); - - let lion = (4211, 200); - let dog = (4212, 300); - let cat = (4213, 400); - let fish = (4214, 500); - - let config = v1::GenesisConfig { - balances: pallet_balances::GenesisConfig { - balances: vec![treasury, alice, bob], - }, - evm_balances: pallet_balances::GenesisConfig { - balances: vec![lion, dog, cat, fish], - }, - ..Default::default() - }; - - let mut v1_ext = v1::new_test_ext_with(config); - v1_ext.execute_with(move || { - // Do runtime upgrade hook. - AllPalletsWithoutSystem::on_runtime_upgrade(); - - // Verify bridges initialization result. - assert!(EvmNativeBridgesInitializer::is_balanced().unwrap()); - assert_eq!( - Balances::total_balance(&SwapBridgeNativeToEvmPot::account_id()), - lion.1 + dog.1 + cat.1 + fish.1 + EXISTENTIAL_DEPOSIT_NATIVE - ); - assert_eq!( - Balances::total_balance(&NativeTreasury::get()), - treasury.1 - (lion.1 + dog.1 + cat.1 + fish.1 + EXISTENTIAL_DEPOSIT_NATIVE) - ); - assert_eq!( - EvmBalances::total_balance(&SwapBridgeEvmToNativePot::account_id(),), - Balances::total_balance(&NativeTreasury::get()) - + alice.1 - + bob.1 - + EXISTENTIAL_DEPOSIT_EVM - ); - }); - }) + let treasury = (NativeTreasury::get(), 1450); + let alice = (4201, 20); + let bob = (4203, 30); + + let lion = (4211, 200); + let dog = (4212, 300); + let cat = (4213, 400); + let fish = (4214, 500); + + let config = v1::GenesisConfig { + balances: pallet_balances::GenesisConfig { + balances: vec![treasury, alice, bob], + }, + evm_balances: pallet_balances::GenesisConfig { + balances: vec![lion, dog, cat, fish], + }, + ..Default::default() + }; + + let mut v1_ext = new_test_ext_with(config); + v1_ext.execute_with(move || { + // Do runtime upgrade hook. + AllPalletsWithoutSystem::on_runtime_upgrade(); + + // Verify bridges initialization result. + assert!(EvmNativeBridgesInitializer::is_balanced().unwrap()); + assert_eq!( + Balances::total_balance(&SwapBridgeNativeToEvmPot::account_id()), + lion.1 + dog.1 + cat.1 + fish.1 + EXISTENTIAL_DEPOSIT_NATIVE + ); + assert_eq!( + Balances::total_balance(&NativeTreasury::get()), + treasury.1 - (lion.1 + dog.1 + cat.1 + fish.1 + EXISTENTIAL_DEPOSIT_NATIVE) + ); + assert_eq!( + EvmBalances::total_balance(&SwapBridgeEvmToNativePot::account_id(),), + Balances::total_balance(&NativeTreasury::get()) + + alice.1 + + bob.1 + + EXISTENTIAL_DEPOSIT_EVM + ); + }); }) } From 421ef86442344cb25ff3c54d8fd9898e50afad1f Mon Sep 17 00:00:00 2001 From: Dmitry Lavrenov Date: Wed, 9 Aug 2023 20:39:53 +0300 Subject: [PATCH 17/38] More explicit mocks usage in tests --- .../src/tests.rs | 69 +++++++++++-------- 1 file changed, 39 insertions(+), 30 deletions(-) diff --git a/crates/pallet-bridges-initializer-currency-swap/src/tests.rs b/crates/pallet-bridges-initializer-currency-swap/src/tests.rs index 829a35b47..4dd771b12 100644 --- a/crates/pallet-bridges-initializer-currency-swap/src/tests.rs +++ b/crates/pallet-bridges-initializer-currency-swap/src/tests.rs @@ -1,6 +1,6 @@ use frame_support::traits::{Currency, OnRuntimeUpgrade}; -use crate::mock::{new_test_ext_with, v1, v2::*, with_runtime_lock, *}; +use crate::mock::{new_test_ext_with, v1, v2, with_runtime_lock, *}; #[test] fn initialization_bridges_ed_works() { @@ -9,7 +9,7 @@ fn initialization_bridges_ed_works() { let alice = (4201, 20); let bob = (4203, 30); let swap_bridge_native_evm = ( - SwapBridgeNativeToEvmPot::account_id(), + v2::SwapBridgeNativeToEvmPot::account_id(), EXISTENTIAL_DEPOSIT_NATIVE, ); @@ -18,11 +18,11 @@ fn initialization_bridges_ed_works() { let cat = (4213, 400); let fish = (4214, 500); let swap_bridge_evm_native = ( - SwapBridgeEvmToNativePot::account_id(), + v2::SwapBridgeEvmToNativePot::account_id(), EXISTENTIAL_DEPOSIT_EVM, ); - let config = GenesisConfig { + let config = v2::GenesisConfig { balances: pallet_balances::GenesisConfig { balances: vec![treasury, alice, bob, swap_bridge_native_evm], }, @@ -39,16 +39,16 @@ fn initialization_bridges_ed_works() { }; new_test_ext_with(config).execute_with(move || { assert_eq!( - Balances::total_balance(&SwapBridgeNativeToEvmPot::account_id()), + v2::Balances::total_balance(&v2::SwapBridgeNativeToEvmPot::account_id()), lion.1 + dog.1 + cat.1 + fish.1 + EXISTENTIAL_DEPOSIT_NATIVE ); assert_eq!( - Balances::total_balance(&NativeTreasury::get()), + v2::Balances::total_balance(&NativeTreasury::get()), treasury.1 - (lion.1 + dog.1 + cat.1 + fish.1) ); assert_eq!( - EvmBalances::total_balance(&SwapBridgeEvmToNativePot::account_id(),), - Balances::total_balance(&NativeTreasury::get()) + v2::EvmBalances::total_balance(&v2::SwapBridgeEvmToNativePot::account_id(),), + v2::Balances::total_balance(&NativeTreasury::get()) + alice.1 + bob.1 + EXISTENTIAL_DEPOSIT_EVM @@ -65,7 +65,7 @@ fn initialization_bridges_ed_delta_works() { let bob = (4203, 30); let native_bridge_delta = 100; let swap_bridge_native_evm = ( - SwapBridgeNativeToEvmPot::account_id(), + v2::SwapBridgeNativeToEvmPot::account_id(), EXISTENTIAL_DEPOSIT_NATIVE + native_bridge_delta, ); @@ -75,11 +75,11 @@ fn initialization_bridges_ed_delta_works() { let fish = (4214, 500); let evm_bridge_delta = 50; let swap_bridge_evm_native = ( - SwapBridgeEvmToNativePot::account_id(), + v2::SwapBridgeEvmToNativePot::account_id(), EXISTENTIAL_DEPOSIT_EVM + evm_bridge_delta, ); - let config = GenesisConfig { + let config = v2::GenesisConfig { balances: pallet_balances::GenesisConfig { balances: vec![treasury, alice, bob, swap_bridge_native_evm], }, @@ -96,16 +96,16 @@ fn initialization_bridges_ed_delta_works() { }; new_test_ext_with(config).execute_with(move || { assert_eq!( - Balances::total_balance(&SwapBridgeNativeToEvmPot::account_id()), + v2::Balances::total_balance(&v2::SwapBridgeNativeToEvmPot::account_id()), lion.1 + dog.1 + cat.1 + fish.1 + EXISTENTIAL_DEPOSIT_NATIVE ); assert_eq!( - Balances::total_balance(&NativeTreasury::get()), + v2::Balances::total_balance(&NativeTreasury::get()), treasury.1 - (lion.1 + dog.1 + cat.1 + fish.1) + native_bridge_delta ); assert_eq!( - EvmBalances::total_balance(&SwapBridgeEvmToNativePot::account_id(),), - Balances::total_balance(&NativeTreasury::get()) + v2::EvmBalances::total_balance(&v2::SwapBridgeEvmToNativePot::account_id(),), + v2::Balances::total_balance(&NativeTreasury::get()) + alice.1 + bob.1 + EXISTENTIAL_DEPOSIT_EVM @@ -120,16 +120,16 @@ fn initialization_fails_overflow() { with_runtime_lock(|| { let treasury = (NativeTreasury::get(), EXISTENTIAL_DEPOSIT_NATIVE); let swap_bridge_native_evm = ( - SwapBridgeNativeToEvmPot::account_id(), + v2::SwapBridgeNativeToEvmPot::account_id(), u64::MAX - EXISTENTIAL_DEPOSIT_NATIVE, ); let swap_bridge_evm_native = ( - SwapBridgeEvmToNativePot::account_id(), + v2::SwapBridgeEvmToNativePot::account_id(), EXISTENTIAL_DEPOSIT_EVM, ); - let config = GenesisConfig { + let config = v2::GenesisConfig { balances: pallet_balances::GenesisConfig { balances: vec![treasury, swap_bridge_native_evm], }, @@ -154,7 +154,7 @@ fn initialization_fails_treasury_insufficient_balance() { with_runtime_lock(|| { let treasury = (NativeTreasury::get(), EXISTENTIAL_DEPOSIT_NATIVE + 10); let swap_bridge_native_evm = ( - SwapBridgeNativeToEvmPot::account_id(), + v2::SwapBridgeNativeToEvmPot::account_id(), EXISTENTIAL_DEPOSIT_NATIVE, ); @@ -164,11 +164,11 @@ fn initialization_fails_treasury_insufficient_balance() { let fish = (4214, 500); let evm_bridge_delta = 50; let swap_bridge_evm_native = ( - SwapBridgeEvmToNativePot::account_id(), + v2::SwapBridgeEvmToNativePot::account_id(), EXISTENTIAL_DEPOSIT_EVM + evm_bridge_delta, ); - let config = GenesisConfig { + let config = v2::GenesisConfig { balances: pallet_balances::GenesisConfig { balances: vec![treasury, swap_bridge_native_evm], }, @@ -199,7 +199,7 @@ fn runtime_upgrade() { let cat = (4213, 400); let fish = (4214, 500); - let config = v1::GenesisConfig { + let v1_config = v1::GenesisConfig { balances: pallet_balances::GenesisConfig { balances: vec![treasury, alice, bob], }, @@ -209,24 +209,33 @@ fn runtime_upgrade() { ..Default::default() }; - let mut v1_ext = new_test_ext_with(config); - v1_ext.execute_with(move || { + new_test_ext_with(v1_config).execute_with(move || { + // Check test preconditions. + assert_eq!( + v2::Balances::total_balance(&v2::SwapBridgeNativeToEvmPot::account_id()), + 0 + ); + assert_eq!( + v2::Balances::total_balance(&v2::SwapBridgeEvmToNativePot::account_id()), + 0 + ); + // Do runtime upgrade hook. - AllPalletsWithoutSystem::on_runtime_upgrade(); + v2::AllPalletsWithoutSystem::on_runtime_upgrade(); // Verify bridges initialization result. - assert!(EvmNativeBridgesInitializer::is_balanced().unwrap()); + assert!(v2::EvmNativeBridgesInitializer::is_balanced().unwrap()); assert_eq!( - Balances::total_balance(&SwapBridgeNativeToEvmPot::account_id()), + v2::Balances::total_balance(&v2::SwapBridgeNativeToEvmPot::account_id()), lion.1 + dog.1 + cat.1 + fish.1 + EXISTENTIAL_DEPOSIT_NATIVE ); assert_eq!( - Balances::total_balance(&NativeTreasury::get()), + v2::Balances::total_balance(&NativeTreasury::get()), treasury.1 - (lion.1 + dog.1 + cat.1 + fish.1 + EXISTENTIAL_DEPOSIT_NATIVE) ); assert_eq!( - EvmBalances::total_balance(&SwapBridgeEvmToNativePot::account_id(),), - Balances::total_balance(&NativeTreasury::get()) + v2::EvmBalances::total_balance(&v2::SwapBridgeEvmToNativePot::account_id(),), + v2::Balances::total_balance(&NativeTreasury::get()) + alice.1 + bob.1 + EXISTENTIAL_DEPOSIT_EVM From 28836f8115145581c0595c9fbc497ee92b326807 Mon Sep 17 00:00:00 2001 From: Dmitry Lavrenov Date: Wed, 9 Aug 2023 22:02:33 +0300 Subject: [PATCH 18/38] Use a struct type for address/balance pair in tests --- .../src/mock/mod.rs | 42 ++++ .../src/tests.rs | 208 +++++++++++------- 2 files changed, 165 insertions(+), 85 deletions(-) diff --git a/crates/pallet-bridges-initializer-currency-swap/src/mock/mod.rs b/crates/pallet-bridges-initializer-currency-swap/src/mock/mod.rs index 3f1c97627..71755e320 100644 --- a/crates/pallet-bridges-initializer-currency-swap/src/mock/mod.rs +++ b/crates/pallet-bridges-initializer-currency-swap/src/mock/mod.rs @@ -46,3 +46,45 @@ pub fn with_runtime_lock(f: impl FnOnce() -> R) -> R { drop(lock); res } + +#[derive(Clone, Copy)] +pub(crate) struct AccountInfo { + pub account: u64, + pub balance: u64, +} + +impl From for (u64, u64) { + fn from(account_info: AccountInfo) -> Self { + (account_info.account, account_info.balance) + } +} + +pub(crate) const ALICE: AccountInfo = AccountInfo { + account: 4201, + balance: 20, +}; + +pub(crate) const BOB: AccountInfo = AccountInfo { + account: 4202, + balance: 30, +}; + +pub(crate) const LION: AccountInfo = AccountInfo { + account: 4211, + balance: 200, +}; + +pub(crate) const DOG: AccountInfo = AccountInfo { + account: 4212, + balance: 300, +}; + +pub(crate) const CAT: AccountInfo = AccountInfo { + account: 4213, + balance: 400, +}; + +pub(crate) const FISH: AccountInfo = AccountInfo { + account: 4214, + balance: 500, +}; diff --git a/crates/pallet-bridges-initializer-currency-swap/src/tests.rs b/crates/pallet-bridges-initializer-currency-swap/src/tests.rs index 4dd771b12..0ccd52d32 100644 --- a/crates/pallet-bridges-initializer-currency-swap/src/tests.rs +++ b/crates/pallet-bridges-initializer-currency-swap/src/tests.rs @@ -5,29 +5,37 @@ use crate::mock::{new_test_ext_with, v1, v2, with_runtime_lock, *}; #[test] fn initialization_bridges_ed_works() { with_runtime_lock(|| { - let treasury = (NativeTreasury::get(), 1450); - let alice = (4201, 20); - let bob = (4203, 30); - let swap_bridge_native_evm = ( - v2::SwapBridgeNativeToEvmPot::account_id(), - EXISTENTIAL_DEPOSIT_NATIVE, - ); - - let lion = (4211, 200); - let dog = (4212, 300); - let cat = (4213, 400); - let fish = (4214, 500); - let swap_bridge_evm_native = ( - v2::SwapBridgeEvmToNativePot::account_id(), - EXISTENTIAL_DEPOSIT_EVM, - ); + let treasury = AccountInfo { + account: NativeTreasury::get(), + balance: 1450, + }; + let swap_bridge_native_evm = AccountInfo { + account: v2::SwapBridgeNativeToEvmPot::account_id(), + balance: EXISTENTIAL_DEPOSIT_NATIVE, + }; + + let swap_bridge_evm_native = AccountInfo { + account: v2::SwapBridgeEvmToNativePot::account_id(), + balance: EXISTENTIAL_DEPOSIT_EVM, + }; let config = v2::GenesisConfig { balances: pallet_balances::GenesisConfig { - balances: vec![treasury, alice, bob, swap_bridge_native_evm], + balances: vec![ + treasury.into(), + ALICE.into(), + BOB.into(), + swap_bridge_native_evm.into(), + ], }, evm_balances: pallet_balances::GenesisConfig { - balances: vec![lion, dog, cat, fish, swap_bridge_evm_native], + balances: vec![ + LION.into(), + DOG.into(), + CAT.into(), + FISH.into(), + swap_bridge_evm_native.into(), + ], }, swap_bridge_native_to_evm_pot: pallet_pot::GenesisConfig { initial_state: pallet_pot::InitialState::Initialized, @@ -40,17 +48,21 @@ fn initialization_bridges_ed_works() { new_test_ext_with(config).execute_with(move || { assert_eq!( v2::Balances::total_balance(&v2::SwapBridgeNativeToEvmPot::account_id()), - lion.1 + dog.1 + cat.1 + fish.1 + EXISTENTIAL_DEPOSIT_NATIVE + LION.balance + + DOG.balance + + CAT.balance + + FISH.balance + + EXISTENTIAL_DEPOSIT_NATIVE ); assert_eq!( v2::Balances::total_balance(&NativeTreasury::get()), - treasury.1 - (lion.1 + dog.1 + cat.1 + fish.1) + treasury.balance - (LION.balance + DOG.balance + CAT.balance + FISH.balance) ); assert_eq!( v2::EvmBalances::total_balance(&v2::SwapBridgeEvmToNativePot::account_id(),), v2::Balances::total_balance(&NativeTreasury::get()) - + alice.1 - + bob.1 + + ALICE.balance + + BOB.balance + EXISTENTIAL_DEPOSIT_EVM ); }); @@ -60,31 +72,39 @@ fn initialization_bridges_ed_works() { #[test] fn initialization_bridges_ed_delta_works() { with_runtime_lock(|| { - let treasury = (NativeTreasury::get(), 1450); - let alice = (4201, 20); - let bob = (4203, 30); + let treasury = AccountInfo { + account: NativeTreasury::get(), + balance: 1450, + }; let native_bridge_delta = 100; - let swap_bridge_native_evm = ( - v2::SwapBridgeNativeToEvmPot::account_id(), - EXISTENTIAL_DEPOSIT_NATIVE + native_bridge_delta, - ); - - let lion = (4211, 200); - let dog = (4212, 300); - let cat = (4213, 400); - let fish = (4214, 500); + let swap_bridge_native_evm = AccountInfo { + account: v2::SwapBridgeNativeToEvmPot::account_id(), + balance: EXISTENTIAL_DEPOSIT_NATIVE + native_bridge_delta, + }; + let evm_bridge_delta = 50; - let swap_bridge_evm_native = ( - v2::SwapBridgeEvmToNativePot::account_id(), - EXISTENTIAL_DEPOSIT_EVM + evm_bridge_delta, - ); + let swap_bridge_evm_native = AccountInfo { + account: v2::SwapBridgeEvmToNativePot::account_id(), + balance: EXISTENTIAL_DEPOSIT_EVM + evm_bridge_delta, + }; let config = v2::GenesisConfig { balances: pallet_balances::GenesisConfig { - balances: vec![treasury, alice, bob, swap_bridge_native_evm], + balances: vec![ + treasury.into(), + ALICE.into(), + BOB.into(), + swap_bridge_native_evm.into(), + ], }, evm_balances: pallet_balances::GenesisConfig { - balances: vec![lion, dog, cat, fish, swap_bridge_evm_native], + balances: vec![ + LION.into(), + DOG.into(), + CAT.into(), + FISH.into(), + swap_bridge_evm_native.into(), + ], }, swap_bridge_native_to_evm_pot: pallet_pot::GenesisConfig { initial_state: pallet_pot::InitialState::Initialized, @@ -97,17 +117,22 @@ fn initialization_bridges_ed_delta_works() { new_test_ext_with(config).execute_with(move || { assert_eq!( v2::Balances::total_balance(&v2::SwapBridgeNativeToEvmPot::account_id()), - lion.1 + dog.1 + cat.1 + fish.1 + EXISTENTIAL_DEPOSIT_NATIVE + LION.balance + + DOG.balance + + CAT.balance + + FISH.balance + + EXISTENTIAL_DEPOSIT_NATIVE ); assert_eq!( v2::Balances::total_balance(&NativeTreasury::get()), - treasury.1 - (lion.1 + dog.1 + cat.1 + fish.1) + native_bridge_delta + treasury.balance - (LION.balance + DOG.balance + CAT.balance + FISH.balance) + + native_bridge_delta ); assert_eq!( v2::EvmBalances::total_balance(&v2::SwapBridgeEvmToNativePot::account_id(),), v2::Balances::total_balance(&NativeTreasury::get()) - + alice.1 - + bob.1 + + ALICE.balance + + BOB.balance + EXISTENTIAL_DEPOSIT_EVM ); }); @@ -118,23 +143,26 @@ fn initialization_bridges_ed_delta_works() { #[should_panic = "error during bridges initialization: Arithmetic(Overflow)"] fn initialization_fails_overflow() { with_runtime_lock(|| { - let treasury = (NativeTreasury::get(), EXISTENTIAL_DEPOSIT_NATIVE); - let swap_bridge_native_evm = ( - v2::SwapBridgeNativeToEvmPot::account_id(), - u64::MAX - EXISTENTIAL_DEPOSIT_NATIVE, - ); + let treasury = AccountInfo { + account: NativeTreasury::get(), + balance: EXISTENTIAL_DEPOSIT_NATIVE, + }; + let swap_bridge_native_evm = AccountInfo { + account: v2::SwapBridgeNativeToEvmPot::account_id(), + balance: u64::MAX - EXISTENTIAL_DEPOSIT_NATIVE, + }; - let swap_bridge_evm_native = ( - v2::SwapBridgeEvmToNativePot::account_id(), - EXISTENTIAL_DEPOSIT_EVM, - ); + let swap_bridge_evm_native = AccountInfo { + account: v2::SwapBridgeEvmToNativePot::account_id(), + balance: EXISTENTIAL_DEPOSIT_EVM, + }; let config = v2::GenesisConfig { balances: pallet_balances::GenesisConfig { - balances: vec![treasury, swap_bridge_native_evm], + balances: vec![treasury.into(), swap_bridge_native_evm.into()], }, evm_balances: pallet_balances::GenesisConfig { - balances: vec![swap_bridge_evm_native], + balances: vec![swap_bridge_evm_native.into()], }, swap_bridge_native_to_evm_pot: pallet_pot::GenesisConfig { initial_state: pallet_pot::InitialState::Initialized, @@ -152,28 +180,33 @@ fn initialization_fails_overflow() { #[should_panic = "error during bridges initialization: Module(ModuleError { index: 1, error: [2, 0, 0, 0], message: Some(\"InsufficientBalance\") })"] fn initialization_fails_treasury_insufficient_balance() { with_runtime_lock(|| { - let treasury = (NativeTreasury::get(), EXISTENTIAL_DEPOSIT_NATIVE + 10); - let swap_bridge_native_evm = ( - v2::SwapBridgeNativeToEvmPot::account_id(), - EXISTENTIAL_DEPOSIT_NATIVE, - ); - - let lion = (4211, 200); - let dog = (4212, 300); - let cat = (4213, 400); - let fish = (4214, 500); + let treasury = AccountInfo { + account: NativeTreasury::get(), + balance: EXISTENTIAL_DEPOSIT_NATIVE + 10, + }; + let swap_bridge_native_evm = AccountInfo { + account: v2::SwapBridgeNativeToEvmPot::account_id(), + balance: EXISTENTIAL_DEPOSIT_NATIVE, + }; + let evm_bridge_delta = 50; - let swap_bridge_evm_native = ( - v2::SwapBridgeEvmToNativePot::account_id(), - EXISTENTIAL_DEPOSIT_EVM + evm_bridge_delta, - ); + let swap_bridge_evm_native = AccountInfo { + account: v2::SwapBridgeEvmToNativePot::account_id(), + balance: EXISTENTIAL_DEPOSIT_EVM + evm_bridge_delta, + }; let config = v2::GenesisConfig { balances: pallet_balances::GenesisConfig { - balances: vec![treasury, swap_bridge_native_evm], + balances: vec![treasury.into(), swap_bridge_native_evm.into()], }, evm_balances: pallet_balances::GenesisConfig { - balances: vec![lion, dog, cat, fish, swap_bridge_evm_native], + balances: vec![ + LION.into(), + DOG.into(), + CAT.into(), + FISH.into(), + swap_bridge_evm_native.into(), + ], }, swap_bridge_native_to_evm_pot: pallet_pot::GenesisConfig { initial_state: pallet_pot::InitialState::Initialized, @@ -190,21 +223,17 @@ fn initialization_fails_treasury_insufficient_balance() { #[test] fn runtime_upgrade() { with_runtime_lock(|| { - let treasury = (NativeTreasury::get(), 1450); - let alice = (4201, 20); - let bob = (4203, 30); - - let lion = (4211, 200); - let dog = (4212, 300); - let cat = (4213, 400); - let fish = (4214, 500); + let treasury = AccountInfo { + account: NativeTreasury::get(), + balance: 1450, + }; let v1_config = v1::GenesisConfig { balances: pallet_balances::GenesisConfig { - balances: vec![treasury, alice, bob], + balances: vec![treasury.into(), ALICE.into(), BOB.into()], }, evm_balances: pallet_balances::GenesisConfig { - balances: vec![lion, dog, cat, fish], + balances: vec![LION.into(), DOG.into(), CAT.into(), FISH.into()], }, ..Default::default() }; @@ -227,17 +256,26 @@ fn runtime_upgrade() { assert!(v2::EvmNativeBridgesInitializer::is_balanced().unwrap()); assert_eq!( v2::Balances::total_balance(&v2::SwapBridgeNativeToEvmPot::account_id()), - lion.1 + dog.1 + cat.1 + fish.1 + EXISTENTIAL_DEPOSIT_NATIVE + LION.balance + + DOG.balance + + CAT.balance + + FISH.balance + + EXISTENTIAL_DEPOSIT_NATIVE ); assert_eq!( v2::Balances::total_balance(&NativeTreasury::get()), - treasury.1 - (lion.1 + dog.1 + cat.1 + fish.1 + EXISTENTIAL_DEPOSIT_NATIVE) + treasury.balance + - (LION.balance + + DOG.balance + + CAT.balance + + FISH.balance + + EXISTENTIAL_DEPOSIT_NATIVE) ); assert_eq!( v2::EvmBalances::total_balance(&v2::SwapBridgeEvmToNativePot::account_id(),), v2::Balances::total_balance(&NativeTreasury::get()) - + alice.1 - + bob.1 + + ALICE.balance + + BOB.balance + EXISTENTIAL_DEPOSIT_EVM ); }); From 0dcc6c48ba4057da39581037550387faa9adfefa Mon Sep 17 00:00:00 2001 From: Dmitry Lavrenov Date: Wed, 9 Aug 2023 23:07:45 +0300 Subject: [PATCH 19/38] Rename version mocks --- .../src/mock/mod.rs | 2 +- .../src/mock/{v2.rs => v0.rs} | 53 +--------------- .../src/mock/v1.rs | 53 +++++++++++++++- .../src/tests.rs | 60 +++++++++---------- 4 files changed, 84 insertions(+), 84 deletions(-) rename crates/pallet-bridges-initializer-currency-swap/src/mock/{v2.rs => v0.rs} (55%) diff --git a/crates/pallet-bridges-initializer-currency-swap/src/mock/mod.rs b/crates/pallet-bridges-initializer-currency-swap/src/mock/mod.rs index 71755e320..b46681e3d 100644 --- a/crates/pallet-bridges-initializer-currency-swap/src/mock/mod.rs +++ b/crates/pallet-bridges-initializer-currency-swap/src/mock/mod.rs @@ -4,8 +4,8 @@ use frame_support::{parameter_types, sp_io, sp_runtime::BuildStorage}; use crate::{self as pallet_bridges_initializer_currency_swap}; +pub mod v0; pub mod v1; -pub mod v2; pub(crate) const EXISTENTIAL_DEPOSIT_NATIVE: u64 = 10; pub(crate) const EXISTENTIAL_DEPOSIT_EVM: u64 = 20; diff --git a/crates/pallet-bridges-initializer-currency-swap/src/mock/v2.rs b/crates/pallet-bridges-initializer-currency-swap/src/mock/v0.rs similarity index 55% rename from crates/pallet-bridges-initializer-currency-swap/src/mock/v2.rs rename to crates/pallet-bridges-initializer-currency-swap/src/mock/v0.rs index 2d8aaa4bf..4a065e679 100644 --- a/crates/pallet-bridges-initializer-currency-swap/src/mock/v2.rs +++ b/crates/pallet-bridges-initializer-currency-swap/src/mock/v0.rs @@ -1,16 +1,15 @@ -//! The v2 mock that includes bridges initialization logic at runtime. +//! The v1 mock that represents just a case with two separate accounts system +//! without bridges initialization logic at runtime. // Allow simple integer arithmetic in tests. #![allow(clippy::integer_arithmetic)] use frame_support::{ - parameter_types, sp_runtime::{ testing::Header, - traits::{BlakeTwo256, Identity, IdentityLookup}, + traits::{BlakeTwo256, IdentityLookup}, }, traits::{ConstU32, ConstU64, StorageMapShim}, - PalletId, }; use sp_core::H256; @@ -28,9 +27,6 @@ frame_support::construct_runtime!( System: frame_system, Balances: pallet_balances::, EvmBalances: pallet_balances::, - SwapBridgeNativeToEvmPot: pallet_pot::, - SwapBridgeEvmToNativePot: pallet_pot::, - EvmNativeBridgesInitializer: pallet_bridges_initializer_currency_swap, } ); @@ -89,46 +85,3 @@ impl pallet_balances::Config for Test { type ReserveIdentifier = [u8; 8]; type WeightInfo = (); } - -parameter_types! { - pub const SwapBridgeNativeToEvmPotPalletId: PalletId = PalletId(*b"humanoNE"); - pub const SwapBridgeEvmToNativePotPalletId: PalletId = PalletId(*b"humanoEN"); -} - -type PotInstanceSwapBridgeNativeToEvm = pallet_pot::Instance1; -type PotInstanceSwapBridgeEvmToNative = pallet_pot::Instance2; - -impl pallet_pot::Config for Test { - type RuntimeEvent = RuntimeEvent; - type AccountId = AccountId; - type PalletId = SwapBridgeNativeToEvmPotPalletId; - type Currency = Balances; -} - -impl pallet_pot::Config for Test { - type RuntimeEvent = RuntimeEvent; - type AccountId = EvmAccountId; - type PalletId = SwapBridgeEvmToNativePotPalletId; - type Currency = EvmBalances; -} - -parameter_types! { - pub const SwapBridgeNativeToEvmPalletId: PalletId = PalletId(*b"hmsb/ne1"); - pub const SwapBridgeEvmToNativePalletId: PalletId = PalletId(*b"hmsb/en1"); -} - -parameter_types! { - pub SwapBridgeNativeToEvmPotAccountId: AccountId = SwapBridgeNativeToEvmPot::account_id(); - pub SwapBridgeEvmToNativePotAccountId: AccountId = SwapBridgeEvmToNativePot::account_id(); -} - -impl pallet_bridges_initializer_currency_swap::Config for Test { - type EvmAccountId = EvmAccountId; - type NativeCurrency = Balances; - type EvmCurrency = EvmBalances; - type BalanceConverterEvmToNative = Identity; - type BalanceConverterNativeToEvm = Identity; - type NativeEvmBridgePot = SwapBridgeNativeToEvmPotAccountId; - type NativeTreasuryPot = NativeTreasury; - type EvmNativeBridgePot = SwapBridgeEvmToNativePotAccountId; -} diff --git a/crates/pallet-bridges-initializer-currency-swap/src/mock/v1.rs b/crates/pallet-bridges-initializer-currency-swap/src/mock/v1.rs index 4a065e679..2d8aaa4bf 100644 --- a/crates/pallet-bridges-initializer-currency-swap/src/mock/v1.rs +++ b/crates/pallet-bridges-initializer-currency-swap/src/mock/v1.rs @@ -1,15 +1,16 @@ -//! The v1 mock that represents just a case with two separate accounts system -//! without bridges initialization logic at runtime. +//! The v2 mock that includes bridges initialization logic at runtime. // Allow simple integer arithmetic in tests. #![allow(clippy::integer_arithmetic)] use frame_support::{ + parameter_types, sp_runtime::{ testing::Header, - traits::{BlakeTwo256, IdentityLookup}, + traits::{BlakeTwo256, Identity, IdentityLookup}, }, traits::{ConstU32, ConstU64, StorageMapShim}, + PalletId, }; use sp_core::H256; @@ -27,6 +28,9 @@ frame_support::construct_runtime!( System: frame_system, Balances: pallet_balances::, EvmBalances: pallet_balances::, + SwapBridgeNativeToEvmPot: pallet_pot::, + SwapBridgeEvmToNativePot: pallet_pot::, + EvmNativeBridgesInitializer: pallet_bridges_initializer_currency_swap, } ); @@ -85,3 +89,46 @@ impl pallet_balances::Config for Test { type ReserveIdentifier = [u8; 8]; type WeightInfo = (); } + +parameter_types! { + pub const SwapBridgeNativeToEvmPotPalletId: PalletId = PalletId(*b"humanoNE"); + pub const SwapBridgeEvmToNativePotPalletId: PalletId = PalletId(*b"humanoEN"); +} + +type PotInstanceSwapBridgeNativeToEvm = pallet_pot::Instance1; +type PotInstanceSwapBridgeEvmToNative = pallet_pot::Instance2; + +impl pallet_pot::Config for Test { + type RuntimeEvent = RuntimeEvent; + type AccountId = AccountId; + type PalletId = SwapBridgeNativeToEvmPotPalletId; + type Currency = Balances; +} + +impl pallet_pot::Config for Test { + type RuntimeEvent = RuntimeEvent; + type AccountId = EvmAccountId; + type PalletId = SwapBridgeEvmToNativePotPalletId; + type Currency = EvmBalances; +} + +parameter_types! { + pub const SwapBridgeNativeToEvmPalletId: PalletId = PalletId(*b"hmsb/ne1"); + pub const SwapBridgeEvmToNativePalletId: PalletId = PalletId(*b"hmsb/en1"); +} + +parameter_types! { + pub SwapBridgeNativeToEvmPotAccountId: AccountId = SwapBridgeNativeToEvmPot::account_id(); + pub SwapBridgeEvmToNativePotAccountId: AccountId = SwapBridgeEvmToNativePot::account_id(); +} + +impl pallet_bridges_initializer_currency_swap::Config for Test { + type EvmAccountId = EvmAccountId; + type NativeCurrency = Balances; + type EvmCurrency = EvmBalances; + type BalanceConverterEvmToNative = Identity; + type BalanceConverterNativeToEvm = Identity; + type NativeEvmBridgePot = SwapBridgeNativeToEvmPotAccountId; + type NativeTreasuryPot = NativeTreasury; + type EvmNativeBridgePot = SwapBridgeEvmToNativePotAccountId; +} diff --git a/crates/pallet-bridges-initializer-currency-swap/src/tests.rs b/crates/pallet-bridges-initializer-currency-swap/src/tests.rs index 0ccd52d32..a9e5c3098 100644 --- a/crates/pallet-bridges-initializer-currency-swap/src/tests.rs +++ b/crates/pallet-bridges-initializer-currency-swap/src/tests.rs @@ -1,6 +1,6 @@ use frame_support::traits::{Currency, OnRuntimeUpgrade}; -use crate::mock::{new_test_ext_with, v1, v2, with_runtime_lock, *}; +use crate::mock::{new_test_ext_with, v0, v1, with_runtime_lock, *}; #[test] fn initialization_bridges_ed_works() { @@ -10,16 +10,16 @@ fn initialization_bridges_ed_works() { balance: 1450, }; let swap_bridge_native_evm = AccountInfo { - account: v2::SwapBridgeNativeToEvmPot::account_id(), + account: v1::SwapBridgeNativeToEvmPot::account_id(), balance: EXISTENTIAL_DEPOSIT_NATIVE, }; let swap_bridge_evm_native = AccountInfo { - account: v2::SwapBridgeEvmToNativePot::account_id(), + account: v1::SwapBridgeEvmToNativePot::account_id(), balance: EXISTENTIAL_DEPOSIT_EVM, }; - let config = v2::GenesisConfig { + let config = v1::GenesisConfig { balances: pallet_balances::GenesisConfig { balances: vec![ treasury.into(), @@ -47,7 +47,7 @@ fn initialization_bridges_ed_works() { }; new_test_ext_with(config).execute_with(move || { assert_eq!( - v2::Balances::total_balance(&v2::SwapBridgeNativeToEvmPot::account_id()), + v1::Balances::total_balance(&v1::SwapBridgeNativeToEvmPot::account_id()), LION.balance + DOG.balance + CAT.balance @@ -55,12 +55,12 @@ fn initialization_bridges_ed_works() { + EXISTENTIAL_DEPOSIT_NATIVE ); assert_eq!( - v2::Balances::total_balance(&NativeTreasury::get()), + v1::Balances::total_balance(&NativeTreasury::get()), treasury.balance - (LION.balance + DOG.balance + CAT.balance + FISH.balance) ); assert_eq!( - v2::EvmBalances::total_balance(&v2::SwapBridgeEvmToNativePot::account_id(),), - v2::Balances::total_balance(&NativeTreasury::get()) + v1::EvmBalances::total_balance(&v1::SwapBridgeEvmToNativePot::account_id(),), + v1::Balances::total_balance(&NativeTreasury::get()) + ALICE.balance + BOB.balance + EXISTENTIAL_DEPOSIT_EVM @@ -78,17 +78,17 @@ fn initialization_bridges_ed_delta_works() { }; let native_bridge_delta = 100; let swap_bridge_native_evm = AccountInfo { - account: v2::SwapBridgeNativeToEvmPot::account_id(), + account: v1::SwapBridgeNativeToEvmPot::account_id(), balance: EXISTENTIAL_DEPOSIT_NATIVE + native_bridge_delta, }; let evm_bridge_delta = 50; let swap_bridge_evm_native = AccountInfo { - account: v2::SwapBridgeEvmToNativePot::account_id(), + account: v1::SwapBridgeEvmToNativePot::account_id(), balance: EXISTENTIAL_DEPOSIT_EVM + evm_bridge_delta, }; - let config = v2::GenesisConfig { + let config = v1::GenesisConfig { balances: pallet_balances::GenesisConfig { balances: vec![ treasury.into(), @@ -116,7 +116,7 @@ fn initialization_bridges_ed_delta_works() { }; new_test_ext_with(config).execute_with(move || { assert_eq!( - v2::Balances::total_balance(&v2::SwapBridgeNativeToEvmPot::account_id()), + v1::Balances::total_balance(&v1::SwapBridgeNativeToEvmPot::account_id()), LION.balance + DOG.balance + CAT.balance @@ -124,13 +124,13 @@ fn initialization_bridges_ed_delta_works() { + EXISTENTIAL_DEPOSIT_NATIVE ); assert_eq!( - v2::Balances::total_balance(&NativeTreasury::get()), + v1::Balances::total_balance(&NativeTreasury::get()), treasury.balance - (LION.balance + DOG.balance + CAT.balance + FISH.balance) + native_bridge_delta ); assert_eq!( - v2::EvmBalances::total_balance(&v2::SwapBridgeEvmToNativePot::account_id(),), - v2::Balances::total_balance(&NativeTreasury::get()) + v1::EvmBalances::total_balance(&v1::SwapBridgeEvmToNativePot::account_id(),), + v1::Balances::total_balance(&NativeTreasury::get()) + ALICE.balance + BOB.balance + EXISTENTIAL_DEPOSIT_EVM @@ -148,16 +148,16 @@ fn initialization_fails_overflow() { balance: EXISTENTIAL_DEPOSIT_NATIVE, }; let swap_bridge_native_evm = AccountInfo { - account: v2::SwapBridgeNativeToEvmPot::account_id(), + account: v1::SwapBridgeNativeToEvmPot::account_id(), balance: u64::MAX - EXISTENTIAL_DEPOSIT_NATIVE, }; let swap_bridge_evm_native = AccountInfo { - account: v2::SwapBridgeEvmToNativePot::account_id(), + account: v1::SwapBridgeEvmToNativePot::account_id(), balance: EXISTENTIAL_DEPOSIT_EVM, }; - let config = v2::GenesisConfig { + let config = v1::GenesisConfig { balances: pallet_balances::GenesisConfig { balances: vec![treasury.into(), swap_bridge_native_evm.into()], }, @@ -185,17 +185,17 @@ fn initialization_fails_treasury_insufficient_balance() { balance: EXISTENTIAL_DEPOSIT_NATIVE + 10, }; let swap_bridge_native_evm = AccountInfo { - account: v2::SwapBridgeNativeToEvmPot::account_id(), + account: v1::SwapBridgeNativeToEvmPot::account_id(), balance: EXISTENTIAL_DEPOSIT_NATIVE, }; let evm_bridge_delta = 50; let swap_bridge_evm_native = AccountInfo { - account: v2::SwapBridgeEvmToNativePot::account_id(), + account: v1::SwapBridgeEvmToNativePot::account_id(), balance: EXISTENTIAL_DEPOSIT_EVM + evm_bridge_delta, }; - let config = v2::GenesisConfig { + let config = v1::GenesisConfig { balances: pallet_balances::GenesisConfig { balances: vec![treasury.into(), swap_bridge_native_evm.into()], }, @@ -228,7 +228,7 @@ fn runtime_upgrade() { balance: 1450, }; - let v1_config = v1::GenesisConfig { + let v1_config = v0::GenesisConfig { balances: pallet_balances::GenesisConfig { balances: vec![treasury.into(), ALICE.into(), BOB.into()], }, @@ -241,21 +241,21 @@ fn runtime_upgrade() { new_test_ext_with(v1_config).execute_with(move || { // Check test preconditions. assert_eq!( - v2::Balances::total_balance(&v2::SwapBridgeNativeToEvmPot::account_id()), + v1::Balances::total_balance(&v1::SwapBridgeNativeToEvmPot::account_id()), 0 ); assert_eq!( - v2::Balances::total_balance(&v2::SwapBridgeEvmToNativePot::account_id()), + v1::Balances::total_balance(&v1::SwapBridgeEvmToNativePot::account_id()), 0 ); // Do runtime upgrade hook. - v2::AllPalletsWithoutSystem::on_runtime_upgrade(); + v1::AllPalletsWithoutSystem::on_runtime_upgrade(); // Verify bridges initialization result. - assert!(v2::EvmNativeBridgesInitializer::is_balanced().unwrap()); + assert!(v1::EvmNativeBridgesInitializer::is_balanced().unwrap()); assert_eq!( - v2::Balances::total_balance(&v2::SwapBridgeNativeToEvmPot::account_id()), + v1::Balances::total_balance(&v1::SwapBridgeNativeToEvmPot::account_id()), LION.balance + DOG.balance + CAT.balance @@ -263,7 +263,7 @@ fn runtime_upgrade() { + EXISTENTIAL_DEPOSIT_NATIVE ); assert_eq!( - v2::Balances::total_balance(&NativeTreasury::get()), + v1::Balances::total_balance(&NativeTreasury::get()), treasury.balance - (LION.balance + DOG.balance @@ -272,8 +272,8 @@ fn runtime_upgrade() { + EXISTENTIAL_DEPOSIT_NATIVE) ); assert_eq!( - v2::EvmBalances::total_balance(&v2::SwapBridgeEvmToNativePot::account_id(),), - v2::Balances::total_balance(&NativeTreasury::get()) + v1::EvmBalances::total_balance(&v1::SwapBridgeEvmToNativePot::account_id(),), + v1::Balances::total_balance(&NativeTreasury::get()) + ALICE.balance + BOB.balance + EXISTENTIAL_DEPOSIT_EVM From d374d66aa06f2a533c5fc8dec059b4fc823c4450 Mon Sep 17 00:00:00 2001 From: Dmitry Lavrenov Date: Wed, 9 Aug 2023 23:20:12 +0300 Subject: [PATCH 20/38] Add initialization idempotence test --- .../src/tests.rs | 81 ++++++++++++++++++- 1 file changed, 80 insertions(+), 1 deletion(-) diff --git a/crates/pallet-bridges-initializer-currency-swap/src/tests.rs b/crates/pallet-bridges-initializer-currency-swap/src/tests.rs index a9e5c3098..b1920c766 100644 --- a/crates/pallet-bridges-initializer-currency-swap/src/tests.rs +++ b/crates/pallet-bridges-initializer-currency-swap/src/tests.rs @@ -1,4 +1,7 @@ -use frame_support::traits::{Currency, OnRuntimeUpgrade}; +use frame_support::{ + assert_storage_noop, + traits::{Currency, OnRuntimeUpgrade}, +}; use crate::mock::{new_test_ext_with, v0, v1, with_runtime_lock, *}; @@ -139,6 +142,82 @@ fn initialization_bridges_ed_delta_works() { }) } +#[test] +fn initialization_idempotence() { + with_runtime_lock(|| { + let treasury = AccountInfo { + account: NativeTreasury::get(), + balance: 1450, + }; + let swap_bridge_native_evm = AccountInfo { + account: v1::SwapBridgeNativeToEvmPot::account_id(), + balance: EXISTENTIAL_DEPOSIT_NATIVE, + }; + + let swap_bridge_evm_native = AccountInfo { + account: v1::SwapBridgeEvmToNativePot::account_id(), + balance: EXISTENTIAL_DEPOSIT_EVM, + }; + + let config = v1::GenesisConfig { + balances: pallet_balances::GenesisConfig { + balances: vec![ + treasury.into(), + ALICE.into(), + BOB.into(), + swap_bridge_native_evm.into(), + ], + }, + evm_balances: pallet_balances::GenesisConfig { + balances: vec![ + LION.into(), + DOG.into(), + CAT.into(), + FISH.into(), + swap_bridge_evm_native.into(), + ], + }, + swap_bridge_native_to_evm_pot: pallet_pot::GenesisConfig { + initial_state: pallet_pot::InitialState::Initialized, + }, + swap_bridge_evm_to_native_pot: pallet_pot::GenesisConfig { + initial_state: pallet_pot::InitialState::Initialized, + }, + ..Default::default() + }; + new_test_ext_with(config).execute_with(move || { + // Verify that bridges initialization has been applied at genesis. + assert!(v1::EvmNativeBridgesInitializer::is_balanced().unwrap()); + assert_eq!( + v1::Balances::total_balance(&v1::SwapBridgeNativeToEvmPot::account_id()), + LION.balance + + DOG.balance + + CAT.balance + + FISH.balance + + EXISTENTIAL_DEPOSIT_NATIVE + ); + assert_eq!( + v1::Balances::total_balance(&NativeTreasury::get()), + treasury.balance - (LION.balance + DOG.balance + CAT.balance + FISH.balance) + ); + assert_eq!( + v1::EvmBalances::total_balance(&v1::SwapBridgeEvmToNativePot::account_id(),), + v1::Balances::total_balance(&NativeTreasury::get()) + + ALICE.balance + + BOB.balance + + EXISTENTIAL_DEPOSIT_EVM + ); + + for _ in 0..5 { + v1::Balances::transfer(Some(ALICE.account).into(), BOB.account, 1).unwrap(); + + // Initialize bridges one more time. + assert_storage_noop!(v1::EvmNativeBridgesInitializer::initialize().unwrap()); + } + }); + }) +} + #[test] #[should_panic = "error during bridges initialization: Arithmetic(Overflow)"] fn initialization_fails_overflow() { From b2d8d28e10617740d1f9e40306342c6aeb5882c6 Mon Sep 17 00:00:00 2001 From: Dmitry Lavrenov Date: Wed, 9 Aug 2023 23:49:11 +0300 Subject: [PATCH 21/38] Add initializer version storage --- .../src/lib.rs | 10 ++++++++ .../src/tests.rs | 22 +++++++++++++++++- .../src/upgrade_init.rs | 23 ++++++++++++------- 3 files changed, 46 insertions(+), 9 deletions(-) diff --git a/crates/pallet-bridges-initializer-currency-swap/src/lib.rs b/crates/pallet-bridges-initializer-currency-swap/src/lib.rs index f845862b2..f8734cc90 100644 --- a/crates/pallet-bridges-initializer-currency-swap/src/lib.rs +++ b/crates/pallet-bridges-initializer-currency-swap/src/lib.rs @@ -26,6 +26,9 @@ mod tests; /// The current storage version. const STORAGE_VERSION: StorageVersion = StorageVersion::new(1); +/// The current bridges initializer version. +pub const CURRENT_BRIDGES_INITIALIZER_VERSION: u16 = 1; + // We have to temporarily allow some clippy lints. Later on we'll send patches to substrate to // fix them at their end. #[allow(clippy::missing_docs_in_private_items)] @@ -93,6 +96,11 @@ pub mod pallet { type EvmNativeBridgePot: Get; } + /// The initializer version. + #[pallet::storage] + #[pallet::getter(fn initializer_version)] + pub type InitializerVersion = StorageValue<_, u16, ValueQuery>; + #[pallet::genesis_config] pub struct GenesisConfig(PhantomData); @@ -116,6 +124,8 @@ pub mod pallet { Err(err) => panic!("error during bridges initialization: {err:?}",), } } + + >::put(CURRENT_BRIDGES_INITIALIZER_VERSION); } } diff --git a/crates/pallet-bridges-initializer-currency-swap/src/tests.rs b/crates/pallet-bridges-initializer-currency-swap/src/tests.rs index b1920c766..6aedb3061 100644 --- a/crates/pallet-bridges-initializer-currency-swap/src/tests.rs +++ b/crates/pallet-bridges-initializer-currency-swap/src/tests.rs @@ -3,7 +3,10 @@ use frame_support::{ traits::{Currency, OnRuntimeUpgrade}, }; -use crate::mock::{new_test_ext_with, v0, v1, with_runtime_lock, *}; +use crate::{ + mock::{new_test_ext_with, v0, v1, with_runtime_lock, *}, + InitializerVersion, CURRENT_BRIDGES_INITIALIZER_VERSION, +}; #[test] fn initialization_bridges_ed_works() { @@ -49,6 +52,10 @@ fn initialization_bridges_ed_works() { ..Default::default() }; new_test_ext_with(config).execute_with(move || { + assert_eq!( + >::get(), + CURRENT_BRIDGES_INITIALIZER_VERSION + ); assert_eq!( v1::Balances::total_balance(&v1::SwapBridgeNativeToEvmPot::account_id()), LION.balance @@ -118,6 +125,10 @@ fn initialization_bridges_ed_delta_works() { ..Default::default() }; new_test_ext_with(config).execute_with(move || { + assert_eq!( + >::get(), + CURRENT_BRIDGES_INITIALIZER_VERSION + ); assert_eq!( v1::Balances::total_balance(&v1::SwapBridgeNativeToEvmPot::account_id()), LION.balance @@ -187,6 +198,10 @@ fn initialization_idempotence() { }; new_test_ext_with(config).execute_with(move || { // Verify that bridges initialization has been applied at genesis. + assert_eq!( + >::get(), + CURRENT_BRIDGES_INITIALIZER_VERSION + ); assert!(v1::EvmNativeBridgesInitializer::is_balanced().unwrap()); assert_eq!( v1::Balances::total_balance(&v1::SwapBridgeNativeToEvmPot::account_id()), @@ -327,11 +342,16 @@ fn runtime_upgrade() { v1::Balances::total_balance(&v1::SwapBridgeEvmToNativePot::account_id()), 0 ); + assert_eq!(>::get(), 0); // Do runtime upgrade hook. v1::AllPalletsWithoutSystem::on_runtime_upgrade(); // Verify bridges initialization result. + assert_eq!( + >::get(), + CURRENT_BRIDGES_INITIALIZER_VERSION + ); assert!(v1::EvmNativeBridgesInitializer::is_balanced().unwrap()); assert_eq!( v1::Balances::total_balance(&v1::SwapBridgeNativeToEvmPot::account_id()), diff --git a/crates/pallet-bridges-initializer-currency-swap/src/upgrade_init.rs b/crates/pallet-bridges-initializer-currency-swap/src/upgrade_init.rs index ea4d49cd5..5c904673b 100644 --- a/crates/pallet-bridges-initializer-currency-swap/src/upgrade_init.rs +++ b/crates/pallet-bridges-initializer-currency-swap/src/upgrade_init.rs @@ -2,18 +2,25 @@ use frame_support::pallet_prelude::*; -use crate::{Config, Pallet}; +use crate::{Config, InitializerVersion, Pallet, CURRENT_BRIDGES_INITIALIZER_VERSION}; /// Initialize the bridges pot accounts. pub fn on_runtime_upgrade() -> Weight { - let is_balanced = Pallet::::is_balanced().unwrap_or_default(); - let mut weight = T::DbWeight::get().reads(8); - - if !is_balanced { - match Pallet::::initialize() { - Ok(w) => weight += w, - Err(err) => sp_tracing::error!("error during bridges initialization: {err:?}"), + let initializer_version = >::get(); + let mut weight = T::DbWeight::get().reads(1); + + if initializer_version != CURRENT_BRIDGES_INITIALIZER_VERSION { + let is_balanced = Pallet::::is_balanced().unwrap_or_default(); + weight += T::DbWeight::get().reads(8); + + if !is_balanced { + match Pallet::::initialize() { + Ok(w) => weight += w, + Err(err) => sp_tracing::error!("error during bridges initialization: {err:?}"), + } } + + >::put(CURRENT_BRIDGES_INITIALIZER_VERSION); } weight From 2a2617a73ed47c20292c4906a93795b34a10e792 Mon Sep 17 00:00:00 2001 From: Dmitry Lavrenov Date: Thu, 10 Aug 2023 00:01:43 +0300 Subject: [PATCH 22/38] Add verify_balanced call --- .../src/lib.rs | 20 +++++++++++++++++++ .../src/mock/v1.rs | 1 + .../src/weights.rs | 15 ++++++++++++++ 3 files changed, 36 insertions(+) create mode 100644 crates/pallet-bridges-initializer-currency-swap/src/weights.rs diff --git a/crates/pallet-bridges-initializer-currency-swap/src/lib.rs b/crates/pallet-bridges-initializer-currency-swap/src/lib.rs index f8734cc90..f0717c68d 100644 --- a/crates/pallet-bridges-initializer-currency-swap/src/lib.rs +++ b/crates/pallet-bridges-initializer-currency-swap/src/lib.rs @@ -14,6 +14,9 @@ use frame_support::{ }; pub use pallet::*; use sp_std::cmp::Ordering; +pub use weights::*; + +pub mod weights; mod upgrade_init; @@ -94,6 +97,9 @@ pub mod pallet { /// The evm-native bridge pot account. type EvmNativeBridgePot: Get; + + /// Weight information for extrinsics in this pallet. + type WeightInfo: WeightInfo; } /// The initializer version. @@ -151,6 +157,20 @@ pub mod pallet { upgrade_init::post_upgrade::(state) } } + + #[pallet::call] + impl Pallet { + /// Verify if currencies are balanced. + #[pallet::call_index(0)] + #[pallet::weight(T::WeightInfo::verify_balanced())] + pub fn verify_balanced(_origin: OriginFor) -> DispatchResult { + if !Pallet::::is_balanced()? { + return Err(Error::::NotBalanced.into()); + } + + Ok(()) + } + } } impl Pallet { diff --git a/crates/pallet-bridges-initializer-currency-swap/src/mock/v1.rs b/crates/pallet-bridges-initializer-currency-swap/src/mock/v1.rs index 2d8aaa4bf..620f4fa8d 100644 --- a/crates/pallet-bridges-initializer-currency-swap/src/mock/v1.rs +++ b/crates/pallet-bridges-initializer-currency-swap/src/mock/v1.rs @@ -131,4 +131,5 @@ impl pallet_bridges_initializer_currency_swap::Config for Test { type NativeEvmBridgePot = SwapBridgeNativeToEvmPotAccountId; type NativeTreasuryPot = NativeTreasury; type EvmNativeBridgePot = SwapBridgeEvmToNativePotAccountId; + type WeightInfo = (); } diff --git a/crates/pallet-bridges-initializer-currency-swap/src/weights.rs b/crates/pallet-bridges-initializer-currency-swap/src/weights.rs new file mode 100644 index 000000000..2c55d478b --- /dev/null +++ b/crates/pallet-bridges-initializer-currency-swap/src/weights.rs @@ -0,0 +1,15 @@ +//! Weights definition for pallet-bridges-initializer-currency-swap. + +use frame_support::weights::Weight; + +/// Weight functions needed for pallet-bridges-initializer-currency-swap. +pub trait WeightInfo { + /// A function to calculate required weights for `verify_balanced` call. + fn verify_balanced() -> Weight; +} + +impl WeightInfo for () { + fn verify_balanced() -> Weight { + Weight::zero() + } +} From bc502f9458884282d19c29f1a402902c3f583813 Mon Sep 17 00:00:00 2001 From: Dmitry Lavrenov <39522748+dmitrylavrenov@users.noreply.github.com> Date: Thu, 10 Aug 2023 09:12:36 +0300 Subject: [PATCH 23/38] Edit docs Co-authored-by: MOZGIII --- .../pallet-bridges-initializer-currency-swap/src/mock/v0.rs | 2 +- .../pallet-bridges-initializer-currency-swap/src/mock/v1.rs | 2 +- crates/pallet-bridges-initializer-currency-swap/src/tests.rs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/pallet-bridges-initializer-currency-swap/src/mock/v0.rs b/crates/pallet-bridges-initializer-currency-swap/src/mock/v0.rs index 4a065e679..fdbe283cf 100644 --- a/crates/pallet-bridges-initializer-currency-swap/src/mock/v0.rs +++ b/crates/pallet-bridges-initializer-currency-swap/src/mock/v0.rs @@ -1,4 +1,4 @@ -//! The v1 mock that represents just a case with two separate accounts system +//! The v0 mock that represents just a case with two separate accounts system //! without bridges initialization logic at runtime. // Allow simple integer arithmetic in tests. diff --git a/crates/pallet-bridges-initializer-currency-swap/src/mock/v1.rs b/crates/pallet-bridges-initializer-currency-swap/src/mock/v1.rs index 620f4fa8d..369513c30 100644 --- a/crates/pallet-bridges-initializer-currency-swap/src/mock/v1.rs +++ b/crates/pallet-bridges-initializer-currency-swap/src/mock/v1.rs @@ -1,4 +1,4 @@ -//! The v2 mock that includes bridges initialization logic at runtime. +//! The v1 mock that includes bridges initialization logic at runtime. // Allow simple integer arithmetic in tests. #![allow(clippy::integer_arithmetic)] diff --git a/crates/pallet-bridges-initializer-currency-swap/src/tests.rs b/crates/pallet-bridges-initializer-currency-swap/src/tests.rs index 6aedb3061..1ef130fff 100644 --- a/crates/pallet-bridges-initializer-currency-swap/src/tests.rs +++ b/crates/pallet-bridges-initializer-currency-swap/src/tests.rs @@ -154,7 +154,7 @@ fn initialization_bridges_ed_delta_works() { } #[test] -fn initialization_idempotence() { +fn initialization_idempotency() { with_runtime_lock(|| { let treasury = AccountInfo { account: NativeTreasury::get(), @@ -226,7 +226,7 @@ fn initialization_idempotence() { for _ in 0..5 { v1::Balances::transfer(Some(ALICE.account).into(), BOB.account, 1).unwrap(); - // Initialize bridges one more time. + // Initialize bridges one more time after a change. assert_storage_noop!(v1::EvmNativeBridgesInitializer::initialize().unwrap()); } }); From c55b0113f0b7535beba960f579a39d71fbfe4c75 Mon Sep 17 00:00:00 2001 From: Dmitry Lavrenov <39522748+dmitrylavrenov@users.noreply.github.com> Date: Thu, 10 Aug 2023 09:18:25 +0300 Subject: [PATCH 24/38] Twice immediate reinvocation idempotency Co-authored-by: MOZGIII --- crates/pallet-bridges-initializer-currency-swap/src/tests.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crates/pallet-bridges-initializer-currency-swap/src/tests.rs b/crates/pallet-bridges-initializer-currency-swap/src/tests.rs index 1ef130fff..5da01c9ee 100644 --- a/crates/pallet-bridges-initializer-currency-swap/src/tests.rs +++ b/crates/pallet-bridges-initializer-currency-swap/src/tests.rs @@ -223,6 +223,10 @@ fn initialization_idempotency() { + EXISTENTIAL_DEPOSIT_EVM ); + // Do it twice to ensure immediate reinvocation idempotency. + assert_storage_noop!(v1::EvmNativeBridgesInitializer::initialize().unwrap()); + assert_storage_noop!(v1::EvmNativeBridgesInitializer::initialize().unwrap()); + for _ in 0..5 { v1::Balances::transfer(Some(ALICE.account).into(), BOB.account, 1).unwrap(); From 55a9f8339c679b0334720a67bb966f28a1329c7e Mon Sep 17 00:00:00 2001 From: Dmitry Lavrenov Date: Thu, 10 Aug 2023 09:22:07 +0300 Subject: [PATCH 25/38] Add transfer with creating account to test --- .../src/tests.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/crates/pallet-bridges-initializer-currency-swap/src/tests.rs b/crates/pallet-bridges-initializer-currency-swap/src/tests.rs index 5da01c9ee..cd1baf523 100644 --- a/crates/pallet-bridges-initializer-currency-swap/src/tests.rs +++ b/crates/pallet-bridges-initializer-currency-swap/src/tests.rs @@ -227,8 +227,16 @@ fn initialization_idempotency() { assert_storage_noop!(v1::EvmNativeBridgesInitializer::initialize().unwrap()); assert_storage_noop!(v1::EvmNativeBridgesInitializer::initialize().unwrap()); - for _ in 0..5 { + for attempt in 0..5 { + // Send to an existing account. v1::Balances::transfer(Some(ALICE.account).into(), BOB.account, 1).unwrap(); + // Create a new one account. + v1::EvmBalances::transfer( + Some(FISH.account).into(), + 5234 + attempt, + EXISTENTIAL_DEPOSIT_EVM, + ) + .unwrap(); // Initialize bridges one more time after a change. assert_storage_noop!(v1::EvmNativeBridgesInitializer::initialize().unwrap()); From f1b4304a5f937188d85c76054f7966a09cebb863 Mon Sep 17 00:00:00 2001 From: Dmitry Lavrenov Date: Thu, 10 Aug 2023 11:54:28 +0300 Subject: [PATCH 26/38] Make is_balanced fn public --- crates/pallet-bridges-initializer-currency-swap/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/pallet-bridges-initializer-currency-swap/src/lib.rs b/crates/pallet-bridges-initializer-currency-swap/src/lib.rs index f0717c68d..2d1cc0cff 100644 --- a/crates/pallet-bridges-initializer-currency-swap/src/lib.rs +++ b/crates/pallet-bridges-initializer-currency-swap/src/lib.rs @@ -351,7 +351,7 @@ impl Pallet { } /// Verify currencies balanced requirements. - fn is_balanced() -> Result { + pub fn is_balanced() -> Result { let is_balanced_native_evm = swap_reserved_balance::< T::AccountId, T::NativeCurrency, From 5ef7ed1dcdc22d4110d42c6b9f9b44bedad0025f Mon Sep 17 00:00:00 2001 From: Dmitry Lavrenov <39522748+dmitrylavrenov@users.noreply.github.com> Date: Fri, 11 Aug 2023 10:57:43 +0300 Subject: [PATCH 27/38] Fix typos Co-authored-by: MOZGIII --- .../pallet-bridges-initializer-currency-swap/src/lib.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/pallet-bridges-initializer-currency-swap/src/lib.rs b/crates/pallet-bridges-initializer-currency-swap/src/lib.rs index 2d1cc0cff..5c07a9678 100644 --- a/crates/pallet-bridges-initializer-currency-swap/src/lib.rs +++ b/crates/pallet-bridges-initializer-currency-swap/src/lib.rs @@ -258,7 +258,7 @@ impl Pallet { )?; weight += T::DbWeight::get().writes(1); - // We can safely ignore the result as overflow cann't be reached. + // We can safely ignore the result as overflow can't be reached. // current_native_bridge_balance < amount. The resulted balance is equal to amount. let _ = T::NativeCurrency::resolve_into_existing( &T::NativeEvmBridgePot::get(), @@ -277,7 +277,7 @@ impl Pallet { )?; weight += T::DbWeight::get().writes(1); - // We can safely ignore the result as overflow cann't be reached. + // We can safely ignore the result as overflow can't be reached. // current_native_bridge_balance + current_native_treasury < total_issuance. // So, imbalance + current_native_treasury < total_issuance. let _ = T::NativeCurrency::resolve_into_existing( @@ -321,7 +321,7 @@ impl Pallet { ); weight += T::DbWeight::get().writes(1); - // We can safely ignore the result as overflow cann't be reached. + // We can safely ignore the result as overflow can't be reached. // current_evm_bridge_balance < amount. The resulted balance is equal to amount. let _ = T::EvmCurrency::resolve_into_existing(&T::EvmNativeBridgePot::get(), imbalance); @@ -335,7 +335,7 @@ impl Pallet { ); weight += T::DbWeight::get().writes(1); - // We can safely ignore the result as underflow cann't be reached. + // We can safely ignore the result as underflow can't be reached. // current_evm_bridge_balance > amount => imbalance < current_evm_bridge_balance. let _ = T::EvmCurrency::settle( &T::EvmNativeBridgePot::get(), From 7bacc72c823577f6d100185ad4c0433f25d64edf Mon Sep 17 00:00:00 2001 From: Dmitry Lavrenov Date: Fri, 11 Aug 2023 11:13:15 +0300 Subject: [PATCH 28/38] Improve docs and debug_assert for make_native_bridge_balance_be --- .../pallet-bridges-initializer-currency-swap/src/lib.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/crates/pallet-bridges-initializer-currency-swap/src/lib.rs b/crates/pallet-bridges-initializer-currency-swap/src/lib.rs index 5c07a9678..ba9a15905 100644 --- a/crates/pallet-bridges-initializer-currency-swap/src/lib.rs +++ b/crates/pallet-bridges-initializer-currency-swap/src/lib.rs @@ -223,10 +223,12 @@ impl Pallet { /// Make native bridge balance be provided amount value. /// - /// The logic can change native swappable balance value. + /// This function TRANSFERS the tokens to/from the treasury to balance the bridge pots. + /// It will not change the total issuance, but it can change the native swappable balance value. fn make_native_bridge_balance_be( amount: >::Balance, ) -> Result { + let native_total_issuance_before = T::NativeCurrency::total_issuance(); let current_native_bridge_balance = T::NativeCurrency::total_balance(&T::NativeEvmBridgePot::get()); let mut weight = T::DbWeight::get().reads(1); @@ -289,6 +291,11 @@ impl Pallet { Ordering::Equal => {} } + debug_assert!( + native_total_issuance_before == T::NativeCurrency::total_issuance(), + "we must ensure that the total issuance isn't altered" + ); + Ok(weight) } From d10ea31094286f52c074feea4a12887b13b70629 Mon Sep 17 00:00:00 2001 From: Dmitry Lavrenov Date: Fri, 11 Aug 2023 11:17:00 +0300 Subject: [PATCH 29/38] Improve docs and debug_assert for make_evm_bridge_balance_be --- .../src/lib.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/crates/pallet-bridges-initializer-currency-swap/src/lib.rs b/crates/pallet-bridges-initializer-currency-swap/src/lib.rs index ba9a15905..c40002754 100644 --- a/crates/pallet-bridges-initializer-currency-swap/src/lib.rs +++ b/crates/pallet-bridges-initializer-currency-swap/src/lib.rs @@ -301,10 +301,14 @@ impl Pallet { /// Make evm bridge balance be provided amount value. /// - /// The logic shouldn't change evm swappable balance value. + /// This function MINTS/BURNS the tokens as it needs to balance out the currencies and bridge pots. + /// The logic shouldn't change evm swappable balance value, but it can change the total evm issuance. fn make_evm_bridge_balance_be( amount: >::Balance, ) -> Result { + let evm_swappable_balance_before = + swappable_balance::()?; + let current_evm_bridge_balance = T::EvmCurrency::total_balance(&T::EvmNativeBridgePot::get()); let mut weight = T::DbWeight::get().reads(1); @@ -354,6 +358,13 @@ impl Pallet { } Ordering::Equal => {} } + + debug_assert!( + evm_swappable_balance_before + == swappable_balance::()?, + "we must ensure that the swappable balance isn't altered" + ); + Ok(weight) } From 4f286829a18af209ab955d441da0db0857701538 Mon Sep 17 00:00:00 2001 From: Dmitry Lavrenov Date: Fri, 11 Aug 2023 11:18:22 +0300 Subject: [PATCH 30/38] Improve assert messages --- crates/pallet-bridges-initializer-currency-swap/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/pallet-bridges-initializer-currency-swap/src/lib.rs b/crates/pallet-bridges-initializer-currency-swap/src/lib.rs index c40002754..a36c72012 100644 --- a/crates/pallet-bridges-initializer-currency-swap/src/lib.rs +++ b/crates/pallet-bridges-initializer-currency-swap/src/lib.rs @@ -293,7 +293,7 @@ impl Pallet { debug_assert!( native_total_issuance_before == T::NativeCurrency::total_issuance(), - "we must ensure that the total issuance isn't altered" + "we must ensure that the native total issuance isn't altered" ); Ok(weight) @@ -362,7 +362,7 @@ impl Pallet { debug_assert!( evm_swappable_balance_before == swappable_balance::()?, - "we must ensure that the swappable balance isn't altered" + "we must ensure that the evm swappable balance isn't altered" ); Ok(weight) From a5876adbb4c2b34288fe34daf3647ae725519df1 Mon Sep 17 00:00:00 2001 From: Dmitry Lavrenov Date: Mon, 14 Aug 2023 16:10:27 +0300 Subject: [PATCH 31/38] Proportionally equal natve and evm total issuances --- .../src/lib.rs | 78 ++++++++++++++++--- .../src/tests.rs | 51 +++--------- 2 files changed, 78 insertions(+), 51 deletions(-) diff --git a/crates/pallet-bridges-initializer-currency-swap/src/lib.rs b/crates/pallet-bridges-initializer-currency-swap/src/lib.rs index a36c72012..7f6a47d25 100644 --- a/crates/pallet-bridges-initializer-currency-swap/src/lib.rs +++ b/crates/pallet-bridges-initializer-currency-swap/src/lib.rs @@ -107,6 +107,18 @@ pub mod pallet { #[pallet::getter(fn initializer_version)] pub type InitializerVersion = StorageValue<_, u16, ValueQuery>; + /// The native-evm bridge minimum balance value. + #[pallet::storage] + #[pallet::getter(fn native_evm_bridge_minimum_balance)] + pub type NativeEvmBridgeMinimumBalance = + StorageValue<_, >::Balance, ValueQuery>; + + /// The evm-native bridge minimum balance value. + #[pallet::storage] + #[pallet::getter(fn evm_native_bridge_minimum_balance)] + pub type EvmNativeBridgeMinimumBalance = + StorageValue<_, >::Balance, ValueQuery>; + #[pallet::genesis_config] pub struct GenesisConfig(PhantomData); @@ -179,6 +191,8 @@ impl Pallet { let mut weight = T::DbWeight::get().reads(0); with_storage_layer(move || { + weight += Self::init_bridges_miminum_balances()?; + let evm_total_issuance = T::EvmCurrency::total_issuance(); let evm_bridge_balance = T::EvmCurrency::total_balance(&T::EvmNativeBridgePot::get()); weight += T::DbWeight::get().reads(2); @@ -189,7 +203,7 @@ impl Pallet { let native_swap_reserved = T::BalanceConverterEvmToNative::convert(evm_swappable); let native_bridge_balance = native_swap_reserved - .checked_add(&T::NativeCurrency::minimum_balance()) + .checked_add(&>::get()) .ok_or(ArithmeticError::Overflow)?; weight += T::DbWeight::get().reads(1); @@ -204,7 +218,7 @@ impl Pallet { let evm_swap_reserved = T::BalanceConverterNativeToEvm::convert(native_swappable); let evm_bridge_balance = evm_swap_reserved - .checked_add(&T::EvmCurrency::minimum_balance()) + .checked_add(&>::get()) .ok_or(ArithmeticError::Overflow)?; weight += T::DbWeight::get().reads(1); @@ -215,12 +229,47 @@ impl Pallet { } weight += T::DbWeight::get().reads(8); + debug_assert!( + T::NativeCurrency::total_issuance() + == T::BalanceConverterEvmToNative::convert(T::EvmCurrency::total_issuance()), + "we must ensure that the native and evm total issuances are proportionally equal" + ); + Ok(()) })?; Ok(weight) } + /// A helper function to init bridges minimum balances be proportionally equal. + fn init_bridges_miminum_balances() -> Result { + let native_ed = T::NativeCurrency::minimum_balance(); + let evm_ed = T::EvmCurrency::minimum_balance(); + let mut weight = T::DbWeight::get().reads(2); + + match native_ed.cmp(&T::BalanceConverterEvmToNative::convert(evm_ed)) { + Ordering::Greater => { + >::put(native_ed); + >::put(T::BalanceConverterNativeToEvm::convert( + native_ed, + )); + } + Ordering::Less => { + >::put(evm_ed); + >::put(T::BalanceConverterEvmToNative::convert( + evm_ed, + )); + } + Ordering::Equal => { + >::put(native_ed); + >::put(evm_ed); + } + }; + weight += T::DbWeight::get().writes(2); + + Ok(weight) + } + /// Make native bridge balance be provided amount value. /// /// This function TRANSFERS the tokens to/from the treasury to balance the bridge pots. @@ -370,20 +419,23 @@ impl Pallet { /// Verify currencies balanced requirements. pub fn is_balanced() -> Result { - let is_balanced_native_evm = swap_reserved_balance::< - T::AccountId, - T::NativeCurrency, - T::NativeEvmBridgePot, - >()? == T::BalanceConverterEvmToNative::convert( - swappable_balance::()?, - ); + let is_balanced_native_evm = + swap_reserved_balance::( + >::get(), + )? == T::BalanceConverterEvmToNative::convert(swappable_balance::< + T::EvmAccountId, + T::EvmCurrency, + T::EvmNativeBridgePot, + >()?); let is_balanced_evm_native = T::BalanceConverterNativeToEvm::convert(swap_reserved_balance::< T::AccountId, T::NativeCurrency, T::NativeEvmBridgePot, - >()?) + >(>::get())?) == swappable_balance::()?; Ok(is_balanced_native_evm && is_balanced_evm_native) @@ -405,11 +457,13 @@ fn swappable_balance, B: Get>( /// A helper function to calculate swap reserved balance. fn swap_reserved_balance, B: Get>( + bridge_minimum_balance: C::Balance, ) -> Result { let bridge = C::total_balance(&B::get()); - let ed = C::minimum_balance(); - let reserved = bridge.checked_sub(&ed).ok_or(ArithmeticError::Underflow)?; + let reserved = bridge + .checked_sub(&bridge_minimum_balance) + .ok_or(ArithmeticError::Underflow)?; Ok(reserved) } diff --git a/crates/pallet-bridges-initializer-currency-swap/src/tests.rs b/crates/pallet-bridges-initializer-currency-swap/src/tests.rs index cd1baf523..99c82b20a 100644 --- a/crates/pallet-bridges-initializer-currency-swap/src/tests.rs +++ b/crates/pallet-bridges-initializer-currency-swap/src/tests.rs @@ -63,10 +63,13 @@ fn initialization_bridges_ed_works() { + CAT.balance + FISH.balance + EXISTENTIAL_DEPOSIT_NATIVE + + (EXISTENTIAL_DEPOSIT_EVM - EXISTENTIAL_DEPOSIT_NATIVE) ); assert_eq!( v1::Balances::total_balance(&NativeTreasury::get()), - treasury.balance - (LION.balance + DOG.balance + CAT.balance + FISH.balance) + treasury.balance + - (LION.balance + DOG.balance + CAT.balance + FISH.balance) + - (EXISTENTIAL_DEPOSIT_EVM - EXISTENTIAL_DEPOSIT_NATIVE) ); assert_eq!( v1::EvmBalances::total_balance(&v1::SwapBridgeEvmToNativePot::account_id(),), @@ -136,11 +139,13 @@ fn initialization_bridges_ed_delta_works() { + CAT.balance + FISH.balance + EXISTENTIAL_DEPOSIT_NATIVE + + (EXISTENTIAL_DEPOSIT_EVM - EXISTENTIAL_DEPOSIT_NATIVE) ); assert_eq!( v1::Balances::total_balance(&NativeTreasury::get()), treasury.balance - (LION.balance + DOG.balance + CAT.balance + FISH.balance) + native_bridge_delta + - (EXISTENTIAL_DEPOSIT_EVM - EXISTENTIAL_DEPOSIT_NATIVE) ); assert_eq!( v1::EvmBalances::total_balance(&v1::SwapBridgeEvmToNativePot::account_id(),), @@ -210,10 +215,13 @@ fn initialization_idempotency() { + CAT.balance + FISH.balance + EXISTENTIAL_DEPOSIT_NATIVE + + (EXISTENTIAL_DEPOSIT_EVM - EXISTENTIAL_DEPOSIT_NATIVE) ); assert_eq!( v1::Balances::total_balance(&NativeTreasury::get()), - treasury.balance - (LION.balance + DOG.balance + CAT.balance + FISH.balance) + treasury.balance + - (LION.balance + DOG.balance + CAT.balance + FISH.balance) + - (EXISTENTIAL_DEPOSIT_EVM - EXISTENTIAL_DEPOSIT_NATIVE) ); assert_eq!( v1::EvmBalances::total_balance(&v1::SwapBridgeEvmToNativePot::account_id(),), @@ -245,43 +253,6 @@ fn initialization_idempotency() { }) } -#[test] -#[should_panic = "error during bridges initialization: Arithmetic(Overflow)"] -fn initialization_fails_overflow() { - with_runtime_lock(|| { - let treasury = AccountInfo { - account: NativeTreasury::get(), - balance: EXISTENTIAL_DEPOSIT_NATIVE, - }; - let swap_bridge_native_evm = AccountInfo { - account: v1::SwapBridgeNativeToEvmPot::account_id(), - balance: u64::MAX - EXISTENTIAL_DEPOSIT_NATIVE, - }; - - let swap_bridge_evm_native = AccountInfo { - account: v1::SwapBridgeEvmToNativePot::account_id(), - balance: EXISTENTIAL_DEPOSIT_EVM, - }; - - let config = v1::GenesisConfig { - balances: pallet_balances::GenesisConfig { - balances: vec![treasury.into(), swap_bridge_native_evm.into()], - }, - evm_balances: pallet_balances::GenesisConfig { - balances: vec![swap_bridge_evm_native.into()], - }, - swap_bridge_native_to_evm_pot: pallet_pot::GenesisConfig { - initial_state: pallet_pot::InitialState::Initialized, - }, - swap_bridge_evm_to_native_pot: pallet_pot::GenesisConfig { - initial_state: pallet_pot::InitialState::Initialized, - }, - ..Default::default() - }; - new_test_ext_with(config).execute_with(move || {}); - }) -} - #[test] #[should_panic = "error during bridges initialization: Module(ModuleError { index: 1, error: [2, 0, 0, 0], message: Some(\"InsufficientBalance\") })"] fn initialization_fails_treasury_insufficient_balance() { @@ -372,6 +343,7 @@ fn runtime_upgrade() { + CAT.balance + FISH.balance + EXISTENTIAL_DEPOSIT_NATIVE + + (EXISTENTIAL_DEPOSIT_EVM - EXISTENTIAL_DEPOSIT_NATIVE) ); assert_eq!( v1::Balances::total_balance(&NativeTreasury::get()), @@ -381,6 +353,7 @@ fn runtime_upgrade() { + CAT.balance + FISH.balance + EXISTENTIAL_DEPOSIT_NATIVE) + - (EXISTENTIAL_DEPOSIT_EVM - EXISTENTIAL_DEPOSIT_NATIVE) ); assert_eq!( v1::EvmBalances::total_balance(&v1::SwapBridgeEvmToNativePot::account_id(),), From 63a5a2735e15a0cf7bb7edc9936fc0f0c5cc1446 Mon Sep 17 00:00:00 2001 From: Dmitry Lavrenov Date: Mon, 14 Aug 2023 16:14:22 +0300 Subject: [PATCH 32/38] Fix is_balanced logic to calculate different swappable balances --- .../src/lib.rs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/crates/pallet-bridges-initializer-currency-swap/src/lib.rs b/crates/pallet-bridges-initializer-currency-swap/src/lib.rs index 7f6a47d25..e5076ee33 100644 --- a/crates/pallet-bridges-initializer-currency-swap/src/lib.rs +++ b/crates/pallet-bridges-initializer-currency-swap/src/lib.rs @@ -428,15 +428,14 @@ impl Pallet { T::EvmNativeBridgePot, >()?); - let is_balanced_evm_native = - T::BalanceConverterNativeToEvm::convert(swap_reserved_balance::< - T::AccountId, - T::NativeCurrency, - T::NativeEvmBridgePot, - >(>::get())?) - == swappable_balance::()?; + let is_balanced_evm_native = T::BalanceConverterNativeToEvm::convert(swappable_balance::< + T::AccountId, + T::NativeCurrency, + T::NativeEvmBridgePot, + >()?) + == swap_reserved_balance::( + >::get(), + )?; Ok(is_balanced_native_evm && is_balanced_evm_native) } From 43fc65c09be5a9aec23cd9b8d8f1b6e438eabd0a Mon Sep 17 00:00:00 2001 From: Dmitry Lavrenov Date: Tue, 15 Aug 2023 10:22:25 +0300 Subject: [PATCH 33/38] Rename pallet --- Cargo.lock | 30 +++++++++---------- .../Cargo.toml | 2 +- .../src/lib.rs | 0 .../src/mock/mod.rs | 0 .../src/mock/v0.rs | 0 .../src/mock/v1.rs | 0 .../src/tests.rs | 0 .../src/upgrade_init.rs | 0 .../src/weights.rs | 0 9 files changed, 16 insertions(+), 16 deletions(-) rename crates/{pallet-bridges-initializer-currency-swap => pallet-balanced-currency-swap-bridges-initializer}/Cargo.toml (96%) rename crates/{pallet-bridges-initializer-currency-swap => pallet-balanced-currency-swap-bridges-initializer}/src/lib.rs (100%) rename crates/{pallet-bridges-initializer-currency-swap => pallet-balanced-currency-swap-bridges-initializer}/src/mock/mod.rs (100%) rename crates/{pallet-bridges-initializer-currency-swap => pallet-balanced-currency-swap-bridges-initializer}/src/mock/v0.rs (100%) rename crates/{pallet-bridges-initializer-currency-swap => pallet-balanced-currency-swap-bridges-initializer}/src/mock/v1.rs (100%) rename crates/{pallet-bridges-initializer-currency-swap => pallet-balanced-currency-swap-bridges-initializer}/src/tests.rs (100%) rename crates/{pallet-bridges-initializer-currency-swap => pallet-balanced-currency-swap-bridges-initializer}/src/upgrade_init.rs (100%) rename crates/{pallet-bridges-initializer-currency-swap => pallet-balanced-currency-swap-bridges-initializer}/src/weights.rs (100%) diff --git a/Cargo.lock b/Cargo.lock index 47ac91b7d..169ead40a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5830,6 +5830,21 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-balanced-currency-swap-bridges-initializer" +version = "0.1.0" +dependencies = [ + "frame-support", + "frame-system", + "pallet-balances", + "pallet-pot", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-std", + "sp-tracing", +] + [[package]] name = "pallet-balances" version = "4.0.0-dev" @@ -5912,21 +5927,6 @@ dependencies = [ "sp-std", ] -[[package]] -name = "pallet-bridges-initializer-currency-swap" -version = "0.1.0" -dependencies = [ - "frame-support", - "frame-system", - "pallet-balances", - "pallet-pot", - "parity-scale-codec", - "scale-info", - "sp-core", - "sp-std", - "sp-tracing", -] - [[package]] name = "pallet-chain-properties" version = "0.1.0" diff --git a/crates/pallet-bridges-initializer-currency-swap/Cargo.toml b/crates/pallet-balanced-currency-swap-bridges-initializer/Cargo.toml similarity index 96% rename from crates/pallet-bridges-initializer-currency-swap/Cargo.toml rename to crates/pallet-balanced-currency-swap-bridges-initializer/Cargo.toml index 9d4091cd0..f383f4049 100644 --- a/crates/pallet-bridges-initializer-currency-swap/Cargo.toml +++ b/crates/pallet-balanced-currency-swap-bridges-initializer/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "pallet-bridges-initializer-currency-swap" +name = "pallet-balanced-currency-swap-bridges-initializer" version = "0.1.0" edition = "2021" publish = false diff --git a/crates/pallet-bridges-initializer-currency-swap/src/lib.rs b/crates/pallet-balanced-currency-swap-bridges-initializer/src/lib.rs similarity index 100% rename from crates/pallet-bridges-initializer-currency-swap/src/lib.rs rename to crates/pallet-balanced-currency-swap-bridges-initializer/src/lib.rs diff --git a/crates/pallet-bridges-initializer-currency-swap/src/mock/mod.rs b/crates/pallet-balanced-currency-swap-bridges-initializer/src/mock/mod.rs similarity index 100% rename from crates/pallet-bridges-initializer-currency-swap/src/mock/mod.rs rename to crates/pallet-balanced-currency-swap-bridges-initializer/src/mock/mod.rs diff --git a/crates/pallet-bridges-initializer-currency-swap/src/mock/v0.rs b/crates/pallet-balanced-currency-swap-bridges-initializer/src/mock/v0.rs similarity index 100% rename from crates/pallet-bridges-initializer-currency-swap/src/mock/v0.rs rename to crates/pallet-balanced-currency-swap-bridges-initializer/src/mock/v0.rs diff --git a/crates/pallet-bridges-initializer-currency-swap/src/mock/v1.rs b/crates/pallet-balanced-currency-swap-bridges-initializer/src/mock/v1.rs similarity index 100% rename from crates/pallet-bridges-initializer-currency-swap/src/mock/v1.rs rename to crates/pallet-balanced-currency-swap-bridges-initializer/src/mock/v1.rs diff --git a/crates/pallet-bridges-initializer-currency-swap/src/tests.rs b/crates/pallet-balanced-currency-swap-bridges-initializer/src/tests.rs similarity index 100% rename from crates/pallet-bridges-initializer-currency-swap/src/tests.rs rename to crates/pallet-balanced-currency-swap-bridges-initializer/src/tests.rs diff --git a/crates/pallet-bridges-initializer-currency-swap/src/upgrade_init.rs b/crates/pallet-balanced-currency-swap-bridges-initializer/src/upgrade_init.rs similarity index 100% rename from crates/pallet-bridges-initializer-currency-swap/src/upgrade_init.rs rename to crates/pallet-balanced-currency-swap-bridges-initializer/src/upgrade_init.rs diff --git a/crates/pallet-bridges-initializer-currency-swap/src/weights.rs b/crates/pallet-balanced-currency-swap-bridges-initializer/src/weights.rs similarity index 100% rename from crates/pallet-bridges-initializer-currency-swap/src/weights.rs rename to crates/pallet-balanced-currency-swap-bridges-initializer/src/weights.rs From 5075aea5262f0af79ff9f7578f8f65b284c41ed4 Mon Sep 17 00:00:00 2001 From: Dmitry Lavrenov Date: Tue, 15 Aug 2023 10:36:40 +0300 Subject: [PATCH 34/38] Use a helper function to calculate required bridges minimum balances --- .../src/lib.rs | 94 +++++++------------ 1 file changed, 32 insertions(+), 62 deletions(-) diff --git a/crates/pallet-balanced-currency-swap-bridges-initializer/src/lib.rs b/crates/pallet-balanced-currency-swap-bridges-initializer/src/lib.rs index e5076ee33..40e6fa420 100644 --- a/crates/pallet-balanced-currency-swap-bridges-initializer/src/lib.rs +++ b/crates/pallet-balanced-currency-swap-bridges-initializer/src/lib.rs @@ -26,6 +26,14 @@ mod mock; #[cfg(test)] mod tests; +/// The native balance from a given config. +type NativeBalanceOf = + <::NativeCurrency as Currency<::AccountId>>::Balance; + +/// The evm balance from a given config. +type EvmBalanceOf = + <::EvmCurrency as Currency<::EvmAccountId>>::Balance; + /// The current storage version. const STORAGE_VERSION: StorageVersion = StorageVersion::new(1); @@ -63,31 +71,19 @@ pub mod pallet { /// The interface into native currency implementation. type NativeCurrency: Currency - + fungible::Inspect< - Self::AccountId, - Balance = >::Balance, - >; + + fungible::Inspect>; /// The interface into evm currency implementation. type EvmCurrency: Currency - + fungible::Inspect< - Self::EvmAccountId, - Balance = >::Balance, - >; + + fungible::Inspect>; /// The converter to determine how the balance amount should be converted from /// native currency to evm currency. - type BalanceConverterNativeToEvm: Convert< - >::Balance, - >::Balance, - >; + type BalanceConverterNativeToEvm: Convert, EvmBalanceOf>; /// The converter to determine how the balance amount should be converted from /// evm currency to native currency. - type BalanceConverterEvmToNative: Convert< - >::Balance, - >::Balance, - >; + type BalanceConverterEvmToNative: Convert, NativeBalanceOf>; /// The native-evm bridge pot account. type NativeEvmBridgePot: Get; @@ -107,18 +103,6 @@ pub mod pallet { #[pallet::getter(fn initializer_version)] pub type InitializerVersion = StorageValue<_, u16, ValueQuery>; - /// The native-evm bridge minimum balance value. - #[pallet::storage] - #[pallet::getter(fn native_evm_bridge_minimum_balance)] - pub type NativeEvmBridgeMinimumBalance = - StorageValue<_, >::Balance, ValueQuery>; - - /// The evm-native bridge minimum balance value. - #[pallet::storage] - #[pallet::getter(fn evm_native_bridge_minimum_balance)] - pub type EvmNativeBridgeMinimumBalance = - StorageValue<_, >::Balance, ValueQuery>; - #[pallet::genesis_config] pub struct GenesisConfig(PhantomData); @@ -191,7 +175,8 @@ impl Pallet { let mut weight = T::DbWeight::get().reads(0); with_storage_layer(move || { - weight += Self::init_bridges_miminum_balances()?; + let (native_evm_bridge_minimum_balance, evm_native_bridge_minimum_balance) = + Self::bridges_miminum_balances(); let evm_total_issuance = T::EvmCurrency::total_issuance(); let evm_bridge_balance = T::EvmCurrency::total_balance(&T::EvmNativeBridgePot::get()); @@ -203,7 +188,7 @@ impl Pallet { let native_swap_reserved = T::BalanceConverterEvmToNative::convert(evm_swappable); let native_bridge_balance = native_swap_reserved - .checked_add(&>::get()) + .checked_add(&native_evm_bridge_minimum_balance) .ok_or(ArithmeticError::Overflow)?; weight += T::DbWeight::get().reads(1); @@ -218,7 +203,7 @@ impl Pallet { let evm_swap_reserved = T::BalanceConverterNativeToEvm::convert(native_swappable); let evm_bridge_balance = evm_swap_reserved - .checked_add(&>::get()) + .checked_add(&evm_native_bridge_minimum_balance) .ok_or(ArithmeticError::Overflow)?; weight += T::DbWeight::get().reads(1); @@ -241,42 +226,26 @@ impl Pallet { Ok(weight) } - /// A helper function to init bridges minimum balances be proportionally equal. - fn init_bridges_miminum_balances() -> Result { + /// A helper function to calculate bridges minimum balances be proportionally equal. + fn bridges_miminum_balances() -> (NativeBalanceOf, EvmBalanceOf) { let native_ed = T::NativeCurrency::minimum_balance(); let evm_ed = T::EvmCurrency::minimum_balance(); - let mut weight = T::DbWeight::get().reads(2); match native_ed.cmp(&T::BalanceConverterEvmToNative::convert(evm_ed)) { - Ordering::Greater => { - >::put(native_ed); - >::put(T::BalanceConverterNativeToEvm::convert( - native_ed, - )); - } - Ordering::Less => { - >::put(evm_ed); - >::put(T::BalanceConverterEvmToNative::convert( - evm_ed, - )); - } - Ordering::Equal => { - >::put(native_ed); - >::put(evm_ed); - } - }; - weight += T::DbWeight::get().writes(2); - - Ok(weight) + Ordering::Greater => ( + native_ed, + T::BalanceConverterNativeToEvm::convert(native_ed), + ), + Ordering::Less => (T::BalanceConverterEvmToNative::convert(evm_ed), evm_ed), + Ordering::Equal => (native_ed, evm_ed), + } } /// Make native bridge balance be provided amount value. /// /// This function TRANSFERS the tokens to/from the treasury to balance the bridge pots. /// It will not change the total issuance, but it can change the native swappable balance value. - fn make_native_bridge_balance_be( - amount: >::Balance, - ) -> Result { + fn make_native_bridge_balance_be(amount: NativeBalanceOf) -> Result { let native_total_issuance_before = T::NativeCurrency::total_issuance(); let current_native_bridge_balance = T::NativeCurrency::total_balance(&T::NativeEvmBridgePot::get()); @@ -352,9 +321,7 @@ impl Pallet { /// /// This function MINTS/BURNS the tokens as it needs to balance out the currencies and bridge pots. /// The logic shouldn't change evm swappable balance value, but it can change the total evm issuance. - fn make_evm_bridge_balance_be( - amount: >::Balance, - ) -> Result { + fn make_evm_bridge_balance_be(amount: EvmBalanceOf) -> Result { let evm_swappable_balance_before = swappable_balance::()?; @@ -419,9 +386,12 @@ impl Pallet { /// Verify currencies balanced requirements. pub fn is_balanced() -> Result { + let (native_evm_bridge_minimum_balance, evm_native_bridge_minimum_balance) = + Self::bridges_miminum_balances(); + let is_balanced_native_evm = swap_reserved_balance::( - >::get(), + native_evm_bridge_minimum_balance, )? == T::BalanceConverterEvmToNative::convert(swappable_balance::< T::EvmAccountId, T::EvmCurrency, @@ -434,7 +404,7 @@ impl Pallet { T::NativeEvmBridgePot, >()?) == swap_reserved_balance::( - >::get(), + evm_native_bridge_minimum_balance, )?; Ok(is_balanced_native_evm && is_balanced_evm_native) From a2263507d50bf848858c70768f4432e2d24fe3ec Mon Sep 17 00:00:00 2001 From: Dmitry Lavrenov Date: Tue, 15 Aug 2023 10:43:45 +0300 Subject: [PATCH 35/38] Fix pallet renaming in tests --- .../src/mock/mod.rs | 2 +- .../src/mock/v1.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/pallet-balanced-currency-swap-bridges-initializer/src/mock/mod.rs b/crates/pallet-balanced-currency-swap-bridges-initializer/src/mock/mod.rs index b46681e3d..aa3853449 100644 --- a/crates/pallet-balanced-currency-swap-bridges-initializer/src/mock/mod.rs +++ b/crates/pallet-balanced-currency-swap-bridges-initializer/src/mock/mod.rs @@ -2,7 +2,7 @@ use frame_support::{parameter_types, sp_io, sp_runtime::BuildStorage}; -use crate::{self as pallet_bridges_initializer_currency_swap}; +use crate::{self as pallet_balanced_currency_swap_bridges_initializer}; pub mod v0; pub mod v1; diff --git a/crates/pallet-balanced-currency-swap-bridges-initializer/src/mock/v1.rs b/crates/pallet-balanced-currency-swap-bridges-initializer/src/mock/v1.rs index 369513c30..d9801d64d 100644 --- a/crates/pallet-balanced-currency-swap-bridges-initializer/src/mock/v1.rs +++ b/crates/pallet-balanced-currency-swap-bridges-initializer/src/mock/v1.rs @@ -30,7 +30,7 @@ frame_support::construct_runtime!( EvmBalances: pallet_balances::, SwapBridgeNativeToEvmPot: pallet_pot::, SwapBridgeEvmToNativePot: pallet_pot::, - EvmNativeBridgesInitializer: pallet_bridges_initializer_currency_swap, + EvmNativeBridgesInitializer: pallet_balanced_currency_swap_bridges_initializer, } ); @@ -122,7 +122,7 @@ parameter_types! { pub SwapBridgeEvmToNativePotAccountId: AccountId = SwapBridgeEvmToNativePot::account_id(); } -impl pallet_bridges_initializer_currency_swap::Config for Test { +impl pallet_balanced_currency_swap_bridges_initializer::Config for Test { type EvmAccountId = EvmAccountId; type NativeCurrency = Balances; type EvmCurrency = EvmBalances; From 682cb95d89c03e73be78520429e1b72e7eef9f5e Mon Sep 17 00:00:00 2001 From: Dmitry Lavrenov Date: Tue, 15 Aug 2023 10:47:06 +0300 Subject: [PATCH 36/38] Fix pallet renaming in features snapshot --- utils/checks/snapshots/features.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/utils/checks/snapshots/features.yaml b/utils/checks/snapshots/features.yaml index dcc57b421..19fa9d5ab 100644 --- a/utils/checks/snapshots/features.yaml +++ b/utils/checks/snapshots/features.yaml @@ -1967,6 +1967,10 @@ - name: pallet-babe 4.0.0-dev features: - std +- name: pallet-balanced-currency-swap-bridges-initializer 0.1.0 + features: + - default + - std - name: pallet-balances 4.0.0-dev features: - default @@ -1990,10 +1994,6 @@ features: - default - std -- name: pallet-bridges-initializer-currency-swap 0.1.0 - features: - - default - - std - name: pallet-chain-properties 0.1.0 features: - default From 7c7f03108e41dbf70df33954e09657f852c8567c Mon Sep 17 00:00:00 2001 From: Dmitry Lavrenov Date: Tue, 15 Aug 2023 11:39:56 +0300 Subject: [PATCH 37/38] Return test --- .../src/tests.rs | 57 ++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/crates/pallet-balanced-currency-swap-bridges-initializer/src/tests.rs b/crates/pallet-balanced-currency-swap-bridges-initializer/src/tests.rs index 99c82b20a..0ee0f04f8 100644 --- a/crates/pallet-balanced-currency-swap-bridges-initializer/src/tests.rs +++ b/crates/pallet-balanced-currency-swap-bridges-initializer/src/tests.rs @@ -5,7 +5,7 @@ use frame_support::{ use crate::{ mock::{new_test_ext_with, v0, v1, with_runtime_lock, *}, - InitializerVersion, CURRENT_BRIDGES_INITIALIZER_VERSION, + swappable_balance, InitializerVersion, CURRENT_BRIDGES_INITIALIZER_VERSION, }; #[test] @@ -253,6 +253,61 @@ fn initialization_idempotency() { }) } +#[test] +fn initialization_evm_swappable_zero() { + with_runtime_lock(|| { + let treasury = AccountInfo { + account: NativeTreasury::get(), + balance: EXISTENTIAL_DEPOSIT_NATIVE, + }; + let swap_bridge_native_evm = AccountInfo { + account: v1::SwapBridgeNativeToEvmPot::account_id(), + balance: u64::MAX - EXISTENTIAL_DEPOSIT_NATIVE, + }; + + let swap_bridge_evm_native = AccountInfo { + account: v1::SwapBridgeEvmToNativePot::account_id(), + balance: EXISTENTIAL_DEPOSIT_EVM, + }; + + let config = v1::GenesisConfig { + balances: pallet_balances::GenesisConfig { + balances: vec![treasury.into(), swap_bridge_native_evm.into()], + }, + evm_balances: pallet_balances::GenesisConfig { + balances: vec![swap_bridge_evm_native.into()], + }, + swap_bridge_native_to_evm_pot: pallet_pot::GenesisConfig { + initial_state: pallet_pot::InitialState::Initialized, + }, + swap_bridge_evm_to_native_pot: pallet_pot::GenesisConfig { + initial_state: pallet_pot::InitialState::Initialized, + }, + ..Default::default() + }; + new_test_ext_with(config).execute_with(move || { + assert_eq!( + swappable_balance::< + EvmAccountId, + v1::EvmBalances, + v1::SwapBridgeEvmToNativePotAccountId, + >() + .unwrap(), + 0 + ); + assert_eq!( + swappable_balance::< + AccountId, + v1::Balances, + v1::SwapBridgeNativeToEvmPotAccountId, + >() + .unwrap(), + EXISTENTIAL_DEPOSIT_NATIVE + ((u64::MAX - EXISTENTIAL_DEPOSIT_NATIVE) - EXISTENTIAL_DEPOSIT_EVM) + ); + }); + }) +} + #[test] #[should_panic = "error during bridges initialization: Module(ModuleError { index: 1, error: [2, 0, 0, 0], message: Some(\"InsufficientBalance\") })"] fn initialization_fails_treasury_insufficient_balance() { From 53dde768dfbe11debd808444bbf4ebe274b54479 Mon Sep 17 00:00:00 2001 From: Dmitry Lavrenov Date: Tue, 15 Aug 2023 12:21:46 +0300 Subject: [PATCH 38/38] Add docs for tests --- .../src/tests.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/crates/pallet-balanced-currency-swap-bridges-initializer/src/tests.rs b/crates/pallet-balanced-currency-swap-bridges-initializer/src/tests.rs index 0ee0f04f8..36f972d44 100644 --- a/crates/pallet-balanced-currency-swap-bridges-initializer/src/tests.rs +++ b/crates/pallet-balanced-currency-swap-bridges-initializer/src/tests.rs @@ -8,6 +8,8 @@ use crate::{ swappable_balance, InitializerVersion, CURRENT_BRIDGES_INITIALIZER_VERSION, }; +/// This test verifies that balanced bridges initialization works in case bridge pot accounts +/// have been created with existential deposit balance values at genesis. #[test] fn initialization_bridges_ed_works() { with_runtime_lock(|| { @@ -82,6 +84,8 @@ fn initialization_bridges_ed_works() { }) } +/// This test verifies that balanced bridges initialization works in case bridge pot accounts +/// have been created with existential deposit balance values plus some deltas at genesis. #[test] fn initialization_bridges_ed_delta_works() { with_runtime_lock(|| { @@ -158,6 +162,8 @@ fn initialization_bridges_ed_delta_works() { }) } +/// This test verifies idempotency of balanced bridges initialization algorithm by changing +/// balances state and applying initialization operation several times. #[test] fn initialization_idempotency() { with_runtime_lock(|| { @@ -253,6 +259,8 @@ fn initialization_idempotency() { }) } +/// This test verifies that balanced bridges initialization works in case genesis configuration +/// leads to 0 evm swappable balance. #[test] fn initialization_evm_swappable_zero() { with_runtime_lock(|| { @@ -308,6 +316,8 @@ fn initialization_evm_swappable_zero() { }) } +/// This test verifies that balanced bridges initialization fails in case genesis configuration +/// contains native treasury account with insufficient balance to properly perform initialization. #[test] #[should_panic = "error during bridges initialization: Module(ModuleError { index: 1, error: [2, 0, 0, 0], message: Some(\"InsufficientBalance\") })"] fn initialization_fails_treasury_insufficient_balance() { @@ -352,6 +362,11 @@ fn initialization_fails_treasury_insufficient_balance() { }) } +/// This test simulates runtime upgrade operation by using different mocked runtime versions and +/// verifies that balanced bridges initialization works as expected for `on_runtime_upgrade` call. +/// +/// - v0: just contains native and evm balances. +/// - v1: v0 with balanced bridges currency swap initializer pallet. #[test] fn runtime_upgrade() { with_runtime_lock(|| {