--- a/Cargo.lock
+++ b/Cargo.lock
@@ -6829,37 +6829,18 @@
name = "pallet-unique"
version = "0.1.0"
dependencies = [
- "ethereum",
- "evm-coder",
- "fp-evm",
- "fp-evm-mapping",
"frame-benchmarking",
"frame-support",
"frame-system",
- "hex-literal",
- "pallet-balances",
"pallet-common",
- "pallet-ethereum",
"pallet-evm",
- "pallet-evm-coder-substrate",
- "pallet-fungible",
- "pallet-nonfungible",
- "pallet-randomness-collective-flip",
- "pallet-refungible",
- "pallet-timestamp",
- "pallet-transaction-payment",
"parity-scale-codec",
- "primitive-types",
- "rlp",
"scale-info",
- "serde",
- "sp-api",
"sp-core",
"sp-io",
"sp-runtime",
"sp-std",
"up-data-structs",
- "up-sponsorship",
]
[[package]]
@@ -11918,6 +11899,35 @@
]
[[package]]
+name = "tests"
+version = "0.1.0"
+dependencies = [
+ "fp-evm-mapping",
+ "frame-support",
+ "frame-system",
+ "pallet-balances",
+ "pallet-common",
+ "pallet-ethereum",
+ "pallet-evm",
+ "pallet-evm-coder-substrate",
+ "pallet-fungible",
+ "pallet-nonfungible",
+ "pallet-refungible",
+ "pallet-structure",
+ "pallet-timestamp",
+ "pallet-transaction-payment",
+ "pallet-unique",
+ "parity-scale-codec",
+ "scale-info",
+ "sp-core",
+ "sp-io",
+ "sp-runtime",
+ "sp-std",
+ "unique-runtime-common",
+ "up-data-structs",
+]
+
+[[package]]
name = "textwrap"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -12677,6 +12687,7 @@
name = "unique-runtime-common"
version = "0.9.18"
dependencies = [
+ "evm-coder",
"fp-rpc",
"frame-support",
"frame-system",
@@ -12693,6 +12704,7 @@
"sp-runtime",
"sp-std",
"up-data-structs",
+ "up-sponsorship",
]
[[package]]
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,16 @@
[workspace]
resolver = "2"
-members = ['node/*', 'pallets/*', 'client/*', 'primitives/*', 'crates/*']
-exclude = ["runtime/unique", "runtime/quartz"]
+members = [
+ 'node/*',
+ 'pallets/*',
+ 'client/*',
+ 'primitives/*',
+ 'crates/*',
+ 'runtime/tests',
+]
+exclude = [
+ "runtime/unique",
+ "runtime/quartz"
+]
[profile.release]
panic = 'unwind'
--- a/pallets/unique/Cargo.toml
+++ b/pallets/unique/Cargo.toml
@@ -19,32 +19,14 @@
runtime-benchmarks = ['frame-benchmarking', 'pallet-common/runtime-benchmarks']
std = [
'codec/std',
- 'serde/std',
'frame-support/std',
'frame-system/std',
- 'pallet-balances/std',
'pallet-evm/std',
- 'pallet-timestamp/std',
- 'pallet-randomness-collective-flip/std',
- 'pallet-transaction-payment/std',
'pallet-common/std',
- 'pallet-fungible/std',
- 'pallet-nonfungible/std',
- 'pallet-refungible/std',
- 'fp-evm/std',
'up-data-structs/std',
- 'up-sponsorship/std',
- 'fp-evm-mapping/std',
'sp-std/std',
- 'sp-api/std',
'sp-runtime/std',
'frame-benchmarking/std',
- 'ethereum/std',
- 'rlp/std',
-
- 'primitive-types/std',
- 'evm-coder/std',
- 'pallet-evm-coder-substrate/std',
]
limit-testing = ["up-data-structs/limit-testing"]
@@ -69,21 +51,6 @@
branch = "polkadot-v0.9.20"
[dependencies.frame-system]
-default-features = false
-git = "https://github.com/paritytech/substrate"
-branch = "polkadot-v0.9.20"
-
-[dependencies.pallet-balances]
-default-features = false
-git = "https://github.com/paritytech/substrate"
-branch = "polkadot-v0.9.20"
-
-[dependencies.pallet-timestamp]
-default-features = false
-git = "https://github.com/paritytech/substrate"
-branch = "polkadot-v0.9.20"
-
-[dependencies.pallet-randomness-collective-flip]
default-features = false
git = "https://github.com/paritytech/substrate"
branch = "polkadot-v0.9.20"
@@ -93,16 +60,6 @@
git = "https://github.com/paritytech/substrate"
branch = "polkadot-v0.9.20"
-[dependencies.pallet-transaction-payment]
-default-features = false
-git = "https://github.com/paritytech/substrate"
-branch = "polkadot-v0.9.20"
-
-[dependencies.serde]
-default-features = false
-features = ['derive']
-version = '1.0.130'
-
[dependencies.sp-runtime]
default-features = false
git = "https://github.com/paritytech/substrate"
@@ -123,28 +80,8 @@
# Local Dependencies
[dependencies]
up-data-structs = { default-features = false, path = "../../primitives/data-structs" }
-
scale-info = { version = "2.0.1", default-features = false, features = [
"derive",
] }
-ethereum = { version = "0.12.0", default-features = false }
-rlp = { default-features = false, version = "0.5.0" }
-sp-api = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.20" }
-
-up-sponsorship = { version = "0.1.0", default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = "polkadot-v0.9.20" }
-fp-evm-mapping = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.20" }
-evm-coder = { default-features = false, path = "../../crates/evm-coder" }
-pallet-evm-coder-substrate = { default-features = false, path = "../../pallets/evm-coder-substrate" }
-primitive-types = { version = "0.11.1", default-features = false, features = [
- "serde_no_std",
-] }
-
-pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.20" }
-pallet-ethereum = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.20" }
-fp-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.20" }
-hex-literal = "0.3.3"
-
+pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier.git", branch = "unique-polkadot-v0.9.18-2" }
pallet-common = { default-features = false, path = "../common" }
-pallet-fungible = { default-features = false, path = "../fungible" }
-pallet-nonfungible = { default-features = false, path = "../nonfungible" }
-pallet-refungible = { default-features = false, path = "../refungible" }
--- a/pallets/unique/src/common.rs
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
-// This file is part of Unique Network.
-
-// Unique Network is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// Unique Network is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with Unique Network. If not, see .
-
-use core::marker::PhantomData;
-use frame_support::{weights::Weight};
-use pallet_common::{CommonWeightInfo, dispatch::dispatch_weight};
-
-use pallet_fungible::{common::CommonWeights as FungibleWeights};
-use pallet_nonfungible::{common::CommonWeights as NonfungibleWeights};
-use pallet_refungible::{common::CommonWeights as RefungibleWeights};
-use up_data_structs::CreateItemExData;
-
-use crate::Config;
-
-macro_rules! max_weight_of {
- ($method:ident ( $($args:tt)* )) => {
- >::$method($($args)*)
- .max(>::$method($($args)*))
- .max(>::$method($($args)*))
- };
-}
-
-pub struct CommonWeights(PhantomData);
-impl CommonWeightInfo for CommonWeights {
- fn create_item() -> Weight {
- dispatch_weight::() + max_weight_of!(create_item())
- }
-
- fn create_multiple_items(amount: u32) -> Weight {
- dispatch_weight::() + max_weight_of!(create_multiple_items(amount))
- }
-
- fn create_multiple_items_ex(data: &CreateItemExData) -> Weight {
- dispatch_weight::() + max_weight_of!(create_multiple_items_ex(data))
- }
-
- fn burn_item() -> Weight {
- dispatch_weight::() + max_weight_of!(burn_item())
- }
-
- fn transfer() -> Weight {
- dispatch_weight::() + max_weight_of!(transfer())
- }
-
- fn approve() -> Weight {
- dispatch_weight::() + max_weight_of!(approve())
- }
-
- fn transfer_from() -> Weight {
- dispatch_weight::() + max_weight_of!(transfer_from())
- }
-
- fn set_variable_metadata(bytes: u32) -> Weight {
- dispatch_weight::() + max_weight_of!(set_variable_metadata(bytes))
- }
-
- fn burn_from() -> Weight {
- dispatch_weight::() + max_weight_of!(burn_from())
- }
-}
--- a/pallets/unique/src/eth/mod.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
-// This file is part of Unique Network.
-
-// Unique Network is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// Unique Network is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with Unique Network. If not, see .
-
-pub mod sponsoring;
--- a/pallets/unique/src/eth/sponsoring.rs
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
-// This file is part of Unique Network.
-
-// Unique Network is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// Unique Network is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with Unique Network. If not, see .
-
-//! Implements EVM sponsoring logic via TransactionValidityHack
-
-use crate::{Config, sponsorship::*};
-use evm_coder::{Call, abi::AbiReader};
-use pallet_common::{CollectionHandle, eth::map_eth_to_id};
-use sp_core::H160;
-use sp_std::prelude::*;
-use up_sponsorship::SponsorshipHandler;
-use core::marker::PhantomData;
-use core::convert::TryInto;
-use pallet_evm::account::CrossAccountId;
-use up_data_structs::{TokenId, CreateItemData, CreateNftData};
-
-use pallet_nonfungible::erc::{
- UniqueNFTCall, ERC721UniqueExtensionsCall, ERC721MintableCall, ERC721Call,
-};
-use pallet_fungible::erc::{UniqueFungibleCall, ERC20Call};
-
-pub struct UniqueEthSponsorshipHandler(PhantomData<*const T>);
-impl SponsorshipHandler)>
- for UniqueEthSponsorshipHandler
-{
- fn get_sponsor(who: &T::CrossAccountId, call: &(H160, Vec)) -> Option {
- let collection_id = map_eth_to_id(&call.0)?;
- let collection = >::new(collection_id)?;
- let sponsor = collection.sponsorship.sponsor()?.clone();
- let (method_id, mut reader) = AbiReader::new_call(&call.1).ok()?;
- Some(T::CrossAccountId::from_sub(match &collection.mode {
- crate::CollectionMode::NFT => {
- let call = >::parse(method_id, &mut reader).ok()??;
- match call {
- UniqueNFTCall::ERC721UniqueExtensions(
- ERC721UniqueExtensionsCall::Transfer { token_id, .. },
- ) => {
- let token_id: TokenId = token_id.try_into().ok()?;
- withdraw_transfer::(&collection, &who, &token_id).map(|()| sponsor)
- }
- UniqueNFTCall::ERC721Mintable(
- ERC721MintableCall::Mint { token_id, .. }
- | ERC721MintableCall::MintWithTokenUri { token_id, .. },
- ) => {
- let _token_id: TokenId = token_id.try_into().ok()?;
- withdraw_create_item::(
- &collection,
- &who,
- &CreateItemData::NFT(CreateNftData::default()),
- )
- .map(|()| sponsor)
- }
- UniqueNFTCall::ERC721(ERC721Call::TransferFrom { token_id, from, .. }) => {
- let token_id: TokenId = token_id.try_into().ok()?;
- let from = T::CrossAccountId::from_eth(from);
- withdraw_transfer::(&collection, &from, &token_id).map(|()| sponsor)
- }
- UniqueNFTCall::ERC721(ERC721Call::Approve { token_id, .. }) => {
- let token_id: TokenId = token_id.try_into().ok()?;
- withdraw_approve::(&collection, who.as_sub(), &token_id)
- .map(|()| sponsor)
- }
- _ => None,
- }
- }
- crate::CollectionMode::Fungible(_) => {
- let call = >::parse(method_id, &mut reader).ok()??;
- #[allow(clippy::single_match)]
- match call {
- UniqueFungibleCall::ERC20(ERC20Call::Transfer { .. }) => {
- withdraw_transfer::(&collection, who, &TokenId::default())
- .map(|()| sponsor)
- }
- UniqueFungibleCall::ERC20(ERC20Call::TransferFrom { from, .. }) => {
- let from = T::CrossAccountId::from_eth(from);
- withdraw_transfer::(&collection, &from, &TokenId::default())
- .map(|()| sponsor)
- }
- UniqueFungibleCall::ERC20(ERC20Call::Approve { .. }) => {
- withdraw_approve::(&collection, who.as_sub(), &TokenId::default())
- .map(|()| sponsor)
- }
- _ => None,
- }
- }
- _ => None,
- }?))
- }
-}
--- a/pallets/unique/src/lib.rs
+++ b/pallets/unique/src/lib.rs
@@ -22,10 +22,6 @@
clippy::unused_unit
)]
-extern crate alloc;
-
-pub use serde::{Serialize, Deserialize};
-
use frame_support::{
decl_module, decl_storage, decl_error, decl_event,
dispatch::DispatchResult,
@@ -50,20 +46,6 @@
CollectionHandle, Pallet as PalletCommon, Error as CommonError, CommonWeightInfo,
dispatch::dispatch_call, dispatch::CollectionDispatch,
};
-
-#[cfg(test)]
-mod mock;
-
-#[cfg(test)]
-mod tests;
-
-mod eth;
-mod sponsorship;
-pub use sponsorship::{UniqueSponsorshipHandler, UniqueSponsorshipPredict};
-pub use eth::sponsoring::UniqueEthSponsorshipHandler;
-
-pub mod common;
-use common::CommonWeights;
#[cfg(feature = "runtime-benchmarks")]
mod benchmarking;
@@ -88,20 +70,12 @@
}
}
-pub trait Config:
- system::Config
- + pallet_evm_coder_substrate::Config
- + pallet_common::Config
- + pallet_nonfungible::Config
- + pallet_refungible::Config
- + pallet_fungible::Config
- + Sized
- + TypeInfo
-{
+pub trait Config: system::Config + pallet_common::Config + Sized + TypeInfo {
type Event: From> + Into<::Event>;
/// Weight information for extrinsics in this pallet.
type WeightInfo: WeightInfo;
+ type CommonWeightInfo: CommonWeightInfo;
}
decl_event! {
@@ -689,7 +663,7 @@
/// * owner: Address, initial owner of the NFT.
///
/// * data: Token data to store on chain.
- #[weight = >::create_item()]
+ #[weight = T::CommonWeightInfo::create_item()]
#[transactional]
pub fn create_item(origin, collection_id: CollectionId, owner: T::CrossAccountId, data: CreateItemData) -> DispatchResultWithPostInfo {
let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
@@ -716,7 +690,7 @@
/// * itemsData: Array items properties. Each property is an array of bytes itself, see [create_item].
///
/// * owner: Address, initial owner of the NFT.
- #[weight = >::create_multiple_items(items_data.len() as u32)]
+ #[weight = T::CommonWeightInfo::create_multiple_items(items_data.len() as u32)]
#[transactional]
pub fn create_multiple_items(origin, collection_id: CollectionId, owner: T::CrossAccountId, items_data: Vec) -> DispatchResultWithPostInfo {
ensure!(!items_data.is_empty(), Error::::EmptyArgument);
@@ -726,7 +700,7 @@
dispatch_call::(collection_id, |d| d.create_multiple_items(sender, owner, items_data, &budget))
}
- #[weight = >::create_multiple_items_ex(&data)]
+ #[weight = T::CommonWeightInfo::create_multiple_items_ex(&data)]
#[transactional]
pub fn create_multiple_items_ex(origin, collection_id: CollectionId, data: CreateItemExData) -> DispatchResultWithPostInfo {
let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
@@ -774,7 +748,7 @@
/// * collection_id: ID of the collection.
///
/// * item_id: ID of NFT to burn.
- #[weight = >::burn_item()]
+ #[weight = T::CommonWeightInfo::burn_item()]
#[transactional]
pub fn burn_item(origin, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {
let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
@@ -806,7 +780,7 @@
/// * item_id: ID of NFT to burn.
///
/// * from: owner of item
- #[weight = >::burn_from()]
+ #[weight = T::CommonWeightInfo::burn_from()]
#[transactional]
pub fn burn_from(origin, collection_id: CollectionId, from: T::CrossAccountId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {
let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
@@ -838,7 +812,7 @@
/// * Non-Fungible Mode: Ignored
/// * Fungible Mode: Must specify transferred amount
/// * Re-Fungible Mode: Must specify transferred portion (between 0 and 1)
- #[weight = >::transfer()]
+ #[weight = T::CommonWeightInfo::transfer()]
#[transactional]
pub fn transfer(origin, recipient: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {
let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
@@ -862,7 +836,7 @@
/// * collection_id.
///
/// * item_id: ID of the item.
- #[weight = >::approve()]
+ #[weight = T::CommonWeightInfo::approve()]
#[transactional]
pub fn approve(origin, spender: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, amount: u128) -> DispatchResultWithPostInfo {
let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
@@ -889,7 +863,7 @@
/// * item_id: ID of the item.
///
/// * value: Amount to transfer.
- #[weight = >::transfer_from()]
+ #[weight = T::CommonWeightInfo::transfer_from()]
#[transactional]
pub fn transfer_from(origin, from: T::CrossAccountId, recipient: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, value: u128 ) -> DispatchResultWithPostInfo {
let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
@@ -910,7 +884,7 @@
/// * collection_id.
///
/// * schema: String representing the offchain data schema.
- #[weight = >::set_variable_metadata(data.len() as u32)]
+ #[weight = T::CommonWeightInfo::set_variable_metadata(data.len() as u32)]
#[transactional]
pub fn set_variable_meta_data (
origin,
--- a/pallets/unique/src/mock.rs
+++ /dev/null
@@ -1,220 +0,0 @@
-// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
-// This file is part of Unique Network.
-
-// Unique Network is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// Unique Network is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with Unique Network. If not, see .
-
-#![allow(clippy::from_over_into)]
-
-use crate as pallet_template;
-use sp_core::{H160, H256};
-use frame_support::{parameter_types, traits::Everything, weights::IdentityFee};
-use sp_runtime::{
- traits::{BlakeTwo256, IdentityLookup},
- testing::Header,
-};
-use pallet_transaction_payment::{CurrencyAdapter};
-use frame_system as system;
-use pallet_evm::{AddressMapping, runner::stack::MaybeMirroredLog, account::CrossAccountId};
-use fp_evm_mapping::EvmBackwardsAddressMapping;
-use codec::{Encode, Decode, MaxEncodedLen};
-use scale_info::TypeInfo;
-use up_data_structs::ConstU32;
-
-type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic;
-type Block = frame_system::mocking::MockBlock;
-
-// Configure a mock runtime to test the pallet.
-frame_support::construct_runtime!(
- pub enum Test where
- Block = Block,
- NodeBlock = Block,
- UncheckedExtrinsic = UncheckedExtrinsic,
- {
- System: frame_system::{Pallet, Call, Config, Storage, Event},
- TemplateModule: pallet_template::{Pallet, Call, Storage},
- Balances: pallet_balances::{Pallet, Call, Storage},
- Common: pallet_common::{Pallet, Storage, Event},
- Fungible: pallet_fungible::{Pallet, Storage},
- Refungible: pallet_refungible::{Pallet, Storage},
- Nonfungible: pallet_nonfungible::{Pallet, Storage},
- }
-);
-
-parameter_types! {
- pub const BlockHashCount: u64 = 250;
- pub const SS58Prefix: u8 = 42;
-}
-
-impl system::Config for Test {
- type BaseCallFilter = Everything;
- type BlockWeights = ();
- type BlockLength = ();
- type DbWeight = ();
- type Origin = Origin;
- type Call = Call;
- type Index = u64;
- type BlockNumber = u64;
- type Hash = H256;
- type Hashing = BlakeTwo256;
- type AccountId = u64;
- type Lookup = IdentityLookup;
- type Header = Header;
- type Event = ();
- type BlockHashCount = BlockHashCount;
- type Version = ();
- type PalletInfo = PalletInfo;
- type AccountData = pallet_balances::AccountData;
- type OnNewAccount = ();
- type OnKilledAccount = ();
- type SystemWeightInfo = ();
- type SS58Prefix = SS58Prefix;
- type OnSetCode = ();
- type MaxConsumers = ConstU32<16>;
-}
-
-parameter_types! {
- pub const ExistentialDeposit: u64 = 1;
- pub const MaxLocks: u32 = 50;
-}
-//frame_system::Module;
-impl pallet_balances::Config for Test {
- type AccountStore = System;
- type Balance = u64;
- type DustRemoval = ();
- type Event = ();
- type ExistentialDeposit = ExistentialDeposit;
- type WeightInfo = ();
- type MaxLocks = MaxLocks;
- type MaxReserves = ();
- type ReserveIdentifier = [u8; 8];
-}
-
-parameter_types! {
- pub const OperationalFeeMultiplier: u8 = 5;
-}
-
-impl pallet_transaction_payment::Config for Test {
- type OnChargeTransaction = CurrencyAdapter, ()>;
- type LengthToFee = IdentityFee;
- type WeightToFee = IdentityFee;
- type FeeMultiplierUpdate = ();
- type OperationalFeeMultiplier = OperationalFeeMultiplier;
-}
-
-parameter_types! {
- pub const MinimumPeriod: u64 = 1;
-}
-impl pallet_timestamp::Config for Test {
- type Moment = u64;
- type OnTimestampSet = ();
- type MinimumPeriod = MinimumPeriod;
- type WeightInfo = ();
-}
-
-parameter_types! {
- pub const CollectionCreationPrice: u32 = 100;
- pub TreasuryAccountId: u64 = 1234;
- pub EthereumChainId: u32 = 1111;
-}
-
-pub struct TestEvmAddressMapping;
-impl AddressMapping for TestEvmAddressMapping {
- fn into_account_id(_addr: sp_core::H160) -> u64 {
- unimplemented!()
- }
-}
-
-pub struct TestEvmBackwardsAddressMapping;
-impl EvmBackwardsAddressMapping for TestEvmBackwardsAddressMapping {
- fn from_account_id(_account_id: u64) -> sp_core::H160 {
- unimplemented!()
- }
-}
-
-#[derive(Encode, Decode, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, TypeInfo, MaxEncodedLen)]
-pub struct TestCrossAccountId(u64, sp_core::H160);
-impl CrossAccountId for TestCrossAccountId {
- fn as_sub(&self) -> &u64 {
- &self.0
- }
- fn as_eth(&self) -> &sp_core::H160 {
- &self.1
- }
- fn from_sub(sub: u64) -> Self {
- let mut eth = [0; 20];
- eth[12..20].copy_from_slice(&sub.to_be_bytes());
- Self(sub, sp_core::H160(eth))
- }
- fn from_eth(eth: sp_core::H160) -> Self {
- let mut sub_raw = [0; 8];
- sub_raw.copy_from_slice(ð.0[0..8]);
- let sub = u64::from_be_bytes(sub_raw);
- Self(sub, eth)
- }
- fn conv_eq(&self, other: &Self) -> bool {
- self.as_sub() == other.as_sub()
- }
-}
-
-impl Default for TestCrossAccountId {
- fn default() -> Self {
- Self::from_sub(0)
- }
-}
-
-pub struct TestEtheremTransactionSender;
-impl pallet_ethereum::EthereumTransactionSender for TestEtheremTransactionSender {
- fn submit_logs_transaction(_source: H160, _logs: Vec) {}
-}
-
-impl pallet_evm_coder_substrate::Config for Test {
- type EthereumTransactionSender = TestEtheremTransactionSender;
- type GasWeightMapping = ();
-}
-
-impl pallet_common::Config for Test {
- type Event = ();
- type Currency = Balances;
- type CollectionCreationPrice = CollectionCreationPrice;
- type TreasuryAccountId = TreasuryAccountId;
-}
-
-impl pallet_evm::account::Config for Test {
- type CrossAccountId = TestCrossAccountId;
- type EvmAddressMapping = TestEvmAddressMapping;
- type EvmBackwardsAddressMapping = TestEvmBackwardsAddressMapping;
-}
-
-impl pallet_fungible::Config for Test {
- type WeightInfo = ();
-}
-impl pallet_refungible::Config for Test {
- type WeightInfo = ();
-}
-impl pallet_nonfungible::Config for Test {
- type WeightInfo = ();
-}
-
-impl pallet_template::Config for Test {
- type Event = ();
- type WeightInfo = ();
-}
-
-// Build genesis storage according to the mock runtime.
-pub fn new_test_ext() -> sp_io::TestExternalities {
- system::GenesisConfig::default()
- .build_storage::()
- .unwrap()
- .into()
-}
--- a/pallets/unique/src/sponsorship.rs
+++ /dev/null
@@ -1,365 +0,0 @@
-// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
-// This file is part of Unique Network.
-
-// Unique Network is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// Unique Network is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with Unique Network. If not, see .
-
-use crate::{
- Config, Call, CreateItemBasket, VariableMetaDataBasket, ReFungibleTransferBasket,
- FungibleTransferBasket, NftTransferBasket, CreateItemData, CollectionMode, NftApproveBasket,
- FungibleApproveBasket, RefungibleApproveBasket,
-};
-use core::marker::PhantomData;
-use up_sponsorship::SponsorshipHandler;
-use frame_support::{
- traits::{IsSubType},
- storage::{StorageMap, StorageDoubleMap, StorageNMap},
-};
-use up_data_structs::{
- CollectionId, FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, MetaUpdatePermission,
- NFT_SPONSOR_TRANSFER_TIMEOUT, REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, TokenId,
-};
-use sp_runtime::traits::Saturating;
-use pallet_common::{CollectionHandle};
-use pallet_evm::account::CrossAccountId;
-
-pub fn withdraw_transfer(
- collection: &CollectionHandle,
- who: &T::CrossAccountId,
- item_id: &TokenId,
-) -> Option<()> {
- // preliminary sponsoring correctness check
- match collection.mode {
- CollectionMode::NFT => {
- let owner = pallet_nonfungible::TokenData::::get((collection.id, item_id))?.owner;
- if !owner.conv_eq(who) {
- return None;
- }
- }
- CollectionMode::Fungible(_) => {
- if item_id != &TokenId::default() {
- return None;
- }
- if >::get((collection.id, who)) == 0 {
- return None;
- }
- }
- CollectionMode::ReFungible => {
- if !>::get((collection.id, who, item_id)) {
- return None;
- }
- }
- }
-
- // sponsor timeout
- let block_number = >::block_number() as T::BlockNumber;
- let limit = collection
- .limits
- .sponsor_transfer_timeout(match collection.mode {
- CollectionMode::NFT => NFT_SPONSOR_TRANSFER_TIMEOUT,
- CollectionMode::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
- CollectionMode::ReFungible => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
- });
-
- let last_tx_block = match collection.mode {
- CollectionMode::NFT => >::get(collection.id, item_id),
- CollectionMode::Fungible(_) => {
- >::get(collection.id, who.as_sub())
- }
- CollectionMode::ReFungible => {
- >::get((collection.id, item_id, who.as_sub()))
- }
- };
-
- if let Some(last_tx_block) = last_tx_block {
- let timeout = last_tx_block + limit.into();
- if block_number < timeout {
- return None;
- }
- }
-
- match collection.mode {
- CollectionMode::NFT => >::insert(collection.id, item_id, block_number),
- CollectionMode::Fungible(_) => {
- >::insert(collection.id, who.as_sub(), block_number)
- }
- CollectionMode::ReFungible => >::insert(
- (collection.id, item_id, who.as_sub()),
- block_number,
- ),
- };
-
- Some(())
-}
-
-pub fn withdraw_create_item(
- collection: &CollectionHandle,
- who: &T::CrossAccountId,
- _properties: &CreateItemData,
-) -> Option<()> {
- if _properties.data_size() as u32 > collection.limits.sponsored_data_size() {
- return None;
- }
-
- // sponsor timeout
- let block_number = >::block_number() as T::BlockNumber;
- let limit = collection
- .limits
- .sponsor_transfer_timeout(match _properties {
- CreateItemData::NFT(_) => NFT_SPONSOR_TRANSFER_TIMEOUT,
- CreateItemData::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
- CreateItemData::ReFungible(_) => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
- });
-
- if let Some(last_tx_block) = >::get((collection.id, who.as_sub())) {
- let timeout = last_tx_block + limit.into();
- if block_number < timeout {
- return None;
- }
- }
-
- CreateItemBasket::::insert((collection.id, who.as_sub()), block_number);
-
- Some(())
-}
-
-pub fn withdraw_set_variable_meta_data(
- who: &T::CrossAccountId,
- collection: &CollectionHandle,
- item_id: &TokenId,
- data: &[u8],
-) -> Option<()> {
- // TODO: make it work for admins
- if collection.meta_update_permission != MetaUpdatePermission::ItemOwner {
- return None;
- }
- // preliminary sponsoring correctness check
- match collection.mode {
- CollectionMode::NFT => {
- let owner = pallet_nonfungible::TokenData::::get((collection.id, item_id))?.owner;
- if !owner.conv_eq(who) {
- return None;
- }
- }
- CollectionMode::Fungible(_) => {
- if item_id != &TokenId::default() {
- return None;
- }
- if >::get((collection.id, who)) == 0 {
- return None;
- }
- }
- CollectionMode::ReFungible => {
- if !>::get((collection.id, who, item_id)) {
- return None;
- }
- }
- }
-
- // Can't sponsor fungible collection, this tx will be rejected
- // as invalid
- if matches!(collection.mode, CollectionMode::Fungible(_)) {
- return None;
- }
- if data.len() > collection.limits.sponsored_data_size() as usize {
- return None;
- }
-
- let block_number = >::block_number() as T::BlockNumber;
- let limit = collection.limits.sponsored_data_rate_limit()?;
-
- if let Some(last_tx_block) = VariableMetaDataBasket::::get(collection.id, item_id) {
- let timeout = last_tx_block + limit.into();
- if block_number < timeout {
- return None;
- }
- }
-
- >::insert(collection.id, item_id, block_number);
-
- Some(())
-}
-
-pub fn withdraw_approve(
- collection: &CollectionHandle,
- who: &T::AccountId,
- item_id: &TokenId,
-) -> Option<()> {
- // sponsor timeout
- let block_number = >::block_number() as T::BlockNumber;
- let limit = collection.limits.sponsor_approve_timeout();
-
- let last_tx_block = match collection.mode {
- CollectionMode::NFT => >::get(collection.id, item_id),
- CollectionMode::Fungible(_) => >::get(collection.id, who),
- CollectionMode::ReFungible => {
- >::get((collection.id, item_id, who))
- }
- };
-
- if let Some(last_tx_block) = last_tx_block {
- let timeout = last_tx_block + limit.into();
- if block_number < timeout {
- return None;
- }
- }
-
- match collection.mode {
- CollectionMode::NFT => >::insert(collection.id, item_id, block_number),
- CollectionMode::Fungible(_) => {
- >::insert(collection.id, who, block_number)
- }
- CollectionMode::ReFungible => {
- >::insert((collection.id, item_id, who), block_number)
- }
- };
-
- Some(())
-}
-
-fn load(id: CollectionId) -> Option<(T::AccountId, CollectionHandle)> {
- let collection = CollectionHandle::new(id)?;
- let sponsor = collection.sponsorship.sponsor().cloned()?;
- Some((sponsor, collection))
-}
-
-pub struct UniqueSponsorshipHandler(PhantomData);
-impl SponsorshipHandler for UniqueSponsorshipHandler
-where
- T: Config,
- C: IsSubType>,
-{
- fn get_sponsor(who: &T::AccountId, call: &C) -> Option {
- match IsSubType::>::is_sub_type(call)? {
- Call::create_item {
- collection_id,
- data,
- ..
- } => {
- let (sponsor, collection) = load(*collection_id)?;
- withdraw_create_item::(
- &collection,
- &T::CrossAccountId::from_sub(who.clone()),
- data,
- )
- .map(|()| sponsor)
- }
- Call::transfer {
- collection_id,
- item_id,
- ..
- } => {
- let (sponsor, collection) = load(*collection_id)?;
- withdraw_transfer::(
- &collection,
- &T::CrossAccountId::from_sub(who.clone()),
- item_id,
- )
- .map(|()| sponsor)
- }
- Call::transfer_from {
- collection_id,
- item_id,
- from,
- ..
- } => {
- let (sponsor, collection) = load(*collection_id)?;
- withdraw_transfer::(&collection, from, item_id).map(|()| sponsor)
- }
- Call::approve {
- collection_id,
- item_id,
- ..
- } => {
- let (sponsor, collection) = load(*collection_id)?;
- withdraw_approve::(&collection, who, item_id).map(|()| sponsor)
- }
- Call::set_variable_meta_data {
- collection_id,
- item_id,
- data,
- } => {
- let (sponsor, collection) = load(*collection_id)?;
- withdraw_set_variable_meta_data::(
- &T::CrossAccountId::from_sub(who.clone()),
- &collection,
- item_id,
- data,
- )
- .map(|()| sponsor)
- }
- _ => None,
- }
- }
-}
-
-use crate::SponsorshipPredict;
-pub struct UniqueSponsorshipPredict(PhantomData);
-
-impl SponsorshipPredict for UniqueSponsorshipPredict
-where
- T: Config,
-{
- fn predict(collection_id: CollectionId, who: T::CrossAccountId, token: TokenId) -> Option
- where
- u64: From<::BlockNumber>,
- {
- let collection = >::try_get(collection_id).ok()?;
- let _ = collection.sponsorship.sponsor()?;
-
- // sponsor timeout
- let block_number = >::block_number() as T::BlockNumber;
- let limit = collection
- .limits
- .sponsor_transfer_timeout(match collection.mode {
- CollectionMode::NFT => NFT_SPONSOR_TRANSFER_TIMEOUT,
- CollectionMode::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
- CollectionMode::ReFungible => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
- });
-
- let last_tx_block = match collection.mode {
- CollectionMode::NFT => >::get(collection.id, token),
- CollectionMode::Fungible(_) => {
- >::get(collection.id, who.as_sub())
- }
- CollectionMode::ReFungible => {
- >::get((collection.id, token, who.as_sub()))
- }
- };
-
- if let Some(last_tx_block) = last_tx_block {
- return Some(
- last_tx_block
- .saturating_add(limit.into())
- .saturating_sub(block_number)
- .into(),
- );
- }
-
- let token_exists = match collection.mode {
- CollectionMode::NFT => {
- >::contains_key((collection.id, token))
- }
- CollectionMode::Fungible(_) => true,
- CollectionMode::ReFungible => {
- >::contains_key((collection.id, token))
- }
- };
-
- if token_exists {
- Some(0)
- } else {
- None
- }
- }
-}
--- a/pallets/unique/src/tests.rs
+++ /dev/null
@@ -1,2912 +0,0 @@
-// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
-// This file is part of Unique Network.
-
-// Unique Network is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// Unique Network is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with Unique Network. If not, see .
-
-// Tests to be written here
-use super::*;
-use crate::mock::*;
-use crate::{AccessMode, CollectionMode};
-use up_data_structs::{
- COLLECTION_NUMBER_LIMIT, CollectionId, CreateItemData, CreateFungibleData, CreateNftData,
- CreateReFungibleData, MAX_DECIMAL_POINTS, COLLECTION_ADMINS_LIMIT, MetaUpdatePermission,
- TokenId, MAX_TOKEN_OWNERSHIP,
-};
-use frame_support::{assert_noop, assert_ok, assert_err};
-use sp_std::convert::TryInto;
-use pallet_balances;
-
-fn add_balance(user: u64, value: u64) {
- const DONOR_USER: u64 = 999;
- assert_ok!(>::set_balance(
- Origin::root(),
- DONOR_USER,
- value,
- 0
- ));
- assert_ok!(>::force_transfer(
- Origin::root(),
- DONOR_USER,
- user,
- value
- ));
-}
-
-fn default_nft_data() -> CreateNftData {
- CreateNftData {
- const_data: vec![1, 2, 3].try_into().unwrap(),
- variable_data: vec![3, 2, 1].try_into().unwrap(),
- }
-}
-
-fn default_fungible_data() -> CreateFungibleData {
- CreateFungibleData { value: 5 }
-}
-
-fn default_re_fungible_data() -> CreateReFungibleData {
- CreateReFungibleData {
- const_data: vec![1, 2, 3].try_into().unwrap(),
- variable_data: vec![3, 2, 1].try_into().unwrap(),
- pieces: 1023,
- }
-}
-
-fn create_test_collection_for_owner(
- mode: &CollectionMode,
- owner: u64,
- id: CollectionId,
-) -> CollectionId {
- add_balance(owner, CollectionCreationPrice::get() as u64 + 1);
-
- let col_name1: Vec = "Test1\0".encode_utf16().collect::>();
- let col_desc1: Vec = "TestDescription1\0".encode_utf16().collect::>();
- let token_prefix1: Vec = b"token_prefix1\0".to_vec();
-
- let data: CreateCollectionData = CreateCollectionData {
- name: col_name1.try_into().unwrap(),
- description: col_desc1.try_into().unwrap(),
- token_prefix: token_prefix1.try_into().unwrap(),
- mode: mode.clone(),
- ..Default::default()
- };
-
- let origin1 = Origin::signed(owner);
- assert_ok!(TemplateModule::create_collection_ex(origin1, data));
-
- let saved_col_name: Vec = "Test1\0".encode_utf16().collect::>();
- let saved_description: Vec = "TestDescription1\0".encode_utf16().collect::>();
- let saved_prefix: Vec = b"token_prefix1\0".to_vec();
- assert_eq!(
- >::get(id)
- .unwrap()
- .owner,
- owner
- );
- assert_eq!(
- >::get(id).unwrap().name,
- saved_col_name
- );
- assert_eq!(
- >::get(id).unwrap().mode,
- *mode
- );
- assert_eq!(
- >::get(id)
- .unwrap()
- .description,
- saved_description
- );
- assert_eq!(
- >::get(id)
- .unwrap()
- .token_prefix,
- saved_prefix
- );
- id
-}
-
-fn create_test_collection(mode: &CollectionMode, id: CollectionId) -> CollectionId {
- create_test_collection_for_owner(&mode, 1, id)
-}
-
-fn create_test_item(collection_id: CollectionId, data: &CreateItemData) {
- let origin1 = Origin::signed(1);
- assert_ok!(TemplateModule::create_item(
- origin1,
- collection_id,
- account(1),
- data.clone()
- ));
-}
-
-fn account(sub: u64) -> TestCrossAccountId {
- TestCrossAccountId::from_sub(sub)
-}
-
-// Use cases tests region
-// #region
-
-#[test]
-fn set_version_schema() {
- new_test_ext().execute_with(|| {
- let origin1 = Origin::signed(1);
- let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
- assert_ok!(TemplateModule::set_schema_version(
- origin1,
- collection_id,
- SchemaVersion::Unique
- ));
- assert_eq!(
- >::get(collection_id)
- .unwrap()
- .schema_version,
- SchemaVersion::Unique
- );
- });
-}
-
-#[test]
-fn check_not_sufficient_founds() {
- new_test_ext().execute_with(|| {
- let acc: u64 = 1;
- >::set_balance(Origin::root(), acc, 0, 0).unwrap();
-
- let name: Vec = "Test1\0".encode_utf16().collect::>();
- let description: Vec = "TestDescription1\0".encode_utf16().collect::>();
- let token_prefix: Vec = b"token_prefix1\0".to_vec();
-
- let data: CreateCollectionData<::AccountId> =
- CreateCollectionData {
- name: name.try_into().unwrap(),
- description: description.try_into().unwrap(),
- token_prefix: token_prefix.try_into().unwrap(),
- mode: CollectionMode::NFT,
- ..Default::default()
- };
-
- let result = TemplateModule::create_collection_ex(Origin::signed(acc), data);
- assert_err!(result, >::NotSufficientFounds);
- });
-}
-
-#[test]
-fn create_fungible_collection_fails_with_large_decimal_numbers() {
- new_test_ext().execute_with(|| {
- let col_name1: Vec = "Test1\0".encode_utf16().collect::>();
- let col_desc1: Vec = "TestDescription1\0".encode_utf16().collect::>();
- let token_prefix1: Vec = b"token_prefix1\0".to_vec();
-
- let data: CreateCollectionData = CreateCollectionData {
- name: col_name1.try_into().unwrap(),
- description: col_desc1.try_into().unwrap(),
- token_prefix: token_prefix1.try_into().unwrap(),
- mode: CollectionMode::Fungible(MAX_DECIMAL_POINTS + 1),
- ..Default::default()
- };
-
- let origin1 = Origin::signed(1);
- assert_noop!(
- TemplateModule::create_collection_ex(origin1, data),
- Error::::CollectionDecimalPointLimitExceeded
- );
- });
-}
-
-#[test]
-fn create_nft_item() {
- new_test_ext().execute_with(|| {
- let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
- let data = default_nft_data();
- create_test_item(collection_id, &data.clone().into());
-
- let item = >::get((collection_id, 1)).unwrap();
- assert_eq!(item.const_data, data.const_data.into_inner());
- assert_eq!(item.variable_data, data.variable_data.into_inner());
- });
-}
-
-// Use cases tests region
-// #region
-#[test]
-fn create_nft_multiple_items() {
- new_test_ext().execute_with(|| {
- create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
- let origin1 = Origin::signed(1);
-
- let items_data = vec![default_nft_data(), default_nft_data(), default_nft_data()];
-
- assert_ok!(TemplateModule::create_multiple_items(
- origin1,
- CollectionId(1),
- account(1),
- items_data
- .clone()
- .into_iter()
- .map(|d| { d.into() })
- .collect()
- ));
- for (index, data) in items_data.into_iter().enumerate() {
- let item = >::get((
- CollectionId(1),
- TokenId((index + 1) as u32),
- ))
- .unwrap();
- assert_eq!(item.const_data.to_vec(), data.const_data.into_inner());
- assert_eq!(item.variable_data.to_vec(), data.variable_data.into_inner());
- }
- });
-}
-
-#[test]
-fn create_refungible_item() {
- new_test_ext().execute_with(|| {
- let collection_id = create_test_collection(&CollectionMode::ReFungible, CollectionId(1));
-
- let data = default_re_fungible_data();
- create_test_item(collection_id, &data.clone().into());
- let item = >::get((collection_id, TokenId(1)));
- let balance =
- >::get((collection_id, TokenId(1), account(1)));
- assert_eq!(item.const_data, data.const_data.into_inner());
- assert_eq!(item.variable_data, data.variable_data.into_inner());
- assert_eq!(balance, 1023);
- });
-}
-
-#[test]
-fn create_multiple_refungible_items() {
- new_test_ext().execute_with(|| {
- create_test_collection(&CollectionMode::ReFungible, CollectionId(1));
-
- let origin1 = Origin::signed(1);
-
- let items_data = vec![
- default_re_fungible_data(),
- default_re_fungible_data(),
- default_re_fungible_data(),
- ];
-
- assert_ok!(TemplateModule::create_multiple_items(
- origin1,
- CollectionId(1),
- account(1),
- items_data
- .clone()
- .into_iter()
- .map(|d| { d.into() })
- .collect()
- ));
- for (index, data) in items_data.into_iter().enumerate() {
- let item = >::get((
- CollectionId(1),
- TokenId((index + 1) as u32),
- ));
- let balance =
- >::get((CollectionId(1), TokenId(1), account(1)));
- assert_eq!(item.const_data.to_vec(), data.const_data.into_inner());
- assert_eq!(item.variable_data.to_vec(), data.variable_data.into_inner());
- assert_eq!(balance, 1023);
- }
- });
-}
-
-#[test]
-fn create_fungible_item() {
- new_test_ext().execute_with(|| {
- let collection_id = create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));
-
- let data = default_fungible_data();
- create_test_item(collection_id, &data.into());
-
- assert_eq!(
- >::get((collection_id, account(1))),
- 5
- );
- });
-}
-
-//#[test]
-// fn create_multiple_fungible_items() {
-// new_test_ext().execute_with(|| {
-// default_limits();
-
-// create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));
-
-// let origin1 = Origin::signed(1);
-
-// let items_data = vec![default_fungible_data(), default_fungible_data(), default_fungible_data()];
-
-// assert_ok!(TemplateModule::create_multiple_items(
-// origin1.clone(),
-// 1,
-// 1,
-// items_data.clone().into_iter().map(|d| { d.into() }).collect()
-// ));
-
-// for (index, _) in items_data.iter().enumerate() {
-// assert_eq!(TemplateModule::fungible_item_id(1, (index + 1) as TokenId).value, 5);
-// }
-// assert_eq!(TemplateModule::balance_count(1, 1), 3000);
-// assert_eq!(TemplateModule::address_tokens(1, 1), [1, 2, 3]);
-// });
-// }
-
-#[test]
-fn transfer_fungible_item() {
- new_test_ext().execute_with(|| {
- let collection_id = create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));
-
- let origin1 = Origin::signed(1);
- let origin2 = Origin::signed(2);
-
- let data = default_fungible_data();
- create_test_item(collection_id, &data.into());
-
- assert_eq!(
- >::get((CollectionId(1), account(1))),
- 5
- );
-
- // change owner scenario
- assert_ok!(TemplateModule::transfer(
- origin1,
- account(2),
- CollectionId(1),
- TokenId(0),
- 5
- ));
- assert_eq!(
- >::get((CollectionId(1), account(1))),
- 0
- );
-
- // split item scenario
- assert_ok!(TemplateModule::transfer(
- origin2.clone(),
- account(3),
- CollectionId(1),
- TokenId(0),
- 3
- ));
-
- // split item and new owner has account scenario
- assert_ok!(TemplateModule::transfer(
- origin2,
- account(3),
- CollectionId(1),
- TokenId(0),
- 1
- ));
- assert_eq!(
- >::get((CollectionId(1), account(2))),
- 1
- );
- assert_eq!(
- >::get((CollectionId(1), account(3))),
- 4
- );
- });
-}
-
-#[test]
-fn transfer_refungible_item() {
- new_test_ext().execute_with(|| {
- let collection_id = create_test_collection(&CollectionMode::ReFungible, CollectionId(1));
-
- // Create RFT 1 in 1023 pieces for account 1
- let data = default_re_fungible_data();
- create_test_item(collection_id, &data.clone().into());
- let item = >::get((collection_id, TokenId(1)));
- assert_eq!(item.const_data, data.const_data.into_inner());
- assert_eq!(item.variable_data, data.variable_data.into_inner());
- assert_eq!(
- >::get((collection_id, account(1))),
- 1
- );
- assert_eq!(
- >::get((collection_id, TokenId(1), account(1))),
- 1023
- );
- assert_eq!(
- >::get((collection_id, account(1), TokenId(1))),
- true
- );
-
- // Account 1 transfers all 1023 pieces of RFT 1 to account 2
- let origin1 = Origin::signed(1);
- let origin2 = Origin::signed(2);
- assert_ok!(TemplateModule::transfer(
- origin1,
- account(2),
- CollectionId(1),
- TokenId(1),
- 1023
- ));
- assert_eq!(
- >::get((collection_id, TokenId(1), account(2))),
- 1023
- );
- assert_eq!(
- >::get((collection_id, account(1))),
- 0
- );
- assert_eq!(
- >::get((collection_id, account(2))),
- 1
- );
- assert_eq!(
- >::get((collection_id, account(1), TokenId(1))),
- false
- );
- assert_eq!(
- >::get((collection_id, account(2), TokenId(1))),
- true
- );
-
- // Account 2 transfers 500 pieces of RFT 1 to account 3
- assert_ok!(TemplateModule::transfer(
- origin2.clone(),
- account(3),
- CollectionId(1),
- TokenId(1),
- 500
- ));
- assert_eq!(
- >::get((collection_id, TokenId(1), account(2))),
- 523
- );
- assert_eq!(
- >::get((collection_id, TokenId(1), account(3))),
- 500
- );
- assert_eq!(
- >::get((collection_id, account(2))),
- 1
- );
- assert_eq!(
- >::get((collection_id, account(3))),
- 1
- );
- assert_eq!(
- >::get((collection_id, account(2), TokenId(1))),
- true
- );
- assert_eq!(
- >::get((collection_id, account(3), TokenId(1))),
- true
- );
-
- // Account 2 transfers 200 more pieces of RFT 1 to account 3 with pre-existing balance
- assert_ok!(TemplateModule::transfer(
- origin2,
- account(3),
- CollectionId(1),
- TokenId(1),
- 200
- ));
- assert_eq!(
- >::get((collection_id, TokenId(1), account(2))),
- 323
- );
- assert_eq!(
- >::get((collection_id, TokenId(1), account(3))),
- 700
- );
- assert_eq!(
- >::get((collection_id, account(2))),
- 1
- );
- assert_eq!(
- >::get((collection_id, account(3))),
- 1
- );
- assert_eq!(
- >::get((collection_id, account(2), TokenId(1))),
- true
- );
- assert_eq!(
- >::get((collection_id, account(3), TokenId(1))),
- true
- );
- });
-}
-
-#[test]
-fn transfer_nft_item() {
- new_test_ext().execute_with(|| {
- let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
- let data = default_nft_data();
- create_test_item(collection_id, &data.into());
- assert_eq!(
- >::get((collection_id, account(1))),
- 1
- );
- assert_eq!(
- >::get((collection_id, account(1), TokenId(1))),
- true
- );
-
- let origin1 = Origin::signed(1);
- // default scenario
- assert_ok!(TemplateModule::transfer(
- origin1,
- account(2),
- CollectionId(1),
- TokenId(1),
- 1
- ));
- assert_eq!(
- >::get((collection_id, account(1))),
- 0
- );
- assert_eq!(
- >::get((collection_id, account(2))),
- 1
- );
- assert_eq!(
- >::get((collection_id, account(1), TokenId(1))),
- false
- );
- assert_eq!(
- >::get((collection_id, account(2), TokenId(1))),
- true
- );
- });
-}
-
-#[test]
-fn transfer_nft_item_wrong_value() {
- new_test_ext().execute_with(|| {
- let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
- let data = default_nft_data();
- create_test_item(collection_id, &data.into());
- assert_eq!(
- >::get((collection_id, account(1))),
- 1
- );
- assert_eq!(
- >::get((collection_id, account(1), TokenId(1))),
- true
- );
-
- let origin1 = Origin::signed(1);
-
- assert_noop!(
- TemplateModule::transfer(origin1, account(2), CollectionId(1), TokenId(1), 2)
- .map_err(|e| e.error),
- >::NonfungibleItemsHaveNoAmount
- );
- });
-}
-
-#[test]
-fn transfer_nft_item_zero_value() {
- new_test_ext().execute_with(|| {
- let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
- let data = default_nft_data();
- create_test_item(collection_id, &data.into());
- assert_eq!(
- >::get((collection_id, account(1))),
- 1
- );
- assert_eq!(
- >::get((collection_id, account(1), TokenId(1))),
- true
- );
-
- let origin1 = Origin::signed(1);
-
- // Transferring 0 amount works on NFT...
- assert_ok!(TemplateModule::transfer(
- origin1,
- account(2),
- CollectionId(1),
- TokenId(1),
- 0
- ));
- // ... and results in no transfer
- assert_eq!(
- >::get((collection_id, account(1))),
- 1
- );
- assert_eq!(
- >::get((collection_id, account(1), TokenId(1))),
- true
- );
- });
-}
-
-#[test]
-fn nft_approve_and_transfer_from() {
- new_test_ext().execute_with(|| {
- let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
- let data = default_nft_data();
- create_test_item(collection_id, &data.into());
-
- let origin1 = Origin::signed(1);
- let origin2 = Origin::signed(2);
-
- assert_eq!(
- >::get((collection_id, account(1))),
- 1
- );
- assert_eq!(
- >::get((collection_id, account(1), TokenId(1))),
- true
- );
-
- // neg transfer_from
- assert_noop!(
- TemplateModule::transfer_from(
- origin2.clone(),
- account(1),
- account(2),
- CollectionId(1),
- TokenId(1),
- 1
- )
- .map_err(|e| e.error),
- CommonError::::ApprovedValueTooLow
- );
-
- // do approve
- assert_ok!(TemplateModule::approve(
- origin1,
- account(2),
- CollectionId(1),
- TokenId(1),
- 1
- ));
- assert_eq!(
- >::get((CollectionId(1), TokenId(1))).unwrap(),
- account(2)
- );
-
- assert_ok!(TemplateModule::transfer_from(
- origin2,
- account(1),
- account(3),
- CollectionId(1),
- TokenId(1),
- 1
- ));
- assert!(
- >::get((CollectionId(1), TokenId(1))).is_none()
- );
- });
-}
-
-#[test]
-fn nft_approve_and_transfer_from_allow_list() {
- new_test_ext().execute_with(|| {
- let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
- let origin1 = Origin::signed(1);
- let origin2 = Origin::signed(2);
-
- // Create NFT 1 for account 1
- let data = default_nft_data();
- create_test_item(collection_id, &data.clone().into());
- assert_eq!(
- &>::get((collection_id, TokenId(1)))
- .unwrap()
- .const_data,
- &data.const_data.into_inner()
- );
- assert_eq!(
- >::get((collection_id, account(1))),
- 1
- );
- assert_eq!(
- >::get((collection_id, account(1), TokenId(1))),
- true
- );
-
- // Allow allow-list users to mint and add accounts 1, 2, and 3 to allow-list
- assert_ok!(TemplateModule::set_mint_permission(
- origin1.clone(),
- CollectionId(1),
- true
- ));
- assert_ok!(TemplateModule::set_public_access_mode(
- origin1.clone(),
- CollectionId(1),
- AccessMode::AllowList
- ));
- assert_ok!(TemplateModule::add_to_allow_list(
- origin1.clone(),
- CollectionId(1),
- account(1)
- ));
- assert_ok!(TemplateModule::add_to_allow_list(
- origin1.clone(),
- CollectionId(1),
- account(2)
- ));
- assert_ok!(TemplateModule::add_to_allow_list(
- origin1.clone(),
- CollectionId(1),
- account(3)
- ));
-
- // Account 1 approves account 2 for NFT 1
- assert_ok!(TemplateModule::approve(
- origin1.clone(),
- account(2),
- CollectionId(1),
- TokenId(1),
- 1
- ));
- assert_eq!(
- >::get((CollectionId(1), TokenId(1))).unwrap(),
- account(2)
- );
-
- // Account 2 transfers NFT 1 from account 1 to account 3
- assert_ok!(TemplateModule::transfer_from(
- origin2,
- account(1),
- account(3),
- CollectionId(1),
- TokenId(1),
- 1
- ));
- assert!(
- >::get((CollectionId(1), TokenId(1))).is_none()
- );
- });
-}
-
-#[test]
-fn refungible_approve_and_transfer_from() {
- new_test_ext().execute_with(|| {
- let collection_id = create_test_collection(&CollectionMode::ReFungible, CollectionId(1));
-
- let origin1 = Origin::signed(1);
- let origin2 = Origin::signed(2);
-
- // Create RFT 1 in 1023 pieces for account 1
- let data = default_re_fungible_data();
- create_test_item(collection_id, &data.into());
-
- assert_eq!(
- >::get((collection_id, account(1))),
- 1
- );
- assert_eq!(
- >::get((collection_id, TokenId(1), account(1))),
- 1023
- );
- assert_eq!(
- >::get((collection_id, account(1), TokenId(1))),
- true
- );
-
- // Allow public minting, enable allow-list and add accounts 1, 2, 3 to allow-list
- assert_ok!(TemplateModule::set_mint_permission(
- origin1.clone(),
- CollectionId(1),
- true
- ));
- assert_ok!(TemplateModule::set_public_access_mode(
- origin1.clone(),
- CollectionId(1),
- AccessMode::AllowList
- ));
- assert_ok!(TemplateModule::add_to_allow_list(
- origin1.clone(),
- CollectionId(1),
- account(1)
- ));
- assert_ok!(TemplateModule::add_to_allow_list(
- origin1.clone(),
- CollectionId(1),
- account(2)
- ));
- assert_ok!(TemplateModule::add_to_allow_list(
- origin1.clone(),
- CollectionId(1),
- account(3)
- ));
-
- // Account 1 approves account 2 for 1023 pieces of RFT 1
- assert_ok!(TemplateModule::approve(
- origin1,
- account(2),
- CollectionId(1),
- TokenId(1),
- 1023
- ));
- assert_eq!(
- >::get((
- CollectionId(1),
- TokenId(1),
- account(1),
- account(2)
- )),
- 1023
- );
-
- // Account 2 transfers 100 pieces of RFT 1 from account 1 to account 3
- assert_ok!(TemplateModule::transfer_from(
- origin2,
- account(1),
- account(3),
- CollectionId(1),
- TokenId(1),
- 100
- ));
- assert_eq!(
- >::get((collection_id, account(1))),
- 1
- );
- assert_eq!(
- >::get((collection_id, account(3))),
- 1
- );
- assert_eq!(
- >::get((collection_id, TokenId(1), account(1))),
- 923
- );
- assert_eq!(
- >::get((collection_id, TokenId(1), account(3))),
- 100
- );
- assert_eq!(
- >::get((collection_id, account(1), TokenId(1))),
- true
- );
- assert_eq!(
- >::get((collection_id, account(1), TokenId(1))),
- true
- );
- assert_eq!(
- >::get((
- CollectionId(1),
- TokenId(1),
- account(1),
- account(2)
- )),
- 923
- );
- });
-}
-
-#[test]
-fn fungible_approve_and_transfer_from() {
- new_test_ext().execute_with(|| {
- let collection_id = create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));
-
- let data = default_fungible_data();
- create_test_item(collection_id, &data.into());
-
- let origin1 = Origin::signed(1);
- let origin2 = Origin::signed(2);
-
- assert_ok!(TemplateModule::set_mint_permission(
- origin1.clone(),
- CollectionId(1),
- true
- ));
- assert_ok!(TemplateModule::set_public_access_mode(
- origin1.clone(),
- CollectionId(1),
- AccessMode::AllowList
- ));
- assert_ok!(TemplateModule::add_to_allow_list(
- origin1.clone(),
- CollectionId(1),
- account(1)
- ));
- assert_ok!(TemplateModule::add_to_allow_list(
- origin1.clone(),
- CollectionId(1),
- account(2)
- ));
- assert_ok!(TemplateModule::add_to_allow_list(
- origin1.clone(),
- CollectionId(1),
- account(3)
- ));
-
- // do approve
- assert_ok!(TemplateModule::approve(
- origin1.clone(),
- account(2),
- CollectionId(1),
- TokenId(0),
- 5
- ));
- assert_eq!(
- >::get((CollectionId(1), account(1), account(2))),
- 5
- );
- assert_ok!(TemplateModule::approve(
- origin1,
- account(3),
- CollectionId(1),
- TokenId(0),
- 5
- ));
- assert_eq!(
- >::get((CollectionId(1), account(1), account(2))),
- 5
- );
- assert_eq!(
- >::get((CollectionId(1), account(1), account(3))),
- 5
- );
-
- assert_ok!(TemplateModule::transfer_from(
- origin2.clone(),
- account(1),
- account(3),
- CollectionId(1),
- TokenId(0),
- 4
- ));
-
- assert_eq!(
- >::get((CollectionId(1), account(1), account(2))),
- 1
- );
-
- assert_noop!(
- TemplateModule::transfer_from(
- origin2,
- account(1),
- account(3),
- CollectionId(1),
- TokenId(0),
- 4
- )
- .map_err(|e| e.error),
- CommonError::::ApprovedValueTooLow
- );
- });
-}
-
-#[test]
-fn change_collection_owner() {
- new_test_ext().execute_with(|| {
- let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
- let origin1 = Origin::signed(1);
- assert_ok!(TemplateModule::change_collection_owner(
- origin1,
- collection_id,
- 2
- ));
- assert_eq!(
- >::get(collection_id)
- .unwrap()
- .owner,
- 2
- );
- });
-}
-
-#[test]
-fn destroy_collection() {
- new_test_ext().execute_with(|| {
- let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
- let origin1 = Origin::signed(1);
- assert_ok!(TemplateModule::destroy_collection(origin1, collection_id));
- });
-}
-
-#[test]
-fn burn_nft_item() {
- new_test_ext().execute_with(|| {
- let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
- let origin1 = Origin::signed(1);
-
- let data = default_nft_data();
- create_test_item(collection_id, &data.into());
-
- // check balance (collection with id = 1, user id = 1)
- assert_eq!(
- >::get((collection_id, account(1))),
- 1
- );
-
- // burn item
- assert_ok!(TemplateModule::burn_item(
- origin1.clone(),
- collection_id,
- TokenId(1),
- 1
- ));
- assert_eq!(
- >::get((collection_id, account(1))),
- 0
- );
- });
-}
-
-#[test]
-fn burn_same_nft_item_twice() {
- new_test_ext().execute_with(|| {
- let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));
-
- let origin1 = Origin::signed(1);
-
- let data = default_nft_data();
- create_test_item(collection_id, &data.into());
-
- // check balance (collection with id = 1, user id = 1)
- assert_eq!(
- >::get((collection_id, account(1))),
- 1
- );
-
- // burn item
- assert_ok!(TemplateModule::burn_item(
- origin1.clone(),
- collection_id,
- TokenId(1),
- 1
- ));
-
- // burn item again
- assert_noop!(
- TemplateModule::burn_item(origin1, collection_id, TokenId(1), 1).map_err(|e| e.error),
- CommonError::::TokenNotFound
- );
-
- assert_eq!(
- >::get((collection_id, account(1))),
- 0
- );
- });
-}
-
-#[test]
-fn burn_fungible_item() {
- new_test_ext().execute_with(|| {
- let collection_id = create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));
-
- let origin1 = Origin::signed(1);
- assert_ok!(TemplateModule::add_collection_admin(
- origin1.clone(),
- collection_id,
- account(2)
- ));
-
- let data = default_fungible_data();
- create_test_item(collection_id, &data.into());
-
- // check balance (collection with id = 1, user id = 1)
- assert_eq!(
- >::get((collection_id, account(1))),
- 5
- );
-
- // burn item
- assert_ok!(TemplateModule::burn_item(
- origin1.clone(),
- CollectionId(1),
- TokenId(0),
- 5
- ));
- assert_noop!(
- TemplateModule::burn_item(origin1, CollectionId(1), TokenId(0), 5).map_err(|e| e.error),
- CommonError::::TokenValueTooLow
- );
-
- assert_eq!(
- >::get((collection_id, account(1))),
- 0
- );
- });
-}
-
-#[test]
-fn burn_fungible_item_with_token_id() {
- new_test_ext().execute_with(|| {
- let collection_id = create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));
-
- let origin1 = Origin::signed(1);
- assert_ok!(TemplateModule::add_collection_admin(
- origin1.clone(),
- collection_id,
- account(2)
- ));
-
- let data = default_fungible_data();
- create_test_item(collection_id, &data.into());
-
- // check balance (collection with id = 1, user id = 1)
- assert_eq!(
- >::get((collection_id, account(1))),
- 5
- );
-
- // Try to burn item using Token ID
- assert_noop!(
- TemplateModule::burn_item(origin1, CollectionId(1), TokenId(1), 5).map_err(|e| e.error),
- >::FungibleItemsHaveNoId
- );
- });
-}
-#[test]
-fn burn_refungible_item() {
- new_test_ext().execute_with(|| {
- let collection_id = create_test_collection(&CollectionMode::ReFungible, CollectionId(1));
- let origin1 = Origin::signed(1);
-
- assert_ok!(TemplateModule::set_mint_permission(
- origin1.clone(),
- collection_id,
- true
- ));
- assert_ok!(TemplateModule::set_public_access_mode(
- origin1.clone(),
- collection_id,
- AccessMode::AllowList
- ));
- assert_ok!(TemplateModule::add_to_allow_list(
- origin1.clone(),
- collection_id,
- account(1)
- ));
-
- assert_ok!(TemplateModule::add_collection_admin(
- origin1.clone(),
- collection_id,
- account(2)
- ));
-
- let data = default_re_fungible_data();
- create_test_item(collection_id, &data.into());
-
- // check balance (collection with id = 1, user id = 2)
- assert_eq!(
- >::get((collection_id, account(1))),
- 1
- );
- assert_eq!(
- >::get((collection_id, TokenId(1), account(1))),
- 1023
- );
-
- // burn item
- assert_ok!(TemplateModule::burn_item(
- origin1.clone(),
- collection_id,
- TokenId(1),
- 1023
- ));
- assert_noop!(
- TemplateModule::burn_item(origin1, collection_id, TokenId(1), 1023)
- .map_err(|e| e.error),
- CommonError::::TokenValueTooLow
- );
-
- assert_eq!(
- >::get((collection_id, TokenId(1), account(1))),
- 0
- );
- });
-}
-
-#[test]
-fn add_collection_admin() {
- new_test_ext().execute_with(|| {
- let collection1_id =
- create_test_collection_for_owner(&CollectionMode::NFT, 1, CollectionId(1));
- let origin1 = Origin::signed(1);
-
- // Add collection admins
- assert_ok!(TemplateModule::add_collection_admin(
- origin1.clone(),
- collection1_id,
- account(2)
- ));
- assert_ok!(TemplateModule::add_collection_admin(
- origin1,
- collection1_id,
- account(3)
- ));
-
- // Owner is not an admin by default
- assert_eq!(
- >::get((CollectionId(1), account(1))),
- false
- );
- assert!(>::get((
- CollectionId(1),
- account(2)
- )));
- assert!(>::get((
- CollectionId(1),
- account(3)
- )));
- });
-}
-
-#[test]
-fn remove_collection_admin() {
- new_test_ext().execute_with(|| {
- let collection1_id =
- create_test_collection_for_owner(&CollectionMode::NFT, 1, CollectionId(1));
- let origin1 = Origin::signed(1);
- let origin2 = Origin::signed(2);
-
- // Add collection admins 2 and 3
- assert_ok!(TemplateModule::add_collection_admin(
- origin1.clone(),
- collection1_id,
- account(2)
- ));
- assert_ok!(TemplateModule::add_collection_admin(
- origin1,
- collection1_id,
- account(3)
- ));
-
- assert!(>::get((
- CollectionId(1),
- account(2)
- )));
- assert!(>::get((
- CollectionId(1),
- account(3)
- )));
-
- // remove admin 3
- assert_ok!(TemplateModule::remove_collection_admin(
- origin2,
- CollectionId(1),
- account(3)
- ));
-
- // 2 is still admin, 3 is not an admin anymore
- assert!(>::get((
- CollectionId(1),
- account(2)
- )));
- assert_eq!(
-