diff --git a/bin/node/runtime/pangolin/src/lib.rs b/bin/node/runtime/pangolin/src/lib.rs index 61e6f5a6ed..23064477c9 100644 --- a/bin/node/runtime/pangolin/src/lib.rs +++ b/bin/node/runtime/pangolin/src/lib.rs @@ -971,16 +971,20 @@ impl darwinia_crab_backing::Trait for Runtime { } parameter_types! { - pub const EthBackingModuleId: ModuleId = ModuleId(*b"da/ethbk"); + pub const EthereumBackingModuleId: ModuleId = ModuleId(*b"da/ethbk"); + pub const EthereumBackingFeeModuleId: ModuleId = ModuleId(*b"da/ethfe"); + pub const AdvancedFee: Balance = 50 * COIN; } impl darwinia_ethereum_backing::Trait for Runtime { - type ModuleId = EthBackingModuleId; + type ModuleId = EthereumBackingModuleId; + type EthereumBackingFeeModuleId = EthereumBackingFeeModuleId; type Event = Event; type RedeemAccountId = AccountId; type EthereumRelay = EthereumRelay; type OnDepositRedeem = Staking; type RingCurrency = Ring; type KtonCurrency = Kton; + type AdvancedFee = AdvancedFee; type WeightInfo = (); } diff --git a/frame/bridge/ethereum/backing/src/lib.rs b/frame/bridge/ethereum/backing/src/lib.rs index 3dc5f1e581..32aad39169 100644 --- a/frame/bridge/ethereum/backing/src/lib.rs +++ b/frame/bridge/ethereum/backing/src/lib.rs @@ -18,14 +18,12 @@ mod types { pub type Balance = u128; pub type DepositId = U256; - pub type RingBalance = - <::RingCurrency as Currency<::AccountId>>::Balance; - #[cfg(feature = "std")] - pub type KtonBalance = - <::KtonCurrency as Currency<::AccountId>>::Balance; + pub type AccountId = ::AccountId; + pub type RingBalance = <::RingCurrency as Currency>>::Balance; + pub type KtonBalance = <::KtonCurrency as Currency>>::Balance; pub type EthereumReceiptProofThing = <::EthereumRelay as EthereumReceipt< - ::AccountId, + AccountId, RingBalance, >>::EthereumReceiptProofThing; } @@ -41,12 +39,12 @@ use frame_support::{ }; use frame_system::{ensure_root, ensure_signed}; use sp_runtime::{ - traits::{AccountIdConversion, SaturatedConversion, Saturating}, + traits::{AccountIdConversion, SaturatedConversion, Saturating, Zero}, DispatchError, DispatchResult, ModuleId, RuntimeDebug, }; #[cfg(not(feature = "std"))] use sp_std::borrow::ToOwned; -use sp_std::{convert::TryFrom, vec}; +use sp_std::{convert::TryFrom, prelude::*}; // --- darwinia --- use array_bytes::array_unchecked; use darwinia_support::{ @@ -57,9 +55,11 @@ use ethereum_primitives::{receipt::EthereumTransactionIndex, EthereumAddress, U2 use types::*; pub trait Trait: frame_system::Trait { - /// The backing's module id, used for deriving its sovereign account ID. + /// The ethereum backing module id, used for deriving its sovereign account ID. type ModuleId: Get; + type EthereumBackingFeeModuleId: Get; + type Event: From> + Into<::Event>; type RedeemAccountId: From<[u8; 32]> + Into; @@ -72,6 +72,8 @@ pub trait Trait: frame_system::Trait { type KtonCurrency: LockableCurrency; + type AdvancedFee: Get>; + /// Weight information for the extrinsics in this pallet. type WeightInfo: WeightInfo; } @@ -83,15 +85,20 @@ impl WeightInfo for () {} decl_event! { pub enum Event where - ::AccountId, + AccountId = AccountId, RingBalance = RingBalance, + KtonBalance = KtonBalance, { - /// Some one redeem some *RING*. [account, amount, transaction index] + /// Someone redeem some *RING*. [account, amount, transaction index] RedeemRing(AccountId, Balance, EthereumTransactionIndex), - /// Some one redeem some *KTON*. [account, amount, transaction index] + /// Someone redeem some *KTON*. [account, amount, transaction index] RedeemKton(AccountId, Balance, EthereumTransactionIndex), - /// Some one redeem a deposit. [account, deposit id, amount, transaction index] + /// Someone redeem a deposit. [account, deposit id, amount, transaction index] RedeemDeposit(AccountId, DepositId, RingBalance, EthereumTransactionIndex), + /// Someone lock some *RING*. [account, amount] + LockRing(AccountId, RingBalance), + /// Someone lock some *KTON*. [account, amount] + LockKton(AccountId, KtonBalance), } } @@ -140,6 +147,10 @@ decl_storage! { pub KtonTokenAddress get(fn kton_token_address) config(): EthereumAddress; pub RedeemStatus get(fn redeem_status): bool = true; + + pub LockAssetEvents + get(fn lock_asset_events) + : Vec<::Event>; } add_extra_genesis { config(ring_locked): RingBalance; @@ -150,11 +161,14 @@ decl_storage! { &>::account_id(), T::RingCurrency::minimum_balance() + config.ring_locked, ); - let _ = T::KtonCurrency::make_free_balance_be( &>::account_id(), T::KtonCurrency::minimum_balance() + config.kton_locked, ); + let _ = T::RingCurrency::make_free_balance_be( + &>::fee_account_id(), + T::RingCurrency::minimum_balance(), + ); }); } } @@ -166,11 +180,20 @@ decl_module! { { type Error = Error; - /// The treasury's module id, used for deriving its sovereign account ID. + /// The ethereum backing module id, used for deriving its sovereign account ID. const ModuleId: ModuleId = T::ModuleId::get(); fn deposit_event() = default; + fn on_runtime_upgrade() -> frame_support::weights::Weight { + let _ = T::RingCurrency::make_free_balance_be( + &>::fee_account_id(), + T::RingCurrency::minimum_balance(), + ); + + 0 + } + /// Redeem balances /// /// # @@ -190,6 +213,47 @@ decl_module! { } } + /// Lock some balances into the module account + /// which very similar to lock some assets into the contract on ethereum side + #[weight = 10_000_000] + pub fn lock( + origin, + #[compact] ring_value: RingBalance, + #[compact] kton_value: KtonBalance, + ) { + let user = ensure_signed(origin)?; + let fee_account = Self::fee_account_id(); + + // 50 Ring for fee + // https://github.com/darwinia-network/darwinia-common/pull/377#issuecomment-730369387 + T::RingCurrency::transfer(&user, &fee_account, T::AdvancedFee::get(), KeepAlive)?; + + if !ring_value.is_zero() { + let ring_to_lock = ring_value.min(T::RingCurrency::usable_balance(&user)); + + T::RingCurrency::transfer(&user, &fee_account, ring_to_lock, KeepAlive)?; + + let raw_event = RawEvent::LockRing(user.clone(), ring_to_lock); + let module_event: ::Event = raw_event.clone().into(); + let system_event: ::Event = module_event.into(); + + >::append(system_event); + Self::deposit_event(raw_event); + } + if !kton_value.is_zero() { + let kton_to_lock = kton_value.min(T::KtonCurrency::usable_balance(&user)); + + T::KtonCurrency::transfer(&user, &fee_account, kton_to_lock, KeepAlive)?; + + let raw_event = RawEvent::LockKton(user, kton_to_lock); + let module_event: ::Event = raw_event.clone().into(); + let system_event: ::Event = module_event.into(); + + >::append(system_event); + Self::deposit_event(raw_event); + } + } + // --- Root Call --- /// Set a new ring redeem address. @@ -244,6 +308,10 @@ impl Module { T::ModuleId::get().into_account() } + pub fn fee_account_id() -> T::AccountId { + T::EthereumBackingFeeModuleId::get().into_account() + } + pub fn account_id_try_from_bytes(bytes: &[u8]) -> Result { ensure!(bytes.len() == 32, >::AddrLenMis); diff --git a/frame/bridge/ethereum/backing/src/mock.rs b/frame/bridge/ethereum/backing/src/mock.rs index dfa0e0db3c..830b283f16 100644 --- a/frame/bridge/ethereum/backing/src/mock.rs +++ b/frame/bridge/ethereum/backing/src/mock.rs @@ -75,16 +75,19 @@ macro_rules! decl_tests { #[derive(Clone, PartialEq, Eq, Debug)] pub struct Test; parameter_types! { - pub const EthBackingModuleId: ModuleId = ModuleId(*b"da/backi"); + pub const EthereumBackingModuleId: ModuleId = ModuleId(*b"da/backi"); + pub const EthereumBackingFeeModuleId: ModuleId = ModuleId(*b"da/ethfe"); } impl Trait for Test { - type ModuleId = EthBackingModuleId; + type ModuleId = EthereumBackingModuleId; + type EthereumBackingFeeModuleId = EthereumBackingFeeModuleId; type Event = (); type RedeemAccountId = AccountId; type EthereumRelay = EthereumRelay; type OnDepositRedeem = Staking; type RingCurrency = Ring; type KtonCurrency = Kton; + type AdvancedFee = (); type WeightInfo = (); }