diff --git a/modules/asset-registry/src/lib.rs b/modules/asset-registry/src/lib.rs index 08ad5f983..fe2892421 100644 --- a/modules/asset-registry/src/lib.rs +++ b/modules/asset-registry/src/lib.rs @@ -27,7 +27,6 @@ use frame_support::{ dispatch::DispatchResult, ensure, pallet_prelude::*, - require_transactional, traits::{Currency, EnsureOrigin}, transactional, weights::constants::WEIGHT_PER_SECOND, @@ -38,7 +37,7 @@ use module_support::{AssetIdMapping, EVMBridge, Erc20InfoMapping, InvokeContext} use primitives::{ currency::{CurrencyIdType, DexShare, DexShareType, Erc20Id, ForeignAssetId, Lease, StableAssetPoolId, TokenInfo}, evm::{ - is_system_contract, Erc20Info, EvmAddress, H160_POSITION_CURRENCY_ID_TYPE, H160_POSITION_DEXSHARE_LEFT_FIELD, + is_system_contract, EvmAddress, H160_POSITION_CURRENCY_ID_TYPE, H160_POSITION_DEXSHARE_LEFT_FIELD, H160_POSITION_DEXSHARE_LEFT_TYPE, H160_POSITION_DEXSHARE_RIGHT_FIELD, H160_POSITION_DEXSHARE_RIGHT_TYPE, H160_POSITION_FOREIGN_ASSET, H160_POSITION_LIQUID_CROADLOAN, H160_POSITION_STABLE_ASSET, H160_POSITION_TOKEN, }, @@ -93,7 +92,7 @@ pub mod module { #[derive(Clone, Eq, PartialEq, RuntimeDebug, Encode, Decode, TypeInfo)] pub enum AssetIds { - Erc20Id(Erc20Id), + Erc20(EvmAddress), StableAssetId(StableAssetPoolId), ForeignAssetId(ForeignAssetId), } @@ -115,8 +114,6 @@ pub mod module { MultiLocationExisted, /// AssetId not exists AssetIdNotExists, - /// CurrencyId existed - CurrencyIdExisted, /// AssetId exists AssetIdExisted, } @@ -176,6 +173,13 @@ pub mod module { #[pallet::getter(fn location_to_currency_ids)] pub type LocationToCurrencyIds = StorageMap<_, Twox64Concat, MultiLocation, CurrencyId, OptionQuery>; + /// The storages for EvmAddress. + /// + /// Erc20IdToAddress: map Erc20Id => Option + #[pallet::storage] + #[pallet::getter(fn erc20_id_to_address)] + pub type Erc20IdToAddress = StorageMap<_, Twox64Concat, Erc20Id, EvmAddress, OptionQuery>; + /// The storages for AssetMetadatas. /// /// AssetMetadatas: map AssetIds => Option @@ -184,15 +188,6 @@ pub mod module { pub type AssetMetadatas = StorageMap<_, Twox64Concat, AssetIds, AssetMetadata>, OptionQuery>; - /// Mapping between u32 and Erc20 address. - /// Erc20 address is 20 byte, take the first 4 non-zero bytes, if it is less - /// than 4, add 0 to the left. - /// - /// map u32 => Option - #[pallet::storage] - #[pallet::getter(fn currency_id_map)] - pub type Erc20InfoMap = StorageMap<_, Twox64Concat, u32, Erc20Info, OptionQuery>; - #[pallet::pallet] pub struct Pallet(_); @@ -273,6 +268,42 @@ pub mod module { }); Ok(()) } + + #[pallet::weight(T::WeightInfo::register_erc20_asset())] + #[transactional] + pub fn register_erc20_asset( + origin: OriginFor, + contract: EvmAddress, + minimal_balance: BalanceOf, + ) -> DispatchResult { + T::RegisterOrigin::ensure_origin(origin)?; + + let metadata = Self::do_register_erc20_asset(contract, minimal_balance)?; + + Self::deposit_event(Event::::AssetRegistered { + asset_id: AssetIds::Erc20(contract), + metadata, + }); + Ok(()) + } + + #[pallet::weight(T::WeightInfo::update_erc20_asset())] + #[transactional] + pub fn update_erc20_asset( + origin: OriginFor, + contract: EvmAddress, + metadata: Box>>, + ) -> DispatchResult { + T::RegisterOrigin::ensure_origin(origin)?; + + Self::do_update_erc20_asset(contract, &metadata)?; + + Self::deposit_event(Event::::AssetUpdated { + asset_id: AssetIds::Erc20(contract), + metadata: *metadata, + }); + Ok(()) + } } } @@ -381,8 +412,49 @@ impl Pallet { ) } - fn get_erc20_mapping(address: EvmAddress) -> Option { - Erc20InfoMap::::get(Into::::into(DexShare::Erc20(address))).filter(|v| v.address == address) + fn do_register_erc20_asset( + contract: EvmAddress, + minimal_balance: BalanceOf, + ) -> Result>, DispatchError> { + let invoke_context = InvokeContext { + contract, + sender: Default::default(), + origin: Default::default(), + }; + + let metadata = AssetMetadata { + name: T::EVMBridge::name(invoke_context)?, + symbol: T::EVMBridge::symbol(invoke_context)?, + decimals: T::EVMBridge::decimals(invoke_context)?, + minimal_balance, + }; + + let erc20_id = Into::::into(DexShare::Erc20(contract)); + + AssetMetadatas::::try_mutate(AssetIds::Erc20(contract), |maybe_asset_metadatas| -> DispatchResult { + ensure!(maybe_asset_metadatas.is_none(), Error::::AssetIdExisted); + + Erc20IdToAddress::::try_mutate(erc20_id, |maybe_address| -> DispatchResult { + ensure!(maybe_address.is_none(), Error::::AssetIdExisted); + *maybe_address = Some(contract); + + Ok(()) + })?; + + *maybe_asset_metadatas = Some(metadata.clone()); + Ok(()) + })?; + + Ok(metadata) + } + + fn do_update_erc20_asset(contract: EvmAddress, metadata: &AssetMetadata>) -> DispatchResult { + AssetMetadatas::::try_mutate(AssetIds::Erc20(contract), |maybe_asset_metadatas| -> DispatchResult { + ensure!(maybe_asset_metadatas.is_some(), Error::::AssetIdNotExists); + + *maybe_asset_metadatas = Some(metadata.clone()); + Ok(()) + }) } } @@ -391,6 +463,10 @@ pub struct AssetIdMaps(sp_std::marker::PhantomData); impl AssetIdMapping>> for AssetIdMaps { + fn get_erc20_asset_metadata(contract: EvmAddress) -> Option>> { + Pallet::::asset_metadatas(AssetIds::Erc20(contract)) + } + fn get_stable_asset_metadata(stable_asset_id: StableAssetPoolId) -> Option>> { Pallet::::asset_metadatas(AssetIds::StableAssetId(stable_asset_id)) } @@ -534,42 +610,6 @@ impl, R: TakeRevenue> Drop for FixedRateOfForeignAsset(sp_std::marker::PhantomData); impl Erc20InfoMapping for EvmErc20InfoMapping { - // Use first 4 non-zero bytes as u32 to the mapping between u32 and evm address. - // Take the first 4 non-zero bytes, if it is less than 4, add 0 to the left. - #[require_transactional] - fn set_erc20_mapping(address: EvmAddress) -> DispatchResult { - Erc20InfoMap::::try_mutate( - Into::::into(DexShare::Erc20(address)), - |maybe_erc20_info| -> DispatchResult { - if let Some(erc20_info) = maybe_erc20_info.as_mut() { - // Multiple settings are allowed, such as enabling multiple LP tokens - ensure!(erc20_info.address == address, Error::::CurrencyIdExisted); - } else { - let invoke_context = InvokeContext { - contract: address, - sender: Default::default(), - origin: Default::default(), - }; - - let info = Erc20Info { - address, - name: T::EVMBridge::name(invoke_context)?, - symbol: T::EVMBridge::symbol(invoke_context)?, - decimals: T::EVMBridge::decimals(invoke_context)?, - }; - - *maybe_erc20_info = Some(info); - } - Ok(()) - }, - ) - } - - // Returns the EvmAddress associated with a given u32. - fn get_evm_address(currency_id: u32) -> Option { - Erc20InfoMap::::get(currency_id).map(|v| v.address) - } - // Returns the name associated with a given CurrencyId. // If CurrencyId is CurrencyId::DexShare and contain DexShare::Erc20, // the EvmAddress must have been mapped. @@ -579,7 +619,7 @@ impl Erc20InfoMapping for EvmErc20InfoMapping { CurrencyId::DexShare(symbol_0, symbol_1) => { let name_0 = match symbol_0 { DexShare::Token(symbol) => CurrencyId::Token(symbol).name().map(|v| v.as_bytes().to_vec()), - DexShare::Erc20(address) => Pallet::::get_erc20_mapping(address).map(|v| v.name), + DexShare::Erc20(address) => AssetMetadatas::::get(AssetIds::Erc20(address)).map(|v| v.name), DexShare::LiquidCroadloan(lease) => Some( format!( "LiquidCroadloan-{}-{}", @@ -596,7 +636,7 @@ impl Erc20InfoMapping for EvmErc20InfoMapping { }?; let name_1 = match symbol_1 { DexShare::Token(symbol) => CurrencyId::Token(symbol).name().map(|v| v.as_bytes().to_vec()), - DexShare::Erc20(address) => Pallet::::get_erc20_mapping(address).map(|v| v.name), + DexShare::Erc20(address) => AssetMetadatas::::get(AssetIds::Erc20(address)).map(|v| v.name), DexShare::LiquidCroadloan(lease) => Some( format!( "LiquidCroadloan-{}-{}", @@ -619,7 +659,7 @@ impl Erc20InfoMapping for EvmErc20InfoMapping { vec.extend_from_slice(&name_1); Some(vec) } - CurrencyId::Erc20(address) => Pallet::::get_erc20_mapping(address).map(|v| v.name), + CurrencyId::Erc20(address) => AssetMetadatas::::get(AssetIds::Erc20(address)).map(|v| v.name), CurrencyId::StableAssetPoolToken(stable_asset_id) => { AssetMetadatas::::get(AssetIds::StableAssetId(stable_asset_id)).map(|v| v.name) } @@ -655,7 +695,7 @@ impl Erc20InfoMapping for EvmErc20InfoMapping { CurrencyId::DexShare(symbol_0, symbol_1) => { let token_symbol_0 = match symbol_0 { DexShare::Token(symbol) => CurrencyId::Token(symbol).symbol().map(|v| v.as_bytes().to_vec()), - DexShare::Erc20(address) => Pallet::::get_erc20_mapping(address).map(|v| v.symbol), + DexShare::Erc20(address) => AssetMetadatas::::get(AssetIds::Erc20(address)).map(|v| v.symbol), DexShare::LiquidCroadloan(lease) => Some( format!( "LC{}-{}", @@ -672,7 +712,7 @@ impl Erc20InfoMapping for EvmErc20InfoMapping { }?; let token_symbol_1 = match symbol_1 { DexShare::Token(symbol) => CurrencyId::Token(symbol).symbol().map(|v| v.as_bytes().to_vec()), - DexShare::Erc20(address) => Pallet::::get_erc20_mapping(address).map(|v| v.symbol), + DexShare::Erc20(address) => AssetMetadatas::::get(AssetIds::Erc20(address)).map(|v| v.symbol), DexShare::LiquidCroadloan(lease) => Some( format!( "LC{}-{}", @@ -695,7 +735,7 @@ impl Erc20InfoMapping for EvmErc20InfoMapping { vec.extend_from_slice(&token_symbol_1); Some(vec) } - CurrencyId::Erc20(address) => Pallet::::get_erc20_mapping(address).map(|v| v.symbol), + CurrencyId::Erc20(address) => AssetMetadatas::::get(AssetIds::Erc20(address)).map(|v| v.symbol), CurrencyId::StableAssetPoolToken(stable_asset_id) => { AssetMetadatas::::get(AssetIds::StableAssetId(stable_asset_id)).map(|v| v.symbol) } @@ -733,14 +773,14 @@ impl Erc20InfoMapping for EvmErc20InfoMapping { // use the decimals of currency_id_0 as the decimals of lp token. match symbol_0 { DexShare::Token(symbol) => CurrencyId::Token(symbol).decimals(), - DexShare::Erc20(address) => Pallet::::get_erc20_mapping(address).map(|v| v.decimals), + DexShare::Erc20(address) => AssetMetadatas::::get(AssetIds::Erc20(address)).map(|v| v.decimals), DexShare::LiquidCroadloan(_) => T::LiquidCroadloanCurrencyId::get().decimals(), DexShare::ForeignAsset(foreign_asset_id) => { AssetMetadatas::::get(AssetIds::ForeignAssetId(foreign_asset_id)).map(|v| v.decimals) } } } - CurrencyId::Erc20(address) => Pallet::::get_erc20_mapping(address).map(|v| v.decimals), + CurrencyId::Erc20(address) => AssetMetadatas::::get(AssetIds::Erc20(address)).map(|v| v.decimals), CurrencyId::StableAssetPoolToken(stable_asset_id) => { AssetMetadatas::::get(AssetIds::StableAssetId(stable_asset_id)).map(|v| v.decimals) } @@ -758,16 +798,16 @@ impl Erc20InfoMapping for EvmErc20InfoMapping { match v { CurrencyId::DexShare(left, right) => { match left { - DexShare::Erc20(addr) => { + DexShare::Erc20(address) => { // ensure erc20 is mapped - Pallet::::get_erc20_mapping(addr).map(|_| ())?; + AssetMetadatas::::get(AssetIds::Erc20(address)).map(|_| ())?; } DexShare::Token(_) | DexShare::LiquidCroadloan(_) | DexShare::ForeignAsset(_) => {} }; match right { - DexShare::Erc20(addr) => { + DexShare::Erc20(address) => { // ensure erc20 is mapped - Pallet::::get_erc20_mapping(addr).map(|_| ())?; + AssetMetadatas::::get(AssetIds::Erc20(address)).map(|_| ())?; } DexShare::Token(_) | DexShare::LiquidCroadloan(_) | DexShare::ForeignAsset(_) => {} }; @@ -801,7 +841,7 @@ impl Erc20InfoMapping for EvmErc20InfoMapping { .ok(), DexShareType::Erc20 => { let id = u32::from_be_bytes(address[H160_POSITION_DEXSHARE_LEFT_FIELD].try_into().ok()?); - Erc20InfoMap::::get(id).map(|v| DexShare::Erc20(v.address)) + Erc20IdToAddress::::get(id).map(DexShare::Erc20) } DexShareType::LiquidCroadloan => { let id = Lease::from_be_bytes(address[H160_POSITION_DEXSHARE_LEFT_FIELD].try_into().ok()?); @@ -821,7 +861,7 @@ impl Erc20InfoMapping for EvmErc20InfoMapping { .ok(), DexShareType::Erc20 => { let id = u32::from_be_bytes(address[H160_POSITION_DEXSHARE_RIGHT_FIELD].try_into().ok()?); - Erc20InfoMap::::get(id).map(|v| DexShare::Erc20(v.address)) + Erc20IdToAddress::::get(id).map(DexShare::Erc20) } DexShareType::LiquidCroadloan => { let id = Lease::from_be_bytes(address[H160_POSITION_DEXSHARE_RIGHT_FIELD].try_into().ok()?); diff --git a/modules/asset-registry/src/mock.rs b/modules/asset-registry/src/mock.rs index ed24eaed1..f835351ec 100644 --- a/modules/asset-registry/src/mock.rs +++ b/modules/asset-registry/src/mock.rs @@ -169,6 +169,10 @@ pub fn erc20_address() -> EvmAddress { EvmAddress::from_str("0x5dddfce53ee040d9eb21afbc0ae1bb4dbb0ba643").unwrap() } +pub fn erc20_address_same_prefix() -> EvmAddress { + EvmAddress::from_str("0x5dddfce53ee040d9eb21afbc0ae1bb4dbb0ba644").unwrap() +} + pub fn erc20_address_not_exists() -> EvmAddress { EvmAddress::from_str("0000000000000000000100000000000002000001").unwrap() } @@ -202,6 +206,38 @@ pub fn deploy_contracts() { assert_ok!(EVM::deploy_free(Origin::signed(CouncilAccount::get()), erc20_address())); } +// Specify contract address +pub fn deploy_contracts_same_prefix() { + let code = from_hex(include!("../../evm-bridge/src/erc20_demo_contract")).unwrap(); + assert_ok!(EVM::create_predeploy_contract( + Origin::signed(NetworkContractAccount::get()), + erc20_address_same_prefix(), + code, + 0, + 2_100_000, + 10000 + )); + + System::assert_last_event(Event::EVM(module_evm::Event::Created { + from: alice_evm_addr(), + contract: erc20_address_same_prefix(), + logs: vec![module_evm::Log { + address: erc20_address_same_prefix(), + topics: vec![ + H256::from_str("0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef").unwrap(), + H256::from_str("0x0000000000000000000000000000000000000000000000000000000000000000").unwrap(), + H256::from_str("0x0000000000000000000000001000000000000000000000000000000000000001").unwrap(), + ], + data: H256::from_low_u64_be(10000).as_bytes().to_vec(), + }], + })); + + assert_ok!(EVM::deploy_free( + Origin::signed(CouncilAccount::get()), + erc20_address_same_prefix() + )); +} + pub struct ExtBuilder { balances: Vec<(AccountId, Balance)>, } diff --git a/modules/asset-registry/src/tests.rs b/modules/asset-registry/src/tests.rs index 40366f3ba..ee1f855b1 100644 --- a/modules/asset-registry/src/tests.rs +++ b/modules/asset-registry/src/tests.rs @@ -23,10 +23,9 @@ use super::*; use frame_support::{assert_noop, assert_ok}; use mock::{ - alice, deploy_contracts, erc20_address, erc20_address_not_exists, AssetRegistry, CouncilAccount, Event, ExtBuilder, - Origin, Runtime, System, + alice, deploy_contracts, deploy_contracts_same_prefix, erc20_address, erc20_address_not_exists, + erc20_address_same_prefix, AssetRegistry, CouncilAccount, Event, ExtBuilder, Origin, Runtime, System, }; -use orml_utilities::with_transaction_result; use primitives::TokenSymbol; use sp_core::H160; use std::str::{from_utf8, FromStr}; @@ -462,58 +461,143 @@ fn update_stable_asset_should_not_work() { } #[test] -fn set_erc20_mapping_works() { +fn register_erc20_asset_work() { ExtBuilder::default() .balances(vec![(alice(), 1_000_000_000_000)]) .build() .execute_with(|| { deploy_contracts(); - assert_ok!(with_transaction_result(|| -> DispatchResult { - EvmErc20InfoMapping::::set_erc20_mapping(erc20_address()) + assert_ok!(AssetRegistry::register_erc20_asset( + Origin::signed(CouncilAccount::get()), + erc20_address(), + 1 + )); + + System::assert_last_event(Event::AssetRegistry(crate::Event::AssetRegistered { + asset_id: AssetIds::Erc20(erc20_address()), + metadata: AssetMetadata { + name: b"long string name, long string name, long string name, long string name, long string name" + .to_vec(), + symbol: b"TestToken".to_vec(), + decimals: 17, + minimal_balance: 1, + }, })); - assert_ok!(with_transaction_result(|| -> DispatchResult { - EvmErc20InfoMapping::::set_erc20_mapping(erc20_address()) - })); + assert_eq!(Erc20IdToAddress::::get(0x5dddfce5), Some(erc20_address())); + + assert_eq!( + AssetMetadatas::::get(AssetIds::Erc20(erc20_address())), + Some(AssetMetadata { + name: b"long string name, long string name, long string name, long string name, long string name" + .to_vec(), + symbol: b"TestToken".to_vec(), + decimals: 17, + minimal_balance: 1, + }) + ); + }); +} + +#[test] +fn register_erc20_asset_should_not_work() { + ExtBuilder::default() + .balances(vec![(alice(), 1_000_000_000_000)]) + .build() + .execute_with(|| { + deploy_contracts(); + deploy_contracts_same_prefix(); + assert_ok!(AssetRegistry::register_erc20_asset( + Origin::signed(CouncilAccount::get()), + erc20_address(), + 1 + )); assert_noop!( - with_transaction_result(|| -> DispatchResult { - let mut addr = erc20_address(); - let addr = addr.as_bytes_mut(); - addr[19] += 1; - EvmErc20InfoMapping::::set_erc20_mapping(EvmAddress::from_slice(addr)) - }), - Error::::CurrencyIdExisted, + AssetRegistry::register_erc20_asset( + Origin::signed(CouncilAccount::get()), + erc20_address_same_prefix(), + 1 + ), + Error::::AssetIdExisted ); assert_noop!( - with_transaction_result(|| -> DispatchResult { - EvmErc20InfoMapping::::set_erc20_mapping(erc20_address_not_exists()) - }), + AssetRegistry::register_erc20_asset( + Origin::signed(CouncilAccount::get()), + erc20_address_not_exists(), + 1 + ), module_evm_bridge::Error::::InvalidReturnValue, ); }); } #[test] -fn get_evm_address_works() { +fn update_erc20_asset_work() { ExtBuilder::default() .balances(vec![(alice(), 1_000_000_000_000)]) .build() .execute_with(|| { deploy_contracts(); - assert_ok!(with_transaction_result(|| -> DispatchResult { - EvmErc20InfoMapping::::set_erc20_mapping(erc20_address()) + assert_ok!(AssetRegistry::register_erc20_asset( + Origin::signed(CouncilAccount::get()), + erc20_address(), + 1 + )); + + assert_ok!(AssetRegistry::update_erc20_asset( + Origin::signed(CouncilAccount::get()), + erc20_address(), + Box::new(AssetMetadata { + name: b"New Token Name".to_vec(), + symbol: b"NTN".to_vec(), + decimals: 13, + minimal_balance: 2, + }) + )); + + System::assert_last_event(Event::AssetRegistry(crate::Event::AssetUpdated { + asset_id: AssetIds::Erc20(erc20_address()), + metadata: AssetMetadata { + name: b"New Token Name".to_vec(), + symbol: b"NTN".to_vec(), + decimals: 13, + minimal_balance: 2, + }, })); + assert_eq!( - EvmErc20InfoMapping::::get_evm_address(DexShare::Erc20(erc20_address()).into()), - Some(erc20_address()) + AssetMetadatas::::get(AssetIds::Erc20(erc20_address())), + Some(AssetMetadata { + name: b"New Token Name".to_vec(), + symbol: b"NTN".to_vec(), + decimals: 13, + minimal_balance: 2, + }) ); - - assert_eq!(EvmErc20InfoMapping::::get_evm_address(u32::default()), None); }); } +#[test] +fn update_erc20_asset_should_not_work() { + ExtBuilder::default().build().execute_with(|| { + assert_noop!( + AssetRegistry::update_stable_asset( + Origin::signed(CouncilAccount::get()), + 0, + Box::new(AssetMetadata { + name: b"New Token Name".to_vec(), + symbol: b"NTN".to_vec(), + decimals: 13, + minimal_balance: 2, + }) + ), + Error::::AssetIdNotExists + ); + }); +} + #[test] fn name_works() { ExtBuilder::default() @@ -521,9 +605,11 @@ fn name_works() { .build() .execute_with(|| { deploy_contracts(); - assert_ok!(with_transaction_result(|| -> DispatchResult { - EvmErc20InfoMapping::::set_erc20_mapping(erc20_address()) - })); + assert_ok!(AssetRegistry::register_erc20_asset( + Origin::signed(CouncilAccount::get()), + erc20_address(), + 1 + )); assert_eq!( EvmErc20InfoMapping::::name(CurrencyId::Token(TokenSymbol::ACA)), Some(b"Acala".to_vec()) @@ -577,9 +663,11 @@ fn symbol_works() { .build() .execute_with(|| { deploy_contracts(); - assert_ok!(with_transaction_result(|| -> DispatchResult { - EvmErc20InfoMapping::::set_erc20_mapping(erc20_address()) - })); + assert_ok!(AssetRegistry::register_erc20_asset( + Origin::signed(CouncilAccount::get()), + erc20_address(), + 1 + )); assert_eq!( EvmErc20InfoMapping::::symbol(CurrencyId::Token(TokenSymbol::ACA)), Some(b"ACA".to_vec()) @@ -648,9 +736,11 @@ fn decimals_works() { .build() .execute_with(|| { deploy_contracts(); - assert_ok!(with_transaction_result(|| -> DispatchResult { - EvmErc20InfoMapping::::set_erc20_mapping(erc20_address()) - })); + assert_ok!(AssetRegistry::register_erc20_asset( + Origin::signed(CouncilAccount::get()), + erc20_address(), + 1 + )); assert_eq!( EvmErc20InfoMapping::::decimals(CurrencyId::Token(TokenSymbol::ACA)), Some(12) @@ -711,9 +801,11 @@ fn encode_evm_address_works() { .build() .execute_with(|| { deploy_contracts(); - assert_ok!(with_transaction_result(|| -> DispatchResult { - EvmErc20InfoMapping::::set_erc20_mapping(erc20_address()) - })); + assert_ok!(AssetRegistry::register_erc20_asset( + Origin::signed(CouncilAccount::get()), + erc20_address(), + 1 + )); // Token assert_eq!( @@ -823,9 +915,11 @@ fn decode_evm_address_works() { .build() .execute_with(|| { deploy_contracts(); - assert_ok!(with_transaction_result(|| -> DispatchResult { - EvmErc20InfoMapping::::set_erc20_mapping(erc20_address()) - })); + assert_ok!(AssetRegistry::register_erc20_asset( + Origin::signed(CouncilAccount::get()), + erc20_address(), + 1 + )); // Token assert_eq!( diff --git a/modules/asset-registry/src/weights.rs b/modules/asset-registry/src/weights.rs index 8d9d47fef..4da20df6b 100644 --- a/modules/asset-registry/src/weights.rs +++ b/modules/asset-registry/src/weights.rs @@ -50,6 +50,8 @@ pub trait WeightInfo { fn update_foreign_asset() -> Weight; fn register_stable_asset() -> Weight; fn update_stable_asset() -> Weight; + fn register_erc20_asset() -> Weight; + fn update_erc20_asset() -> Weight; } /// Weights for module_asset_registry using the Acala node and recommended hardware. @@ -75,6 +77,16 @@ impl WeightInfo for AcalaWeight { .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } + fn register_erc20_asset() -> Weight { + (23_399_000 as Weight) + .saturating_add(T::DbWeight::get().reads(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) + } + fn update_erc20_asset() -> Weight { + (21_479_000 as Weight) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } } // For backwards compatibility and tests @@ -99,4 +111,14 @@ impl WeightInfo for () { .saturating_add(RocksDbWeight::get().reads(1 as Weight)) .saturating_add(RocksDbWeight::get().writes(1 as Weight)) } + fn register_erc20_asset() -> Weight { + (23_399_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(2 as Weight)) + .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + } + fn update_erc20_asset() -> Weight { + (21_479_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(1 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } } diff --git a/modules/dex/src/lib.rs b/modules/dex/src/lib.rs index 5b0c7d12e..b0dd6eac6 100644 --- a/modules/dex/src/lib.rs +++ b/modules/dex/src/lib.rs @@ -511,14 +511,6 @@ pub mod module { Error::::NotAllowedList ); - // TODO: Remove this in another PR - if let CurrencyId::Erc20(address) = currency_id_a { - T::Erc20InfoMapping::set_erc20_mapping(address)?; - } - if let CurrencyId::Erc20(address) = currency_id_b { - T::Erc20InfoMapping::set_erc20_mapping(address)?; - } - let check_asset_registry = |currency_id: CurrencyId| match currency_id { CurrencyId::Erc20(_) | CurrencyId::ForeignAsset(_) => T::Erc20InfoMapping::name(currency_id) .map(|_| ()) diff --git a/modules/support/src/lib.rs b/modules/support/src/lib.rs index 386b8cd9d..b0a6200d9 100644 --- a/modules/support/src/lib.rs +++ b/modules/support/src/lib.rs @@ -497,6 +497,8 @@ pub trait AddressMapping { /// A mapping between AssetId and AssetMetadata. pub trait AssetIdMapping { + /// Returns the AssetMetadata associated with a given contract address. + fn get_erc20_asset_metadata(contract: EvmAddress) -> Option; /// Returns the AssetMetadata associated with a given StableAssetPoolId. fn get_stable_asset_metadata(stable_asset_id: StableAssetPoolId) -> Option; /// Returns the AssetMetadata associated with a given ForeignAssetId. @@ -510,11 +512,6 @@ pub trait AssetIdMapping DispatchResult; - /// Returns the EvmAddress associated with a given u32. - fn get_evm_address(currency_id: u32) -> Option; /// Returns the name associated with a given CurrencyId. /// If CurrencyId is CurrencyId::DexShare and contain DexShare::Erc20, /// the EvmAddress must have been mapped. @@ -539,14 +536,6 @@ pub trait Erc20InfoMapping { #[cfg(feature = "std")] impl Erc20InfoMapping for () { - fn set_erc20_mapping(_address: EvmAddress) -> DispatchResult { - Err(DispatchError::Other("unimplemented CurrencyIdMapping")) - } - - fn get_evm_address(_currency_id: u32) -> Option { - None - } - fn name(_currency_id: CurrencyId) -> Option> { None } diff --git a/modules/support/src/mocks.rs b/modules/support/src/mocks.rs index 8ae0229c0..5bec5cc1a 100644 --- a/modules/support/src/mocks.rs +++ b/modules/support/src/mocks.rs @@ -18,7 +18,6 @@ use crate::{AddressMapping, CurrencyId, Erc20InfoMapping}; use codec::Encode; -use frame_support::pallet_prelude::DispatchResult; use primitives::{ currency::TokenInfo, evm::{is_mirrored_tokens_address_prefix, EvmAddress, H160_POSITION_TOKEN}, @@ -66,14 +65,6 @@ impl AddressMapping for MockAddressMapping { pub struct MockErc20InfoMapping; impl Erc20InfoMapping for MockErc20InfoMapping { - fn set_erc20_mapping(_address: EvmAddress) -> DispatchResult { - Ok(()) - } - - fn get_evm_address(_currency_id: u32) -> Option { - Some(EvmAddress::default()) - } - fn name(currency_id: CurrencyId) -> Option> { currency_id.name().map(|v| v.as_bytes().to_vec()) } diff --git a/primitives/src/currency.rs b/primitives/src/currency.rs index 4351e25f3..9ff43c0c4 100644 --- a/primitives/src/currency.rs +++ b/primitives/src/currency.rs @@ -309,6 +309,8 @@ impl From for u32 { bytes[3] = token.into(); } DexShare::Erc20(address) => { + // Use first 4 non-zero bytes as u32 to the mapping between u32 and evm address. + // Take the first 4 non-zero bytes, if it is less than 4, add 0 to the left. let is_zero = |&&d: &&u8| -> bool { d == 0 }; let leading_zeros = address.as_bytes().iter().take_while(is_zero).count(); let index = if leading_zeros > 16 { 16 } else { leading_zeros }; diff --git a/primitives/src/evm.rs b/primitives/src/evm.rs index ca45b386a..a3cab411b 100644 --- a/primitives/src/evm.rs +++ b/primitives/src/evm.rs @@ -59,15 +59,6 @@ pub struct ExecutionInfo { pub type CallInfo = ExecutionInfo>; pub type CreateInfo = ExecutionInfo; -#[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] -#[cfg_attr(feature = "std", derive(Serialize, Deserialize))] -pub struct Erc20Info { - pub address: EvmAddress, - pub name: Vec, - pub symbol: Vec, - pub decimals: u8, -} - #[derive(Clone, Eq, PartialEq, Encode, Decode, RuntimeDebug, TypeInfo)] #[cfg_attr(feature = "std", derive(Serialize, Deserialize))] pub struct EstimateResourcesRequest { diff --git a/runtime/acala/src/lib.rs b/runtime/acala/src/lib.rs index 03ddcc3b6..467a5c912 100644 --- a/runtime/acala/src/lib.rs +++ b/runtime/acala/src/lib.rs @@ -762,9 +762,10 @@ parameter_type_with_key! { // use the ED of currency_id_0 as the ED of lp token. if currency_id_0 == GetNativeCurrencyId::get() { NativeTokenExistentialDeposit::get() - } else if let CurrencyId::Erc20(_) = currency_id_0 { + } else if let CurrencyId::Erc20(address) = currency_id_0 { // LP token with erc20 - 1 + AssetIdMaps::::get_erc20_asset_metadata(address). + map_or(Balance::max_value(), |metatata| metatata.minimal_balance) } else { Self::get(¤cy_id_0) } diff --git a/runtime/acala/src/weights/module_asset_registry.rs b/runtime/acala/src/weights/module_asset_registry.rs index f0b3bd083..e25c91b78 100644 --- a/runtime/acala/src/weights/module_asset_registry.rs +++ b/runtime/acala/src/weights/module_asset_registry.rs @@ -19,7 +19,7 @@ //! Autogenerated weights for module_asset_registry //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-12-23, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2021-12-24, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("acala-latest"), DB CACHE: 128 // Executed Command: @@ -47,22 +47,32 @@ use sp_std::marker::PhantomData; pub struct WeightInfo(PhantomData); impl module_asset_registry::WeightInfo for WeightInfo { fn register_foreign_asset() -> Weight { - (42_225_000 as Weight) + (42_272_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } fn update_foreign_asset() -> Weight { - (37_714_000 as Weight) + (37_293_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } fn register_stable_asset() -> Weight { - (28_833_000 as Weight) + (30_198_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } fn update_stable_asset() -> Weight { - (27_084_000 as Weight) + (27_312_000 as Weight) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + fn register_erc20_asset() -> Weight { + (295_173_000 as Weight) + .saturating_add(T::DbWeight::get().reads(11 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) + } + fn update_erc20_asset() -> Weight { + (33_521_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } diff --git a/runtime/integration-tests/src/evm.rs b/runtime/integration-tests/src/evm.rs index 61085009f..f6c5a4c9f 100644 --- a/runtime/integration-tests/src/evm.rs +++ b/runtime/integration-tests/src/evm.rs @@ -70,6 +70,11 @@ pub fn deploy_erc20_contracts() { })); assert_ok!(EVM::deploy_free(Origin::root(), erc20_address_0())); + assert_ok!(AssetRegistry::register_erc20_asset( + Origin::root(), + erc20_address_0(), + 1 + )); assert_ok!(EVM::create(Origin::signed(alice()), code, 0, 2100_000, 100000)); @@ -88,6 +93,11 @@ pub fn deploy_erc20_contracts() { })); assert_ok!(EVM::deploy_free(Origin::root(), erc20_address_1())); + assert_ok!(AssetRegistry::register_erc20_asset( + Origin::root(), + erc20_address_1(), + 1 + )); } fn deploy_contract(account: AccountId) -> Result { diff --git a/runtime/karura/src/lib.rs b/runtime/karura/src/lib.rs index 4f222015c..b30e5ef35 100644 --- a/runtime/karura/src/lib.rs +++ b/runtime/karura/src/lib.rs @@ -771,9 +771,10 @@ parameter_type_with_key! { // use the ED of currency_id_0 as the ED of lp token. if currency_id_0 == GetNativeCurrencyId::get() { NativeTokenExistentialDeposit::get() - } else if let CurrencyId::Erc20(_) = currency_id_0 { + } else if let CurrencyId::Erc20(address) = currency_id_0 { // LP token with erc20 - 1 + AssetIdMaps::::get_erc20_asset_metadata(address). + map_or(Balance::max_value(), |metatata| metatata.minimal_balance) } else { Self::get(¤cy_id_0) } @@ -783,7 +784,7 @@ parameter_type_with_key! { AssetIdMaps::::get_stable_asset_metadata(*stable_asset_id). map_or(Balance::max_value(), |metatata| metatata.minimal_balance) }, - CurrencyId::LiquidCroadloan(_) => Balance::max_value(), // TODO: unsupported + CurrencyId::LiquidCroadloan(_) => ExistentialDeposits::get(&CurrencyId::Token(TokenSymbol::KSM)), // the same as KSM CurrencyId::ForeignAsset(foreign_asset_id) => { AssetIdMaps::::get_foreign_asset_metadata(*foreign_asset_id). map_or(Balance::max_value(), |metatata| metatata.minimal_balance) diff --git a/runtime/karura/src/weights/module_asset_registry.rs b/runtime/karura/src/weights/module_asset_registry.rs index 25d2684e8..efd0f984b 100644 --- a/runtime/karura/src/weights/module_asset_registry.rs +++ b/runtime/karura/src/weights/module_asset_registry.rs @@ -19,7 +19,7 @@ //! Autogenerated weights for module_asset_registry //! //! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev -//! DATE: 2021-12-23, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! DATE: 2021-12-24, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` //! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("karura-dev"), DB CACHE: 128 // Executed Command: @@ -47,22 +47,32 @@ use sp_std::marker::PhantomData; pub struct WeightInfo(PhantomData); impl module_asset_registry::WeightInfo for WeightInfo { fn register_foreign_asset() -> Weight { - (39_006_000 as Weight) + (41_564_000 as Weight) .saturating_add(T::DbWeight::get().reads(4 as Weight)) .saturating_add(T::DbWeight::get().writes(4 as Weight)) } fn update_foreign_asset() -> Weight { - (34_267_000 as Weight) + (36_823_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } fn register_stable_asset() -> Weight { - (27_149_000 as Weight) + (29_213_000 as Weight) .saturating_add(T::DbWeight::get().reads(2 as Weight)) .saturating_add(T::DbWeight::get().writes(2 as Weight)) } fn update_stable_asset() -> Weight { - (25_181_000 as Weight) + (26_713_000 as Weight) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + fn register_erc20_asset() -> Weight { + (289_102_000 as Weight) + .saturating_add(T::DbWeight::get().reads(11 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) + } + fn update_erc20_asset() -> Weight { + (32_742_000 as Weight) .saturating_add(T::DbWeight::get().reads(1 as Weight)) .saturating_add(T::DbWeight::get().writes(1 as Weight)) } diff --git a/runtime/mandala/src/benchmarking/asset_registry.rs b/runtime/mandala/src/benchmarking/asset_registry.rs index 4fd2567ee..bfbd4eeaa 100644 --- a/runtime/mandala/src/benchmarking/asset_registry.rs +++ b/runtime/mandala/src/benchmarking/asset_registry.rs @@ -16,14 +16,40 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -use crate::{AssetRegistry, Runtime}; +use crate::{dollar, AccountId, AssetRegistry, CurrencyId, GetNativeCurrencyId, Origin, Runtime, EVM}; +use super::utils::set_balance; +use frame_support::assert_ok; use frame_system::RawOrigin; use module_asset_registry::AssetMetadata; +use module_evm::EvmAddress; +use module_support::AddressMapping; use orml_benchmarking::runtime_benchmarks; -use sp_std::boxed::Box; +use sp_std::{boxed::Box, str::FromStr}; use xcm::{v1::MultiLocation, VersionedMultiLocation}; +const NATIVE: CurrencyId = GetNativeCurrencyId::get(); + +pub fn alice() -> AccountId { + ::AddressMapping::get_account_id(&alice_evm_addr()) +} +pub fn alice_evm_addr() -> EvmAddress { + EvmAddress::from_str("1000000000000000000000000000000000000001").unwrap() +} + +pub fn erc20_address() -> EvmAddress { + EvmAddress::from_str("0x5dddfce53ee040d9eb21afbc0ae1bb4dbb0ba643").unwrap() +} + +pub fn deploy_contract() { + //let alice_account = alice_account_id(); + set_balance(NATIVE, &alice(), 1_000_000 * dollar(NATIVE)); + // modules/evm-bridge/src/erc20_demo_contract + let contract = hex_literal::hex!("60806040523480156200001157600080fd5b506040518060800160405280605881526020016200152c605891396040518060400160405280600981526020017f54657374546f6b656e000000000000000000000000000000000000000000000081525081600390805190602001906200007a9291906200037c565b508060049080519060200190620000939291906200037c565b506012600560006101000a81548160ff021916908360ff1602179055505050620000da731000000000000000000000000000000000000001612710620000f260201b60201c565b620000ec6011620002d060201b60201c565b6200042b565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141562000196576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f45524332303a206d696e7420746f20746865207a65726f20616464726573730081525060200191505060405180910390fd5b620001aa60008383620002ee60201b60201c565b620001c681600254620002f360201b62000f2d1790919060201c565b60028190555062000224816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054620002f360201b62000f2d1790919060201c565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b80600560006101000a81548160ff021916908360ff16021790555050565b505050565b60008082840190508381101562000372576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620003bf57805160ff1916838001178555620003f0565b82800160010185558215620003f0579182015b82811115620003ef578251825591602001919060010190620003d2565b5b509050620003ff919062000403565b5090565b6200042891905b80821115620004245760008160009055506001016200040a565b5090565b90565b6110f1806200043b6000396000f3fe608060405234801561001057600080fd5b50600436106100a95760003560e01c80633950935111610071578063395093511461025f57806370a08231146102c557806395d89b411461031d578063a457c2d7146103a0578063a9059cbb14610406578063dd62ed3e1461046c576100a9565b806306fdde03146100ae578063095ea7b31461013157806318160ddd1461019757806323b872dd146101b5578063313ce5671461023b575b600080fd5b6100b66104e4565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100f65780820151818401526020810190506100db565b50505050905090810190601f1680156101235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61017d6004803603604081101561014757600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610586565b604051808215151515815260200191505060405180910390f35b61019f6105a4565b6040518082815260200191505060405180910390f35b610221600480360360608110156101cb57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506105ae565b604051808215151515815260200191505060405180910390f35b610243610687565b604051808260ff1660ff16815260200191505060405180910390f35b6102ab6004803603604081101561027557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061069e565b604051808215151515815260200191505060405180910390f35b610307600480360360208110156102db57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610751565b6040518082815260200191505060405180910390f35b610325610799565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561036557808201518184015260208101905061034a565b50505050905090810190601f1680156103925780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103ec600480360360408110156103b657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061083b565b604051808215151515815260200191505060405180910390f35b6104526004803603604081101561041c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610908565b604051808215151515815260200191505060405180910390f35b6104ce6004803603604081101561048257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610926565b6040518082815260200191505060405180910390f35b606060038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561057c5780601f106105515761010080835404028352916020019161057c565b820191906000526020600020905b81548152906001019060200180831161055f57829003601f168201915b5050505050905090565b600061059a6105936109ad565b84846109b5565b6001905092915050565b6000600254905090565b60006105bb848484610bac565b61067c846105c76109ad565b6106778560405180606001604052806028815260200161102660289139600160008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600061062d6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b600190509392505050565b6000600560009054906101000a900460ff16905090565b60006107476106ab6109ad565b8461074285600160006106bc6109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6109b5565b6001905092915050565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b606060048054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156108315780601f1061080657610100808354040283529160200191610831565b820191906000526020600020905b81548152906001019060200180831161081457829003601f168201915b5050505050905090565b60006108fe6108486109ad565b846108f98560405180606001604052806025815260200161109760259139600160006108726109ad565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6109b5565b6001905092915050565b600061091c6109156109ad565b8484610bac565b6001905092915050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610a3b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806110736024913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610ac1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180610fde6022913960400191505060405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610c32576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602581526020018061104e6025913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610cb8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180610fbb6023913960400191505060405180910390fd5b610cc3838383610fb5565b610d2e81604051806060016040528060268152602001611000602691396000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e6d9092919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550610dc1816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610f2d90919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6000838311158290610f1a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610edf578082015181840152602081019050610ec4565b50505050905090810190601f168015610f0c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b600080828401905083811015610fab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b50505056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220cd01ee5a91a881794c7b04ba72b192caf5c93474b9dbe4b16207f9ef5ccc7e2364736f6c634300060200336c6f6e6720737472696e67206e616d652c206c6f6e6720737472696e67206e616d652c206c6f6e6720737472696e67206e616d652c206c6f6e6720737472696e67206e616d652c206c6f6e6720737472696e67206e616d65").to_vec(); + assert_ok!(EVM::create(Origin::signed(alice()), contract, 0, 2_100_000, 1_000_000)); + assert_ok!(EVM::deploy_free(Origin::root(), erc20_address())); +} + runtime_benchmarks! { { Runtime, module_asset_registry } @@ -74,6 +100,22 @@ runtime_benchmarks! { AssetRegistry::register_stable_asset(RawOrigin::Root.into(), Box::new(asset_metadata.clone()))?; }: _(RawOrigin::Root, 0, Box::new(asset_metadata)) + + register_erc20_asset { + deploy_contract(); + }: _(RawOrigin::Root, erc20_address(), 1) + + update_erc20_asset { + let asset_metadata = AssetMetadata { + name: b"Token Name".to_vec(), + symbol: b"TN".to_vec(), + decimals: 12, + minimal_balance: 1, + }; + + deploy_contract(); + AssetRegistry::register_erc20_asset(RawOrigin::Root.into(), erc20_address(), 1)?; + }: _(RawOrigin::Root, erc20_address(), Box::new(asset_metadata)) } #[cfg(test)] diff --git a/runtime/mandala/src/lib.rs b/runtime/mandala/src/lib.rs index 059b3dfb9..d6875f65a 100644 --- a/runtime/mandala/src/lib.rs +++ b/runtime/mandala/src/lib.rs @@ -798,9 +798,10 @@ parameter_type_with_key! { // use the ED of currency_id_0 as the ED of lp token. if currency_id_0 == GetNativeCurrencyId::get() { NativeTokenExistentialDeposit::get() - } else if let CurrencyId::Erc20(_) = currency_id_0 { + } else if let CurrencyId::Erc20(address) = currency_id_0 { // LP token with erc20 - 1 + AssetIdMaps::::get_erc20_asset_metadata(address). + map_or(Balance::max_value(), |metatata| metatata.minimal_balance) } else { Self::get(¤cy_id_0) } diff --git a/runtime/mandala/src/weights/module_asset_registry.rs b/runtime/mandala/src/weights/module_asset_registry.rs index 2e3b2a1c5..2e7edef48 100644 --- a/runtime/mandala/src/weights/module_asset_registry.rs +++ b/runtime/mandala/src/weights/module_asset_registry.rs @@ -66,4 +66,14 @@ impl module_asset_registry::WeightInfo for WeightInfo Weight { + (23_499_000 as Weight) + .saturating_add(T::DbWeight::get().reads(2 as Weight)) + .saturating_add(T::DbWeight::get().writes(2 as Weight)) + } + fn update_erc20_asset() -> Weight { + (21_399_000 as Weight) + .saturating_add(T::DbWeight::get().reads(1 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } }