From d7edfd604280657c119cca992d3ac4b79ad28e37 Mon Sep 17 00:00:00 2001 From: Christian Cuaresma Date: Fri, 10 Nov 2023 15:41:32 +0100 Subject: [PATCH 1/2] remove ownership pallet fix format format removed test add runtime to mocks fix precompile test Fix conflicts --- Cargo.lock | 65 ---- Cargo.toml | 2 - .../living-assets-ownership/Cargo.toml | 54 --- .../living-assets-ownership/src/functions.rs | 26 -- .../living-assets-ownership/src/lib.rs | 280 -------------- .../living-assets-ownership/src/mock.rs | 75 ---- .../living-assets-ownership/src/tests.rs | 334 ---------------- .../living-assets-ownership/src/traits.rs | 99 ----- .../living-assets-ownership/src/types.rs | 16 - ownership-chain/precompile/erc721/Cargo.toml | 55 --- .../precompile/erc721/contracts/IERC721.sol | 16 - ownership-chain/precompile/erc721/src/lib.rs | 124 ------ .../precompile/erc721/src/tests.rs | 365 ------------------ .../precompile/living-assets/Cargo.toml | 57 --- .../contracts/LivingAssetsOwnership.sol | 17 - .../precompile/living-assets/src/lib.rs | 90 ----- .../precompile/living-assets/src/tests.rs | 211 ---------- ownership-chain/runtime/Cargo.toml | 8 - ownership-chain/runtime/src/lib.rs | 12 - .../runtime/src/precompiles/mock.rs | 10 +- .../runtime/src/precompiles/mod.rs | 20 +- .../runtime/src/precompiles/test.rs | 4 - ownership-chain/runtime/src/tests.rs | 61 --- 23 files changed, 2 insertions(+), 1999 deletions(-) delete mode 100644 ownership-chain/pallets/living-assets-ownership/Cargo.toml delete mode 100644 ownership-chain/pallets/living-assets-ownership/src/functions.rs delete mode 100644 ownership-chain/pallets/living-assets-ownership/src/lib.rs delete mode 100644 ownership-chain/pallets/living-assets-ownership/src/mock.rs delete mode 100644 ownership-chain/pallets/living-assets-ownership/src/tests.rs delete mode 100644 ownership-chain/pallets/living-assets-ownership/src/traits.rs delete mode 100644 ownership-chain/pallets/living-assets-ownership/src/types.rs delete mode 100644 ownership-chain/precompile/erc721/Cargo.toml delete mode 100644 ownership-chain/precompile/erc721/contracts/IERC721.sol delete mode 100644 ownership-chain/precompile/erc721/src/lib.rs delete mode 100644 ownership-chain/precompile/erc721/src/tests.rs delete mode 100644 ownership-chain/precompile/living-assets/Cargo.toml delete mode 100644 ownership-chain/precompile/living-assets/contracts/LivingAssetsOwnership.sol delete mode 100644 ownership-chain/precompile/living-assets/src/lib.rs delete mode 100644 ownership-chain/precompile/living-assets/src/tests.rs diff --git a/Cargo.lock b/Cargo.lock index 36af59868..b2e5d13e9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4811,13 +4811,10 @@ dependencies = [ "pallet-ethereum", "pallet-evm", "pallet-evm-chain-id", - "pallet-evm-erc721", "pallet-evm-laos-evolution", - "pallet-evm-living-assets-ownership", "pallet-evm-precompile-modexp", "pallet-evm-precompile-simple", "pallet-laos-evolution", - "pallet-living-assets-ownership", "pallet-multisig", "pallet-session", "pallet-sudo", @@ -6688,28 +6685,6 @@ dependencies = [ "sp-runtime", ] -[[package]] -name = "pallet-evm-erc721" -version = "0.0.1" -dependencies = [ - "evm", - "fp-evm", - "frame-support", - "hex", - "num_enum 0.5.11", - "ownership-parachain-primitives", - "pallet-evm", - "pallet-living-assets-ownership", - "parity-scale-codec", - "precompile-utils", - "precompile-utils-macro", - "scale-info", - "sp-arithmetic", - "sp-core", - "sp-runtime", - "sp-std", -] - [[package]] name = "pallet-evm-laos-evolution" version = "2.0.0-dev" @@ -6731,27 +6706,6 @@ dependencies = [ "sp-std", ] -[[package]] -name = "pallet-evm-living-assets-ownership" -version = "2.0.0-dev" -dependencies = [ - "evm", - "fp-evm", - "frame-support", - "hex", - "num_enum 0.5.11", - "pallet-evm", - "pallet-living-assets-ownership", - "parity-scale-codec", - "precompile-utils", - "precompile-utils-macro", - "scale-info", - "sp-arithmetic", - "sp-core", - "sp-runtime", - "sp-std", -] - [[package]] name = "pallet-evm-precompile-modexp" version = "2.0.0-dev" @@ -6881,25 +6835,6 @@ dependencies = [ "sp-std", ] -[[package]] -name = "pallet-living-assets-ownership" -version = "0.0.1" -dependencies = [ - "fp-account", - "frame-support", - "frame-system", - "hex", - "hex-literal 0.4.1", - "parity-scale-codec", - "scale-info", - "serde", - "sp-arithmetic", - "sp-core", - "sp-io", - "sp-runtime", - "sp-std", -] - [[package]] name = "pallet-membership" version = "4.0.0-dev" diff --git a/Cargo.toml b/Cargo.toml index 5a2b8449f..b119b64af 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -221,9 +221,7 @@ polkadot-cli = { git = "https://github.com/paritytech/polkadot", branch = "relea polkadot-service = { git = "https://github.com/paritytech/polkadot", branch = "release-v1.0.0" } # LAOS pallets -pallet-living-assets-ownership = { path = "./ownership-chain/pallets/living-assets-ownership", default-features = false } pallet-laos-evolution = { path = "./ownership-chain/pallets/laos-evolution", default-features = false } -pallet-evm-living-assets-ownership = { path = "./ownership-chain/precompile/living-assets", default-features = false } pallet-evm-laos-evolution = { path = "./ownership-chain/precompile/laos-evolution", default-features = false } pallet-evm-erc721 = { path = "./ownership-chain/precompile/erc721", default-features = false } diff --git a/ownership-chain/pallets/living-assets-ownership/Cargo.toml b/ownership-chain/pallets/living-assets-ownership/Cargo.toml deleted file mode 100644 index dd3b98e68..000000000 --- a/ownership-chain/pallets/living-assets-ownership/Cargo.toml +++ /dev/null @@ -1,54 +0,0 @@ -[package] -name = "pallet-living-assets-ownership" -authors = [""] -description = "" -version = "0.0.1" -license = "Unlicense" -homepage = "" -repository = "https://github.com/freeverseio/pallet-livingassets-ownership" -edition = "2021" - -[package.metadata.docs.rs] -targets = ["x86_64-unknown-linux-gnu"] - -[dependencies] -hex-literal = { workspace = true, optional = true } -parity-scale-codec = { workspace = true, features = ["derive"] } -scale-info = { workspace = true, features = ["derive"] } - -# Substrate -frame-support = { workspace = true } -frame-system = { workspace = true } -sp-arithmetic = { workspace = true } -sp-core = { workspace = true } -sp-std = { workspace = true } -sp-io = { workspace = true } -sp-runtime = { workspace = true } - -[dev-dependencies] -serde = { workspace = true } -hex = { workspace = true } -fp-account = { workspace = true, features = ["std", "serde"] } - -[features] -default = ["std"] -runtime-benchmarks = [ - "frame-system/runtime-benchmarks", - "frame-support/runtime-benchmarks" -] -std = [ - "parity-scale-codec/std", - "scale-info/std", - "frame-support/std", - "frame-system/std", - "fp-account/std", - "sp-arithmetic/std", - "sp-core/std", - "sp-std/std", - "sp-io/std", - "sp-runtime/std", -] -try-runtime = [ - "frame-system/try-runtime", - "frame-support/try-runtime" -] diff --git a/ownership-chain/pallets/living-assets-ownership/src/functions.rs b/ownership-chain/pallets/living-assets-ownership/src/functions.rs deleted file mode 100644 index 052746a80..000000000 --- a/ownership-chain/pallets/living-assets-ownership/src/functions.rs +++ /dev/null @@ -1,26 +0,0 @@ -//! Contains helper and utility functions of the pallet -use super::*; -use frame_support::sp_runtime::traits::One; - -impl Pallet { - /// See [Self::create_collection] - pub fn do_create_collection( - who: T::AccountId, - base_uri: BaseURIOf, - ) -> Result> { - // Retrieve the current collection count to use as the new collection's ID - let collection_id = Self::collection_counter(); - - CollectionBaseURI::::insert(collection_id, base_uri); - - // Attempt to increment the collection counter by 1. If this operation - // would result in an overflow, return early with an error - let counter = - collection_id.checked_add(One::one()).ok_or(Error::::CollectionIdOverflow)?; - CollectionCounter::::put(counter); - - Self::deposit_event(Event::CollectionCreated { collection_id, who }); - - Ok(collection_id) - } -} diff --git a/ownership-chain/pallets/living-assets-ownership/src/lib.rs b/ownership-chain/pallets/living-assets-ownership/src/lib.rs deleted file mode 100644 index 3350c12e2..000000000 --- a/ownership-chain/pallets/living-assets-ownership/src/lib.rs +++ /dev/null @@ -1,280 +0,0 @@ -#![cfg_attr(not(feature = "std"), no_std)] - -/// Edit this file to define custom logic or remove it if it is not needed. -/// Learn more about FRAME and the core library of Substrate FRAME pallets: -/// -use parity_scale_codec::alloc::string::ToString; -use sp_std::vec::Vec; - -pub use pallet::*; -pub use types::*; - -mod functions; -pub mod traits; -mod types; -#[frame_support::pallet] -pub mod pallet { - - use super::*; - use frame_support::pallet_prelude::{OptionQuery, ValueQuery, *}; - use sp_runtime::traits::Convert; - - #[pallet::pallet] - pub struct Pallet(_); - - /// Configure the pallet by specifying the parameters and types on which it depends. - #[pallet::config] - pub trait Config: frame_system::Config { - /// Because this pallet emits events, it depends on the runtime's definition of an event. - type RuntimeEvent: From> + IsType<::RuntimeEvent>; - - /// Specifies the advised maximum length for a Base URI. - /// - /// The URI standard (RFC 3986) doesn't dictates a limit for the length of URIs. - /// However it seems the max supported length in browsers is 2,048 characters. - /// - /// The base should be capped at 2,015 characters in length. This ensures room for - /// the token URI formation, where it combines `BaseURILimit`, a `'/'`, and a `AssetId` - /// (which takes up 33 characters). - #[pallet::constant] - type BaseURILimit: Get; - - /// Simply a null address in EVM. - #[pallet::constant] - type NullAddress: Get>; - - /// Type alias for implementing the `AssetIdToInitialOwner` trait for a given account ID - /// type. This allows you to specify which account should initially own each new asset. - type AssetIdToInitialOwner: Convert; - } - - /// Collection counter - #[pallet::storage] - #[pallet::getter(fn collection_counter)] - pub(super) type CollectionCounter = StorageValue<_, CollectionId, ValueQuery>; - - /// Collection base URI - #[pallet::storage] - #[pallet::getter(fn collection_base_uri)] - pub(super) type CollectionBaseURI = - StorageMap<_, Blake2_128Concat, CollectionId, BaseURIOf, OptionQuery>; - - /// Asset owner - #[pallet::storage] - pub(super) type AssetOwner = StorageDoubleMap< - _, - Blake2_128Concat, - CollectionId, - Blake2_128Concat, - AssetId, - AccountIdOf, - OptionQuery, - >; - - fn asset_owner(collection_id: CollectionId, asset_id: AssetId) -> AccountIdOf { - AssetOwner::::get(collection_id, asset_id) - .unwrap_or_else(|| T::AssetIdToInitialOwner::convert(asset_id)) - } - - /// Pallet events - #[pallet::event] - #[pallet::generate_deposit(pub(super) fn deposit_event)] - pub enum Event { - /// Collection created - /// parameters. [collection_id, who] - CollectionCreated { collection_id: CollectionId, who: AccountIdOf }, - /// Asset transferred to `who` - /// parameters. [collection_id, asset_id, who] - AssetTransferred { collection_id: CollectionId, asset_id: AssetId, to: AccountIdOf }, - } - - // Errors inform users that something went wrong. - #[pallet::error] - #[derive(PartialEq)] - pub enum Error { - /// Collection id overflow - CollectionIdOverflow, - /// Collection does not exist - CollectionDoesNotExist, - // NoPermission, - NoPermission, - // AssetDoesNotExist, - AssetDoesNotExist, - // CannotTransferSelf, - CannotTransferSelf, - // TransferToNullAddress, - TransferToNullAddress, - } - - impl AsRef<[u8]> for Error { - fn as_ref(&self) -> &[u8] { - match self { - Error::__Ignore(_, _) => b"__Ignore", - Error::CollectionIdOverflow => b"CollectionIdOverflow", - Error::CollectionDoesNotExist => b"CollectionDoesNotExist", - Error::NoPermission => b"NoPermission", - Error::AssetDoesNotExist => b"AssetDoesNotExist", - Error::CannotTransferSelf => b"CannotTransferSelf", - Error::TransferToNullAddress => b"TransferToNullAddress", - } - } - } - - // Dispatchable functions allows users to interact with the pallet and invoke state changes. - // These functions materialize as "extrinsics", which are often compared to transactions. - // Dispatchable functions must be annotated with a weight and must return a DispatchResult. - #[pallet::call] - impl Pallet {} - - impl traits::CollectionManager, BaseURIOf> for Pallet { - type Error = Error; - - fn base_uri(collection_id: CollectionId) -> Option> { - CollectionBaseURI::::get(collection_id) - } - - fn create_collection( - owner: AccountIdOf, - base_uri: BaseURIOf, - ) -> Result { - Self::do_create_collection(owner, base_uri) - } - } - - impl traits::Erc721> for Pallet { - type Error = Error; - - fn owner_of( - collection_id: CollectionId, - asset_id: AssetId, - ) -> Result, Self::Error> { - ensure!( - Pallet::::collection_base_uri(collection_id).is_some(), - Error::CollectionDoesNotExist - ); - Ok(asset_owner::(collection_id, asset_id)) - } - - fn transfer_from( - origin: AccountIdOf, - collection_id: CollectionId, - from: AccountIdOf, - to: AccountIdOf, - asset_id: AssetId, - ) -> Result<(), Self::Error> { - ensure!( - Pallet::::collection_base_uri(collection_id).is_some(), - Error::CollectionDoesNotExist - ); - ensure!(origin == from, Error::NoPermission); - ensure!(asset_owner::(collection_id, asset_id) == from, Error::NoPermission); - ensure!(from != to, Error::CannotTransferSelf); - ensure!(to != T::NullAddress::get(), Error::TransferToNullAddress); - - AssetOwner::::set(collection_id, asset_id, Some(to.clone())); - Self::deposit_event(Event::AssetTransferred { collection_id, asset_id, to }); - - Ok(()) - } - - fn token_uri( - collection_id: CollectionId, - asset_id: AssetId, - ) -> Result, Self::Error> { - let base_uri = Pallet::::collection_base_uri(collection_id) - .ok_or(Error::CollectionDoesNotExist)?; - - // concatenate base_uri with asset_id - let mut token_uri = base_uri.to_vec(); - token_uri.push(b'/'); - token_uri.extend_from_slice(asset_id.to_string().as_bytes()); - Ok(token_uri) - } - } -} - -/// `ASSET_PRECOMPILE_ADDRESS_PREFIX` is a predefined prefix used to identify collection addresses. -/// -/// All addresses that start with this prefix are considered as collection addresses. -/// Since `CollectionId` is represented as a `u64`, it leaves these bits free to be -/// utilized for such a prefix. -/// -/// Usage of this prefix provides a consistent and recognizable pattern for distinguishing -/// collection addresses from other types of addresses in the system. -pub const ASSET_PRECOMPILE_ADDRESS_PREFIX: &[u8] = &[0xff; 12]; - -/// Enum representing possible errors related to collections. -#[derive(Debug, PartialEq)] -pub enum CollectionError { - /// Error indicating that the provided address does not have the correct prefix. - InvalidPrefix, -} - -/// Converts a `CollectionId` into an `Address`. -/// -/// This function takes the given `CollectionId`, which is assumed to be a `u64`, -/// and maps it into an `Address` address, prepending it with the `ASSET_PRECOMPILE_ADDRESS_PREFIX`. -/// -/// # Arguments -/// -/// * `collection_id`: The ID of the collection to be converted. -/// -/// # Returns -/// -/// * An `Address` representation of the collection ID. -pub fn collection_id_to_address>(collection_id: CollectionId) -> Address { - let mut bytes = [0u8; 20]; - bytes[12..20].copy_from_slice(&collection_id.to_be_bytes()); - for (i, byte) in ASSET_PRECOMPILE_ADDRESS_PREFIX.iter().enumerate() { - bytes[i] = *byte; - } - Address::from(bytes) -} - -/// Converts an `Address` address into a `CollectionId` format. -/// -/// This function takes the given `Address` address, checks for the correct prefix, and extracts -/// the `CollectionId` from it. If the prefix is incorrect, it returns a -/// `CollectionError::InvalidPrefix` error. -/// -/// # Arguments -/// -/// * `address`: The `Address` address to be converted. -/// -/// # Returns -/// -/// * A `Result` which is either the `CollectionId` or an error indicating the address is invalid. -pub fn address_to_collection_id>( - address: Address, -) -> Result { - let address_bytes: [u8; 20] = address.into(); - if &address_bytes[0..12] != ASSET_PRECOMPILE_ADDRESS_PREFIX { - return Err(CollectionError::InvalidPrefix) - } - let mut id_bytes = [0u8; 8]; - id_bytes.copy_from_slice(&address_bytes[12..]); - - Ok(CollectionId::from_be_bytes(id_bytes)) -} - -/// Checks if a given `Address` address is a collection address. -/// -/// This function examines the prefix of the given `Address` address to determine if it is a -/// collection address, based on the `ASSET_PRECOMPILE_ADDRESS_PREFIX`. -/// -/// # Arguments -/// -/// * `address`: The `Address` address to be checked. -/// -/// # Returns -/// -/// * A boolean indicating if the address is a collection address. -pub fn is_collection_address>(address: Address) -> bool { - &address.into()[0..12] == ASSET_PRECOMPILE_ADDRESS_PREFIX -} - -#[cfg(test)] -mod mock; - -#[cfg(test)] -mod tests; diff --git a/ownership-chain/pallets/living-assets-ownership/src/mock.rs b/ownership-chain/pallets/living-assets-ownership/src/mock.rs deleted file mode 100644 index 4b4d71ad2..000000000 --- a/ownership-chain/pallets/living-assets-ownership/src/mock.rs +++ /dev/null @@ -1,75 +0,0 @@ -use crate::{self as pallet_livingassets_ownership}; -use frame_support::traits::{ConstU16, ConstU64}; -use sp_core::{ConstU32, H256, U256}; -use sp_runtime::{ - traits::{BlakeTwo256, Convert, IdentifyAccount, IdentityLookup, Verify}, - BuildStorage, -}; -use sp_std::{boxed::Box, prelude::*}; - -type Block = frame_system::mocking::MockBlock; -type Nonce = u32; -type Signature = fp_account::EthereumSignature; -pub type AccountId = <::Signer as IdentifyAccount>::AccountId; - -// Configure a mock runtime to test the pallet. -frame_support::construct_runtime!( - pub enum Test - { - System: frame_system, - LivingAssetsModule: pallet_livingassets_ownership, - } -); - -impl frame_system::Config for Test { - type BaseCallFilter = frame_support::traits::Everything; - type BlockWeights = (); - type BlockLength = (); - type DbWeight = (); - type RuntimeOrigin = RuntimeOrigin; - type RuntimeCall = RuntimeCall; - type Block = Block; - type Hash = H256; - type Nonce = Nonce; - type Hashing = BlakeTwo256; - type AccountId = AccountId; - type Lookup = IdentityLookup; - type RuntimeEvent = RuntimeEvent; - type BlockHashCount = ConstU64<250>; - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = (); - type OnNewAccount = (); - type OnKilledAccount = (); - type SystemWeightInfo = (); - type SS58Prefix = ConstU16<42>; - type OnSetCode = (); - type MaxConsumers = frame_support::traits::ConstU32<16>; -} - -frame_support::parameter_types! { - pub NullAddress: AccountId = [0u8; 20].into(); -} - -impl pallet_livingassets_ownership::Config for Test { - type RuntimeEvent = RuntimeEvent; - type BaseURILimit = ConstU32<256>; - type NullAddress = NullAddress; - type AssetIdToInitialOwner = MockAssetIdToInitialOwner; -} - -pub struct MockAssetIdToInitialOwner; -impl Convert for MockAssetIdToInitialOwner { - fn convert(asset_id: U256) -> AccountId { - // initial owner is the last 20 bytes of the asset id - let mut initial_owner = [0u8; 20]; - let asset_id_bytes: [u8; 32] = asset_id.into(); - initial_owner.copy_from_slice(&asset_id_bytes[12..]); - AccountId::from(initial_owner) - } -} - -// Build genesis storage according to the mock runtime. -pub fn new_test_ext() -> sp_io::TestExternalities { - RuntimeGenesisConfig::default().build_storage().unwrap().into() -} diff --git a/ownership-chain/pallets/living-assets-ownership/src/tests.rs b/ownership-chain/pallets/living-assets-ownership/src/tests.rs deleted file mode 100644 index ad0a8b8cf..000000000 --- a/ownership-chain/pallets/living-assets-ownership/src/tests.rs +++ /dev/null @@ -1,334 +0,0 @@ -use crate::{ - address_to_collection_id, collection_id_to_address, is_collection_address, mock::*, - traits::CollectionManager, AssetOwner, CollectionBaseURI, CollectionError, CollectionId, Event, -}; -use core::str::FromStr; -use frame_support::assert_ok; - -type BaseURI = crate::BaseURIOf; -type AccountId = ::AccountId; - -const ALICE: [u8; 20] = [1u8; 20]; -const BOB: [u8; 20] = [2u8; 20]; - -/// Create a new collection with the given base URI. -fn create_collection(who: AccountId, base_uri: Option) -> CollectionId { - >::create_collection( - who, - base_uri.unwrap_or_default(), - ) - .unwrap() -} - -#[test] -fn base_uri_unexistent_collection_is_none() { - new_test_ext().execute_with(|| { - assert_eq!(LivingAssetsModule::collection_base_uri(0), None); - assert_eq!(LivingAssetsModule::collection_base_uri(1), None); - }); -} - -#[test] -fn create_new_collection_should_create_sequential_collections() { - new_test_ext().execute_with(|| { - // Check initial condition - assert_eq!(LivingAssetsModule::collection_base_uri(0), None); - - let base_uri = BaseURI::try_from("https://example.com/".as_bytes().to_vec()).unwrap(); - - // Iterate through the collections to be created - for _ in 0..3 { - // Create the collection - let i = create_collection(ALICE.into(), Some(base_uri.clone())); - - // Assert that the collection was created with the expected URI - assert_eq!(LivingAssetsModule::collection_base_uri(i).unwrap(), base_uri); - } - }); -} - -#[test] -fn should_set_base_uri_when_creating_new_collection() { - let base_uri = BaseURI::try_from("https://example.com/".as_bytes().to_vec()).unwrap(); - - new_test_ext().execute_with(|| { - create_collection(ALICE.into(), Some(base_uri.clone())); - assert_eq!(LivingAssetsModule::collection_base_uri(0).unwrap(), base_uri); - }); -} - -#[test] -fn create_new_collections_should_emit_events_with_collection_id_consecutive() { - new_test_ext().execute_with(|| { - // Go past genesis block so events get deposited - System::set_block_number(1); - - assert_ok!(LivingAssetsModule::create_collection(ALICE.into(), BaseURI::default())); - System::assert_last_event( - Event::CollectionCreated { collection_id: 0, who: ALICE.into() }.into(), - ); - assert_ok!(LivingAssetsModule::create_collection(ALICE.into(), BaseURI::default())); - System::assert_last_event( - Event::CollectionCreated { collection_id: 1, who: ALICE.into() }.into(), - ); - assert_ok!(LivingAssetsModule::create_collection(ALICE.into(), BaseURI::default())); - System::assert_last_event( - Event::CollectionCreated { collection_id: 2, who: ALICE.into() }.into(), - ); - assert_ok!(LivingAssetsModule::create_collection(ALICE.into(), BaseURI::default())); - System::assert_last_event( - Event::CollectionCreated { collection_id: 3, who: ALICE.into() }.into(), - ); - }); -} - -#[test] -fn test_collection_id_to_address() { - let collection_id = 5; - let expected_address = AccountId::from_str("ffffffffffffffffffffffff0000000000000005").unwrap(); - assert_eq!(collection_id_to_address::(collection_id), expected_address); -} - -#[test] -fn invalid_collection_address_should_error() { - let address = AccountId::from_str("8000000000000000000000000000000000000005").unwrap(); - let error = address_to_collection_id::(address).unwrap_err(); - assert_eq!(error, CollectionError::InvalidPrefix); -} - -#[test] -fn valid_collection_address_should_return_collection_id() { - let address = AccountId::from_str("ffffffffffffffffffffffff0000000000000005").unwrap(); - let collection_id = address_to_collection_id::(address).unwrap(); - assert_eq!(collection_id, 5); -} - -#[test] -fn test_is_collection_address_valid() { - let collection_id = 1234567890; - let address = collection_id_to_address::(collection_id); - - assert!(is_collection_address::(address)); -} - -#[test] -fn test_is_collection_address_invalid() { - let invalid_address = [0u8; 20].into(); - - assert!(!is_collection_address::(invalid_address)); -} - -mod traits { - use super::*; - use crate::{ - traits::{CollectionManager, Erc721}, - Error, Event, - }; - use frame_support::{assert_err, assert_noop, assert_ok}; - use sp_core::{H160, U256}; - - #[test] - fn base_uri_of_unexistent_collection_is_none() { - new_test_ext().execute_with(|| { - assert_eq!(LivingAssetsModule::base_uri(0), None); - assert_eq!(LivingAssetsModule::base_uri(1), None); - }); - } - - #[test] - fn create_new_collection_should_emit_an_event() { - new_test_ext().execute_with(|| { - // Go past genesis block so events get deposited - System::set_block_number(1); - - create_collection(ALICE.into(), None); - System::assert_last_event( - Event::CollectionCreated { collection_id: 0, who: ALICE.into() }.into(), - ); - }); - } - - #[test] - fn living_assets_ownership_trait_id_of_new_collection_should_be_consecutive() { - new_test_ext().execute_with(|| { - assert_eq!(create_collection(ALICE.into(), None), 0); - - for i in 0..5 { - assert_eq!(create_collection(ALICE.into(), None), i + 1,) - } - }); - } - - #[test] - fn living_assets_ownership_trait_should_set_base_uri_when_creating_new_collection() { - let base_uri = BaseURI::try_from("https://example.com/".as_bytes().to_vec()).unwrap(); - - new_test_ext().execute_with(|| { - let _ = create_collection(ALICE.into(), Some(base_uri.clone())); - assert_eq!(LivingAssetsModule::collection_base_uri(0).unwrap(), base_uri); - }); - } - - #[test] - fn owner_of_asset_of_unexistent_collection_should_error() { - new_test_ext().execute_with(|| { - let result = LivingAssetsModule::owner_of(0, 2.into()); - assert_err!(result, Error::CollectionDoesNotExist); - }); - } - - #[test] - fn verify_different_owners_for_same_asset_across_different_collections() { - let asset_id = U256::from( - hex::decode("03C0F0f4ab324C46e55D02D0033343B4Be8A55532d").unwrap().as_slice(), - ); - let sender = AccountId::from_str("c0f0f4ab324c46e55d02d0033343b4be8a55532d").unwrap(); - let receiver = BOB.into(); - new_test_ext().execute_with(|| { - CollectionBaseURI::::insert(1, BaseURI::default()); - CollectionBaseURI::::insert(2, BaseURI::default()); - assert_eq!(LivingAssetsModule::owner_of(1, asset_id).unwrap(), sender); - assert_ok!(LivingAssetsModule::transfer_from(sender, 1, sender, receiver, asset_id,)); - assert_eq!(LivingAssetsModule::owner_of(1, asset_id).unwrap(), receiver); - assert_eq!(LivingAssetsModule::owner_of(2, asset_id).unwrap(), sender); - }); - } - - #[test] - fn erc721_owner_of_asset_of_collection() { - new_test_ext().execute_with(|| { - let collection_id = create_collection(ALICE.into(), None); - assert_eq!( - LivingAssetsModule::owner_of(collection_id, 2.into()).unwrap(), - H160::from_low_u64_be(0x0000000000000002).0.into() - ); - }); - } - - #[test] - fn caller_is_not_current_owner_should_fail() { - let asset_id = U256::from(5); - let sender = AccountId::from_str("0000000000000000000000000000000000000006").unwrap(); - let receiver = BOB.into(); - new_test_ext().execute_with(|| { - System::set_block_number(1); - assert!(AssetOwner::::get(0, asset_id).is_none()); - CollectionBaseURI::::insert(1, BaseURI::default()); - assert_noop!( - LivingAssetsModule::transfer_from(ALICE.into(), 1, sender, receiver, asset_id,), - Error::::NoPermission - ); - }); - } - - #[test] - fn sender_is_not_current_owner_should_fail() { - let asset_id = U256::from(5); - let sender = AccountId::from_str("0000000000000000000000000000000000000006").unwrap(); - let receiver = BOB.into(); - new_test_ext().execute_with(|| { - System::set_block_number(1); - assert!(AssetOwner::::get(0, asset_id).is_none()); - CollectionBaseURI::::insert(1, BaseURI::default()); - assert_noop!( - LivingAssetsModule::transfer_from(sender, 1, sender, receiver, asset_id,), - Error::::NoPermission - ); - }); - } - - #[test] - fn same_sender_and_receiver_should_fail() { - let asset_id = U256::from(5); - let sender = AccountId::from_str("0000000000000000000000000000000000000005").unwrap(); - new_test_ext().execute_with(|| { - System::set_block_number(1); - assert!(AssetOwner::::get(0, asset_id).is_none()); - CollectionBaseURI::::insert(1, BaseURI::default()); - assert_noop!( - LivingAssetsModule::transfer_from(sender, 1, sender, sender, asset_id,), - Error::::CannotTransferSelf - ); - }); - } - - #[test] - fn receiver_is_the_zero_address_should_fail() { - let asset_id = U256::from(5); - let sender = AccountId::from_str("0000000000000000000000000000000000000005").unwrap(); - let receiver = AccountId::from_str("0000000000000000000000000000000000000000").unwrap(); - new_test_ext().execute_with(|| { - System::set_block_number(1); - assert!(AssetOwner::::get(0, asset_id).is_none()); - CollectionBaseURI::::insert(1, BaseURI::default()); - assert_noop!( - LivingAssetsModule::transfer_from(sender, 1, sender, receiver, asset_id,), - Error::::TransferToNullAddress - ); - }); - } - - #[test] - fn unexistent_collection_when_transfer_from_should_fail() { - let asset_id = U256::from(5); - let sender = AccountId::from_str("0000000000000000000000000000000000000005").unwrap(); - let receiver = BOB.into(); - new_test_ext().execute_with(|| { - System::set_block_number(1); - assert!(AssetOwner::::get(0, asset_id).is_none()); - assert_noop!( - LivingAssetsModule::transfer_from(sender, 1, sender, receiver, asset_id,), - Error::::CollectionDoesNotExist - ); - }); - } - - #[test] - fn successful_transfer_from_trait_should_work() { - let asset_id = U256::from( - hex::decode("03C0F0f4ab324C46e55D02D0033343B4Be8A55532d").unwrap().as_slice(), - ); - let sender = AccountId::from_str("c0f0f4ab324c46e55d02d0033343b4be8a55532d").unwrap(); - let receiver = BOB.into(); - let collection_id = 1; - new_test_ext().execute_with(|| { - System::set_block_number(1); - CollectionBaseURI::::insert(collection_id, BaseURI::default()); - assert!(AssetOwner::::get(collection_id, asset_id).is_none()); - assert_eq!(LivingAssetsModule::owner_of(collection_id, asset_id).unwrap(), sender); - assert_ok!(LivingAssetsModule::transfer_from( - sender, - collection_id, - sender, - receiver, - asset_id, - )); - assert_eq!(AssetOwner::::get(collection_id, asset_id).unwrap(), BOB.into()); - assert_eq!(LivingAssetsModule::owner_of(collection_id, asset_id).unwrap(), receiver); - System::assert_last_event( - Event::AssetTransferred { collection_id, asset_id, to: BOB.into() }.into(), - ); - }); - } - - #[test] - fn token_uri_of_unexistent_collection() { - new_test_ext().execute_with(|| { - let result = LivingAssetsModule::token_uri(0, 2.into()); - assert_err!(result, Error::CollectionDoesNotExist); - }); - } - - #[test] - fn token_uri_should_concatenate_the_base_uri_with_the_token_id() { - let base_uri = BaseURI::try_from("https://example.com".as_bytes().to_vec()).unwrap(); - - new_test_ext().execute_with(|| { - let collection_id = create_collection(ALICE.into(), Some(base_uri.clone())); - assert_eq!( - LivingAssetsModule::token_uri(collection_id, 2.into()).unwrap(), - "https://example.com/2".as_bytes().to_vec() - ); - }); - } -} diff --git a/ownership-chain/pallets/living-assets-ownership/src/traits.rs b/ownership-chain/pallets/living-assets-ownership/src/traits.rs deleted file mode 100644 index 10a65d1a3..000000000 --- a/ownership-chain/pallets/living-assets-ownership/src/traits.rs +++ /dev/null @@ -1,99 +0,0 @@ -use crate::{types::AssetId, CollectionId}; -use sp_std::vec::Vec; - -/// The `CollectionManager` trait provides an interface for managing collections in a decentralized -/// system. -/// -/// A collection is a container for non-fungible assets, uniquely identified by a `collection_id`. -/// The system allows for the creation and ownership management of these collections. -/// -/// # Methods -/// -/// - `owner_of_collection`: Retrieve the owner of a specified collection. -/// - `create_collection`: Create a new collection and assign it to an owner. -pub trait CollectionManager -where - BaseURI: TryFrom>, -{ - type Error: AsRef<[u8]> + PartialEq; - - /// Retrieves the base uri of the specified collection. - /// - /// # Arguments - /// - /// * `collection_id` - The unique identifier of the collection. - /// - /// # Returns - /// - /// The base URI associated with the specified collection or `None` if the collection doesn't - /// exist. - fn base_uri(collection_id: CollectionId) -> Option; - - /// Creates a new collection and assigns it to the specified owner. - /// - /// # Arguments - /// - /// * `owner` - The account ID of the new collection's owner. - /// - /// # Returns - /// - /// A result containing the `collection_id` of the newly created collection or an error. - fn create_collection(owner: AccountId, base_uri: BaseURI) -> Result; -} - -/// The `Erc721` trait provides an interface for handling ERC721 tokens in a blockchain environment. -/// -/// ERC721 tokens are a standard for representing ownership of unique items on the Ethereum -/// blockchain. -/// -/// # Methods -/// -/// - `owner_of`: Retrieve the owner of a specific asset within a collection. -/// - `token_uri`: Retrieve the URI associated with a specific asset within a collection. -pub trait Erc721 { - type Error: AsRef<[u8]> + PartialEq; - - /// Retrieves the owner of a specific asset within the specified collection. - /// - /// # Arguments - /// - /// * `collection_id` - The unique identifier for the collection. - /// * `asset_id` - The unique identifier for the asset within the collection. - /// - /// # Returns - /// - /// The Ethereum address (`H160`) of the asset's owner or an error. - fn owner_of(collection_id: CollectionId, asset_id: AssetId) -> Result; - - /// Retrieves the URI associated with a specific asset within the specified collection. - /// - /// The URI is often used to provide metadata, images, or other information related to the - /// asset. This URI should conform to the ERC721 metadata standards and can be a URL, IPFS hash, - /// or other URI format. - /// - /// # Arguments - /// - /// * `asset_id` - The unique identifier for the asset within the collection. - /// - /// # Returns - /// - /// A `Vec` representing the URI of the asset or an error if retrieval fails. - fn token_uri(collection_id: CollectionId, asset_id: AssetId) -> Result, Self::Error>; - - /// Transfers the ownership of a asset from one address to another address - /// - /// # Arguments - /// - /// * `origin` - The caller's address. - /// * `collection_id` - The unique identifier for the collection. - /// * `from` - The current owner of the asset. - /// * `to` - The new owner. - /// * `asset_id` - The unique identifier for the asset within the collection. - fn transfer_from( - origin: AccountId, - collection_id: CollectionId, - from: AccountId, - to: AccountId, - asset_id: AssetId, - ) -> Result<(), Self::Error>; -} diff --git a/ownership-chain/pallets/living-assets-ownership/src/types.rs b/ownership-chain/pallets/living-assets-ownership/src/types.rs deleted file mode 100644 index c44193132..000000000 --- a/ownership-chain/pallets/living-assets-ownership/src/types.rs +++ /dev/null @@ -1,16 +0,0 @@ -//! Types and type aliases used in LivingAssetsOwnership pallet. -use crate::Config; -use sp_core::U256; -use sp_runtime::BoundedVec; - -/// Explicit AccountId of the pallet. -pub type AccountIdOf = ::AccountId; - -/// AssetId type. -pub type AssetId = U256; - -/// Collection id type -pub type CollectionId = u64; - -/// Base URI type -pub type BaseURIOf = BoundedVec::BaseURILimit>; diff --git a/ownership-chain/precompile/erc721/Cargo.toml b/ownership-chain/precompile/erc721/Cargo.toml deleted file mode 100644 index f9d33d449..000000000 --- a/ownership-chain/precompile/erc721/Cargo.toml +++ /dev/null @@ -1,55 +0,0 @@ -[package] -name = "pallet-evm-erc721" -version = "0.0.1" -edition = "2021" - -[dependencies] -parity-scale-codec = { workspace = true, features = ["derive"] } -scale-info = { workspace = true, features = [ - "derive", -] } - -# Frontier -fp-evm = { workspace = true } -pallet-evm = { workspace = true } - -# Substrate -frame-support = { workspace = true } -sp-arithmetic = { workspace = true } -sp-core = { workspace = true } -sp-runtime = { workspace = true } -sp-std = { workspace = true } - -# Local pallet -pallet-living-assets-ownership = { workspace = true } -ownership-parachain-primitives = { workspace = true } - -# Utils -precompile-utils = { workspace = true } -precompile-utils-macro = { workspace = true } - -num_enum = { workspace = true } - -[dev-dependencies] -evm = { workspace = true } -hex = { workspace = true } -precompile-utils = { workspace = true, features = ["testing"]} - -[features] -default = ["std"] -std = [ - # Frontier - "fp-evm/std", - "pallet-evm/std", - "sp-core/std", - "sp-runtime/std", - "sp-std/std", - "pallet-living-assets-ownership/std", - "num_enum/std", - "frame-support/std", - "sp-arithmetic/std", - "precompile-utils/std", - "parity-scale-codec/std", - "scale-info/std", - "ownership-parachain-primitives/std", -] diff --git a/ownership-chain/precompile/erc721/contracts/IERC721.sol b/ownership-chain/precompile/erc721/contracts/IERC721.sol deleted file mode 100644 index 5c4014cfd..000000000 --- a/ownership-chain/precompile/erc721/contracts/IERC721.sol +++ /dev/null @@ -1,16 +0,0 @@ -// SPDX-License-Identifier: MIT -// derived from OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/IERC721.sol) -pragma solidity >=0.8.3; - -interface IERC721 { - /** - * @dev See {IERC721Metadata-tokenURI}. - */ - function tokenURI(uint256 _tokenId) external view returns (string memory); - - function ownerOf(uint256 _tokenId) external view returns (address); - - event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId); - - function transferFrom(address _from, address _to, uint256 _tokenId) external; -} diff --git a/ownership-chain/precompile/erc721/src/lib.rs b/ownership-chain/precompile/erc721/src/lib.rs deleted file mode 100644 index a319fe582..000000000 --- a/ownership-chain/precompile/erc721/src/lib.rs +++ /dev/null @@ -1,124 +0,0 @@ -#![cfg_attr(not(feature = "std"), no_std)] -use fp_evm::{Precompile, PrecompileHandle, PrecompileOutput}; -use pallet_living_assets_ownership::{address_to_collection_id, CollectionId}; -use precompile_utils::{ - keccak256, revert, succeed, Address, Bytes, EvmDataWriter, EvmResult, FunctionModifier, LogExt, - LogsBuilder, PrecompileHandleExt, -}; - -use sp_core::{H160, H256, U256}; -use sp_std::{fmt::Debug, marker::PhantomData, vec, vec::Vec}; - -/// Solidity selector of the TransferFrom log, which is the Keccak of the Log signature. -pub const SELECTOR_LOG_TRANSFER_FROM: [u8; 32] = keccak256!("Transfer(address,address,uint256)"); - -#[precompile_utils_macro::generate_function_selector] -#[derive(Debug, PartialEq)] -pub enum Action { - /// Get token URI - TokenURI = "tokenURI(uint256)", - /// Owner of - OwnerOf = "ownerOf(uint256)", - /// Transfer from - TransferFrom = "transferFrom(address,address,uint256)", -} - -/// Wrapper for the precompile function. -pub struct Erc721Precompile(PhantomData<(AccountId, AssetManager)>); - -impl Precompile for Erc721Precompile -where - AccountId: Into + From + Into<[u8; 20]>, - AssetManager: pallet_living_assets_ownership::traits::Erc721, -{ - fn execute(handle: &mut impl PrecompileHandle) -> EvmResult { - // collection id is encoded into the contract address - let collection_id = address_to_collection_id(handle.code_address()) - .map_err(|_| revert("invalid collection address"))?; - - let selector = handle.read_selector()?; - - handle.check_function_modifier(match selector { - Action::TokenURI => FunctionModifier::View, - Action::OwnerOf => FunctionModifier::View, - Action::TransferFrom => FunctionModifier::NonPayable, - })?; - - match selector { - Action::TokenURI => Self::token_uri(collection_id, handle), - Action::OwnerOf => Self::owner_of(collection_id, handle), - Action::TransferFrom => Self::transfer_from(collection_id, handle), - } - } -} - -impl Erc721Precompile -where - AccountId: Into + From + Into<[u8; 20]>, - AssetManager: pallet_living_assets_ownership::traits::Erc721, -{ - fn owner_of( - collection_id: CollectionId, - handle: &mut impl PrecompileHandle, - ) -> EvmResult { - let mut input = handle.read_input()?; - input.expect_arguments(1)?; - - let asset_id: U256 = input.read()?; - - let owner: H160 = AssetManager::owner_of(collection_id, asset_id).map_err(revert)?.into(); - - Ok(succeed(EvmDataWriter::new().write(Address(owner)).build())) - } - - fn token_uri( - collection_id: CollectionId, - handle: &mut impl PrecompileHandle, - ) -> EvmResult { - let mut input = handle.read_input()?; - input.expect_arguments(1)?; - - let asset_id: U256 = input.read()?; - - let uri = AssetManager::token_uri(collection_id, asset_id).map_err(revert)?; - Ok(succeed(EvmDataWriter::new().write(Bytes(uri)).build())) - } - - fn transfer_from( - collection_id: CollectionId, - handle: &mut impl PrecompileHandle, - ) -> EvmResult { - // get input data - let mut input = handle.read_input()?; - input.expect_arguments(3)?; - let from = input.read::
()?; - let to = input.read::
()?; - let asset_id: pallet_living_assets_ownership::AssetId = input.read()?; - let mut asset_id_big_endian = [0u8; 32]; - asset_id.to_big_endian(&mut asset_id_big_endian); - - AssetManager::transfer_from( - handle.context().caller.into(), - collection_id, - from.0.into(), - to.0.into(), - asset_id, - ) - .map_err(revert)?; - - LogsBuilder::new(handle.context().address) - .log4( - SELECTOR_LOG_TRANSFER_FROM, - from.0, - to.0, - H256::from_slice(asset_id_big_endian.as_slice()), - Vec::new(), - ) - .record(handle)?; - - Ok(succeed(vec![])) - } -} - -#[cfg(test)] -mod tests; diff --git a/ownership-chain/precompile/erc721/src/tests.rs b/ownership-chain/precompile/erc721/src/tests.rs deleted file mode 100644 index 49a4997b5..000000000 --- a/ownership-chain/precompile/erc721/src/tests.rs +++ /dev/null @@ -1,365 +0,0 @@ -use core::str::FromStr; - -use super::*; -use frame_support::assert_ok; -use pallet_living_assets_ownership::{AssetId, CollectionId}; -use precompile_utils::testing::create_mock_handle_from_input; -use sp_core::{H160, U256}; - -type AccountId = H160; - -#[test] -fn check_selectors() { - assert_eq!(Action::OwnerOf as u32, 0x6352211E); - assert_eq!(Action::TokenURI as u32, 0xC87B56DD); - assert_eq!(Action::TransferFrom as u32, 0x23b872dd); -} - -#[test] -fn owner_of_asset_should_return_an_address() { - impl_precompile_mock_simple!( - Mock, - Ok(H160::from_str("ff00000000000000000000000000000012345678").unwrap()), - Ok(vec![]), - Ok(()) - ); - - let owner_of_asset_4 = - hex::decode("6352211e0000000000000000000000000000000000000000000000000000000000000004") - .unwrap(); - let mut handle = create_mock_handle_from_input(owner_of_asset_4); - handle.code_address = H160::from_str("ffffffffffffffffffffffff0000000000000005").unwrap(); - let result = Mock::execute(&mut handle); - - assert!(result.is_ok()); - assert_eq!( - result.unwrap(), - succeed( - hex::decode("000000000000000000000000ff00000000000000000000000000000012345678") - .unwrap() - ), - ); -} - -#[test] -fn if_mock_fails_should_return_the_error() { - impl_precompile_mock_simple!(Mock, Err("this is an error"), Ok(vec![]), Ok(())); - - let owner_of_asset_4 = - hex::decode("6352211e0000000000000000000000000000000000000000000000000000000000000004") - .unwrap(); - let mut handle = create_mock_handle_from_input(owner_of_asset_4); - handle.code_address = H160::from_str("ffffffffffffffffffffffff0000000000000005").unwrap(); - let result = Mock::execute(&mut handle); - assert!(result.is_err()); - assert_eq!(result.unwrap_err(), revert("this is an error")); -} - -#[test] -fn invalid_contract_address_should_error() { - impl_precompile_mock_simple!(Mock, Ok(H160::zero()), Ok(vec![]), Ok(())); - - let mut handle = create_mock_handle_from_input(Vec::new()); - handle.code_address = H160::zero(); - let result = Mock::execute(&mut handle); - assert!(result.is_err()); - assert_eq!(result.unwrap_err(), revert("invalid collection address")); -} - -#[test] -fn token_owners_should_have_at_least_token_id_as_argument() { - impl_precompile_mock_simple!(Mock, Ok(H160::zero()), Ok(vec![]), Ok(())); - - let owner_of_with_2_arguments: Vec = - hex::decode("6352211e00000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000004") - .unwrap(); - let mut handle = create_mock_handle_from_input(owner_of_with_2_arguments); - handle.code_address = H160::from_str("ffffffffffffffffffffffff0000000000000005").unwrap(); - let result = Mock::execute(&mut handle); - assert!(result.is_ok()); - - let owner_of_with_0_arguments: Vec = hex::decode("6352211e").unwrap(); - let mut handle = create_mock_handle_from_input(owner_of_with_0_arguments); - handle.code_address = H160::from_str("ffffffffffffffffffffffff0000000000000005").unwrap(); - let result = Mock::execute(&mut handle); - assert!(result.is_err()); - assert_eq!(result.unwrap_err(), revert("input doesn't match expected length")); -} - -mod transfer_from { - use super::*; - use frame_support::assert_ok; - use precompile_utils::testing::create_mock_handle; - - #[test] - fn send_value_as_money_should_fail() { - impl_precompile_mock_simple!( - Mock, - // owner_of result - Ok(H160::from_str("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa").unwrap()), - // token_uri result - Ok(vec![]), - // transfer_from result - Ok(()) - ); - - // test data - let from = H160::repeat_byte(0xAA); - let to = H160::repeat_byte(0x0); - let asset_id = 4; - let contract_address = H160::from_str("ffffffffffffffffffffffff0000000000000005"); - - let input_data = EvmDataWriter::new_with_selector(Action::TransferFrom) - .write(Address(from)) - .write(Address(to)) - .write(U256::from(asset_id)) - .build(); - - let mut handle = create_mock_handle(input_data, 0, 1, H160::zero()); - handle.code_address = contract_address.unwrap(); - let result = Mock::execute(&mut handle); - assert!(result.is_err()); - assert_eq!(result.unwrap_err(), revert("function is not payable")); - } - - #[test] - fn sucessful_transfer_should_work() { - impl_precompile_mock_simple!( - Mock, - // owner_of result - Ok(H160::from_str("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa").unwrap()), - // token_uri result - Ok(vec![]), - // transfer_from result - Ok(()) - ); - - // test data - let from = H160::repeat_byte(0xAA); - let to = H160::repeat_byte(0xBB); - let asset_id = 4; - let contract_address = H160::from_str("ffffffffffffffffffffffff0000000000000005"); - - let input_data = EvmDataWriter::new_with_selector(Action::TransferFrom) - .write(Address(from)) - .write(Address(to)) - .write(U256::from(asset_id)) - .build(); - - let mut handle = create_mock_handle( - input_data, - 0, - 0, - H160::from_str("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa").unwrap(), - ); - handle.code_address = contract_address.unwrap(); - assert_ok!(Mock::execute(&mut handle)); - } - #[test] - fn unsucessful_transfer_should_fail() { - impl_precompile_mock_simple!( - Mock, - // owner_of result - Ok(H160::from_str("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa").unwrap()), - // token_uri result - Ok(vec![]), - // transfer_from result - Err("this is an error") - ); - - // test data - let from = H160::repeat_byte(0xAA); - let to = H160::repeat_byte(0xBB); - let asset_id = 4; - let contract_address = H160::from_str("ffffffffffffffffffffffff0000000000000005"); - - let input_data = EvmDataWriter::new_with_selector(Action::TransferFrom) - .write(Address(from)) - .write(Address(to)) - .write(U256::from(asset_id)) - .build(); - - let mut handle = create_mock_handle( - input_data, - 0, - 0, - H160::from_str("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa").unwrap(), - ); - handle.code_address = contract_address.unwrap(); - let result = Mock::execute(&mut handle); - assert!(result.is_err()); - assert_eq!(result.unwrap_err(), revert("this is an error")); - } - - #[test] - fn check_log_selectors() { - assert_eq!( - hex::encode(SELECTOR_LOG_TRANSFER_FROM), - "ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef" - ); - } - - #[test] - fn transfer_from_should_generate_log() { - impl_precompile_mock_simple!( - Mock, - // owner_of result - Ok(H160::from_str("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa").unwrap()), - // token_uri result - Ok(vec![]), - // transfer_from result - Ok(()) - ); - - // test data - let from = H160::repeat_byte(0xAA); - let to = H160::repeat_byte(0xBB); - let asset_id = 4; - let contract_address = H160::from_str("ffffffffffffffffffffffff0000000000000005"); - - let input_data = EvmDataWriter::new_with_selector(Action::TransferFrom) - .write(Address(from)) - .write(Address(to)) - .write(U256::from(asset_id)) - .build(); - - let mut handle = create_mock_handle( - input_data, - 0, - 0, - H160::from_str("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa").unwrap(), - ); - handle.code_address = contract_address.unwrap(); - assert_ok!(Mock::execute(&mut handle)); - - let logs = handle.logs; - assert_eq!(logs.len(), 1); - assert_eq!(logs[0].address, H160::zero()); - assert_eq!(logs[0].topics.len(), 4); - assert_eq!(logs[0].topics[0], SELECTOR_LOG_TRANSFER_FROM.into()); - assert_eq!( - hex::encode(logs[0].topics[1]), - "000000000000000000000000aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - ); - assert_eq!( - hex::encode(logs[0].topics[2]), - "000000000000000000000000bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" - ); - assert_eq!( - hex::encode(logs[0].topics[3]), - "0000000000000000000000000000000000000000000000000000000000000004" - ); - assert_eq!(logs[0].data, Vec::::new()); - } -} -#[test] -fn token_uri_should_return_a_string() { - impl_precompile_mock_simple!( - Mock, - Ok(H160::zero()), - Ok("This is the token URI".to_string().into_bytes()), - Ok(()) - ); - - let input = EvmDataWriter::new_with_selector(Action::TokenURI).write(U256::from(4)).build(); - let mut handle = create_mock_handle_from_input(input); - handle.code_address = H160::from_str("ffffffffffffffffffffffff0000000000000005").unwrap(); - - let result = Mock::execute(&mut handle); - assert_ok!( - result, - succeed( - EvmDataWriter::new() - .write(Bytes("This is the token URI".to_string().into_bytes())) - .build() - ) - ); -} - -mod helpers { - /// Macro to define a precompile mock with custom closures for testing. - /// - /// This macro creates mock implementations of the `Erc721` trait, - /// allowing you to test how your code interacts with the precompiled contracts. - /// You can define a custom closure for the owner_of function. - /// - /// # Arguments - /// - /// * `$name`: An identifier to name the precompile mock type. - /// * `$owner_of_collection`: A closure that takes `collection_id` and `asset_id` and returns a - /// `Result`. - /// - /// # Example - /// - /// ``` - /// impl_precompile_mock!( - /// MyMock, - /// |collection_id, asset_id| { Ok(AccountId::default()) } - /// ); - /// ``` - #[macro_export] - macro_rules! impl_precompile_mock { - ($name:ident, $owner_of_collection:expr, $token_uri:expr, $transfer_from:expr) => { - struct Erc721Mock; - - impl pallet_living_assets_ownership::traits::Erc721 for Erc721Mock { - type Error = &'static str; - - fn owner_of( - collection_id: CollectionId, - asset_id: AssetId, - ) -> Result { - ($owner_of_collection)(collection_id, asset_id) - } - - fn token_uri( - collection_id: CollectionId, - asset_id: AssetId, - ) -> Result, Self::Error> { - ($token_uri)(collection_id, asset_id) - } - - fn transfer_from( - origin: AccountId, - collection_id: CollectionId, - from: AccountId, - to: AccountId, - asset_id: AssetId, - ) -> Result<(), Self::Error> { - ($transfer_from)(origin, collection_id, from, to, asset_id) - } - } - - type $name = Erc721Precompile; - }; - } - - /// Macro to define a precompile mock for testing. - /// - /// This macro creates mock implementations of the `Erc721` trait, - /// allowing you to test how your code interacts with the precompiled contracts. - /// The mock type is named based on the provided identifier, and the implementation uses the - /// provided expression. - /// - /// # Arguments - /// - /// * `$name`: An identifier to name the precompile mock type. - /// * `$owner_of`: An expression that evaluates to a `Result`. - /// - /// # Example - /// - /// ``` - /// impl_precompile_mock_simple!(Mock, Ok(AccountId::default())); - /// ``` - #[macro_export] - macro_rules! impl_precompile_mock_simple { - ($name:ident, $owner_of:expr, $token_uri:expr, $transfer_from:expr) => { - impl_precompile_mock!( - $name, - |_asset_id, _collection_id| { $owner_of }, - |_asset_id, _collection_id| { $token_uri }, - |_origin, _collection_id, _from, _to, _asset_id| { $transfer_from } - ); - }; - } -} diff --git a/ownership-chain/precompile/living-assets/Cargo.toml b/ownership-chain/precompile/living-assets/Cargo.toml deleted file mode 100644 index e08678741..000000000 --- a/ownership-chain/precompile/living-assets/Cargo.toml +++ /dev/null @@ -1,57 +0,0 @@ -[package] -name = "pallet-evm-living-assets-ownership" -version = "2.0.0-dev" -authors = ["Parity Technologies ", "Drew Stone "] -license = "Apache-2.0" -description = "Living assets ownership precompile" -repository = "https://github.com/freeverseio/pallet-livingassets-ownership" -edition = "2021" - -[dependencies] -parity-scale-codec = { workspace = true, features = ["derive"] } -scale-info = { workspace = true, features = [ - "derive", -] } - -# Frontier -fp-evm = { workspace = true, features = ["serde"] } -pallet-evm = { workspace = true } - -# Substrate -frame-support = { workspace = true } -sp-arithmetic = { workspace = true } -sp-core = { workspace = true } -sp-runtime = { workspace = true } -sp-std = { workspace = true } - -# Local pallet -pallet-living-assets-ownership = { workspace = true } - -# Utils -precompile-utils = { workspace = true } -precompile-utils-macro = { workspace = true } - -num_enum = { workspace = true } - -[dev-dependencies] -evm = { workspace = true } -hex = { workspace = true } -precompile-utils = { workspace = true, features = ["testing"]} - -[features] -default = ["std"] -std = [ - # Frontier - "fp-evm/std", - "pallet-evm/std", - "sp-core/std", - "sp-runtime/std", - "sp-std/std", - "pallet-living-assets-ownership/std", - "num_enum/std", - "frame-support/std", - "sp-arithmetic/std", - "precompile-utils/std", - "parity-scale-codec/std", - "scale-info/std", -] diff --git a/ownership-chain/precompile/living-assets/contracts/LivingAssetsOwnership.sol b/ownership-chain/precompile/living-assets/contracts/LivingAssetsOwnership.sol deleted file mode 100644 index a702738ae..000000000 --- a/ownership-chain/precompile/living-assets/contracts/LivingAssetsOwnership.sol +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-only -pragma solidity >=0.8.3; - -/// @title Pallet Collection Manager Interface -/// @author Freeverse team -/// @notice This interface allows Solidity contracts to interact with pallet-living-assets -/// @custom:address 0x0000000000000000000000000000000000000402 -interface LivingAssets { - /// @notice Event emitted when a new collection is created - /// @param collectionAddress Address of the newly created ERC721 collection - event CreateCollection(address indexed collectionAddress); - - /// @notice Creates a new collection - /// @dev Call this function to create a new collection - /// @return address of the ERC721 collection - function createCollection(string memory baseURI) external returns (address); -} diff --git a/ownership-chain/precompile/living-assets/src/lib.rs b/ownership-chain/precompile/living-assets/src/lib.rs deleted file mode 100644 index 4f2665eec..000000000 --- a/ownership-chain/precompile/living-assets/src/lib.rs +++ /dev/null @@ -1,90 +0,0 @@ -//! Living Assets precompile module. - -#![cfg_attr(not(feature = "std"), no_std)] -use fp_evm::{Precompile, PrecompileHandle, PrecompileOutput}; -use pallet_living_assets_ownership::{ - collection_id_to_address, traits::CollectionManager, CollectionId, -}; -use parity_scale_codec::Encode; -use precompile_utils::{ - keccak256, revert, succeed, Address, Bytes, EvmDataWriter, EvmResult, FunctionModifier, LogExt, - LogsBuilder, PrecompileHandleExt, -}; -use sp_runtime::SaturatedConversion; - -use sp_std::{fmt::Debug, marker::PhantomData, vec::Vec}; - -/// Solidity selector of the CreateCollection log, which is the Keccak of the Log signature. -pub const SELECTOR_LOG_CREATE_COLLECTION: [u8; 32] = keccak256!("CreateCollection(address)"); - -#[precompile_utils_macro::generate_function_selector] -#[derive(Debug, PartialEq)] -pub enum Action { - /// Create collection - CreateCollection = "createCollection(string)", -} - -/// Wrapper for the precompile function. -pub struct CollectionManagerPrecompile( - PhantomData<(AddressMapping, AccountId, BaseURI, LivingAssets)>, -) -where - AddressMapping: pallet_evm::AddressMapping, - AccountId: Encode + Debug, - BaseURI: TryFrom>, - LivingAssets: CollectionManager; - -impl Precompile - for CollectionManagerPrecompile -where - AddressMapping: pallet_evm::AddressMapping, - AccountId: Encode + Debug, - BaseURI: TryFrom>, - LivingAssets: CollectionManager, -{ - fn execute(handle: &mut impl PrecompileHandle) -> EvmResult { - let selector = handle.read_selector()?; - - handle.check_function_modifier(match selector { - Action::CreateCollection => FunctionModifier::NonPayable, - })?; - - match selector { - Action::CreateCollection => { - let mut input = handle.read_input()?; - input.expect_arguments(1)?; - - let base_uri_bytes: Vec = match input.read::() { - Ok(bytes) => bytes.into(), - Err(e) => return Err(e), - }; - - let base_uri = match base_uri_bytes.try_into() { - Ok(value) => value, - Err(_) => return Err(revert("base_uri too long")), - }; - - let caller = handle.context().caller; - let owner = AddressMapping::into_account_id(caller); - - match LivingAssets::create_collection(owner, base_uri) { - Ok(collection_id) => { - let collection_address = collection_id_to_address( - collection_id.saturated_into::(), - ); - - LogsBuilder::new(handle.context().address) - .log2(SELECTOR_LOG_CREATE_COLLECTION, collection_address, Vec::new()) - .record(handle)?; - - Ok(succeed(EvmDataWriter::new().write(Address(collection_address)).build())) - }, - Err(err) => Err(revert(err)), - } - }, - } - } -} - -#[cfg(test)] -mod tests; diff --git a/ownership-chain/precompile/living-assets/src/tests.rs b/ownership-chain/precompile/living-assets/src/tests.rs deleted file mode 100644 index 97311f998..000000000 --- a/ownership-chain/precompile/living-assets/src/tests.rs +++ /dev/null @@ -1,211 +0,0 @@ -//! Living assets precompile tests. - -//TODO: remove this and fix clippy issues -#![allow(clippy::redundant_closure_call)] - -use super::*; -use frame_support::assert_ok; -use precompile_utils::{ - revert, succeed, - testing::{create_mock_handle, create_mock_handle_from_input}, -}; -use sp_core::H160; -use sp_std::vec::Vec; - -type AccountId = H160; -type AddressMapping = pallet_evm::IdentityAddressMapping; - -#[test] -fn check_selectors() { - assert_eq!(Action::CreateCollection as u32, 0x059dfe13); -} - -#[test] -fn check_log_selectors() { - assert_eq!( - hex::encode(SELECTOR_LOG_CREATE_COLLECTION), - "18896a5e5f9fd6b9d74f89291fe4640722c8dc4d6a1025ccf047607f3e6954ee" - ); -} - -#[test] -fn failing_create_collection_should_return_error() { - impl_precompile_mock_simple!(Mock, Err("this is an error"), Some(BaseURI::new())); - - let input = EvmDataWriter::new_with_selector(Action::CreateCollection) - .write(Bytes("ipfs::/carbonara".into())) - .build(); - let mut handle = create_mock_handle_from_input(input); - - let result = Mock::execute(&mut handle); - assert_eq!(result.unwrap_err(), revert("this is an error")); -} - -#[test] -fn create_collection_should_return_address() { - impl_precompile_mock_simple!(Mock, Ok(5), Some(BaseURI::new())); - - let input = EvmDataWriter::new_with_selector(Action::CreateCollection) - .write(Bytes("ipfs::/carbonara".into())) - .build(); - let mut handle = create_mock_handle_from_input(input); - - let result = Mock::execute(&mut handle); - assert_ok!( - result, - succeed( - hex::decode("000000000000000000000000ffffffffffffffffffffffff0000000000000005") - .unwrap() - ) - ); -} - -#[test] -fn create_collection_should_generate_log() { - impl_precompile_mock_simple!(Mock, Ok(0xffff), Some(BaseURI::new())); - - let input = EvmDataWriter::new_with_selector(Action::CreateCollection) - .write(Bytes("ipfs::/carbonara".into())) - .build(); - let mut handle = create_mock_handle_from_input(input); - - let result = Mock::execute(&mut handle); - assert!(result.is_ok()); - let logs = handle.logs; - assert_eq!(logs.len(), 1); - assert_eq!(logs[0].address, H160::zero()); - assert_eq!(logs[0].topics.len(), 2); - assert_eq!(logs[0].topics[0], SELECTOR_LOG_CREATE_COLLECTION.into()); - assert_eq!( - hex::encode(logs[0].topics[1]), - "000000000000000000000000ffffffffffffffffffffffff000000000000ffff" - ); - assert_eq!(logs[0].data, Vec::::new()); -} - -#[test] -fn create_collection_on_mock_with_nonzero_value_fails() { - impl_precompile_mock_simple!(Mock, Ok(5), Some(BaseURI::new())); - - let input = EvmDataWriter::new_with_selector(Action::CreateCollection) - .write(Bytes("ipfs::/carbonara".into())) - .build(); - let mut handle = create_mock_handle(input, 0, 1, H160::zero()); - - let result = Mock::execute(&mut handle); - assert!(result.is_err()); - assert_eq!(result.unwrap_err(), revert("function is not payable")); -} - -#[test] -fn create_collection_assign_collection_to_caller() { - impl_precompile_mock!( - Mock, // name of the defined precompile - |owner, base_uri: BaseURI| { - assert_eq!(owner, H160::from_low_u64_be(0x1234)); - assert_eq!(base_uri.escape_ascii().to_string(), "ipfs://carbonara"); - Ok(0) - }, // Closure for create_collection result - |_| { Some(BaseURI::new()) } // Closure for owner_of_collection result - ); - - let input = EvmDataWriter::new_with_selector(Action::CreateCollection) - .write(Bytes("ipfs://carbonara".into())) - .build(); - - let mut handle = create_mock_handle(input, 0, 0, H160::from_low_u64_be(0x1234)); - let result = Mock::execute(&mut handle); - assert!(result.is_ok()); -} - -#[test] -fn call_unexistent_selector_should_fail() { - impl_precompile_mock_simple!(Mock, Ok(0), Some(BaseURI::new())); - - let nonexistent_selector = - hex::decode("fb24ae530000000000000000000000000000000000000000000000000000000000000000") - .unwrap(); - let mut handle = create_mock_handle_from_input(nonexistent_selector); - let result = Mock::execute(&mut handle); - assert_eq!(result.unwrap_err(), revert("unknown selector")); -} - -mod helpers { - /// Macro to define a precompile mock for testing. - /// - /// This macro creates mock implementations of the `CollectionManager` trait, - /// allowing you to test how your code interacts with the precompiled contracts. - /// The mock type is named `Mock`, and the implementation uses the provided expressions. - /// - /// # Arguments - /// - /// * `$name`: An identifier to name the precompile mock type. - /// * `$create_collection_result`: An expression that evaluates to a `Result`. - /// * `$owner_of_collection_result`: An expression that evaluates to an `Option`. - /// - /// # Example - /// - /// ``` - /// impl_precompile_mock_simple!(Mock, Ok(0), Some(BaseURI::new()); - /// ``` - #[macro_export] - macro_rules! impl_precompile_mock { - ($name:ident, $create_collection_result:expr, $base_uri_result:expr) => { - type BaseURI = Vec; - - struct CollectionManagerMock; - - impl pallet_living_assets_ownership::traits::CollectionManager - for CollectionManagerMock - { - type Error = &'static str; - - fn create_collection( - owner: AccountId, - base_uri: BaseURI, - ) -> Result { - ($create_collection_result)(owner, base_uri) - } - - fn base_uri(collection_id: CollectionId) -> Option { - ($base_uri_result)(collection_id) - } - } - - type $name = CollectionManagerPrecompile< - AddressMapping, - AccountId, - BaseURI, - CollectionManagerMock, - >; - }; - } - - /// Macro to define a precompile mock for testing. - /// - /// This macro creates mock implementations of the `CollectionManager` trait, - /// allowing you to test how your code interacts with the precompiled contracts. - /// The mock type is named `Mock`, and the implementation uses the provided expressions. - /// - /// # Arguments - /// - /// * `$create_collection_result`: An expression that evaluates to a `Result`. - /// * `$owner_of_collection_result`: An expression that evaluates to an `Option`. - /// - /// # Example - /// - /// ``` - /// impl_precompile_mock_simple!(Mock, Ok(0), Some(BaseURI::new()); - /// ``` - #[macro_export] - macro_rules! impl_precompile_mock_simple { - ($name:ident, $create_collection_result:expr, $base_uri_result:expr) => { - impl_precompile_mock!( - $name, - |_owner, _base_uri| { $create_collection_result }, - |_collection_id| { $base_uri_result } - ); - }; - } -} diff --git a/ownership-chain/runtime/Cargo.toml b/ownership-chain/runtime/Cargo.toml index cb545dab3..6b46a89f7 100644 --- a/ownership-chain/runtime/Cargo.toml +++ b/ownership-chain/runtime/Cargo.toml @@ -54,10 +54,7 @@ sp-std = { workspace = true } sp-transaction-pool = { workspace = true } sp-version = { workspace = true } -pallet-living-assets-ownership = { workspace = true } pallet-laos-evolution = { workspace = true } -pallet-evm-living-assets-ownership = { workspace = true } -pallet-evm-erc721 = { workspace = true } pallet-evm-laos-evolution = { workspace = true } # Polkadot @@ -124,7 +121,6 @@ std = [ "pallet-collator-selection/std", "pallet-session/std", "pallet-sudo/std", - "pallet-living-assets-ownership/std", "pallet-laos-evolution/std", "pallet-multisig/std", "pallet-timestamp/std", @@ -158,7 +154,6 @@ std = [ "pallet-base-fee/std", "pallet-ethereum/std", "pallet-evm/std", - "pallet-evm-erc721/std", "pallet-evm-laos-evolution/std", "pallet-evm-chain-id/std", "pallet-evm-precompile-modexp/std", @@ -167,7 +162,6 @@ std = [ "frame-benchmarking", "frame-system-benchmarking", "frame-try-runtime", - "pallet-evm-living-assets-ownership/std", # Bridge deps, "ownership-parachain-primitives/std", "hex/std", @@ -180,7 +174,6 @@ runtime-benchmarks = [ "frame-system/runtime-benchmarks", "pallet-balances/runtime-benchmarks", "pallet-collator-selection/runtime-benchmarks", - "pallet-living-assets-ownership/runtime-benchmarks", "pallet-laos-evolution/runtime-benchmarks", "pallet-multisig/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", @@ -214,7 +207,6 @@ try-runtime = [ "pallet-collator-selection/try-runtime", "pallet-session/try-runtime", "pallet-sudo/try-runtime", - "pallet-living-assets-ownership/try-runtime", "pallet-laos-evolution/try-runtime", "pallet-multisig/try-runtime", "pallet-timestamp/try-runtime", diff --git a/ownership-chain/runtime/src/lib.rs b/ownership-chain/runtime/src/lib.rs index 3a4440eb1..1de0fd186 100644 --- a/ownership-chain/runtime/src/lib.rs +++ b/ownership-chain/runtime/src/lib.rs @@ -84,9 +84,6 @@ use pallet_evm::{ mod precompiles; use precompiles::FrontierPrecompiles; -/// Import the living assets ownership pallet. -pub use pallet_living_assets_ownership; - /// Alias to 512-bit hash when used in the context of a transaction signature on the chain. pub type Signature = ownership_parachain_primitives::Signature; @@ -473,13 +470,6 @@ parameter_types! { pub NullAddress: AccountId = [0u8; 20].into(); } -impl pallet_living_assets_ownership::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type BaseURILimit = ConstU32<2015>; - type NullAddress = NullAddress; - type AssetIdToInitialOwner = AssetIdToInitialOwner; -} - parameter_types! { /// Max length of the `TokenUri` pub const MaxTokenUriLength: u32 = 512; @@ -731,8 +721,6 @@ construct_runtime!( // Sudo Sudo: pallet_sudo = 40, - // Local pallets - LaosLivingAssetsOwnership: pallet_living_assets_ownership = 41, LaosEvolution: pallet_laos_evolution = 42, // Frontier diff --git a/ownership-chain/runtime/src/precompiles/mock.rs b/ownership-chain/runtime/src/precompiles/mock.rs index 27a9766c3..7bd728431 100644 --- a/ownership-chain/runtime/src/precompiles/mock.rs +++ b/ownership-chain/runtime/src/precompiles/mock.rs @@ -1,6 +1,6 @@ use frame_support::{ construct_runtime, parameter_types, - traits::{ConstU32, ConstU64, FindAuthor}, + traits::{ConstU64, FindAuthor}, weights::Weight, }; use pallet_evm::{ @@ -26,7 +26,6 @@ construct_runtime!( System: frame_system, Balances: pallet_balances, Timestamp: pallet_timestamp, - LivingassetsOwnership: pallet_living_assets_ownership, EVM: pallet_evm, } ); @@ -92,13 +91,6 @@ parameter_types! { pub NullAddress: AccountId = AccountId::zero(); } -impl pallet_living_assets_ownership::Config for Runtime { - type RuntimeEvent = RuntimeEvent; - type BaseURILimit = ConstU32<256>; - type NullAddress = NullAddress; - type AssetIdToInitialOwner = MockAssetIdToInitialOwner; -} - pub struct MockAssetIdToInitialOwner; impl Convert for MockAssetIdToInitialOwner { fn convert(_asset_id: U256) -> AccountId { diff --git a/ownership-chain/runtime/src/precompiles/mod.rs b/ownership-chain/runtime/src/precompiles/mod.rs index a530292a2..03238b362 100644 --- a/ownership-chain/runtime/src/precompiles/mod.rs +++ b/ownership-chain/runtime/src/precompiles/mod.rs @@ -6,13 +6,10 @@ use pallet_evm::{ use sp_core::H160; use sp_std::marker::PhantomData; -use pallet_evm_erc721::Erc721Precompile; use pallet_evm_laos_evolution::LaosEvolutionPrecompile; -use pallet_evm_living_assets_ownership::CollectionManagerPrecompile; use pallet_evm_precompile_modexp::Modexp; use pallet_evm_precompile_simple::{ECRecover, ECRecoverPublicKey, Identity, Ripemd160, Sha256}; use pallet_laos_evolution::TokenUriOf; -use pallet_living_assets_ownership::{is_collection_address, BaseURIOf}; use crate::{AccountId, Runtime}; @@ -30,15 +27,6 @@ where } } -type LivingAssetsPrecompile = CollectionManagerPrecompile< - pallet_evm::IdentityAddressMapping, - AccountId, - BaseURIOf, - pallet_living_assets_ownership::Pallet, ->; - -type Erc721 = Erc721Precompile>; - type LaosEvolution = LaosEvolutionPrecompile< pallet_evm::IdentityAddressMapping, AccountId, @@ -48,7 +36,7 @@ type LaosEvolution = LaosEvolutionPrecompile< impl PrecompileSet for FrontierPrecompiles where - Runtime: pallet_evm::Config + pallet_living_assets_ownership::Config, + Runtime: pallet_evm::Config, { fn execute(&self, handle: &mut impl PrecompileHandle) -> Option { match handle.code_address() { @@ -61,18 +49,12 @@ where // Non-Frontier specific nor Ethereum precompiles : // a if a == hash(1024) => Some(Sha3FIPS256::execute(handle)), a if a == hash(1025) => Some(ECRecoverPublicKey::execute(handle)), - a if a == hash(1026) => Some(LivingAssetsPrecompile::execute(handle)), a if a == hash(1027) => Some(LaosEvolution::execute(handle)), - a if is_collection_address(a) => Some(Erc721::execute(handle)), _ => None, } } fn is_precompile(&self, address: H160, _gas: u64) -> IsPrecompileResult { - if is_collection_address(address) { - return IsPrecompileResult::Answer { is_precompile: true, extra_cost: 0 } - } - IsPrecompileResult::Answer { is_precompile: Self::used_addresses().contains(&address), extra_cost: 0, diff --git a/ownership-chain/runtime/src/precompiles/test.rs b/ownership-chain/runtime/src/precompiles/test.rs index 0da0bd617..6d9a91217 100644 --- a/ownership-chain/runtime/src/precompiles/test.rs +++ b/ownership-chain/runtime/src/precompiles/test.rs @@ -1,5 +1,4 @@ use super::{hash, mock::*, FrontierPrecompiles}; -use core::str::FromStr; use pallet_evm::{IsPrecompileResult, PrecompileSet}; use sp_core::H160; @@ -23,8 +22,5 @@ fn ethereum_precompiled_addresses_are_precompile() { assert!(is_precompile(hash(3)).unwrap()); assert!(is_precompile(hash(4)).unwrap()); assert!(is_precompile(hash(5)).unwrap()); - assert!(is_precompile(hash(1026)).unwrap()); assert!(is_precompile(hash(1027)).unwrap()); - assert!(is_precompile(H160::from_str("0xffffffffffffffffffffffff0000000000000005").unwrap()) - .unwrap()); } diff --git a/ownership-chain/runtime/src/tests.rs b/ownership-chain/runtime/src/tests.rs index df228cc25..282bfb340 100644 --- a/ownership-chain/runtime/src/tests.rs +++ b/ownership-chain/runtime/src/tests.rs @@ -1,68 +1,7 @@ -use core::str::FromStr; - use super::*; use frame_support::assert_ok; use sp_core::U256; -#[test] -fn asset_id_to_address_type_zero_values() { - type TestAssetIdToInitialOwner = - ::AssetIdToInitialOwner; - - assert_eq!(TestAssetIdToInitialOwner::convert(U256::from(0)), AccountId::from([0u8; 20])); -} - -#[test] -fn asset_id_to_address_type_max_values() { - type TestAssetIdToInitialOwner = - ::AssetIdToInitialOwner; - assert_eq!( - TestAssetIdToInitialOwner::convert(U256::max_value()), - AccountId::from_str("ffffffffffffffffffffffffffffffffffffffff").unwrap() - ); -} - -#[test] -fn asset_id_to_address_two_assets_same_owner() { - type TestAssetIdToInitialOwner = - ::AssetIdToInitialOwner; - assert_eq!( - TestAssetIdToInitialOwner::convert(U256::max_value()), - AccountId::from_str("ffffffffffffffffffffffffffffffffffffffff").unwrap() - ); - - // create two different assets - let asset1 = - U256::from(hex::decode("01C0F0f4ab324C46e55D02D0033343B4Be8A55532d").unwrap().as_slice()); - let asset2 = - U256::from(hex::decode("03C0F0f4ab324C46e55D02D0033343B4Be8A55532d").unwrap().as_slice()); - assert_ne!(asset1, asset2); - - // check asset in decimal format - assert_eq!( - U256::from_str_radix("01C0F0f4ab324C46e55D02D0033343B4Be8A55532d", 16).unwrap(), - U256::from_dec_str("2563001357829637001682277476112176020532353127213").unwrap() - ); - assert_eq!( - U256::from_str_radix("03C0F0f4ab324C46e55D02D0033343B4Be8A55532d", 16).unwrap(), - U256::from_dec_str("5486004632491442838089647141544742059844218213165").unwrap() - ); - - let mut owner = [0u8; 20]; - owner.copy_from_slice( - hex::decode("C0F0f4ab324C46e55D02D0033343B4Be8A55532d").unwrap().as_slice(), - ); - - assert_eq!( - TestAssetIdToInitialOwner::convert(asset1), - AccountId::from_str("c0f0f4ab324c46e55d02d0033343b4be8a55532d").unwrap() - ); - assert_eq!( - TestAssetIdToInitialOwner::convert(asset2), - AccountId::from_str("c0f0f4ab324c46e55d02d0033343b4be8a55532d").unwrap() - ); -} - #[test] fn test_block_and_gas_limit_constants() { use crate::Runtime; From a73bac27c2e0c6c217c9d52691cc27717c5a8794 Mon Sep 17 00:00:00 2001 From: Christian Cuaresma Date: Tue, 14 Nov 2023 09:59:31 +0100 Subject: [PATCH 2/2] Improved test for hash(1026) not being precompile --- ownership-chain/runtime/src/precompiles/mod.rs | 4 ++-- ownership-chain/runtime/src/precompiles/test.rs | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/ownership-chain/runtime/src/precompiles/mod.rs b/ownership-chain/runtime/src/precompiles/mod.rs index 03238b362..df18416c7 100644 --- a/ownership-chain/runtime/src/precompiles/mod.rs +++ b/ownership-chain/runtime/src/precompiles/mod.rs @@ -22,8 +22,8 @@ where pub fn new() -> Self { Self(Default::default()) } - pub fn used_addresses() -> [H160; 8] { - [hash(1), hash(2), hash(3), hash(4), hash(5), hash(1025), hash(1026), hash(1027)] + pub fn used_addresses() -> [H160; 7] { + [hash(1), hash(2), hash(3), hash(4), hash(5), hash(1025), hash(1027)] } } diff --git a/ownership-chain/runtime/src/precompiles/test.rs b/ownership-chain/runtime/src/precompiles/test.rs index 6d9a91217..4255da922 100644 --- a/ownership-chain/runtime/src/precompiles/test.rs +++ b/ownership-chain/runtime/src/precompiles/test.rs @@ -22,5 +22,6 @@ fn ethereum_precompiled_addresses_are_precompile() { assert!(is_precompile(hash(3)).unwrap()); assert!(is_precompile(hash(4)).unwrap()); assert!(is_precompile(hash(5)).unwrap()); + assert!(!is_precompile(hash(1026)).unwrap()); assert!(is_precompile(hash(1027)).unwrap()); }