difftreelog
feat eth address mapping
in: master
5 files changed
pallets/nft/src/eth/account.rsdiffbeforeafterboth--- /dev/null
+++ b/pallets/nft/src/eth/account.rs
@@ -0,0 +1,135 @@
+use crate::Config;
+use codec::{Encode, EncodeLike, Decode};
+use sp_core::{H160, H256, crypto::AccountId32};
+use core::cmp::Ordering;
+#[cfg(feature = "std")]
+use serde::{Serialize, Deserialize};
+use pallet_evm::AddressMapping;
+use sp_std::vec::Vec;
+use sp_std::clone::Clone;
+
+pub trait CrossAccountId<AccountId>:
+ Encode + EncodeLike + Decode +
+ Clone + PartialEq + Ord + core::fmt::Debug // +
+ // Serialize + Deserialize<'static>
+{
+ fn as_sub(&self) -> &AccountId;
+ fn as_eth(&self) -> &H160;
+
+ fn from_sub(account: AccountId) -> Self;
+ fn from_eth(account: H160) -> Self;
+}
+
+#[derive(Eq)]
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+pub struct BasicCrossAccountId<T: Config> {
+ /// If true - then ethereum is canonical encoding
+ from_ethereum: bool,
+ substrate: T::AccountId,
+ ethereum: H160,
+}
+
+impl<T: Config> core::fmt::Debug for BasicCrossAccountId<T> {
+ fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
+ if self.from_ethereum {
+ fmt.debug_tuple("CrossAccountId::Ethereum")
+ .field(&self.ethereum)
+ .finish()
+ } else {
+ fmt.debug_tuple("CrossAccountId::Substrate")
+ .field(&self.substrate)
+ .finish()
+ }
+ }
+}
+
+impl<T: Config> PartialOrd for BasicCrossAccountId<T> {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ Some(self.substrate.cmp(&other.substrate))
+ }
+}
+
+impl<T: Config> Ord for BasicCrossAccountId<T> {
+ fn cmp(&self, other: &Self) -> Ordering {
+ self.partial_cmp(other).expect("substrate account is total ordered")
+ }
+}
+
+impl<T: Config> PartialEq for BasicCrossAccountId<T> {
+ fn eq(&self, other: &Self) -> bool {
+ if self.from_ethereum == other.from_ethereum {
+ self.substrate == other.substrate && self.ethereum == other.ethereum
+ } else if self.from_ethereum {
+ // ethereum is canonical encoding, but we need to compare derived address
+ self.substrate == other.substrate
+ } else {
+ self.ethereum == other.ethereum
+ }
+ }
+}
+impl<T: Config> Clone for BasicCrossAccountId<T> {
+ fn clone(&self) -> Self {
+ Self {
+ from_ethereum: self.from_ethereum,
+ substrate: self.substrate.clone(),
+ ethereum: self.ethereum,
+ }
+ }
+}
+impl<T: Config> Encode for BasicCrossAccountId<T> {
+ fn encode(&self) -> Vec<u8> {
+ let as_result = if !self.from_ethereum {
+ Ok(self.substrate.clone())
+ } else {
+ Err(self.ethereum)
+ };
+ as_result.encode()
+ }
+}
+impl<T: Config> EncodeLike for BasicCrossAccountId<T> {}
+impl<T: Config> Decode for BasicCrossAccountId<T> {
+ fn decode<I>(input: &mut I) -> Result<Self, codec::Error>
+ where I: codec::Input
+ {
+ Ok(match <Result<T::AccountId, H160>>::decode(input)? {
+ Ok(s) => Self::from_sub(s),
+ Err(e) => Self::from_eth(e),
+ })
+ }
+}
+impl<T: Config> CrossAccountId<T::AccountId> for BasicCrossAccountId<T> {
+ fn as_sub(&self) -> &T::AccountId {
+ &self.substrate
+ }
+ fn as_eth(&self) -> &H160 {
+ &self.ethereum
+ }
+ fn from_sub(substrate: T::AccountId) -> Self {
+ Self {
+ ethereum: T::EvmBackwardsAddressMapping::from_account_id(substrate.clone()),
+ substrate,
+ from_ethereum: false,
+ }
+ }
+ fn from_eth(ethereum: H160) -> Self {
+ Self {
+ ethereum,
+ substrate: T::EvmAddressMapping::into_account_id(ethereum),
+ from_ethereum: true,
+ }
+ }
+}
+
+pub trait EvmBackwardsAddressMapping<AccountId> {
+ fn from_account_id(account_id: AccountId) -> H160;
+}
+
+/// Should have same mapping as EnsureAddressTruncated
+pub struct MapBackwardsAddressTruncated;
+impl EvmBackwardsAddressMapping<AccountId32> for MapBackwardsAddressTruncated {
+ fn from_account_id(account_id: AccountId32) -> H160 {
+ let mut out = [0; 20];
+ out.copy_from_slice(&(account_id.as_ref() as &[u8])[0..20]);
+ H160(out)
+ }
+}
\ No newline at end of file
pallets/nft/src/eth/mod.rsdiffbeforeafterboth--- /dev/null
+++ b/pallets/nft/src/eth/mod.rs
@@ -0,0 +1,2 @@
+pub mod account;
+use account::CrossAccountId;
pallets/nft/src/lib.rsdiffbeforeafterboth778#![cfg_attr(not(feature = "std"), no_std)]8#![cfg_attr(not(feature = "std"), no_std)]910#[cfg(feature = "std")]11pub use std::*;12913#[cfg(feature = "std")]10#[cfg(feature = "std")]14pub use serde::*;11pub use serde::*;33};30};343135use frame_system::{self as system, ensure_signed, ensure_root};32use frame_system::{self as system, ensure_signed, ensure_root};33use sp_core::{H160, H256};36use sp_runtime::sp_std::prelude::Vec;34use sp_runtime::sp_std::prelude::Vec;37use sp_runtime::{35use sp_runtime::{38 traits::{36 traits::{45};43};46use sp_runtime::traits::StaticLookup;44use sp_runtime::traits::StaticLookup;47use pallet_contracts::chain_extension::UncheckedFrom;45use pallet_contracts::chain_extension::UncheckedFrom;46use pallet_evm::AddressMapping;48use pallet_transaction_payment::OnChargeTransaction;47use pallet_transaction_payment::OnChargeTransaction;494850#[cfg(test)]49#[cfg(test)]54mod tests;53mod tests;555456mod default_weights;55mod default_weights;56mod eth;5758pub use eth::account::*;575958pub const MAX_DECIMAL_POINTS: DecimalPoints = 30;60pub const MAX_DECIMAL_POINTS: DecimalPoints = 30;59pub const MAX_REFUNGIBLE_PIECES: u128 = 1_000_000_000_000_000_000_000;61pub const MAX_REFUNGIBLE_PIECES: u128 = 1_000_000_000_000_000_000_000;164#[derive(Encode, Decode, Clone, PartialEq)]166#[derive(Encode, Decode, Clone, PartialEq)]165#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]167#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]166pub struct Collection<T: Config> {168pub struct Collection<T: Config> {167 pub owner: T::AccountId,169 pub owner: T::CrossAccountId,168 pub mode: CollectionMode,170 pub mode: CollectionMode,169 pub access: AccessMode,171 pub access: AccessMode,170 pub decimal_points: DecimalPoints,172 pub decimal_points: DecimalPoints,174 pub mint_mode: bool,176 pub mint_mode: bool,175 pub offchain_schema: Vec<u8>,177 pub offchain_schema: Vec<u8>,176 pub schema_version: SchemaVersion,178 pub schema_version: SchemaVersion,177 pub sponsorship: SponsorshipState<T::AccountId>,179 pub sponsorship: SponsorshipState<T::CrossAccountId>,178 pub limits: CollectionLimits<T::BlockNumber>, // Collection private restrictions 180 pub limits: CollectionLimits<T::BlockNumber>, // Collection private restrictions 179 pub variable_on_chain_schema: Vec<u8>, //181 pub variable_on_chain_schema: Vec<u8>, //180 pub const_on_chain_schema: Vec<u8>, //182 pub const_on_chain_schema: Vec<u8>, //461 /// Weight information for extrinsics in this pallet.463 /// Weight information for extrinsics in this pallet.462 type WeightInfo: WeightInfo;464 type WeightInfo: WeightInfo;463465466 type EvmAddressMapping: pallet_evm::AddressMapping<Self::AccountId>;467 type EvmBackwardsAddressMapping: EvmBackwardsAddressMapping<Self::AccountId>;468 type EvmWithdrawOrigin: pallet_evm::EnsureAddressOrigin<Self::Origin, Success = Self::AccountId>;469470 type CrossAccountId: CrossAccountId<Self::AccountId>;464 type Currency: Currency<Self::AccountId>;471 type Currency: Currency<Self::AccountId>;465 type CollectionCreationPrice: Get<<<Self as Config>::Currency as Currency<Self::AccountId>>::Balance>;472 type CollectionCreationPrice: Get<<<Self as Config>::Currency as Currency<Self::AccountId>>::Balance>;466 type TreasuryAccountId: Get<Self::AccountId>;473 type TreasuryAccountId: Get<Self::AccountId>;525 pub CollectionById get(fn collection_id) config(): map hasher(blake2_128_concat) CollectionId => Option<Collection<T>> = None;532 pub CollectionById get(fn collection_id) config(): map hasher(blake2_128_concat) CollectionId => Option<Collection<T>> = None;526 /// List of collection admins533 /// List of collection admins527 /// Collection id (controlled?2)534 /// Collection id (controlled?2)528 pub AdminList get(fn admin_list_collection): map hasher(blake2_128_concat) CollectionId => Vec<T::AccountId>;535 pub AdminList get(fn admin_list_collection): map hasher(blake2_128_concat) CollectionId => Vec<T::CrossAccountId>;529 /// Whitelisted collection users536 /// Whitelisted collection users530 /// Collection id (controlled?2), user id (controlled?3)537 /// Collection id (controlled?2), user id (controlled?3)531 pub WhiteList get(fn white_list): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) T::AccountId => bool;538 pub WhiteList get(fn white_list): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) T::AccountId => bool;542549543 //#region Item collections550 //#region Item collections544 /// Collection id (controlled?2), token id (controlled?1)551 /// Collection id (controlled?2), token id (controlled?1)545 pub NftItemList get(fn nft_item_id) config(): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<NftItemType<T::AccountId>>;552 pub NftItemList get(fn nft_item_id) config(): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<NftItemType<T::CrossAccountId>>;546 /// Collection id (controlled?2), owner (controlled?2)553 /// Collection id (controlled?2), owner (controlled?2)547 pub FungibleItemList get(fn fungible_item_id) config(): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) T::AccountId => FungibleItemType;554 pub FungibleItemList get(fn fungible_item_id) config(): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) T::AccountId => FungibleItemType;548 /// Collection id (controlled?2), token id (controlled?1)555 /// Collection id (controlled?2), token id (controlled?1)549 pub ReFungibleItemList get(fn refungible_item_id) config(): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<ReFungibleItemType<T::AccountId>>;556 pub ReFungibleItemList get(fn refungible_item_id) config(): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<ReFungibleItemType<T::CrossAccountId>>;550 //#endregion557 //#endregion551558552 //#region Index list559 //#region Index list610decl_event!(617decl_event!(611 pub enum Event<T>618 pub enum Event<T>612 where619 where613 AccountId = <T as system::Config>::AccountId,620 CrossAccountId = <T as Config>::CrossAccountId,614 {621 {615 /// New collection was created622 /// New collection was created616 /// 623 /// 621 /// * mode: [CollectionMode] converted into u8.628 /// * mode: [CollectionMode] converted into u8.622 /// 629 /// 623 /// * account_id: Collection owner.630 /// * account_id: Collection owner.624 CollectionCreated(CollectionId, u8, AccountId),631 CollectionCreated(CollectionId, u8, CrossAccountId),625632626 /// New item was created.633 /// New item was created.627 /// 634 /// 632 /// * item_id: Id of an item. Unique within the collection.639 /// * item_id: Id of an item. Unique within the collection.633 ///640 ///634 /// * recipient: Owner of newly created item 641 /// * recipient: Owner of newly created item 635 ItemCreated(CollectionId, TokenId, AccountId),642 ItemCreated(CollectionId, TokenId, CrossAccountId),636643637 /// Collection item was burned.644 /// Collection item was burned.638 /// 645 /// 654 /// * recipient: New owner of item661 /// * recipient: New owner of item655 ///662 ///656 /// * amount: Always 1 for NFT663 /// * amount: Always 1 for NFT657 Transfer(CollectionId, TokenId, AccountId, AccountId, u128),664 Transfer(CollectionId, TokenId, CrossAccountId, CrossAccountId, u128),658665659 /// * collection_id666 /// * collection_id660 ///667 ///665 /// * spender672 /// * spender666 ///673 ///667 /// * amount674 /// * amount668 Approved(CollectionId, TokenId, AccountId, AccountId, u128),675 Approved(CollectionId, TokenId, CrossAccountId, CrossAccountId, u128),669 }676 }670);677);671678runtime/src/lib.rsdiffbeforeafterboth--- a/runtime/src/lib.rs
+++ b/runtime/src/lib.rs
@@ -578,6 +578,12 @@
impl pallet_nft::Config for Runtime {
type Event = Event;
type WeightInfo = nft_weights::WeightInfo;
+
+ type EvmWithdrawOrigin = EnsureAddressTruncated;
+ type EvmBackwardsAddressMapping = pallet_nft::MapBackwardsAddressTruncated;
+ type EvmAddressMapping = HashedAddressMapping<Self::Hashing>;
+ type CrossAccountId = pallet_nft::BasicCrossAccountId<Self>;
+
type Currency = Balances;
type CollectionCreationPrice = CollectionCreationPrice;
type TreasuryAccountId = TreasuryAccountId;
runtime_types.jsondiffbeforeafterboth--- a/runtime_types.json
+++ b/runtime_types.json
@@ -1,4 +1,10 @@
{
+ "CrossAccountId": {
+ "_enum": {
+ "substrate": "AccountId",
+ "ethereum": "H160"
+ }
+ },
"AccessMode": {
"_enum": [
"Normal",
@@ -15,31 +21,31 @@
}
},
"Ownership": {
- "Owner": "AccountId",
+ "Owner": "CrossAccountId",
"Fraction": "u128"
},
"FungibleItemType": {
"Value": "u128"
},
"NftItemType": {
- "Owner": "AccountId",
+ "Owner": "CrossAccountId",
"ConstData": "Vec<u8>",
"VariableData": "Vec<u8>"
},
"ReFungibleItemType": {
- "Owner": "Vec<Ownership<AccountId>>",
+ "Owner": "Vec<Ownership<CrossAccountId>>",
"ConstData": "Vec<u8>",
"VariableData": "Vec<u8>"
},
"SponsorshipState": {
"_enum": {
- "Disabled": null,
- "Unconfirmed": "AccountId",
- "Confirmed": "AccountId"
+ "disabled": null,
+ "unconfirmed": "CrossAccountId",
+ "confirmed": "CrossAccountId"
}
},
"Collection": {
- "Owner": "AccountId",
+ "Owner": "CrossAccountId",
"Mode": "CollectionMode",
"Access": "AccessMode",
"DecimalPoints": "DecimalPoints",