Skip to content

Commit

Permalink
Merge pull request #76 from toints/upstream-polkadot-v1.7.0
Browse files Browse the repository at this point in the history
perf(*): removed the binding relationship before transfer tokens between Substrate Account and EVM Account
  • Loading branch information
wd30130 authored Apr 28, 2024
2 parents eca602b + 7ebe558 commit 03d19c1
Show file tree
Hide file tree
Showing 16 changed files with 2,776 additions and 585 deletions.
913 changes: 504 additions & 409 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,13 @@ members = [
"primitives/system",
"pallets/evm-utils",
"pallets/evm/precompile/substrate-utils",
"pallets/evm/precompile/transfer-to-magnet",
"pallets/pot/runtime-api",
"pallets/pot/rpc",
"pallets/pot",
"pallets/assurance",
"pallets/liquidation",
"pallets/assets-bridge",
]
resolver = "2"

Expand Down
172 changes: 21 additions & 151 deletions pallets/assets-bridge/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,17 @@ use frame_support::{
pallet_prelude::*,
traits::{
tokens::{Fortitude, Precision},
Currency, ExistenceRequirement, IsType,
Currency, IsType,
},
transactional,
};

use sp_core::{ecdsa, H160, U256};
use sp_io::{crypto::secp256k1_ecdsa_recover, hashing::keccak_256};
use sp_runtime::traits::{StaticLookup, UniqueSaturatedInto, Zero};
use sp_std::vec::Vec;
use sp_std::{collections::btree_set::BTreeSet, vec::Vec};

use pallet_evm::{AddressMapping, ExitReason, Runner};
use pallet_evm::{ExitReason, Runner};

pub type EcdsaSignature = ecdsa::Signature;
pub type AddressMappingOf<T> = <T as pallet_evm::Config>::AddressMapping;
Expand All @@ -57,9 +57,6 @@ pub type ReserveBalanceOf<T> = <<T as pallet_assets::Config>::Currency as Curren

#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, scale_info::TypeInfo)]
pub enum ActionType<AssetId> {
Direct(H160),
FromSubToEth,
FromEthToSub,
BackForeign(AssetId),
}

Expand Down Expand Up @@ -197,7 +194,7 @@ pub use pallet::*;
#[frame_support::pallet]
pub mod pallet {
use super::*;
use frame_support::traits::{fungibles::Mutate, ReservableCurrency};
use frame_support::traits::fungibles::Mutate;
use frame_system::pallet_prelude::*;

#[pallet::pallet]
Expand All @@ -215,6 +212,10 @@ pub mod pallet {
/// How much should be locked up in order to claim account.
#[pallet::constant]
type ClaimBond: Get<ReserveBalanceOf<Self>>;

/// The assets-bridge's evm contract deployer.
#[pallet::constant]
type EvmAdmins: Get<BTreeSet<H160>>;
}

/// The Substrate Account for Evm Addresses
Expand Down Expand Up @@ -356,78 +357,18 @@ pub mod pallet {
where
DispatchError: From<<<T as pallet_evm::Config>::Runner as pallet_evm::Runner<T>>::Error>,
{
/// Claim account mapping between Substrate accounts and EVM accounts.
/// Ensure eth_address has not been mapped.
/// Note: for general users
///
/// - `eth_address`: The address to bind to the caller's account
/// - `eth_signature`: A signature generated by the address to prove ownership
#[pallet::call_index(0)]
#[pallet::weight(Weight::from_parts(10_000, 0) + T::DbWeight::get().writes(1))]
#[transactional]
pub fn claim_account(
origin: OriginFor<T>,
eth_address: H160,
eth_signature: EcdsaSignature,
) -> DispatchResult {
let who = ensure_signed(origin)?;

// ensure account_id and eth_address has not been mapped
ensure!(!EvmAccounts::<T>::contains_key(&who), Error::<T>::AccountIdHasMapped);
ensure!(!SubAccounts::<T>::contains_key(eth_address), Error::<T>::EthAddressHasMapped);

// recover evm address from signature
let address = eth_recover(&eth_signature, &who.using_encoded(to_ascii_hex), &[][..])
.ok_or(Error::<T>::BadSignature)?;

ensure!(eth_address == address, Error::<T>::InvalidSignature);

<T as pallet_assets::Config>::Currency::reserve(&who, T::ClaimBond::get())?;

SubAccounts::<T>::insert(eth_address, &who);
EvmAccounts::<T>::insert(&who, eth_address);

Self::deposit_event(Event::ClaimAccount(who, eth_address));

Ok(())
}

/// Dissolve substrate accounts and EVM accounts.
/// Note: for general users
#[pallet::call_index(1)]
#[pallet::weight(Weight::from_parts(10_000, 0) + T::DbWeight::get().writes(1))]
#[transactional]
pub fn dissolve(origin: OriginFor<T>) -> DispatchResult {
let who = ensure_signed(origin)?;

let evm_account = Self::evm_accounts(&who).ok_or(Error::<T>::EthAddressHasNotMapped)?;

ensure!(
SubAccounts::<T>::contains_key(evm_account),
Error::<T>::EthAddressHasNotMapped
);

<T as pallet_assets::Config>::Currency::unreserve(&who, T::ClaimBond::get());

SubAccounts::<T>::remove(evm_account);
EvmAccounts::<T>::remove(&who);

Self::deposit_event(Event::Dissolve(who));

Ok(())
}

/// Deposit substrate assets into evm erc20 contracts.
/// Note: for general users
///
/// - `asset_id`: The asset id
/// - `amount`: Deposit amount
#[pallet::call_index(2)]
#[pallet::call_index(0)]
#[pallet::weight(Weight::from_parts(10_000, 0) + T::DbWeight::get().writes(1))]
#[transactional]
pub fn deposit(
origin: OriginFor<T>,
asset_id: T::AssetId,
evm_account: H160,
amount: T::Balance,
precision: LocalPrecision,
force: LocalFortitude,
Expand All @@ -437,7 +378,7 @@ pub mod pallet {
ensure!(!amount.is_zero(), Error::<T>::ZeroBalance);

// 1. check evm account
let evm_account = Self::evm_accounts(&who).ok_or(Error::<T>::EthAddressHasNotMapped)?;
//let evm_account = Self::evm_accounts(&who).ok_or(Error::<T>::EthAddressHasNotMapped)?;

let external_precision: Precision = precision.into();
let external_force: Fortitude = force.into();
Expand All @@ -463,58 +404,13 @@ pub mod pallet {
Ok(Pays::No.into())
}

/// Withdraw from evm erc20 contracts into substrate assets
/// Note: for general users
///
/// - `asset_id`: The asset id
/// - `amount`: Withdraw amount
#[pallet::call_index(3)]
#[pallet::weight(Weight::from_parts(10_000, 0) + T::DbWeight::get().writes(1))]
#[transactional]
pub fn withdraw(
origin: OriginFor<T>,
asset_id: T::AssetId,
amount: T::Balance,
) -> DispatchResultWithPostInfo {
let who = ensure_signed(origin)?;
ensure!(!Self::is_in_emergency(asset_id.clone()), Error::<T>::InEmergency);
ensure!(!amount.is_zero(), Error::<T>::ZeroBalance);

// 1. check evm account
let evm_account = Self::evm_accounts(&who).ok_or(Error::<T>::EthAddressHasNotMapped)?;

// 2. burn erc20
let erc20 =
Self::erc20s(asset_id.clone()).ok_or(Error::<T>::ContractAddressHasNotMapped)?;

let inputs = burn_from_encode(evm_account, amount.unique_saturated_into());

Self::call_evm(erc20, inputs)?;

// 3. mint asset
pallet_assets::Pallet::<T>::mint_into(asset_id.clone(), &who, amount)?;

Self::deposit_event(Event::WithdrawExecuted(
asset_id.clone(),
who,
evm_account,
amount,
erc20,
));

Ok(Pays::No.into())
}

/// Teleport native currency between substrate account and evm address
/// Ensure eth_address has been mapped
/// Note: for general users
///
/// - `amount`: Teleport amount
/// - `action`: (1) Direct(H160): direct transfer into unchecked evm address (2)
/// FromSubToEth: transfer from substrate account to mapped evm address (3) FromEthToSub:
/// transfer from mapped evm address to substrate account
/// - companion with `relay`: (4) BackForeign(asset_id): transfer assets back foreign chain
#[pallet::call_index(4)]
/// - `action`:
/// - (1) BackForeign(asset_id): transfer assets back foreign chain
#[pallet::call_index(1)]
#[pallet::weight(Weight::from_parts(10_000, 0) + T::DbWeight::get().writes(1))]
#[transactional]
pub fn teleport(
Expand All @@ -529,24 +425,7 @@ pub mod pallet {

ensure!(!amount.is_zero(), Error::<T>::ZeroBalance);

let (from, to, back_foreign) = match action {
ActionType::Direct(unchecked) => {
(who.clone(), AddressMappingOf::<T>::into_account_id(unchecked), false)
},
ActionType::FromSubToEth => (
who.clone(),
Self::evm_accounts(&who)
.map(AddressMappingOf::<T>::into_account_id)
.ok_or(Error::<T>::EthAddressHasNotMapped)?,
false,
),
ActionType::FromEthToSub => (
Self::evm_accounts(&who)
.map(AddressMappingOf::<T>::into_account_id)
.ok_or(Error::<T>::EthAddressHasNotMapped)?,
who.clone(),
false,
),
let (_from, _to, _back_foreign) = match action {
ActionType::BackForeign(asset_id) => {
// ensure asset_id registered in back_foreign list
ensure!(Self::is_in_back_foreign(asset_id.clone()), Error::<T>::BanBackForeign);
Expand All @@ -569,15 +448,6 @@ pub mod pallet {
},
};

if !back_foreign {
<T as pallet_evm::Config>::Currency::transfer(
&from,
&to,
amount,
ExistenceRequirement::AllowDeath,
)?;
}

Self::deposit_event(Event::Teleport(who, amount, action_clone));

Ok(Pays::No.into())
Expand All @@ -588,7 +458,7 @@ pub mod pallet {
///
/// - `asset_id`: The asset id
/// - `erc20`: The erc20 contract address
#[pallet::call_index(5)]
#[pallet::call_index(2)]
#[pallet::weight(Weight::from_parts(10_000, 0) + T::DbWeight::get().writes(1))]
pub fn register(
origin: OriginFor<T>,
Expand All @@ -614,7 +484,7 @@ pub mod pallet {
/// Note: for admin
///
/// - `asset_id`: None will pause all, Some(id) will pause the specified asset
#[pallet::call_index(6)]
#[pallet::call_index(3)]
#[pallet::weight(Weight::from_parts(10_000, 0) + T::DbWeight::get().writes(1))]
pub fn pause(
origin: OriginFor<T>,
Expand Down Expand Up @@ -649,7 +519,7 @@ pub mod pallet {
/// Note: for admin
///
/// - `asset_id`: None will unpause all, Some(id) will unpause the specified asset
#[pallet::call_index(7)]
#[pallet::call_index(4)]
#[pallet::weight(Weight::from_parts(10_000, 0) + T::DbWeight::get().writes(1))]
pub fn unpause(
origin: OriginFor<T>,
Expand Down Expand Up @@ -682,7 +552,7 @@ pub mod pallet {
/// Note: for admin
///
/// - `asset_id`:
#[pallet::call_index(8)]
#[pallet::call_index(5)]
#[pallet::weight(Weight::from_parts(10_000, 0) + T::DbWeight::get().writes(1))]
pub fn back_foreign(
origin: OriginFor<T>,
Expand All @@ -709,7 +579,7 @@ pub mod pallet {

/// Set this pallet admin key
/// Note: for super admin
#[pallet::call_index(9)]
#[pallet::call_index(6)]
#[pallet::weight(Weight::from_parts(10_000, 0) + T::DbWeight::get().writes(1))]
pub fn set_admin(
origin: OriginFor<T>,
Expand All @@ -734,7 +604,7 @@ pub mod pallet {

/// Force unregister substrate assets and erc20 contracts
/// Note: for super admin
#[pallet::call_index(10)]
#[pallet::call_index(7)]
#[pallet::weight(Weight::from_parts(10_000, 0) + T::DbWeight::get().writes(1))]
pub fn force_unregister(
origin: OriginFor<T>,
Expand Down
10 changes: 9 additions & 1 deletion pallets/assets-bridge/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
pub use crate as assets_bridge;
pub use assets_bridge::{Config, Error, Event as AssetsBridgeEvent};

use sp_std::collections::btree_set::BTreeSet;

use frame_support::{
derive_impl,
pallet_prelude::Weight,
Expand Down Expand Up @@ -127,7 +129,12 @@ parameter_types! {
// 0x1111111111111111111111111111111111111111
pub EvmCaller: H160 = H160::from_slice(&[17u8;20][..]);
pub ClaimBond: u128 = 2;

//pub EvmAdmin: H160 = H160([0x05, 0xF9, 0xb8, 0xC7, 0x6E, 0x89, 0x87, 0xB8, 0x15, 0xC9, 0x3C, 0x27, 0xD1, 0x45, 0x20, 0xb6, 0xeD, 0x57, 0x39, 0x02]);
pub EvmAdmins: BTreeSet<H160> = {
let mut set = BTreeSet::new();
set.insert(H160([0x05, 0xF9, 0xb8, 0xC7, 0x6E, 0x89, 0x87, 0xB8, 0x15, 0xC9, 0x3C, 0x27, 0xD1, 0x45, 0x20, 0xb6, 0xeD, 0x57, 0x39, 0x02]));
set
};
pub const WeightPerGas: Weight = Weight::from_parts(20_000, 0);

pub const GasLimitPovSizeRatio: u64 = BLOCK_GAS_LIMIT.saturating_div(MAX_POV_SIZE);
Expand Down Expand Up @@ -186,6 +193,7 @@ impl assets_bridge::Config for Test {
type RuntimeEvent = RuntimeEvent;
type EvmCaller = EvmCaller;
type ClaimBond = ClaimBond;
type EvmAdmins = EvmAdmins;
}

pub const ALICE: [u8; 32] = [1u8; 32];
Expand Down
Loading

0 comments on commit 03d19c1

Please sign in to comment.