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.rsdiffbeforeafterboth--- a/pallets/nft/src/lib.rs
+++ b/pallets/nft/src/lib.rs
@@ -8,9 +8,6 @@
#![cfg_attr(not(feature = "std"), no_std)]
#[cfg(feature = "std")]
-pub use std::*;
-
-#[cfg(feature = "std")]
pub use serde::*;
use core::ops::{Deref, DerefMut};
@@ -33,6 +30,7 @@
};
use frame_system::{self as system, ensure_signed, ensure_root};
+use sp_core::{H160, H256};
use sp_runtime::sp_std::prelude::Vec;
use sp_runtime::{
traits::{
@@ -45,6 +43,7 @@
};
use sp_runtime::traits::StaticLookup;
use pallet_contracts::chain_extension::UncheckedFrom;
+use pallet_evm::AddressMapping;
use pallet_transaction_payment::OnChargeTransaction;
#[cfg(test)]
@@ -54,6 +53,9 @@
mod tests;
mod default_weights;
+mod eth;
+
+pub use eth::account::*;
pub const MAX_DECIMAL_POINTS: DecimalPoints = 30;
pub const MAX_REFUNGIBLE_PIECES: u128 = 1_000_000_000_000_000_000_000;
@@ -164,7 +166,7 @@
#[derive(Encode, Decode, Clone, PartialEq)]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
pub struct Collection<T: Config> {
- pub owner: T::AccountId,
+ pub owner: T::CrossAccountId,
pub mode: CollectionMode,
pub access: AccessMode,
pub decimal_points: DecimalPoints,
@@ -174,7 +176,7 @@
pub mint_mode: bool,
pub offchain_schema: Vec<u8>,
pub schema_version: SchemaVersion,
- pub sponsorship: SponsorshipState<T::AccountId>,
+ pub sponsorship: SponsorshipState<T::CrossAccountId>,
pub limits: CollectionLimits<T::BlockNumber>, // Collection private restrictions
pub variable_on_chain_schema: Vec<u8>, //
pub const_on_chain_schema: Vec<u8>, //
@@ -461,6 +463,11 @@
/// Weight information for extrinsics in this pallet.
type WeightInfo: WeightInfo;
+ type EvmAddressMapping: pallet_evm::AddressMapping<Self::AccountId>;
+ type EvmBackwardsAddressMapping: EvmBackwardsAddressMapping<Self::AccountId>;
+ type EvmWithdrawOrigin: pallet_evm::EnsureAddressOrigin<Self::Origin, Success = Self::AccountId>;
+
+ type CrossAccountId: CrossAccountId<Self::AccountId>;
type Currency: Currency<Self::AccountId>;
type CollectionCreationPrice: Get<<<Self as Config>::Currency as Currency<Self::AccountId>>::Balance>;
type TreasuryAccountId: Get<Self::AccountId>;
@@ -525,7 +532,7 @@
pub CollectionById get(fn collection_id) config(): map hasher(blake2_128_concat) CollectionId => Option<Collection<T>> = None;
/// List of collection admins
/// Collection id (controlled?2)
- pub AdminList get(fn admin_list_collection): map hasher(blake2_128_concat) CollectionId => Vec<T::AccountId>;
+ pub AdminList get(fn admin_list_collection): map hasher(blake2_128_concat) CollectionId => Vec<T::CrossAccountId>;
/// Whitelisted collection users
/// Collection id (controlled?2), user id (controlled?3)
pub WhiteList get(fn white_list): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) T::AccountId => bool;
@@ -542,11 +549,11 @@
//#region Item collections
/// Collection id (controlled?2), token id (controlled?1)
- pub NftItemList get(fn nft_item_id) config(): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<NftItemType<T::AccountId>>;
+ pub NftItemList get(fn nft_item_id) config(): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<NftItemType<T::CrossAccountId>>;
/// Collection id (controlled?2), owner (controlled?2)
pub FungibleItemList get(fn fungible_item_id) config(): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) T::AccountId => FungibleItemType;
/// Collection id (controlled?2), token id (controlled?1)
- pub ReFungibleItemList get(fn refungible_item_id) config(): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<ReFungibleItemType<T::AccountId>>;
+ pub ReFungibleItemList get(fn refungible_item_id) config(): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<ReFungibleItemType<T::CrossAccountId>>;
//#endregion
//#region Index list
@@ -610,7 +617,7 @@
decl_event!(
pub enum Event<T>
where
- AccountId = <T as system::Config>::AccountId,
+ CrossAccountId = <T as Config>::CrossAccountId,
{
/// New collection was created
///
@@ -621,7 +628,7 @@
/// * mode: [CollectionMode] converted into u8.
///
/// * account_id: Collection owner.
- CollectionCreated(CollectionId, u8, AccountId),
+ CollectionCreated(CollectionId, u8, CrossAccountId),
/// New item was created.
///
@@ -632,7 +639,7 @@
/// * item_id: Id of an item. Unique within the collection.
///
/// * recipient: Owner of newly created item
- ItemCreated(CollectionId, TokenId, AccountId),
+ ItemCreated(CollectionId, TokenId, CrossAccountId),
/// Collection item was burned.
///
@@ -654,7 +661,7 @@
/// * recipient: New owner of item
///
/// * amount: Always 1 for NFT
- Transfer(CollectionId, TokenId, AccountId, AccountId, u128),
+ Transfer(CollectionId, TokenId, CrossAccountId, CrossAccountId, u128),
/// * collection_id
///
@@ -665,7 +672,7 @@
/// * spender
///
/// * amount
- Approved(CollectionId, TokenId, AccountId, AccountId, u128),
+ Approved(CollectionId, TokenId, CrossAccountId, CrossAccountId, u128),
}
);
runtime/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.jsondiffbeforeafterboth1{1{2 "CrossAccountId": {3 "_enum": {4 "substrate": "AccountId",5 "ethereum": "H160"6 }7 },2 "AccessMode": {8 "AccessMode": {3 "_enum": [9 "_enum": [4 "Normal",10 "Normal",15 }21 }16 },22 },17 "Ownership": {23 "Ownership": {18 "Owner": "AccountId",24 "Owner": "CrossAccountId",19 "Fraction": "u128"25 "Fraction": "u128"20 },26 },21 "FungibleItemType": {27 "FungibleItemType": {22 "Value": "u128"28 "Value": "u128"23 },29 },24 "NftItemType": {30 "NftItemType": {25 "Owner": "AccountId",31 "Owner": "CrossAccountId",26 "ConstData": "Vec<u8>",32 "ConstData": "Vec<u8>",27 "VariableData": "Vec<u8>"33 "VariableData": "Vec<u8>"28 },34 },29 "ReFungibleItemType": {35 "ReFungibleItemType": {30 "Owner": "Vec<Ownership<AccountId>>",36 "Owner": "Vec<Ownership<CrossAccountId>>",31 "ConstData": "Vec<u8>",37 "ConstData": "Vec<u8>",32 "VariableData": "Vec<u8>"38 "VariableData": "Vec<u8>"33 },39 },34 "SponsorshipState": {40 "SponsorshipState": {35 "_enum": {41 "_enum": {36 "Disabled": null,42 "disabled": null,37 "Unconfirmed": "AccountId",43 "unconfirmed": "CrossAccountId",38 "Confirmed": "AccountId"44 "confirmed": "CrossAccountId"39 }45 }40 },46 },41 "Collection": {47 "Collection": {42 "Owner": "AccountId",48 "Owner": "CrossAccountId",43 "Mode": "CollectionMode",49 "Mode": "CollectionMode",44 "Access": "AccessMode",50 "Access": "AccessMode",45 "DecimalPoints": "DecimalPoints",51 "DecimalPoints": "DecimalPoints",