difftreelog
Merge pull request #825 from UniqueNetwork/feature/evm_coder_types_refactor
in: master
Feature/evm_coder_types_refactor
39 files changed
Cargo.lockdiffbeforeafterboth--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2330,7 +2330,6 @@
"hex",
"hex-literal",
"impl-trait-for-tuples",
- "pallet-evm",
"primitive-types 0.12.1",
"sha3-const",
"similar-asserts",
crates/evm-coder/Cargo.tomldiffbeforeafterboth--- a/crates/evm-coder/Cargo.toml
+++ b/crates/evm-coder/Cargo.toml
@@ -19,8 +19,6 @@
# We have tuple-heavy code in solidity.rs
impl-trait-for-tuples = "0.2.2"
-pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.36" }
-
[dev-dependencies]
# We want to assert some large binary blobs equality in tests
hex = "0.4.3"
crates/evm-coder/procedural/src/solidity_interface.rsdiffbeforeafterboth--- a/crates/evm-coder/procedural/src/solidity_interface.rs
+++ b/crates/evm-coder/procedural/src/solidity_interface.rs
@@ -347,14 +347,14 @@
fn is_value(&self) -> bool {
if let Ok(ident) = self.plain() {
- return ident == "value";
+ return ident == "Value";
}
false
}
fn is_caller(&self) -> bool {
if let Ok(ident) = self.plain() {
- return ident == "caller";
+ return ident == "Caller";
}
false
}
@@ -610,7 +610,7 @@
let custom_signature = self.expand_custom_signature();
quote! {
const #screaming_name_signature: ::evm_coder::custom_signature::SignatureUnit = #custom_signature;
- const #screaming_name: ::evm_coder::types::bytes4 = {
+ const #screaming_name: ::evm_coder::types::Bytes4 = {
let mut sum = ::evm_coder::sha3_const::Keccak256::new();
let mut pos = 0;
while pos < Self::#screaming_name_signature.len {
@@ -974,7 +974,7 @@
#consts
)*
/// Return this call ERC165 selector
- pub const fn interface_id() -> ::evm_coder::types::bytes4 {
+ pub const fn interface_id() -> ::evm_coder::types::Bytes4 {
let mut interface_id = 0;
#(#interface_id)*
#(#inline_interface_id)*
@@ -999,7 +999,7 @@
)*),
};
- let mut out = ::evm_coder::types::string::new();
+ let mut out = ::evm_coder::types::String::new();
if #solidity_name.starts_with("Inline") {
out.push_str("/// @dev inlined interface\n");
}
@@ -1019,7 +1019,7 @@
}
}
impl #gen_ref ::evm_coder::Call for #call_name #gen_ref {
- fn parse(method_id: ::evm_coder::types::bytes4, reader: &mut ::evm_coder::abi::AbiReader) -> ::evm_coder::execution::Result<Option<Self>> {
+ fn parse(method_id: ::evm_coder::types::Bytes4, reader: &mut ::evm_coder::abi::AbiReader) -> ::evm_coder::execution::Result<Option<Self>> {
use ::evm_coder::abi::AbiRead;
match method_id {
::evm_coder::ERC165Call::INTERFACE_ID => return Ok(
@@ -1041,7 +1041,7 @@
#gen_where
{
/// Is this contract implements specified ERC165 selector
- pub fn supports_interface(this: &#name, interface_id: ::evm_coder::types::bytes4) -> bool {
+ pub fn supports_interface(this: &#name, interface_id: ::evm_coder::types::Bytes4) -> bool {
interface_id != u32::to_be_bytes(0xffffff) && (
interface_id == ::evm_coder::ERC165Call::INTERFACE_ID ||
interface_id == Self::interface_id()
crates/evm-coder/procedural/src/to_log.rsdiffbeforeafterboth--- a/crates/evm-coder/procedural/src/to_log.rs
+++ b/crates/evm-coder/procedural/src/to_log.rs
@@ -137,7 +137,7 @@
Self::#name {#(
#fields,
)*} => {
- topics.push(topic::from(Self::#name_screaming));
+ topics.push(::evm_coder::types::Topic::from(Self::#name_screaming));
#(
topics.push(#indexed.to_topic());
)*
@@ -222,7 +222,7 @@
#solidity_functions,
)*),
};
- let mut out = string::new();
+ let mut out = ::evm_coder::types::String::new();
out.push_str("/// @dev inlined interface\n");
let _ = interface.format(is_impl, &mut out, tc);
tc.collect(out);
@@ -231,7 +231,7 @@
#[automatically_derived]
impl ::evm_coder::events::ToLog for #name {
- fn to_log(&self, contract: address) -> ::ethereum::Log {
+ fn to_log(&self, contract: Address) -> ::ethereum::Log {
use ::evm_coder::events::ToTopic;
use ::evm_coder::abi::AbiWrite;
let mut writer = ::evm_coder::abi::AbiWriter::new();
crates/evm-coder/src/abi/impls.rsdiffbeforeafterboth--- a/crates/evm-coder/src/abi/impls.rs
+++ b/crates/evm-coder/src/abi/impls.rs
@@ -63,27 +63,27 @@
impl_abi!(u128, uint128, false);
impl_abi!(U256, uint256, false);
impl_abi!(H160, address, false);
-impl_abi!(string, string, true);
+impl_abi!(String, string, true);
impl_abi_writeable!(&str, string);
-impl_abi_type!(bytes, bytes, true);
+impl_abi_type!(Bytes, bytes, true);
-impl AbiRead for bytes {
- fn abi_read(reader: &mut AbiReader) -> Result<bytes> {
- Ok(bytes(reader.bytes()?))
+impl AbiRead for Bytes {
+ fn abi_read(reader: &mut AbiReader) -> Result<Bytes> {
+ Ok(Bytes(reader.bytes()?))
}
}
-impl AbiWrite for bytes {
+impl AbiWrite for Bytes {
fn abi_write(&self, writer: &mut AbiWriter) {
writer.bytes(self.0.as_slice())
}
}
-impl_abi_type!(bytes4, bytes4, false);
-impl AbiRead for bytes4 {
- fn abi_read(reader: &mut AbiReader) -> Result<bytes4> {
+impl_abi_type!(Bytes4, bytes4, false);
+impl AbiRead for Bytes4 {
+ fn abi_read(reader: &mut AbiReader) -> Result<Bytes4> {
reader.bytes4()
}
}
crates/evm-coder/src/abi/mod.rsdiffbeforeafterboth--- a/crates/evm-coder/src/abi/mod.rs
+++ b/crates/evm-coder/src/abi/mod.rs
@@ -54,7 +54,7 @@
}
}
/// Start reading RLP buffer, parsing first 4 bytes as selector
- pub fn new_call(buf: &'i [u8]) -> Result<(bytes4, Self)> {
+ pub fn new_call(buf: &'i [u8]) -> Result<(Bytes4, Self)> {
if buf.len() < 4 {
return Err(Error::Error(ExitError::OutOfOffset));
}
@@ -148,8 +148,8 @@
}
/// Read [`string`] at current position, then advance
- pub fn string(&mut self) -> Result<string> {
- string::from_utf8(self.bytes()?).map_err(|_| Error::Error(ExitError::InvalidRange))
+ pub fn string(&mut self) -> Result<String> {
+ String::from_utf8(self.bytes()?).map_err(|_| Error::Error(ExitError::InvalidRange))
}
/// Read [`u8`] at current position, then advance
crates/evm-coder/src/abi/test.rsdiffbeforeafterboth--- a/crates/evm-coder/src/abi/test.rs
+++ b/crates/evm-coder/src/abi/test.rs
@@ -39,22 +39,22 @@
#[test]
fn encode_decode_uint8() {
- test_impl_uint!(uint8);
+ test_impl_uint!(u8);
}
#[test]
fn encode_decode_uint32() {
- test_impl_uint!(uint32);
+ test_impl_uint!(u32);
}
#[test]
fn encode_decode_uint128() {
- test_impl_uint!(uint128);
+ test_impl_uint!(u128);
}
#[test]
fn encode_decode_uint256() {
- test_impl::<uint256>(
+ test_impl::<U256>(
0xdeadbeef,
U256([255, 0, 0, 0]),
&hex!(
@@ -101,7 +101,7 @@
#[test]
fn encode_decode_vec_tuple_address_uint256() {
- test_impl::<Vec<(address, uint256)>>(
+ test_impl::<Vec<(Address, U256)>>(
0x1ACF2D55,
vec![
(
@@ -138,7 +138,7 @@
#[test]
fn encode_decode_vec_tuple_uint256_string() {
- test_impl::<Vec<(uint256, string)>>(
+ test_impl::<Vec<(U256, String)>>(
0xdeadbeef,
vec![
(1.into(), "Test URI 0".to_string()),
@@ -261,7 +261,7 @@
let (call, mut decoder) = AbiReader::new_call(encoded_data).unwrap();
assert_eq!(call, u32::to_be_bytes(decoded_data.0));
let address = decoder.address().unwrap();
- let data = <Vec<(uint256, string)>>::abi_read(&mut decoder).unwrap();
+ let data = <Vec<(U256, String)>>::abi_read(&mut decoder).unwrap();
assert_eq!(data, decoded_data.1);
let mut writer = AbiWriter::new_call(decoded_data.0);
@@ -273,12 +273,12 @@
#[test]
fn encode_decode_vec_tuple_string_bytes() {
- test_impl::<Vec<(string, bytes)>>(
+ test_impl::<Vec<(String, Bytes)>>(
0xdeadbeef,
vec![
(
"Test URI 0".to_string(),
- bytes(vec![
+ Bytes(vec![
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
@@ -287,14 +287,14 @@
),
(
"Test URI 1".to_string(),
- bytes(vec![
+ Bytes(vec![
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
]),
),
- ("Test URI 2".to_string(), bytes(vec![0x33, 0x33])),
+ ("Test URI 2".to_string(), Bytes(vec![0x33, 0x33])),
],
&hex!(
"
@@ -337,10 +337,10 @@
// #[ignore = "reason"]
fn encode_decode_tuple0_tuple1_uint8_tuple1_string_bytes_tuple1_uint8_bytes() {
let int = 0xff;
- let by = bytes(vec![0x11, 0x22, 0x33]);
+ let by = Bytes(vec![0x11, 0x22, 0x33]);
let string = "some string".to_string();
- test_impl::<((u8,), (String, bytes), (u8, bytes))>(
+ test_impl::<((u8,), (String, Bytes), (u8, Bytes))>(
0xdeadbeef,
((int,), (string.clone(), by.clone()), (int, by)),
&hex!(
@@ -485,9 +485,9 @@
#[test]
fn encode_decode_tuple0_tuple1_string_bytes() {
- test_impl::<((String, bytes),)>(
+ test_impl::<((String, Bytes),)>(
0xdeadbeef,
- (("some string".to_string(), bytes(vec![1, 2, 3])),),
+ (("some string".to_string(), Bytes(vec![1, 2, 3])),),
&hex!(
"
deadbeef
crates/evm-coder/src/events.rsdiffbeforeafterboth--- a/crates/evm-coder/src/events.rs
+++ b/crates/evm-coder/src/events.rs
@@ -15,7 +15,7 @@
// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
use ethereum::Log;
-use primitive_types::{H160, H256};
+use primitive_types::{H160, H256, U256};
use crate::types::*;
@@ -45,7 +45,7 @@
}
}
-impl ToTopic for uint256 {
+impl ToTopic for U256 {
fn to_topic(&self) -> H256 {
let mut out = [0u8; 32];
self.to_big_endian(&mut out);
@@ -53,7 +53,7 @@
}
}
-impl ToTopic for address {
+impl ToTopic for Address {
fn to_topic(&self) -> H256 {
let mut out = [0u8; 32];
out[12..32].copy_from_slice(&self.0);
@@ -61,7 +61,7 @@
}
}
-impl ToTopic for uint32 {
+impl ToTopic for u32 {
fn to_topic(&self) -> H256 {
let mut out = [0u8; 32];
out[28..32].copy_from_slice(&self.to_be_bytes());
crates/evm-coder/src/lib.rsdiffbeforeafterboth--- a/crates/evm-coder/src/lib.rs
+++ b/crates/evm-coder/src/lib.rs
@@ -131,33 +131,23 @@
use alloc::{vec::Vec};
use primitive_types::{U256, H160, H256};
- pub type address = H160;
- pub type uint8 = u8;
- pub type uint16 = u16;
- pub type uint32 = u32;
- pub type uint64 = u64;
- pub type uint128 = u128;
- pub type uint256 = U256;
- pub type bytes4 = [u8; 4];
- pub type topic = H256;
+ pub type Address = H160;
+ pub type Bytes4 = [u8; 4];
+ pub type Topic = H256;
#[cfg(not(feature = "std"))]
- pub type string = ::alloc::string::String;
+ pub type String = ::alloc::string::String;
#[cfg(feature = "std")]
- pub type string = ::std::string::String;
+ pub type String = ::std::string::String;
#[derive(Default, Debug, PartialEq, Eq, Clone)]
- pub struct bytes(pub Vec<u8>);
-
- /// Solidity doesn't have `void` type, however we have special implementation
- /// for empty tuple return type
- pub type void = ();
+ pub struct Bytes(pub Vec<u8>);
//#region Special types
/// Makes function payable
- pub type value = U256;
+ pub type Value = U256;
/// Makes function caller-sensitive
- pub type caller = address;
+ pub type Caller = Address;
//#endregion
/// Ethereum typed call message, similar to solidity
@@ -172,20 +162,20 @@
pub value: U256,
}
- impl From<Vec<u8>> for bytes {
+ impl From<Vec<u8>> for Bytes {
fn from(src: Vec<u8>) -> Self {
Self(src)
}
}
#[allow(clippy::from_over_into)]
- impl Into<Vec<u8>> for bytes {
+ impl Into<Vec<u8>> for Bytes {
fn into(self) -> Vec<u8> {
self.0
}
}
- impl bytes {
+ impl Bytes {
#[must_use]
pub fn len(&self) -> usize {
self.0.len()
@@ -201,7 +191,7 @@
/// Parseable EVM call, this trait should be implemented with [`solidity_interface`] macro
pub trait Call: Sized {
/// Parse call buffer into typed call enum
- fn parse(selector: types::bytes4, input: &mut AbiReader) -> execution::Result<Option<Self>>;
+ fn parse(selector: types::Bytes4, input: &mut AbiReader) -> execution::Result<Option<Self>>;
}
/// Intended to be used as `#[weight]` output type
@@ -237,22 +227,22 @@
/// implements specified interface
SupportsInterface {
/// Requested interface
- interface_id: types::bytes4,
+ interface_id: types::Bytes4,
},
}
impl ERC165Call {
/// ERC165 selector is provided by standard
- pub const INTERFACE_ID: types::bytes4 = u32::to_be_bytes(0x01ffc9a7);
+ pub const INTERFACE_ID: types::Bytes4 = u32::to_be_bytes(0x01ffc9a7);
}
impl Call for ERC165Call {
- fn parse(selector: types::bytes4, input: &mut AbiReader) -> execution::Result<Option<Self>> {
+ fn parse(selector: types::Bytes4, input: &mut AbiReader) -> execution::Result<Option<Self>> {
if selector != Self::INTERFACE_ID {
return Ok(None);
}
Ok(Some(Self::SupportsInterface {
- interface_id: types::bytes4::abi_read(input)?,
+ interface_id: types::Bytes4::abi_read(input)?,
}))
}
}
crates/evm-coder/src/solidity/impls.rsdiffbeforeafterboth--- a/crates/evm-coder/src/solidity/impls.rs
+++ b/crates/evm-coder/src/solidity/impls.rs
@@ -27,14 +27,14 @@
u64 => "uint64" true = "0",
u128 => "uint128" true = "0",
U256 => "uint256" true = "0",
- bytes4 => "bytes4" true = "bytes4(0)",
+ Bytes4 => "bytes4" true = "bytes4(0)",
H160 => "address" true = "0x0000000000000000000000000000000000000000",
- string => "string" false = "\"\"",
- bytes => "bytes" false = "hex\"\"",
+ String => "string" false = "\"\"",
+ Bytes => "bytes" false = "hex\"\"",
bool => "bool" true = "false",
}
-impl SolidityTypeName for void {
+impl SolidityTypeName for () {
fn solidity_name(_writer: &mut impl fmt::Write, _tc: &TypeCollector) -> fmt::Result {
Ok(())
}
@@ -72,10 +72,10 @@
macro_rules! impl_tuples {
($($ident:ident)+) => {
impl<$($ident: SolidityTypeName + 'static),+> SolidityTupleTy for ($($ident,)+) {
- fn fields(tc: &TypeCollector) -> Vec<string> {
+ fn fields(tc: &TypeCollector) -> Vec<String> {
let mut collected = Vec::with_capacity(Self::len());
$({
- let mut out = string::new();
+ let mut out = String::new();
$ident::solidity_name(&mut out, tc).expect("no fmt error");
collected.push(out);
})*;
crates/evm-coder/src/solidity/mod.rsdiffbeforeafterboth--- a/crates/evm-coder/src/solidity/mod.rs
+++ b/crates/evm-coder/src/solidity/mod.rs
@@ -26,7 +26,7 @@
mod impls;
#[cfg(not(feature = "std"))]
-use alloc::{string::String, vec::Vec, collections::BTreeMap, format};
+use alloc::{vec::Vec, collections::BTreeMap, format};
#[cfg(feature = "std")]
use std::collections::BTreeMap;
use core::{
@@ -42,16 +42,16 @@
pub struct TypeCollector {
/// Code => id
/// id ordering is required to perform topo-sort on the resulting data
- structs: RefCell<BTreeMap<string, usize>>,
- anonymous: RefCell<BTreeMap<Vec<string>, usize>>,
- // generic: RefCell<BTreeMap<string, usize>>,
+ structs: RefCell<BTreeMap<String, usize>>,
+ anonymous: RefCell<BTreeMap<Vec<String>, usize>>,
+ // generic: RefCell<BTreeMap<String, usize>>,
id: Cell<usize>,
}
impl TypeCollector {
pub fn new() -> Self {
Self::default()
}
- pub fn collect(&self, item: string) {
+ pub fn collect(&self, item: String) {
let id = self.next_id();
self.structs.borrow_mut().insert(item, id);
}
@@ -84,7 +84,7 @@
pub fn collect_enum<T: SolidityEnumTy>(&self) -> String {
T::generate_solidity_interface(self)
}
- pub fn finish(self) -> Vec<string> {
+ pub fn finish(self) -> Vec<String> {
let mut data = self.structs.into_inner().into_iter().collect::<Vec<_>>();
data.sort_by_key(|(_, id)| Reverse(*id));
data.into_iter().map(|(code, _)| code).collect()
@@ -360,7 +360,7 @@
pub struct SolidityInterface<F: SolidityFunctions> {
pub docs: &'static [&'static str],
- pub selector: bytes4,
+ pub selector: Bytes4,
pub name: &'static str,
pub is: &'static [&'static str],
pub functions: F,
crates/evm-coder/tests/abi_derive_generation.rsdiffbeforeafterboth--- a/crates/evm-coder/tests/abi_derive_generation.rs
+++ b/crates/evm-coder/tests/abi_derive_generation.rs
@@ -1,6 +1,6 @@
mod test_struct {
use evm_coder_procedural::AbiCoder;
- use evm_coder::types::bytes;
+ use evm_coder::types::Bytes;
#[test]
fn empty_struct() {
@@ -27,13 +27,13 @@
#[derive(AbiCoder, PartialEq, Debug)]
struct TypeStruct2DynamicParam {
_a: String,
- _b: bytes,
+ _b: Bytes,
}
#[derive(AbiCoder, PartialEq, Debug)]
struct TypeStruct2MixedParam {
_a: u8,
- _b: bytes,
+ _b: Bytes,
}
#[derive(AbiCoder, PartialEq, Debug)]
@@ -236,10 +236,10 @@
struct TupleStruct2SimpleParam(u8, u32);
#[derive(AbiCoder, PartialEq, Debug)]
- struct TupleStruct2DynamicParam(String, bytes);
+ struct TupleStruct2DynamicParam(String, Bytes);
#[derive(AbiCoder, PartialEq, Debug)]
- struct TupleStruct2MixedParam(u8, bytes);
+ struct TupleStruct2MixedParam(u8, Bytes);
#[derive(AbiCoder, PartialEq, Debug)]
struct TupleStruct1DerivedSimpleParam(TupleStruct1SimpleParam);
@@ -562,8 +562,8 @@
#[test]
fn codec_struct_2_dynamic() {
let _a: String = "some string".into();
- let _b: bytes = bytes(vec![0x11, 0x22, 0x33]);
- test_impl::<(String, bytes), TupleStruct2DynamicParam, TypeStruct2DynamicParam>(
+ let _b: Bytes = Bytes(vec![0x11, 0x22, 0x33]);
+ test_impl::<(String, Bytes), TupleStruct2DynamicParam, TypeStruct2DynamicParam>(
(_a.clone(), _b.clone()),
TupleStruct2DynamicParam(_a.clone(), _b.clone()),
TypeStruct2DynamicParam { _a, _b },
@@ -573,8 +573,8 @@
#[test]
fn codec_struct_2_mixed() {
let _a: u8 = 0xff;
- let _b: bytes = bytes(vec![0x11, 0x22, 0x33]);
- test_impl::<(u8, bytes), TupleStruct2MixedParam, TypeStruct2MixedParam>(
+ let _b: Bytes = Bytes(vec![0x11, 0x22, 0x33]);
+ test_impl::<(u8, Bytes), TupleStruct2MixedParam, TypeStruct2MixedParam>(
(_a.clone(), _b.clone()),
TupleStruct2MixedParam(_a.clone(), _b.clone()),
TypeStruct2MixedParam { _a, _b },
@@ -605,9 +605,9 @@
#[test]
fn codec_struct_2_derived_dynamic() {
let _a = "some string".to_string();
- let _b = bytes(vec![0x11, 0x22, 0x33]);
+ let _b = Bytes(vec![0x11, 0x22, 0x33]);
test_impl::<
- ((String,), (String, bytes)),
+ ((String,), (String, Bytes)),
TupleStruct2DerivedDynamicParam,
TypeStruct2DerivedDynamicParam,
>(
@@ -626,10 +626,10 @@
#[test]
fn codec_struct_3_derived_mixed() {
let int = 0xff;
- let by = bytes(vec![0x11, 0x22, 0x33]);
+ let by = Bytes(vec![0x11, 0x22, 0x33]);
let string = "some string".to_string();
test_impl::<
- ((u8,), (String, bytes), (u8, bytes)),
+ ((u8,), (String, Bytes), (u8, Bytes)),
TupleStruct3DerivedMixedParam,
TypeStruct3DerivedMixedParam,
>(
crates/evm-coder/tests/conditional_is.rsdiffbeforeafterboth--- a/crates/evm-coder/tests/conditional_is.rs
+++ b/crates/evm-coder/tests/conditional_is.rs
@@ -4,14 +4,14 @@
#[solidity_interface(name = A)]
impl Contract {
- fn method_a() -> Result<void> {
+ fn method_a() -> Result<()> {
Ok(())
}
}
#[solidity_interface(name = B)]
impl Contract {
- fn method_b() -> Result<void> {
+ fn method_b() -> Result<()> {
Ok(())
}
}
crates/evm-coder/tests/generics.rsdiffbeforeafterboth--- a/crates/evm-coder/tests/generics.rs
+++ b/crates/evm-coder/tests/generics.rs
@@ -16,19 +16,20 @@
use std::marker::PhantomData;
use evm_coder::{execution::Result, generate_stubgen, solidity_interface, types::*};
+use primitive_types::U256;
pub struct Generic<T>(PhantomData<T>);
#[solidity_interface(name = GenericIs)]
impl<T> Generic<T> {
- fn test_1(&self) -> Result<uint256> {
+ fn test_1(&self) -> Result<U256> {
unreachable!()
}
}
#[solidity_interface(name = Generic, is(GenericIs))]
impl<T: Into<u32>> Generic<T> {
- fn test_2(&self) -> Result<uint256> {
+ fn test_2(&self) -> Result<U256> {
unreachable!()
}
}
@@ -40,7 +41,7 @@
where
T: core::fmt::Debug,
{
- fn test_3(&self) -> Result<uint256> {
+ fn test_3(&self) -> Result<U256> {
unreachable!()
}
}
crates/evm-coder/tests/log.rsdiffbeforeafterboth--- a/crates/evm-coder/tests/log.rs
+++ b/crates/evm-coder/tests/log.rs
@@ -17,19 +17,20 @@
#![allow(dead_code)]
use evm_coder::{ToLog, types::*};
+use primitive_types::U256;
#[derive(ToLog)]
enum ERC721Log {
Transfer {
#[indexed]
- from: address,
+ from: Address,
#[indexed]
- to: address,
- value: uint256,
+ to: Address,
+ value: U256,
},
Eee {
#[indexed]
- aaa: address,
- bbb: uint256,
+ aaa: Address,
+ bbb: U256,
},
}
crates/evm-coder/tests/random.rsdiffbeforeafterboth--- a/crates/evm-coder/tests/random.rs
+++ b/crates/evm-coder/tests/random.rs
@@ -19,19 +19,20 @@
use evm_coder::{
abi::AbiType, ToLog, execution::Result, solidity_interface, types::*, solidity, weight,
};
+use primitive_types::U256;
pub struct Impls;
#[solidity_interface(name = OurInterface)]
impl Impls {
- fn fn_a(&self, _input: uint256) -> Result<bool> {
+ fn fn_a(&self, _input: U256) -> Result<bool> {
unreachable!()
}
}
#[solidity_interface(name = OurInterface1)]
impl Impls {
- fn fn_b(&self, _input: uint128) -> Result<uint32> {
+ fn fn_b(&self, _input: u128) -> Result<u32> {
unreachable!()
}
}
@@ -39,12 +40,12 @@
#[derive(ToLog)]
enum OurEvents {
Event1 {
- field1: uint32,
+ field1: u32,
},
Event2 {
- field1: uint32,
+ field1: u32,
#[indexed]
- field2: uint32,
+ field2: u32,
},
}
@@ -56,27 +57,27 @@
)]
impl Impls {
#[solidity(rename_selector = "fnK")]
- fn fn_c(&self, _input: uint32) -> Result<uint8> {
+ fn fn_c(&self, _input: u32) -> Result<u8> {
unreachable!()
}
- fn fn_d(&self, _value: uint32) -> Result<uint32> {
+ fn fn_d(&self, _value: u32) -> Result<u32> {
unreachable!()
}
- fn caller_sensitive(&self, _caller: caller) -> Result<uint8> {
+ fn caller_sensitive(&self, _caller: Caller) -> Result<u8> {
unreachable!()
}
- fn payable(&mut self, _value: value) -> Result<uint8> {
+ fn payable(&mut self, _value: Value) -> Result<u8> {
unreachable!()
}
#[weight(*_weight)]
- fn with_weight(&self, _weight: uint64) -> Result<void> {
+ fn with_weight(&self, _weight: u64) -> Result<()> {
unreachable!()
}
/// Doccoment example
- fn with_doc(&self) -> Result<void> {
+ fn with_doc(&self) -> Result<()> {
unreachable!()
}
}
crates/evm-coder/tests/solidity_generation.rsdiffbeforeafterboth--- a/crates/evm-coder/tests/solidity_generation.rs
+++ b/crates/evm-coder/tests/solidity_generation.rs
@@ -15,34 +15,35 @@
// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
use evm_coder::{abi::AbiType, execution::Result, generate_stubgen, solidity_interface, types::*};
+use primitive_types::U256;
pub struct ERC20;
#[solidity_interface(name = ERC20)]
impl ERC20 {
- fn decimals(&self) -> Result<uint8> {
+ fn decimals(&self) -> Result<u8> {
unreachable!()
}
/// Get balance of specified owner
- fn balance_of(&self, _owner: address) -> Result<uint256> {
+ fn balance_of(&self, _owner: Address) -> Result<U256> {
unreachable!()
}
- fn transfer(&mut self, _caller: caller, _to: address, _value: uint256) -> Result<bool> {
+ fn transfer(&mut self, _caller: Caller, _to: Address, _value: U256) -> Result<bool> {
unreachable!()
}
fn transfer_from(
&mut self,
- _caller: caller,
- _from: address,
- _to: address,
- _value: uint256,
+ _caller: Caller,
+ _from: Address,
+ _to: Address,
+ _value: U256,
) -> Result<bool> {
unreachable!()
}
- fn approve(&mut self, _caller: caller, _spender: address, _value: uint256) -> Result<bool> {
+ fn approve(&mut self, _caller: Caller, _spender: Address, _value: U256) -> Result<bool> {
unreachable!()
}
- fn allowance(&self, _owner: address, _spender: address) -> Result<uint256> {
+ fn allowance(&self, _owner: Address, _spender: Address) -> Result<U256> {
unreachable!()
}
}
pallets/common/src/erc.rsdiffbeforeafterboth--- a/pallets/common/src/erc.rs
+++ b/pallets/common/src/erc.rs
@@ -26,6 +26,7 @@
};
use pallet_evm_coder_substrate::dispatch_to_evm;
use sp_std::{vec, vec::Vec};
+use sp_core::U256;
use up_data_structs::{
AccessMode, CollectionMode, CollectionPermissions, OwnerRestrictedSet, Property,
SponsoringRateLimit, SponsorshipState,
@@ -42,32 +43,32 @@
CollectionCreated {
/// Collection owner.
#[indexed]
- owner: address,
+ owner: Address,
/// Collection ID.
#[indexed]
- collection_id: address,
+ collection_id: Address,
},
/// The collection has been destroyed.
CollectionDestroyed {
/// Collection ID.
#[indexed]
- collection_id: address,
+ collection_id: Address,
},
/// The collection has been changed.
CollectionChanged {
/// Collection ID.
#[indexed]
- collection_id: address,
+ collection_id: Address,
},
/// The token has been changed.
TokenChanged {
/// Collection ID.
#[indexed]
- collection_id: address,
+ collection_id: Address,
/// Token ID.
- token_id: uint256,
+ token_id: U256,
},
}
@@ -93,12 +94,7 @@
/// @param value Propery value.
#[solidity(hide)]
#[weight(<SelfWeightOf<T>>::set_collection_properties(1))]
- fn set_collection_property(
- &mut self,
- caller: caller,
- key: string,
- value: bytes,
- ) -> Result<void> {
+ fn set_collection_property(&mut self, caller: Caller, key: String, value: Bytes) -> Result<()> {
let caller = T::CrossAccountId::from_eth(caller);
let key = <Vec<u8>>::from(key)
.try_into()
@@ -115,9 +111,9 @@
#[weight(<SelfWeightOf<T>>::set_collection_properties(properties.len() as u32))]
fn set_collection_properties(
&mut self,
- caller: caller,
+ caller: Caller,
properties: Vec<eth::Property>,
- ) -> Result<void> {
+ ) -> Result<()> {
let caller = T::CrossAccountId::from_eth(caller);
let properties = properties
@@ -134,7 +130,7 @@
/// @param key Property key.
#[solidity(hide)]
#[weight(<SelfWeightOf<T>>::delete_collection_properties(1))]
- fn delete_collection_property(&mut self, caller: caller, key: string) -> Result<()> {
+ fn delete_collection_property(&mut self, caller: Caller, key: String) -> Result<()> {
let caller = T::CrossAccountId::from_eth(caller);
let key = <Vec<u8>>::from(key)
.try_into()
@@ -147,7 +143,7 @@
///
/// @param keys Properties keys.
#[weight(<SelfWeightOf<T>>::delete_collection_properties(keys.len() as u32))]
- fn delete_collection_properties(&mut self, caller: caller, keys: Vec<string>) -> Result<()> {
+ fn delete_collection_properties(&mut self, caller: Caller, keys: Vec<String>) -> Result<()> {
let caller = T::CrossAccountId::from_eth(caller);
let keys = keys
.into_iter()
@@ -168,7 +164,7 @@
///
/// @param key Property key.
/// @return bytes The property corresponding to the key.
- fn collection_property(&self, key: string) -> Result<bytes> {
+ fn collection_property(&self, key: String) -> Result<Bytes> {
let key = <Vec<u8>>::from(key)
.try_into()
.map_err(|_| "key too large")?;
@@ -176,14 +172,14 @@
let props = CollectionProperties::<T>::get(self.id);
let prop = props.get(&key).ok_or("key not found")?;
- Ok(bytes(prop.to_vec()))
+ Ok(Bytes(prop.to_vec()))
}
/// Get collection properties.
///
/// @param keys Properties keys. Empty keys for all propertyes.
/// @return Vector of properties key/value pairs.
- fn collection_properties(&self, keys: Vec<string>) -> Result<Vec<eth::Property>> {
+ fn collection_properties(&self, keys: Vec<String>) -> Result<Vec<eth::Property>> {
let keys = keys
.into_iter()
.map(|key| {
@@ -212,7 +208,7 @@
///
/// @param sponsor Address of the sponsor from whose account funds will be debited for operations with the contract.
#[solidity(hide)]
- fn set_collection_sponsor(&mut self, caller: caller, sponsor: address) -> Result<void> {
+ fn set_collection_sponsor(&mut self, caller: Caller, sponsor: Address) -> Result<()> {
self.consume_store_reads_and_writes(1, 1)?;
let caller = T::CrossAccountId::from_eth(caller);
@@ -229,9 +225,9 @@
/// @param sponsor Cross account address of the sponsor from whose account funds will be debited for operations with the contract.
fn set_collection_sponsor_cross(
&mut self,
- caller: caller,
+ caller: Caller,
sponsor: eth::CrossAddress,
- ) -> Result<void> {
+ ) -> Result<()> {
self.consume_store_reads_and_writes(1, 1)?;
let caller = T::CrossAccountId::from_eth(caller);
@@ -252,7 +248,7 @@
/// Collection sponsorship confirmation.
///
/// @dev After setting the sponsor for the collection, it must be confirmed with this function.
- fn confirm_collection_sponsorship(&mut self, caller: caller) -> Result<void> {
+ fn confirm_collection_sponsorship(&mut self, caller: Caller) -> Result<()> {
self.consume_store_writes(1)?;
let caller = T::CrossAccountId::from_eth(caller);
@@ -261,7 +257,7 @@
}
/// Remove collection sponsor.
- fn remove_collection_sponsor(&mut self, caller: caller) -> Result<void> {
+ fn remove_collection_sponsor(&mut self, caller: Caller) -> Result<()> {
self.consume_store_reads_and_writes(1, 1)?;
let caller = T::CrossAccountId::from_eth(caller);
self.remove_sponsor(&caller).map_err(dispatch_to_evm::<T>)
@@ -343,11 +339,7 @@
/// @dev Throws error if limit not found.
/// @param limit Some limit.
#[solidity(rename_selector = "setCollectionLimit")]
- fn set_collection_limit(
- &mut self,
- caller: caller,
- limit: eth::CollectionLimit,
- ) -> Result<void> {
+ fn set_collection_limit(&mut self, caller: Caller, limit: eth::CollectionLimit) -> Result<()> {
self.consume_store_reads_and_writes(1, 1)?;
if !limit.has_value() {
@@ -359,7 +351,7 @@
}
/// Get contract address.
- fn contract_address(&self) -> Result<address> {
+ fn contract_address(&self) -> Result<Address> {
Ok(crate::eth::collection_id_to_address(self.id))
}
@@ -367,9 +359,9 @@
/// @param newAdmin Cross account administrator address.
fn add_collection_admin_cross(
&mut self,
- caller: caller,
+ caller: Caller,
new_admin: eth::CrossAddress,
- ) -> Result<void> {
+ ) -> Result<()> {
self.consume_store_reads_and_writes(2, 2)?;
let caller = T::CrossAccountId::from_eth(caller);
@@ -382,9 +374,9 @@
/// @param admin Cross account administrator address.
fn remove_collection_admin_cross(
&mut self,
- caller: caller,
+ caller: Caller,
admin: eth::CrossAddress,
- ) -> Result<void> {
+ ) -> Result<()> {
self.consume_store_reads_and_writes(2, 2)?;
let caller = T::CrossAccountId::from_eth(caller);
@@ -396,7 +388,7 @@
/// Add collection admin.
/// @param newAdmin Address of the added administrator.
#[solidity(hide)]
- fn add_collection_admin(&mut self, caller: caller, new_admin: address) -> Result<void> {
+ fn add_collection_admin(&mut self, caller: Caller, new_admin: Address) -> Result<()> {
self.consume_store_reads_and_writes(2, 2)?;
let caller = T::CrossAccountId::from_eth(caller);
@@ -409,7 +401,7 @@
///
/// @param admin Address of the removed administrator.
#[solidity(hide)]
- fn remove_collection_admin(&mut self, caller: caller, admin: address) -> Result<void> {
+ fn remove_collection_admin(&mut self, caller: Caller, admin: Address) -> Result<()> {
self.consume_store_reads_and_writes(2, 2)?;
let caller = T::CrossAccountId::from_eth(caller);
@@ -422,7 +414,7 @@
///
/// @param enable If "true" degenerates to nesting: 'Owner' else to nesting: 'Disabled'
#[solidity(rename_selector = "setCollectionNesting")]
- fn set_nesting_bool(&mut self, caller: caller, enable: bool) -> Result<void> {
+ fn set_nesting_bool(&mut self, caller: Caller, enable: bool) -> Result<()> {
self.consume_store_reads_and_writes(1, 1)?;
let caller = T::CrossAccountId::from_eth(caller);
@@ -443,10 +435,10 @@
#[solidity(rename_selector = "setCollectionNesting")]
fn set_nesting(
&mut self,
- caller: caller,
+ caller: Caller,
enable: bool,
- collections: Vec<address>,
- ) -> Result<void> {
+ collections: Vec<Address>,
+ ) -> Result<()> {
self.consume_store_reads_and_writes(1, 1)?;
if collections.is_empty() {
@@ -511,18 +503,12 @@
}
/// Set the collection access method.
/// @param mode Access mode
- /// 0 for Normal
- /// 1 for AllowList
- fn set_collection_access(&mut self, caller: caller, mode: uint8) -> Result<void> {
+ fn set_collection_access(&mut self, caller: Caller, mode: eth::AccessMode) -> Result<()> {
self.consume_store_reads_and_writes(1, 1)?;
let caller = T::CrossAccountId::from_eth(caller);
let permissions = CollectionPermissions {
- access: Some(match mode {
- 0 => AccessMode::Normal,
- 1 => AccessMode::AllowList,
- _ => return Err("not supported access mode".into()),
- }),
+ access: Some(mode.into()),
..Default::default()
};
<Pallet<T>>::update_permissions(&caller, self, permissions).map_err(dispatch_to_evm::<T>)
@@ -540,7 +526,7 @@
///
/// @param user Address of a trusted user.
#[solidity(hide)]
- fn add_to_collection_allow_list(&mut self, caller: caller, user: address) -> Result<void> {
+ fn add_to_collection_allow_list(&mut self, caller: Caller, user: Address) -> Result<()> {
self.consume_store_writes(1)?;
let caller = T::CrossAccountId::from_eth(caller);
@@ -554,9 +540,9 @@
/// @param user User cross account address.
fn add_to_collection_allow_list_cross(
&mut self,
- caller: caller,
+ caller: Caller,
user: eth::CrossAddress,
- ) -> Result<void> {
+ ) -> Result<()> {
self.consume_store_writes(1)?;
let caller = T::CrossAccountId::from_eth(caller);
@@ -569,7 +555,7 @@
///
/// @param user Address of a removed user.
#[solidity(hide)]
- fn remove_from_collection_allow_list(&mut self, caller: caller, user: address) -> Result<void> {
+ fn remove_from_collection_allow_list(&mut self, caller: Caller, user: Address) -> Result<()> {
self.consume_store_writes(1)?;
let caller = T::CrossAccountId::from_eth(caller);
@@ -583,9 +569,9 @@
/// @param user User cross account address.
fn remove_from_collection_allow_list_cross(
&mut self,
- caller: caller,
+ caller: Caller,
user: eth::CrossAddress,
- ) -> Result<void> {
+ ) -> Result<()> {
self.consume_store_writes(1)?;
let caller = T::CrossAccountId::from_eth(caller);
@@ -597,7 +583,7 @@
/// Switch permission for minting.
///
/// @param mode Enable if "true".
- fn set_collection_mint_mode(&mut self, caller: caller, mode: bool) -> Result<void> {
+ fn set_collection_mint_mode(&mut self, caller: Caller, mode: bool) -> Result<()> {
self.consume_store_reads_and_writes(1, 1)?;
let caller = T::CrossAccountId::from_eth(caller);
@@ -613,7 +599,7 @@
/// @param user account to verify
/// @return "true" if account is the owner or admin
#[solidity(hide, rename_selector = "isOwnerOrAdmin")]
- fn is_owner_or_admin_eth(&self, user: address) -> Result<bool> {
+ fn is_owner_or_admin_eth(&self, user: Address) -> Result<bool> {
let user = T::CrossAccountId::from_eth(user);
Ok(self.is_owner_or_admin(&user))
}
@@ -630,7 +616,7 @@
/// Returns collection type
///
/// @return `Fungible` or `NFT` or `ReFungible`
- fn unique_collection_type(&self) -> Result<string> {
+ fn unique_collection_type(&self) -> Result<String> {
let mode = match self.collection.mode {
CollectionMode::Fungible(_) => "Fungible",
CollectionMode::NFT => "NFT",
@@ -654,7 +640,7 @@
/// @dev Owner can be changed only by current owner
/// @param newOwner new owner account
#[solidity(hide, rename_selector = "changeCollectionOwner")]
- fn set_owner(&mut self, caller: caller, new_owner: address) -> Result<void> {
+ fn set_owner(&mut self, caller: Caller, new_owner: Address) -> Result<()> {
self.consume_store_writes(1)?;
let caller = T::CrossAccountId::from_eth(caller);
@@ -680,9 +666,9 @@
/// @param newOwner new owner cross account
fn change_collection_owner_cross(
&mut self,
- caller: caller,
+ caller: Caller,
new_owner: eth::CrossAddress,
- ) -> Result<void> {
+ ) -> Result<()> {
self.consume_store_writes(1)?;
let caller = T::CrossAccountId::from_eth(caller);
pallets/common/src/eth.rsdiffbeforeafterboth--- a/pallets/common/src/eth.rs
+++ b/pallets/common/src/eth.rs
@@ -18,12 +18,9 @@
use alloc::format;
use sp_std::{vec, vec::Vec};
-use evm_coder::{
- AbiCoder,
- types::{uint256, address},
-};
+use evm_coder::{AbiCoder, types::Address};
pub use pallet_evm::{Config, account::CrossAccountId};
-use sp_core::H160;
+use sp_core::{H160, U256};
use up_data_structs::CollectionId;
// 0x17c4e6453Cc49AAAaEACA894e6D9683e00000001 - collection 1
@@ -33,7 +30,7 @@
];
/// Maps the ethereum address of the collection in substrate.
-pub fn map_eth_to_id(eth: &H160) -> Option<CollectionId> {
+pub fn map_eth_to_id(eth: &Address) -> Option<CollectionId> {
if eth[0..16] != ETH_COLLECTION_PREFIX {
return None;
}
@@ -43,7 +40,7 @@
}
/// Maps the substrate collection id in ethereum.
-pub fn collection_id_to_address(id: CollectionId) -> H160 {
+pub fn collection_id_to_address(id: CollectionId) -> Address {
let mut out = [0; 20];
out[0..16].copy_from_slice(Ð_COLLECTION_PREFIX);
out[16..20].copy_from_slice(&u32::to_be_bytes(id.0));
@@ -51,12 +48,12 @@
}
/// Check if the ethereum address is a collection.
-pub fn is_collection(address: &H160) -> bool {
+pub fn is_collection(address: &Address) -> bool {
address[0..16] == ETH_COLLECTION_PREFIX
}
-/// Convert `uint256` to `CrossAccountId`.
-pub fn convert_uint256_to_cross_account<T: Config>(from: uint256) -> T::CrossAccountId
+/// Convert `U256` to `CrossAccountId`.
+pub fn convert_uint256_to_cross_account<T: Config>(from: U256) -> T::CrossAccountId
where
T::AccountId: From<[u8; 32]>,
{
@@ -69,8 +66,8 @@
/// Cross account struct
#[derive(Debug, Default, AbiCoder)]
pub struct CrossAddress {
- pub(crate) eth: address,
- pub(crate) sub: uint256,
+ pub(crate) eth: Address,
+ pub(crate) sub: U256,
}
impl CrossAddress {
@@ -97,7 +94,7 @@
{
Self {
eth: Default::default(),
- sub: uint256::from_big_endian(account_id.as_ref()),
+ sub: U256::from_big_endian(account_id.as_ref()),
}
}
/// Converts [`CrossAddress`] to `CrossAccountId`.
@@ -121,17 +118,17 @@
/// Ethereum representation of collection [`PropertyKey`](up_data_structs::PropertyKey) and [`PropertyValue`](up_data_structs::PropertyValue).
#[derive(Debug, Default, AbiCoder)]
pub struct Property {
- key: evm_coder::types::string,
- value: evm_coder::types::bytes,
+ key: evm_coder::types::String,
+ value: evm_coder::types::Bytes,
}
impl TryFrom<up_data_structs::Property> for Property {
type Error = evm_coder::execution::Error;
fn try_from(from: up_data_structs::Property) -> Result<Self, Self::Error> {
- let key = evm_coder::types::string::from_utf8(from.key.into())
+ let key = evm_coder::types::String::from_utf8(from.key.into())
.map_err(|e| Self::Error::Revert(format!("utf8 conversion error: {}", e)))?;
- let value = evm_coder::types::bytes(from.value.to_vec());
+ let value = evm_coder::types::Bytes(from.value.to_vec());
Ok(Property { key, value })
}
}
@@ -187,7 +184,7 @@
#[derive(Debug, Default, AbiCoder)]
pub struct CollectionLimit {
field: CollectionLimitField,
- value: Option<uint256>,
+ value: Option<U256>,
}
impl CollectionLimit {
@@ -345,7 +342,7 @@
#[derive(Debug, Default, AbiCoder)]
pub struct TokenPropertyPermission {
/// Token property key.
- key: evm_coder::types::string,
+ key: evm_coder::types::String,
/// Token property permissions.
permissions: Vec<PropertyPermission>,
}
@@ -363,7 +360,7 @@
),
) -> Self {
let (key, permission) = value;
- let key = evm_coder::types::string::from_utf8(key.into_inner())
+ let key = evm_coder::types::String::from_utf8(key.into_inner())
.expect("Stored key must be valid");
let permissions = PropertyPermission::into_vec(permission);
Self { key, permissions }
@@ -393,12 +390,12 @@
#[derive(Debug, Default, AbiCoder)]
pub struct CollectionNesting {
token_owner: bool,
- ids: Vec<uint256>,
+ ids: Vec<U256>,
}
impl CollectionNesting {
/// Create [`CollectionNesting`].
- pub fn new(token_owner: bool, ids: Vec<uint256>) -> Self {
+ pub fn new(token_owner: bool, ids: Vec<U256>) -> Self {
Self { token_owner, ids }
}
}
@@ -416,3 +413,32 @@
Self { field, value }
}
}
+
+/// Ethereum representation of `AccessMode` (see [`up_data_structs::AccessMode`]).
+#[derive(AbiCoder, Copy, Clone, Default, Debug)]
+#[repr(u8)]
+pub enum AccessMode {
+ /// Access grant for owner and admins. Used as default.
+ #[default]
+ Normal,
+ /// Like a [`Normal`](AccessMode::Normal) but also users in allow list.
+ AllowList,
+}
+
+impl From<up_data_structs::AccessMode> for AccessMode {
+ fn from(value: up_data_structs::AccessMode) -> Self {
+ match value {
+ up_data_structs::AccessMode::Normal => AccessMode::Normal,
+ up_data_structs::AccessMode::AllowList => AccessMode::AllowList,
+ }
+ }
+}
+
+impl Into<up_data_structs::AccessMode> for AccessMode {
+ fn into(self) -> up_data_structs::AccessMode {
+ match self {
+ AccessMode::Normal => up_data_structs::AccessMode::Normal,
+ AccessMode::AllowList => up_data_structs::AccessMode::AllowList,
+ }
+ }
+}
pallets/evm-coder-substrate/src/lib.rsdiffbeforeafterboth--- a/pallets/evm-coder-substrate/src/lib.rs
+++ b/pallets/evm-coder-substrate/src/lib.rs
@@ -41,7 +41,7 @@
use evm_coder::{
abi::{AbiReader, AbiWrite, AbiWriter},
execution,
- types::{Msg, value},
+ types::{Msg, Value},
};
pub use pallet::*;
@@ -256,7 +256,7 @@
>(
caller: H160,
e: &mut E,
- value: value,
+ value: Value,
input: &[u8],
) -> execution::Result<Option<AbiWriter>> {
let (selector, mut reader) = AbiReader::new_call(input)?;
pallets/evm-contract-helpers/src/eth.rsdiffbeforeafterboth--- a/pallets/evm-contract-helpers/src/eth.rs
+++ b/pallets/evm-contract-helpers/src/eth.rs
@@ -49,25 +49,25 @@
ContractSponsorSet {
/// Contract address of the affected collection.
#[indexed]
- contract_address: address,
+ contract_address: Address,
/// New sponsor address.
- sponsor: address,
+ sponsor: Address,
},
/// New sponsor was confirm.
ContractSponsorshipConfirmed {
/// Contract address of the affected collection.
#[indexed]
- contract_address: address,
+ contract_address: Address,
/// New sponsor address.
- sponsor: address,
+ sponsor: Address,
},
/// Collection sponsor was removed.
ContractSponsorRemoved {
/// Contract address of the affected collection.
#[indexed]
- contract_address: address,
+ contract_address: Address,
},
}
@@ -96,7 +96,7 @@
/// @dev Returns zero address if contract does not exists
/// @param contractAddress Contract to get owner of
/// @return address Owner of contract
- fn contract_owner(&self, contract_address: address) -> Result<address> {
+ fn contract_owner(&self, contract_address: Address) -> Result<Address> {
Ok(<Owner<T>>::get(contract_address))
}
@@ -105,10 +105,10 @@
/// @param sponsor User address who set as pending sponsor.
fn set_sponsor(
&mut self,
- caller: caller,
- contract_address: address,
- sponsor: address,
- ) -> Result<void> {
+ caller: Caller,
+ contract_address: Address,
+ sponsor: Address,
+ ) -> Result<()> {
self.recorder().consume_sload()?;
self.recorder().consume_sstore()?;
@@ -125,7 +125,7 @@
/// Set contract as self sponsored.
///
/// @param contractAddress Contract for which a self sponsoring is being enabled.
- fn self_sponsored_enable(&mut self, caller: caller, contract_address: address) -> Result<void> {
+ fn self_sponsored_enable(&mut self, caller: Caller, contract_address: Address) -> Result<()> {
self.recorder().consume_sload()?;
self.recorder().consume_sstore()?;
@@ -146,7 +146,7 @@
/// Remove sponsor.
///
/// @param contractAddress Contract for which a sponsorship is being removed.
- fn remove_sponsor(&mut self, caller: caller, contract_address: address) -> Result<void> {
+ fn remove_sponsor(&mut self, caller: Caller, contract_address: Address) -> Result<()> {
self.recorder().consume_sload()?;
self.recorder().consume_sstore()?;
@@ -161,7 +161,7 @@
/// @dev Caller must be same that set via [`setSponsor`].
///
/// @param contractAddress Сontract for which need to confirm sponsorship.
- fn confirm_sponsorship(&mut self, caller: caller, contract_address: address) -> Result<void> {
+ fn confirm_sponsorship(&mut self, caller: Caller, contract_address: Address) -> Result<()> {
self.recorder().consume_sload()?;
self.recorder().consume_sstore()?;
@@ -175,7 +175,7 @@
///
/// @param contractAddress The contract for which a sponsor is requested.
/// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.
- fn sponsor(&self, contract_address: address) -> Result<Option<eth::CrossAddress>> {
+ fn sponsor(&self, contract_address: Address) -> Result<Option<eth::CrossAddress>> {
Ok(match Pallet::<T>::get_sponsor(contract_address) {
Some(ref value) => Some(eth::CrossAddress::from_sub_cross_account::<T>(value)),
None => None,
@@ -186,7 +186,7 @@
///
/// @param contractAddress The contract for which the presence of a confirmed sponsor is checked.
/// @return **true** if contract has confirmed sponsor.
- fn has_sponsor(&self, contract_address: address) -> Result<bool> {
+ fn has_sponsor(&self, contract_address: Address) -> Result<bool> {
Ok(Pallet::<T>::get_sponsor(contract_address).is_some())
}
@@ -194,23 +194,23 @@
///
/// @param contractAddress The contract for which the presence of a pending sponsor is checked.
/// @return **true** if contract has pending sponsor.
- fn has_pending_sponsor(&self, contract_address: address) -> Result<bool> {
+ fn has_pending_sponsor(&self, contract_address: Address) -> Result<bool> {
Ok(match Sponsoring::<T>::get(contract_address) {
SponsorshipState::Disabled | SponsorshipState::Confirmed(_) => false,
SponsorshipState::Unconfirmed(_) => true,
})
}
- fn sponsoring_enabled(&self, contract_address: address) -> Result<bool> {
+ fn sponsoring_enabled(&self, contract_address: Address) -> Result<bool> {
Ok(<Pallet<T>>::sponsoring_mode(contract_address) != SponsoringModeT::Disabled)
}
fn set_sponsoring_mode(
&mut self,
- caller: caller,
- contract_address: address,
+ caller: Caller,
+ contract_address: Address,
mode: SponsoringModeT,
- ) -> Result<void> {
+ ) -> Result<()> {
self.recorder().consume_sload()?;
self.recorder().consume_sstore()?;
@@ -223,7 +223,7 @@
/// Get current contract sponsoring rate limit
/// @param contractAddress Contract to get sponsoring rate limit of
/// @return uint32 Amount of blocks between two sponsored transactions
- fn sponsoring_rate_limit(&self, contract_address: address) -> Result<uint32> {
+ fn sponsoring_rate_limit(&self, contract_address: Address) -> Result<u32> {
self.recorder().consume_sload()?;
Ok(<SponsoringRateLimit<T>>::get(contract_address)
@@ -239,10 +239,10 @@
/// @dev Only contract owner can change this setting
fn set_sponsoring_rate_limit(
&mut self,
- caller: caller,
- contract_address: address,
- rate_limit: uint32,
- ) -> Result<void> {
+ caller: Caller,
+ contract_address: Address,
+ rate_limit: u32,
+ ) -> Result<()> {
self.recorder().consume_sload()?;
self.recorder().consume_sstore()?;
@@ -259,10 +259,10 @@
/// @dev Only contract owner can change this setting
fn set_sponsoring_fee_limit(
&mut self,
- caller: caller,
- contract_address: address,
- fee_limit: uint256,
- ) -> Result<void> {
+ caller: Caller,
+ contract_address: Address,
+ fee_limit: U256,
+ ) -> Result<()> {
self.recorder().consume_sload()?;
self.recorder().consume_sstore()?;
@@ -276,7 +276,7 @@
/// @param contractAddress Contract to get sponsoring fee limit of
/// @return uint256 Maximum amount of fee that could be spent by single
/// transaction
- fn sponsoring_fee_limit(&self, contract_address: address) -> Result<uint256> {
+ fn sponsoring_fee_limit(&self, contract_address: Address) -> Result<U256> {
self.recorder().consume_sload()?;
Ok(get_sponsoring_fee_limit::<T>(contract_address))
@@ -287,7 +287,7 @@
/// @param contractAddress Contract to check allowlist of
/// @param user User to check
/// @return bool Is specified users exists in contract allowlist
- fn allowed(&self, contract_address: address, user: address) -> Result<bool> {
+ fn allowed(&self, contract_address: Address, user: Address) -> Result<bool> {
self.0.consume_sload()?;
Ok(<Pallet<T>>::allowed(contract_address, user))
}
@@ -300,11 +300,11 @@
/// @dev Only contract owner can change this setting
fn toggle_allowed(
&mut self,
- caller: caller,
- contract_address: address,
- user: address,
+ caller: Caller,
+ contract_address: Address,
+ user: Address,
is_allowed: bool,
- ) -> Result<void> {
+ ) -> Result<()> {
self.recorder().consume_sload()?;
self.recorder().consume_sstore()?;
@@ -320,7 +320,7 @@
/// in case of allowlist access enabled, only users from allowlist may call this contract
/// @param contractAddress Contract to get allowlist access of
/// @return bool Is specified contract has allowlist access enabled
- fn allowlist_enabled(&self, contract_address: address) -> Result<bool> {
+ fn allowlist_enabled(&self, contract_address: Address) -> Result<bool> {
Ok(<AllowlistEnabled<T>>::get(contract_address))
}
@@ -329,10 +329,10 @@
/// @param enabled Should allowlist access to be enabled?
fn toggle_allowlist(
&mut self,
- caller: caller,
- contract_address: address,
+ caller: Caller,
+ contract_address: Address,
enabled: bool,
- ) -> Result<void> {
+ ) -> Result<()> {
self.recorder().consume_sload()?;
self.recorder().consume_sstore()?;
@@ -441,7 +441,7 @@
}
}
-fn get_sponsoring_fee_limit<T: Config>(contract_address: address) -> uint256 {
+fn get_sponsoring_fee_limit<T: Config>(contract_address: Address) -> U256 {
<SponsoringFeeLimit<T>>::get(contract_address)
.get(&0xffffffff)
.cloned()
pallets/fungible/src/erc.rsdiffbeforeafterboth--- a/pallets/fungible/src/erc.rs
+++ b/pallets/fungible/src/erc.rs
@@ -32,7 +32,7 @@
use pallet_evm::{account::CrossAccountId, PrecompileHandle};
use pallet_evm_coder_substrate::{call, dispatch_to_evm};
use pallet_structure::{SelfWeightOf as StructureWeight, weights::WeightInfo as _};
-use sp_core::Get;
+use sp_core::{U256, Get};
use crate::{
Allowance, Balance, Config, FungibleHandle, Pallet, SelfWeightOf, TotalSupply,
@@ -43,50 +43,50 @@
pub enum ERC20Events {
Transfer {
#[indexed]
- from: address,
+ from: Address,
#[indexed]
- to: address,
- value: uint256,
+ to: Address,
+ value: U256,
},
Approval {
#[indexed]
- owner: address,
+ owner: Address,
#[indexed]
- spender: address,
- value: uint256,
+ spender: Address,
+ value: U256,
},
}
#[solidity_interface(name = ERC20, events(ERC20Events))]
impl<T: Config> FungibleHandle<T> {
- fn name(&self) -> Result<string> {
+ fn name(&self) -> Result<String> {
Ok(decode_utf16(self.name.iter().copied())
.map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))
- .collect::<string>())
+ .collect::<String>())
}
- fn symbol(&self) -> Result<string> {
- Ok(string::from_utf8_lossy(&self.token_prefix).into())
+ fn symbol(&self) -> Result<String> {
+ Ok(String::from_utf8_lossy(&self.token_prefix).into())
}
- fn total_supply(&self) -> Result<uint256> {
+ fn total_supply(&self) -> Result<U256> {
self.consume_store_reads(1)?;
Ok(<TotalSupply<T>>::get(self.id).into())
}
- fn decimals(&self) -> Result<uint8> {
+ fn decimals(&self) -> Result<u8> {
Ok(if let CollectionMode::Fungible(decimals) = &self.mode {
*decimals
} else {
unreachable!()
})
}
- fn balance_of(&self, owner: address) -> Result<uint256> {
+ fn balance_of(&self, owner: Address) -> Result<U256> {
self.consume_store_reads(1)?;
let owner = T::CrossAccountId::from_eth(owner);
let balance = <Balance<T>>::get((self.id, owner));
Ok(balance.into())
}
#[weight(<SelfWeightOf<T>>::transfer())]
- fn transfer(&mut self, caller: caller, to: address, amount: uint256) -> Result<bool> {
+ fn transfer(&mut self, caller: Caller, to: Address, amount: U256) -> Result<bool> {
let caller = T::CrossAccountId::from_eth(caller);
let to = T::CrossAccountId::from_eth(to);
let amount = amount.try_into().map_err(|_| "amount overflow")?;
@@ -101,10 +101,10 @@
#[weight(<SelfWeightOf<T>>::transfer_from())]
fn transfer_from(
&mut self,
- caller: caller,
- from: address,
- to: address,
- amount: uint256,
+ caller: Caller,
+ from: Address,
+ to: Address,
+ amount: U256,
) -> Result<bool> {
let caller = T::CrossAccountId::from_eth(caller);
let from = T::CrossAccountId::from_eth(from);
@@ -119,7 +119,7 @@
Ok(true)
}
#[weight(<SelfWeightOf<T>>::approve())]
- fn approve(&mut self, caller: caller, spender: address, amount: uint256) -> Result<bool> {
+ fn approve(&mut self, caller: Caller, spender: Address, amount: U256) -> Result<bool> {
let caller = T::CrossAccountId::from_eth(caller);
let spender = T::CrossAccountId::from_eth(spender);
let amount = amount.try_into().map_err(|_| "amount overflow")?;
@@ -128,7 +128,7 @@
.map_err(dispatch_to_evm::<T>)?;
Ok(true)
}
- fn allowance(&self, owner: address, spender: address) -> Result<uint256> {
+ fn allowance(&self, owner: Address, spender: Address) -> Result<U256> {
self.consume_store_reads(1)?;
let owner = T::CrossAccountId::from_eth(owner);
let spender = T::CrossAccountId::from_eth(spender);
@@ -137,7 +137,7 @@
}
/// @notice Returns collection helper contract address
- fn collection_helper_address(&self) -> Result<address> {
+ fn collection_helper_address(&self) -> Result<Address> {
Ok(T::ContractAddress::get())
}
}
@@ -148,7 +148,7 @@
/// @param to account that will receive minted tokens
/// @param amount amount of tokens to mint
#[weight(<SelfWeightOf<T>>::create_item())]
- fn mint(&mut self, caller: caller, to: address, amount: uint256) -> Result<bool> {
+ fn mint(&mut self, caller: Caller, to: Address, amount: U256) -> Result<bool> {
let caller = T::CrossAccountId::from_eth(caller);
let to = T::CrossAccountId::from_eth(to);
let amount = amount.try_into().map_err(|_| "amount overflow")?;
@@ -167,18 +167,18 @@
T::AccountId: From<[u8; 32]>,
{
/// @notice A description for the collection.
- fn description(&self) -> Result<string> {
+ fn description(&self) -> Result<String> {
Ok(decode_utf16(self.description.iter().copied())
.map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))
- .collect::<string>())
+ .collect::<String>())
}
#[weight(<SelfWeightOf<T>>::create_item())]
fn mint_cross(
&mut self,
- caller: caller,
+ caller: Caller,
to: pallet_common::eth::CrossAddress,
- amount: uint256,
+ amount: U256,
) -> Result<bool> {
let caller = T::CrossAccountId::from_eth(caller);
let to = to.into_sub_cross_account::<T>()?;
@@ -194,9 +194,9 @@
#[weight(<SelfWeightOf<T>>::approve())]
fn approve_cross(
&mut self,
- caller: caller,
+ caller: Caller,
spender: pallet_common::eth::CrossAddress,
- amount: uint256,
+ amount: U256,
) -> Result<bool> {
let caller = T::CrossAccountId::from_eth(caller);
let spender = spender.into_sub_cross_account::<T>()?;
@@ -214,7 +214,7 @@
/// @param amount The amount that will be burnt.
#[solidity(hide)]
#[weight(<SelfWeightOf<T>>::burn_from())]
- fn burn_from(&mut self, caller: caller, from: address, amount: uint256) -> Result<bool> {
+ fn burn_from(&mut self, caller: Caller, from: Address, amount: U256) -> Result<bool> {
let caller = T::CrossAccountId::from_eth(caller);
let from = T::CrossAccountId::from_eth(from);
let amount = amount.try_into().map_err(|_| "amount overflow")?;
@@ -235,9 +235,9 @@
#[weight(<SelfWeightOf<T>>::burn_from())]
fn burn_from_cross(
&mut self,
- caller: caller,
+ caller: Caller,
from: pallet_common::eth::CrossAddress,
- amount: uint256,
+ amount: U256,
) -> Result<bool> {
let caller = T::CrossAccountId::from_eth(caller);
let from = from.into_sub_cross_account::<T>()?;
@@ -254,7 +254,7 @@
/// Mint tokens for multiple accounts.
/// @param amounts array of pairs of account address and amount
#[weight(<SelfWeightOf<T>>::create_multiple_items_ex(amounts.len() as u32))]
- fn mint_bulk(&mut self, caller: caller, amounts: Vec<(address, uint256)>) -> Result<bool> {
+ fn mint_bulk(&mut self, caller: Caller, amounts: Vec<(Address, U256)>) -> Result<bool> {
let caller = T::CrossAccountId::from_eth(caller);
let budget = self
.recorder
@@ -277,9 +277,9 @@
#[weight(<SelfWeightOf<T>>::transfer())]
fn transfer_cross(
&mut self,
- caller: caller,
+ caller: Caller,
to: pallet_common::eth::CrossAddress,
- amount: uint256,
+ amount: U256,
) -> Result<bool> {
let caller = T::CrossAccountId::from_eth(caller);
let to = to.into_sub_cross_account::<T>()?;
@@ -295,10 +295,10 @@
#[weight(<SelfWeightOf<T>>::transfer_from())]
fn transfer_from_cross(
&mut self,
- caller: caller,
+ caller: Caller,
from: pallet_common::eth::CrossAddress,
to: pallet_common::eth::CrossAddress,
- amount: uint256,
+ amount: U256,
) -> Result<bool> {
let caller = T::CrossAccountId::from_eth(caller);
let from = from.into_sub_cross_account::<T>()?;
pallets/fungible/src/stubs/UniqueFungible.rawdiffbeforeafterbothbinary blob — no preview
pallets/fungible/src/stubs/UniqueFungible.soldiffbeforeafterboth--- a/pallets/fungible/src/stubs/UniqueFungible.sol
+++ b/pallets/fungible/src/stubs/UniqueFungible.sol
@@ -274,11 +274,9 @@
/// Set the collection access method.
/// @param mode Access mode
- /// 0 for Normal
- /// 1 for AllowList
/// @dev EVM selector for this function is: 0x41835d4c,
/// or in textual repr: setCollectionAccess(uint8)
- function setCollectionAccess(uint8 mode) public {
+ function setCollectionAccess(AccessMode mode) public {
require(false, stub_error);
mode;
dummy = 0;
@@ -443,6 +441,14 @@
uint256 sub;
}
+/// Ethereum representation of `AccessMode` (see [`up_data_structs::AccessMode`]).
+enum AccessMode {
+ /// Access grant for owner and admins. Used as default.
+ Normal,
+ /// Like a [`Normal`](AccessMode::Normal) but also users in allow list.
+ AllowList
+}
+
/// Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) field.
struct CollectionNestingPermission {
CollectionPermissionField field;
pallets/nonfungible/src/erc.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/erc.rs
+++ b/pallets/nonfungible/src/erc.rs
@@ -43,7 +43,7 @@
use pallet_evm::{account::CrossAccountId, PrecompileHandle};
use pallet_evm_coder_substrate::call;
use pallet_structure::{SelfWeightOf as StructureWeight, weights::WeightInfo as _};
-use sp_core::Get;
+use sp_core::{U256, Get};
use crate::{
AccountBalance, Config, CreateItemData, NonfungibleHandle, Pallet, TokenData, TokensMinted,
@@ -63,8 +63,8 @@
#[solidity(hide)]
fn set_token_property_permission(
&mut self,
- caller: caller,
- key: string,
+ caller: Caller,
+ key: String,
is_mutable: bool,
collection_admin: bool,
token_owner: bool,
@@ -93,7 +93,7 @@
#[weight(<SelfWeightOf<T>>::set_token_property_permissions(permissions.len() as u32))]
fn set_token_property_permissions(
&mut self,
- caller: caller,
+ caller: Caller,
permissions: Vec<eth::TokenPropertyPermission>,
) -> Result<()> {
let caller = T::CrossAccountId::from_eth(caller);
@@ -121,10 +121,10 @@
#[weight(<SelfWeightOf<T>>::set_token_properties(1))]
fn set_property(
&mut self,
- caller: caller,
- token_id: uint256,
- key: string,
- value: bytes,
+ caller: Caller,
+ token_id: U256,
+ key: String,
+ value: Bytes,
) -> Result<()> {
let caller = T::CrossAccountId::from_eth(caller);
let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;
@@ -154,8 +154,8 @@
#[weight(<SelfWeightOf<T>>::set_token_properties(properties.len() as u32))]
fn set_properties(
&mut self,
- caller: caller,
- token_id: uint256,
+ caller: Caller,
+ token_id: U256,
properties: Vec<eth::Property>,
) -> Result<()> {
let caller = T::CrossAccountId::from_eth(caller);
@@ -187,7 +187,7 @@
/// @param key Property key.
#[solidity(hide)]
#[weight(<SelfWeightOf<T>>::delete_token_properties(1))]
- fn delete_property(&mut self, token_id: uint256, caller: caller, key: string) -> Result<()> {
+ fn delete_property(&mut self, token_id: U256, caller: Caller, key: String) -> Result<()> {
let caller = T::CrossAccountId::from_eth(caller);
let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;
let key = <Vec<u8>>::from(key)
@@ -209,9 +209,9 @@
#[weight(<SelfWeightOf<T>>::delete_token_properties(keys.len() as u32))]
fn delete_properties(
&mut self,
- token_id: uint256,
- caller: caller,
- keys: Vec<string>,
+ token_id: U256,
+ caller: Caller,
+ keys: Vec<String>,
) -> Result<()> {
let caller = T::CrossAccountId::from_eth(caller);
let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;
@@ -239,7 +239,7 @@
/// @param tokenId ID of the token.
/// @param key Property key.
/// @return Property value bytes
- fn property(&self, token_id: uint256, key: string) -> Result<bytes> {
+ fn property(&self, token_id: U256, key: String) -> Result<Bytes> {
let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;
let key = <Vec<u8>>::from(key)
.try_into()
@@ -261,11 +261,11 @@
/// any transfer, the approved address for that NFT (if any) is reset to none.
Transfer {
#[indexed]
- from: address,
+ from: Address,
#[indexed]
- to: address,
+ to: Address,
#[indexed]
- token_id: uint256,
+ token_id: U256,
},
/// @dev This emits when the approved address for an NFT is changed or
/// reaffirmed. The zero address indicates there is no approved address.
@@ -273,20 +273,20 @@
/// address for that NFT (if any) is reset to none.
Approval {
#[indexed]
- owner: address,
+ owner: Address,
#[indexed]
- approved: address,
+ approved: Address,
#[indexed]
- token_id: uint256,
+ token_id: U256,
},
/// @dev This emits when an operator is enabled or disabled for an owner.
/// The operator can manage all NFTs of the owner.
#[allow(dead_code)]
ApprovalForAll {
#[indexed]
- owner: address,
+ owner: Address,
#[indexed]
- operator: address,
+ operator: Address,
approved: bool,
},
}
@@ -301,14 +301,14 @@
/// @notice A descriptive name for a collection of NFTs in this contract
/// @dev real implementation of this function lies in `ERC721UniqueExtensions`
#[solidity(hide, rename_selector = "name")]
- fn name_proxy(&self) -> Result<string> {
+ fn name_proxy(&self) -> Result<String> {
self.name()
}
/// @notice An abbreviated name for NFTs in this contract
/// @dev real implementation of this function lies in `ERC721UniqueExtensions`
#[solidity(hide, rename_selector = "symbol")]
- fn symbol_proxy(&self) -> Result<string> {
+ fn symbol_proxy(&self) -> Result<String> {
self.symbol()
}
@@ -322,7 +322,7 @@
///
/// @return token's const_metadata
#[solidity(rename_selector = "tokenURI")]
- fn token_uri(&self, token_id: uint256) -> Result<string> {
+ fn token_uri(&self, token_id: U256) -> Result<String> {
let token_id_u32: u32 = token_id.try_into().map_err(|_| "token id overflow")?;
match get_token_property(self, token_id_u32, &key::url()).as_deref() {
@@ -335,7 +335,7 @@
let base_uri =
pallet_common::Pallet::<T>::get_collection_property(self.id, &key::base_uri())
.map(BoundedVec::into_inner)
- .map(string::from_utf8)
+ .map(String::from_utf8)
.transpose()
.map_err(|e| {
Error::Revert(alloc::format!(
@@ -368,12 +368,12 @@
/// @param index A counter less than `totalSupply()`
/// @return The token identifier for the `index`th NFT,
/// (sort order not specified)
- fn token_by_index(&self, index: uint256) -> Result<uint256> {
+ fn token_by_index(&self, index: U256) -> Result<U256> {
Ok(index)
}
/// @dev Not implemented
- fn token_of_owner_by_index(&self, _owner: address, _index: uint256) -> Result<uint256> {
+ fn token_of_owner_by_index(&self, _owner: Address, _index: U256) -> Result<U256> {
// TODO: Not implemetable
Err("not implemented".into())
}
@@ -381,7 +381,7 @@
/// @notice Count NFTs tracked by this contract
/// @return A count of valid NFTs tracked by this contract, where each one of
/// them has an assigned and queryable owner not equal to the zero address
- fn total_supply(&self) -> Result<uint256> {
+ fn total_supply(&self) -> Result<U256> {
self.consume_store_reads(1)?;
Ok(<Pallet<T>>::total_supply(self).into())
}
@@ -396,7 +396,7 @@
/// function throws for queries about the zero address.
/// @param owner An address for whom to query the balance
/// @return The number of NFTs owned by `owner`, possibly zero
- fn balance_of(&self, owner: address) -> Result<uint256> {
+ fn balance_of(&self, owner: Address) -> Result<U256> {
self.consume_store_reads(1)?;
let owner = T::CrossAccountId::from_eth(owner);
let balance = <AccountBalance<T>>::get((self.id, owner));
@@ -407,7 +407,7 @@
/// about them do throw.
/// @param tokenId The identifier for an NFT
/// @return The address of the owner of the NFT
- fn owner_of(&self, token_id: uint256) -> Result<address> {
+ fn owner_of(&self, token_id: U256) -> Result<Address> {
self.consume_store_reads(1)?;
let token: TokenId = token_id.try_into()?;
Ok(*<TokenData<T>>::get((self.id, token))
@@ -419,21 +419,16 @@
#[solidity(rename_selector = "safeTransferFrom")]
fn safe_transfer_from_with_data(
&mut self,
- _from: address,
- _to: address,
- _token_id: uint256,
- _data: bytes,
- ) -> Result<void> {
+ _from: Address,
+ _to: Address,
+ _token_id: U256,
+ _data: Bytes,
+ ) -> Result<()> {
// TODO: Not implemetable
Err("not implemented".into())
}
/// @dev Not implemented
- fn safe_transfer_from(
- &mut self,
- _from: address,
- _to: address,
- _token_id: uint256,
- ) -> Result<void> {
+ fn safe_transfer_from(&mut self, _from: Address, _to: Address, _token_id: U256) -> Result<()> {
// TODO: Not implemetable
Err("not implemented".into())
}
@@ -450,11 +445,11 @@
#[weight(<SelfWeightOf<T>>::transfer_from())]
fn transfer_from(
&mut self,
- caller: caller,
- from: address,
- to: address,
- token_id: uint256,
- ) -> Result<void> {
+ caller: Caller,
+ from: Address,
+ to: Address,
+ token_id: U256,
+ ) -> Result<()> {
let caller = T::CrossAccountId::from_eth(caller);
let from = T::CrossAccountId::from_eth(from);
let to = T::CrossAccountId::from_eth(to);
@@ -475,7 +470,7 @@
/// @param approved The new approved NFT controller
/// @param tokenId The NFT to approve
#[weight(<SelfWeightOf<T>>::approve())]
- fn approve(&mut self, caller: caller, approved: address, token_id: uint256) -> Result<void> {
+ fn approve(&mut self, caller: Caller, approved: Address, token_id: U256) -> Result<()> {
let caller = T::CrossAccountId::from_eth(caller);
let approved = T::CrossAccountId::from_eth(approved);
let token = token_id.try_into()?;
@@ -492,10 +487,10 @@
#[weight(<SelfWeightOf<T>>::set_allowance_for_all())]
fn set_approval_for_all(
&mut self,
- caller: caller,
- operator: address,
+ caller: Caller,
+ operator: Address,
approved: bool,
- ) -> Result<void> {
+ ) -> Result<()> {
let caller = T::CrossAccountId::from_eth(caller);
let operator = T::CrossAccountId::from_eth(operator);
@@ -505,14 +500,14 @@
}
/// @dev Not implemented
- fn get_approved(&self, _token_id: uint256) -> Result<address> {
+ fn get_approved(&self, _token_id: U256) -> Result<Address> {
// TODO: Not implemetable
Err("not implemented".into())
}
/// @notice Tells whether the given `owner` approves the `operator`.
#[weight(<SelfWeightOf<T>>::allowance_for_all())]
- fn is_approved_for_all(&self, owner: address, operator: address) -> Result<bool> {
+ fn is_approved_for_all(&self, owner: Address, operator: Address) -> Result<bool> {
let owner = T::CrossAccountId::from_eth(owner);
let operator = T::CrossAccountId::from_eth(operator);
@@ -528,7 +523,7 @@
/// operator of the current owner.
/// @param tokenId The NFT to approve
#[weight(<SelfWeightOf<T>>::burn_item())]
- fn burn(&mut self, caller: caller, token_id: uint256) -> Result<void> {
+ fn burn(&mut self, caller: Caller, token_id: U256) -> Result<()> {
let caller = T::CrossAccountId::from_eth(caller);
let token = token_id.try_into()?;
@@ -544,8 +539,8 @@
/// @param to The new owner
/// @return uint256 The id of the newly minted token
#[weight(<SelfWeightOf<T>>::create_item())]
- fn mint(&mut self, caller: caller, to: address) -> Result<uint256> {
- let token_id: uint256 = <TokensMinted<T>>::get(self.id)
+ fn mint(&mut self, caller: Caller, to: Address) -> Result<U256> {
+ let token_id: U256 = <TokensMinted<T>>::get(self.id)
.checked_add(1)
.ok_or("item id overflow")?
.into();
@@ -560,7 +555,7 @@
/// @param tokenId ID of the minted NFT
#[solidity(hide, rename_selector = "mint")]
#[weight(<SelfWeightOf<T>>::create_item())]
- fn mint_check_id(&mut self, caller: caller, to: address, token_id: uint256) -> Result<bool> {
+ fn mint_check_id(&mut self, caller: Caller, to: Address, token_id: U256) -> Result<bool> {
let caller = T::CrossAccountId::from_eth(caller);
let to = T::CrossAccountId::from_eth(to);
let token_id: u32 = token_id.try_into()?;
@@ -598,11 +593,11 @@
#[weight(<SelfWeightOf<T>>::create_item())]
fn mint_with_token_uri(
&mut self,
- caller: caller,
- to: address,
- token_uri: string,
- ) -> Result<uint256> {
- let token_id: uint256 = <TokensMinted<T>>::get(self.id)
+ caller: Caller,
+ to: Address,
+ token_uri: String,
+ ) -> Result<U256> {
+ let token_id: U256 = <TokensMinted<T>>::get(self.id)
.checked_add(1)
.ok_or("item id overflow")?
.into();
@@ -620,10 +615,10 @@
#[weight(<SelfWeightOf<T>>::create_item())]
fn mint_with_token_uri_check_id(
&mut self,
- caller: caller,
- to: address,
- token_id: uint256,
- token_uri: string,
+ caller: Caller,
+ to: Address,
+ token_id: U256,
+ token_uri: String,
) -> Result<bool> {
let key = key::url();
let permission = get_token_permission::<T>(self.id, &key)?;
@@ -675,12 +670,12 @@
collection: &CollectionHandle<T>,
token_id: u32,
key: &up_data_structs::PropertyKey,
-) -> Result<string> {
+) -> Result<String> {
collection.consume_store_reads(1)?;
let properties = <TokenProperties<T>>::try_get((collection.id, token_id))
.map_err(|_| Error::Revert("Token properties not found".into()))?;
if let Some(property) = properties.get(key) {
- return Ok(string::from_utf8_lossy(property).into());
+ return Ok(String::from_utf8_lossy(property).into());
}
Err("Property tokenURI not found".into())
@@ -696,7 +691,7 @@
.get(key)
.map(Clone::clone)
.ok_or_else(|| {
- let key = string::from_utf8(key.clone().into_inner()).unwrap_or_default();
+ let key = String::from_utf8(key.clone().into_inner()).unwrap_or_default();
Error::Revert(alloc::format!("No permission for key {}", key))
})?;
Ok(a)
@@ -709,28 +704,28 @@
T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]>,
{
/// @notice A descriptive name for a collection of NFTs in this contract
- fn name(&self) -> Result<string> {
+ fn name(&self) -> Result<String> {
Ok(decode_utf16(self.name.iter().copied())
.map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))
- .collect::<string>())
+ .collect::<String>())
}
/// @notice An abbreviated name for NFTs in this contract
- fn symbol(&self) -> Result<string> {
- Ok(string::from_utf8_lossy(&self.token_prefix).into())
+ fn symbol(&self) -> Result<String> {
+ Ok(String::from_utf8_lossy(&self.token_prefix).into())
}
/// @notice A description for the collection.
- fn description(&self) -> Result<string> {
+ fn description(&self) -> Result<String> {
Ok(decode_utf16(self.description.iter().copied())
.map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))
- .collect::<string>())
+ .collect::<String>())
}
/// Returns the owner (in cross format) of the token.
///
/// @param tokenId Id for the token.
- fn cross_owner_of(&self, token_id: uint256) -> Result<eth::CrossAddress> {
+ fn cross_owner_of(&self, token_id: U256) -> Result<eth::CrossAddress> {
Self::token_owner(&self, token_id.try_into()?)
.map(|o| eth::CrossAddress::from_sub_cross_account::<T>(&o))
.ok_or(Error::Revert("key too large".into()))
@@ -741,7 +736,7 @@
/// @param tokenId Id for the token.
/// @param keys Properties keys. Empty keys for all propertyes.
/// @return Vector of properties key/value pairs.
- fn properties(&self, token_id: uint256, keys: Vec<string>) -> Result<Vec<eth::Property>> {
+ fn properties(&self, token_id: U256, keys: Vec<String>) -> Result<Vec<eth::Property>> {
let keys = keys
.into_iter()
.map(|key| {
@@ -770,10 +765,10 @@
#[weight(<SelfWeightOf<T>>::approve())]
fn approve_cross(
&mut self,
- caller: caller,
+ caller: Caller,
approved: eth::CrossAddress,
- token_id: uint256,
- ) -> Result<void> {
+ token_id: U256,
+ ) -> Result<()> {
let caller = T::CrossAccountId::from_eth(caller);
let approved = approved.into_sub_cross_account::<T>()?;
let token = token_id.try_into()?;
@@ -789,7 +784,7 @@
/// @param to The new owner
/// @param tokenId The NFT to transfer
#[weight(<SelfWeightOf<T>>::transfer())]
- fn transfer(&mut self, caller: caller, to: address, token_id: uint256) -> Result<void> {
+ fn transfer(&mut self, caller: Caller, to: Address, token_id: U256) -> Result<()> {
let caller = T::CrossAccountId::from_eth(caller);
let to = T::CrossAccountId::from_eth(to);
let token = token_id.try_into()?;
@@ -809,10 +804,10 @@
#[weight(<SelfWeightOf<T>>::transfer())]
fn transfer_cross(
&mut self,
- caller: caller,
+ caller: Caller,
to: eth::CrossAddress,
- token_id: uint256,
- ) -> Result<void> {
+ token_id: U256,
+ ) -> Result<()> {
let caller = T::CrossAccountId::from_eth(caller);
let to = to.into_sub_cross_account::<T>()?;
let token = token_id.try_into()?;
@@ -833,11 +828,11 @@
#[weight(<SelfWeightOf<T>>::transfer())]
fn transfer_from_cross(
&mut self,
- caller: caller,
+ caller: Caller,
from: eth::CrossAddress,
to: eth::CrossAddress,
- token_id: uint256,
- ) -> Result<void> {
+ token_id: U256,
+ ) -> Result<()> {
let caller = T::CrossAccountId::from_eth(caller);
let from = from.into_sub_cross_account::<T>()?;
let to = to.into_sub_cross_account::<T>()?;
@@ -858,7 +853,7 @@
/// @param tokenId The NFT to transfer
#[solidity(hide)]
#[weight(<SelfWeightOf<T>>::burn_from())]
- fn burn_from(&mut self, caller: caller, from: address, token_id: uint256) -> Result<void> {
+ fn burn_from(&mut self, caller: Caller, from: Address, token_id: U256) -> Result<()> {
let caller = T::CrossAccountId::from_eth(caller);
let from = T::CrossAccountId::from_eth(from);
let token = token_id.try_into()?;
@@ -880,10 +875,10 @@
#[weight(<SelfWeightOf<T>>::burn_from())]
fn burn_from_cross(
&mut self,
- caller: caller,
+ caller: Caller,
from: eth::CrossAddress,
- token_id: uint256,
- ) -> Result<void> {
+ token_id: U256,
+ ) -> Result<()> {
let caller = T::CrossAccountId::from_eth(caller);
let from = from.into_sub_cross_account::<T>()?;
let token = token_id.try_into()?;
@@ -897,7 +892,7 @@
}
/// @notice Returns next free NFT ID.
- fn next_token_id(&self) -> Result<uint256> {
+ fn next_token_id(&self) -> Result<U256> {
self.consume_store_reads(1)?;
Ok(<TokensMinted<T>>::get(self.id)
.checked_add(1)
@@ -912,7 +907,7 @@
/// @param tokenIds IDs of the minted NFTs
#[solidity(hide)]
#[weight(<SelfWeightOf<T>>::create_multiple_items(token_ids.len() as u32))]
- fn mint_bulk(&mut self, caller: caller, to: address, token_ids: Vec<uint256>) -> Result<bool> {
+ fn mint_bulk(&mut self, caller: Caller, to: Address, token_ids: Vec<U256>) -> Result<bool> {
let caller = T::CrossAccountId::from_eth(caller);
let to = T::CrossAccountId::from_eth(to);
let mut expected_index = <TokensMinted<T>>::get(self.id)
@@ -951,9 +946,9 @@
#[weight(<SelfWeightOf<T>>::create_multiple_items(tokens.len() as u32))]
fn mint_bulk_with_token_uri(
&mut self,
- caller: caller,
- to: address,
- tokens: Vec<(uint256, string)>,
+ caller: Caller,
+ to: Address,
+ tokens: Vec<(U256, String)>,
) -> Result<bool> {
let key = key::url();
let caller = T::CrossAccountId::from_eth(caller);
@@ -1002,10 +997,10 @@
#[weight(<SelfWeightOf<T>>::create_item())]
fn mint_cross(
&mut self,
- caller: caller,
+ caller: Caller,
to: eth::CrossAddress,
properties: Vec<eth::Property>,
- ) -> Result<uint256> {
+ ) -> Result<U256> {
let token_id = <TokensMinted<T>>::get(self.id)
.checked_add(1)
.ok_or("item id overflow")?;
@@ -1040,7 +1035,7 @@
}
/// @notice Returns collection helper contract address
- fn collection_helper_address(&self) -> Result<address> {
+ fn collection_helper_address(&self) -> Result<Address> {
Ok(T::ContractAddress::get())
}
}
pallets/nonfungible/src/stubs/UniqueNFT.rawdiffbeforeafterbothbinary blob — no preview
pallets/nonfungible/src/stubs/UniqueNFT.soldiffbeforeafterboth--- a/pallets/nonfungible/src/stubs/UniqueNFT.sol
+++ b/pallets/nonfungible/src/stubs/UniqueNFT.sol
@@ -416,11 +416,9 @@
/// Set the collection access method.
/// @param mode Access mode
- /// 0 for Normal
- /// 1 for AllowList
/// @dev EVM selector for this function is: 0x41835d4c,
/// or in textual repr: setCollectionAccess(uint8)
- function setCollectionAccess(uint8 mode) public {
+ function setCollectionAccess(AccessMode mode) public {
require(false, stub_error);
mode;
dummy = 0;
@@ -585,6 +583,14 @@
uint256 sub;
}
+/// Ethereum representation of `AccessMode` (see [`up_data_structs::AccessMode`]).
+enum AccessMode {
+ /// Access grant for owner and admins. Used as default.
+ Normal,
+ /// Like a [`Normal`](AccessMode::Normal) but also users in allow list.
+ AllowList
+}
+
/// Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) field.
struct CollectionNestingPermission {
CollectionPermissionField field;
pallets/refungible/src/erc.rsdiffbeforeafterboth--- a/pallets/refungible/src/erc.rs
+++ b/pallets/refungible/src/erc.rs
@@ -39,7 +39,7 @@
use pallet_evm::{account::CrossAccountId, PrecompileHandle};
use pallet_evm_coder_substrate::{call, dispatch_to_evm};
use pallet_structure::{SelfWeightOf as StructureWeight, weights::WeightInfo as _};
-use sp_core::{H160, Get};
+use sp_core::{H160, U256, Get};
use sp_std::{collections::btree_map::BTreeMap, vec::Vec, vec};
use up_data_structs::{
CollectionId, CollectionPropertiesVec, mapping::TokenAddressMapping, Property, PropertyKey,
@@ -66,8 +66,8 @@
#[solidity(hide)]
fn set_token_property_permission(
&mut self,
- caller: caller,
- key: string,
+ caller: Caller,
+ key: String,
is_mutable: bool,
collection_admin: bool,
token_owner: bool,
@@ -96,7 +96,7 @@
#[weight(<SelfWeightOf<T>>::set_token_property_permissions(permissions.len() as u32))]
fn set_token_property_permissions(
&mut self,
- caller: caller,
+ caller: Caller,
permissions: Vec<eth::TokenPropertyPermission>,
) -> Result<()> {
let caller = T::CrossAccountId::from_eth(caller);
@@ -124,10 +124,10 @@
#[weight(<SelfWeightOf<T>>::set_token_properties(1))]
fn set_property(
&mut self,
- caller: caller,
- token_id: uint256,
- key: string,
- value: bytes,
+ caller: Caller,
+ token_id: U256,
+ key: String,
+ value: Bytes,
) -> Result<()> {
let caller = T::CrossAccountId::from_eth(caller);
let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;
@@ -157,8 +157,8 @@
#[weight(<SelfWeightOf<T>>::set_token_properties(properties.len() as u32))]
fn set_properties(
&mut self,
- caller: caller,
- token_id: uint256,
+ caller: Caller,
+ token_id: U256,
properties: Vec<eth::Property>,
) -> Result<()> {
let caller = T::CrossAccountId::from_eth(caller);
@@ -190,7 +190,7 @@
/// @param key Property key.
#[solidity(hide)]
#[weight(<SelfWeightOf<T>>::delete_token_properties(1))]
- fn delete_property(&mut self, token_id: uint256, caller: caller, key: string) -> Result<()> {
+ fn delete_property(&mut self, token_id: U256, caller: Caller, key: String) -> Result<()> {
let caller = T::CrossAccountId::from_eth(caller);
let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;
let key = <Vec<u8>>::from(key)
@@ -212,9 +212,9 @@
#[weight(<SelfWeightOf<T>>::delete_token_properties(keys.len() as u32))]
fn delete_properties(
&mut self,
- token_id: uint256,
- caller: caller,
- keys: Vec<string>,
+ token_id: U256,
+ caller: Caller,
+ keys: Vec<String>,
) -> Result<()> {
let caller = T::CrossAccountId::from_eth(caller);
let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;
@@ -242,7 +242,7 @@
/// @param tokenId ID of the token.
/// @param key Property key.
/// @return Property value bytes
- fn property(&self, token_id: uint256, key: string) -> Result<bytes> {
+ fn property(&self, token_id: U256, key: String) -> Result<Bytes> {
let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;
let key = <Vec<u8>>::from(key)
.try_into()
@@ -262,28 +262,28 @@
/// may be created and assigned without emitting Transfer.
Transfer {
#[indexed]
- from: address,
+ from: Address,
#[indexed]
- to: address,
+ to: Address,
#[indexed]
- token_id: uint256,
+ token_id: U256,
},
/// @dev Not supported
Approval {
#[indexed]
- owner: address,
+ owner: Address,
#[indexed]
- approved: address,
+ approved: Address,
#[indexed]
- token_id: uint256,
+ token_id: U256,
},
/// @dev Not supported
#[allow(dead_code)]
ApprovalForAll {
#[indexed]
- owner: address,
+ owner: Address,
#[indexed]
- operator: address,
+ operator: Address,
approved: bool,
},
}
@@ -298,14 +298,14 @@
/// @notice A descriptive name for a collection of NFTs in this contract
/// @dev real implementation of this function lies in `ERC721UniqueExtensions`
#[solidity(hide, rename_selector = "name")]
- fn name_proxy(&self) -> Result<string> {
+ fn name_proxy(&self) -> Result<String> {
self.name()
}
/// @notice An abbreviated name for NFTs in this contract
/// @dev real implementation of this function lies in `ERC721UniqueExtensions`
#[solidity(hide, rename_selector = "symbol")]
- fn symbol_proxy(&self) -> Result<string> {
+ fn symbol_proxy(&self) -> Result<String> {
self.symbol()
}
@@ -319,7 +319,7 @@
///
/// @return token's const_metadata
#[solidity(rename_selector = "tokenURI")]
- fn token_uri(&self, token_id: uint256) -> Result<string> {
+ fn token_uri(&self, token_id: U256) -> Result<String> {
let token_id_u32: u32 = token_id.try_into().map_err(|_| "token id overflow")?;
match get_token_property(self, token_id_u32, &key::url()).as_deref() {
@@ -332,7 +332,7 @@
let base_uri =
pallet_common::Pallet::<T>::get_collection_property(self.id, &key::base_uri())
.map(BoundedVec::into_inner)
- .map(string::from_utf8)
+ .map(String::from_utf8)
.transpose()
.map_err(|e| {
Error::Revert(alloc::format!(
@@ -365,12 +365,12 @@
/// @param index A counter less than `totalSupply()`
/// @return The token identifier for the `index`th NFT,
/// (sort order not specified)
- fn token_by_index(&self, index: uint256) -> Result<uint256> {
+ fn token_by_index(&self, index: U256) -> Result<U256> {
Ok(index)
}
/// Not implemented
- fn token_of_owner_by_index(&self, _owner: address, _index: uint256) -> Result<uint256> {
+ fn token_of_owner_by_index(&self, _owner: Address, _index: U256) -> Result<U256> {
// TODO: Not implemetable
Err("not implemented".into())
}
@@ -378,7 +378,7 @@
/// @notice Count RFTs tracked by this contract
/// @return A count of valid RFTs tracked by this contract, where each one of
/// them has an assigned and queryable owner not equal to the zero address
- fn total_supply(&self) -> Result<uint256> {
+ fn total_supply(&self) -> Result<U256> {
self.consume_store_reads(1)?;
Ok(<Pallet<T>>::total_supply(self).into())
}
@@ -393,7 +393,7 @@
/// function throws for queries about the zero address.
/// @param owner An address for whom to query the balance
/// @return The number of RFTs owned by `owner`, possibly zero
- fn balance_of(&self, owner: address) -> Result<uint256> {
+ fn balance_of(&self, owner: Address) -> Result<U256> {
self.consume_store_reads(1)?;
let owner = T::CrossAccountId::from_eth(owner);
let balance = <AccountBalance<T>>::get((self.id, owner));
@@ -407,7 +407,7 @@
/// the tokens that are partially owned.
/// @param tokenId The identifier for an RFT
/// @return The address of the owner of the RFT
- fn owner_of(&self, token_id: uint256) -> Result<address> {
+ fn owner_of(&self, token_id: U256) -> Result<Address> {
self.consume_store_reads(2)?;
let token = token_id.try_into()?;
let owner = <Pallet<T>>::token_owner(self.id, token);
@@ -420,23 +420,18 @@
#[solidity(rename_selector = "safeTransferFrom")]
fn safe_transfer_from_with_data(
&mut self,
- _from: address,
- _to: address,
- _token_id: uint256,
- _data: bytes,
- ) -> Result<void> {
+ _from: Address,
+ _to: Address,
+ _token_id: U256,
+ _data: Bytes,
+ ) -> Result<()> {
// TODO: Not implemetable
Err("not implemented".into())
}
/// @dev Not implemented
#[solidity(rename_selector = "safeTransferFrom")]
- fn safe_transfer_from(
- &mut self,
- _from: address,
- _to: address,
- _token_id: uint256,
- ) -> Result<void> {
+ fn safe_transfer_from(&mut self, _from: Address, _to: Address, _token_id: U256) -> Result<()> {
// TODO: Not implemetable
Err("not implemented".into())
}
@@ -454,11 +449,11 @@
#[weight(<SelfWeightOf<T>>::transfer_from_creating_removing())]
fn transfer_from(
&mut self,
- caller: caller,
- from: address,
- to: address,
- token_id: uint256,
- ) -> Result<void> {
+ caller: Caller,
+ from: Address,
+ to: Address,
+ token_id: U256,
+ ) -> Result<()> {
let caller = T::CrossAccountId::from_eth(caller);
let from = T::CrossAccountId::from_eth(from);
let to = T::CrossAccountId::from_eth(to);
@@ -477,7 +472,7 @@
}
/// @dev Not implemented
- fn approve(&mut self, _caller: caller, _approved: address, _token_id: uint256) -> Result<void> {
+ fn approve(&mut self, _caller: Caller, _approved: Address, _token_id: U256) -> Result<()> {
Err("not implemented".into())
}
@@ -488,10 +483,10 @@
#[weight(<SelfWeightOf<T>>::set_allowance_for_all())]
fn set_approval_for_all(
&mut self,
- caller: caller,
- operator: address,
+ caller: Caller,
+ operator: Address,
approved: bool,
- ) -> Result<void> {
+ ) -> Result<()> {
let caller = T::CrossAccountId::from_eth(caller);
let operator = T::CrossAccountId::from_eth(operator);
@@ -501,14 +496,14 @@
}
/// @dev Not implemented
- fn get_approved(&self, _token_id: uint256) -> Result<address> {
+ fn get_approved(&self, _token_id: U256) -> Result<Address> {
// TODO: Not implemetable
Err("not implemented".into())
}
/// @notice Tells whether the given `owner` approves the `operator`.
#[weight(<SelfWeightOf<T>>::allowance_for_all())]
- fn is_approved_for_all(&self, owner: address, operator: address) -> Result<bool> {
+ fn is_approved_for_all(&self, owner: Address, operator: Address) -> Result<bool> {
let owner = T::CrossAccountId::from_eth(owner);
let operator = T::CrossAccountId::from_eth(operator);
@@ -556,7 +551,7 @@
/// operator of the current owner.
/// @param tokenId The RFT to approve
#[weight(<SelfWeightOf<T>>::burn_item_fully())]
- fn burn(&mut self, caller: caller, token_id: uint256) -> Result<void> {
+ fn burn(&mut self, caller: Caller, token_id: U256) -> Result<()> {
let caller = T::CrossAccountId::from_eth(caller);
let token = token_id.try_into()?;
@@ -575,8 +570,8 @@
/// @param to The new owner
/// @return uint256 The id of the newly minted token
#[weight(<SelfWeightOf<T>>::create_item())]
- fn mint(&mut self, caller: caller, to: address) -> Result<uint256> {
- let token_id: uint256 = <TokensMinted<T>>::get(self.id)
+ fn mint(&mut self, caller: Caller, to: Address) -> Result<U256> {
+ let token_id: U256 = <TokensMinted<T>>::get(self.id)
.checked_add(1)
.ok_or("item id overflow")?
.into();
@@ -591,7 +586,7 @@
/// @param tokenId ID of the minted RFT
#[solidity(hide, rename_selector = "mint")]
#[weight(<SelfWeightOf<T>>::create_item())]
- fn mint_check_id(&mut self, caller: caller, to: address, token_id: uint256) -> Result<bool> {
+ fn mint_check_id(&mut self, caller: Caller, to: Address, token_id: U256) -> Result<bool> {
let caller = T::CrossAccountId::from_eth(caller);
let to = T::CrossAccountId::from_eth(to);
let token_id: u32 = token_id.try_into()?;
@@ -634,11 +629,11 @@
#[weight(<SelfWeightOf<T>>::create_item())]
fn mint_with_token_uri(
&mut self,
- caller: caller,
- to: address,
- token_uri: string,
- ) -> Result<uint256> {
- let token_id: uint256 = <TokensMinted<T>>::get(self.id)
+ caller: Caller,
+ to: Address,
+ token_uri: String,
+ ) -> Result<U256> {
+ let token_id: U256 = <TokensMinted<T>>::get(self.id)
.checked_add(1)
.ok_or("item id overflow")?
.into();
@@ -656,10 +651,10 @@
#[weight(<SelfWeightOf<T>>::create_item())]
fn mint_with_token_uri_check_id(
&mut self,
- caller: caller,
- to: address,
- token_id: uint256,
- token_uri: string,
+ caller: Caller,
+ to: Address,
+ token_id: U256,
+ token_uri: String,
) -> Result<bool> {
let key = key::url();
let permission = get_token_permission::<T>(self.id, &key)?;
@@ -713,12 +708,12 @@
collection: &CollectionHandle<T>,
token_id: u32,
key: &up_data_structs::PropertyKey,
-) -> Result<string> {
+) -> Result<String> {
collection.consume_store_reads(1)?;
let properties = <TokenProperties<T>>::try_get((collection.id, token_id))
.map_err(|_| Error::Revert("Token properties not found".into()))?;
if let Some(property) = properties.get(key) {
- return Ok(string::from_utf8_lossy(property).into());
+ return Ok(String::from_utf8_lossy(property).into());
}
Err("Property tokenURI not found".into())
@@ -734,7 +729,7 @@
.get(key)
.map(Clone::clone)
.ok_or_else(|| {
- let key = string::from_utf8(key.clone().into_inner()).unwrap_or_default();
+ let key = String::from_utf8(key.clone().into_inner()).unwrap_or_default();
Error::Revert(alloc::format!("No permission for key {}", key))
})?;
Ok(a)
@@ -747,28 +742,28 @@
T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]>,
{
/// @notice A descriptive name for a collection of NFTs in this contract
- fn name(&self) -> Result<string> {
+ fn name(&self) -> Result<String> {
Ok(decode_utf16(self.name.iter().copied())
.map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))
- .collect::<string>())
+ .collect::<String>())
}
/// @notice An abbreviated name for NFTs in this contract
- fn symbol(&self) -> Result<string> {
- Ok(string::from_utf8_lossy(&self.token_prefix).into())
+ fn symbol(&self) -> Result<String> {
+ Ok(String::from_utf8_lossy(&self.token_prefix).into())
}
/// @notice A description for the collection.
- fn description(&self) -> Result<string> {
+ fn description(&self) -> Result<String> {
Ok(decode_utf16(self.description.iter().copied())
.map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))
- .collect::<string>())
+ .collect::<String>())
}
/// Returns the owner (in cross format) of the token.
///
/// @param tokenId Id for the token.
- fn cross_owner_of(&self, token_id: uint256) -> Result<eth::CrossAddress> {
+ fn cross_owner_of(&self, token_id: U256) -> Result<eth::CrossAddress> {
Self::token_owner(&self, token_id.try_into()?)
.map(|o| eth::CrossAddress::from_sub_cross_account::<T>(&o))
.ok_or(Error::Revert("key too large".into()))
@@ -779,7 +774,7 @@
/// @param tokenId Id for the token.
/// @param keys Properties keys. Empty keys for all propertyes.
/// @return Vector of properties key/value pairs.
- fn properties(&self, token_id: uint256, keys: Vec<string>) -> Result<Vec<eth::Property>> {
+ fn properties(&self, token_id: U256, keys: Vec<String>) -> Result<Vec<eth::Property>> {
let keys = keys
.into_iter()
.map(|key| {
@@ -805,7 +800,7 @@
/// @param to The new owner
/// @param tokenId The RFT to transfer
#[weight(<SelfWeightOf<T>>::transfer_creating_removing())]
- fn transfer(&mut self, caller: caller, to: address, token_id: uint256) -> Result<void> {
+ fn transfer(&mut self, caller: Caller, to: Address, token_id: U256) -> Result<()> {
let caller = T::CrossAccountId::from_eth(caller);
let to = T::CrossAccountId::from_eth(to);
let token = token_id.try_into()?;
@@ -830,10 +825,10 @@
#[weight(<SelfWeightOf<T>>::transfer_creating_removing())]
fn transfer_cross(
&mut self,
- caller: caller,
+ caller: Caller,
to: eth::CrossAddress,
- token_id: uint256,
- ) -> Result<void> {
+ token_id: U256,
+ ) -> Result<()> {
let caller = T::CrossAccountId::from_eth(caller);
let to = to.into_sub_cross_account::<T>()?;
let token = token_id.try_into()?;
@@ -858,11 +853,11 @@
#[weight(<SelfWeightOf<T>>::transfer_creating_removing())]
fn transfer_from_cross(
&mut self,
- caller: caller,
+ caller: Caller,
from: eth::CrossAddress,
to: eth::CrossAddress,
- token_id: uint256,
- ) -> Result<void> {
+ token_id: U256,
+ ) -> Result<()> {
let caller = T::CrossAccountId::from_eth(caller);
let from = from.into_sub_cross_account::<T>()?;
let to = to.into_sub_cross_account::<T>()?;
@@ -888,7 +883,7 @@
/// @param tokenId The RFT to transfer
#[solidity(hide)]
#[weight(<SelfWeightOf<T>>::burn_from())]
- fn burn_from(&mut self, caller: caller, from: address, token_id: uint256) -> Result<void> {
+ fn burn_from(&mut self, caller: Caller, from: Address, token_id: U256) -> Result<()> {
let caller = T::CrossAccountId::from_eth(caller);
let from = T::CrossAccountId::from_eth(from);
let token = token_id.try_into()?;
@@ -914,10 +909,10 @@
#[weight(<SelfWeightOf<T>>::burn_from())]
fn burn_from_cross(
&mut self,
- caller: caller,
+ caller: Caller,
from: eth::CrossAddress,
- token_id: uint256,
- ) -> Result<void> {
+ token_id: U256,
+ ) -> Result<()> {
let caller = T::CrossAccountId::from_eth(caller);
let from = from.into_sub_cross_account::<T>()?;
let token = token_id.try_into()?;
@@ -934,7 +929,7 @@
}
/// @notice Returns next free RFT ID.
- fn next_token_id(&self) -> Result<uint256> {
+ fn next_token_id(&self) -> Result<U256> {
self.consume_store_reads(1)?;
Ok(<TokensMinted<T>>::get(self.id)
.checked_add(1)
@@ -949,7 +944,7 @@
/// @param tokenIds IDs of the minted RFTs
#[solidity(hide)]
#[weight(<SelfWeightOf<T>>::create_multiple_items(token_ids.len() as u32))]
- fn mint_bulk(&mut self, caller: caller, to: address, token_ids: Vec<uint256>) -> Result<bool> {
+ fn mint_bulk(&mut self, caller: Caller, to: Address, token_ids: Vec<U256>) -> Result<bool> {
let caller = T::CrossAccountId::from_eth(caller);
let to = T::CrossAccountId::from_eth(to);
let mut expected_index = <TokensMinted<T>>::get(self.id)
@@ -994,9 +989,9 @@
#[weight(<SelfWeightOf<T>>::create_multiple_items(tokens.len() as u32))]
fn mint_bulk_with_token_uri(
&mut self,
- caller: caller,
- to: address,
- tokens: Vec<(uint256, string)>,
+ caller: Caller,
+ to: Address,
+ tokens: Vec<(U256, String)>,
) -> Result<bool> {
let key = key::url();
let caller = T::CrossAccountId::from_eth(caller);
@@ -1051,10 +1046,10 @@
#[weight(<SelfWeightOf<T>>::create_item())]
fn mint_cross(
&mut self,
- caller: caller,
+ caller: Caller,
to: eth::CrossAddress,
properties: Vec<eth::Property>,
- ) -> Result<uint256> {
+ ) -> Result<U256> {
let token_id = <TokensMinted<T>>::get(self.id)
.checked_add(1)
.ok_or("item id overflow")?;
@@ -1093,7 +1088,7 @@
/// Returns EVM address for refungible token
///
/// @param token ID of the token
- fn token_contract_address(&self, token: uint256) -> Result<address> {
+ fn token_contract_address(&self, token: U256) -> Result<Address> {
Ok(T::EvmTokenAddressMapping::token_to_address(
self.id,
token.try_into().map_err(|_| "token id overflow")?,
@@ -1101,7 +1096,7 @@
}
/// @notice Returns collection helper contract address
- fn collection_helper_address(&self) -> Result<address> {
+ fn collection_helper_address(&self) -> Result<Address> {
Ok(T::ContractAddress::get())
}
}
pallets/refungible/src/erc_token.rsdiffbeforeafterboth--- a/pallets/refungible/src/erc_token.rs
+++ b/pallets/refungible/src/erc_token.rs
@@ -37,6 +37,7 @@
use pallet_evm_coder_substrate::{call, dispatch_to_evm, WithRecorder};
use pallet_structure::{SelfWeightOf as StructureWeight, weights::WeightInfo as _};
use sp_std::vec::Vec;
+use sp_core::U256;
use up_data_structs::TokenId;
use crate::{
@@ -51,11 +52,11 @@
#[solidity_interface(name = ERC1633)]
impl<T: Config> RefungibleTokenHandle<T> {
- fn parent_token(&self) -> Result<address> {
+ fn parent_token(&self) -> Result<Address> {
Ok(collection_id_to_address(self.id))
}
- fn parent_token_id(&self) -> Result<uint256> {
+ fn parent_token_id(&self) -> Result<U256> {
Ok(self.1.into())
}
}
@@ -68,19 +69,19 @@
/// of burning tokens the transfer is to 0.
Transfer {
#[indexed]
- from: address,
+ from: Address,
#[indexed]
- to: address,
- value: uint256,
+ to: Address,
+ value: U256,
},
/// @dev This event is emitted when the amount of tokens (value) is approved
/// by the owner to be used by the spender.
Approval {
#[indexed]
- owner: address,
+ owner: Address,
#[indexed]
- spender: address,
- value: uint256,
+ spender: Address,
+ value: U256,
},
}
@@ -91,25 +92,25 @@
#[solidity_interface(name = ERC20, events(ERC20Events))]
impl<T: Config> RefungibleTokenHandle<T> {
/// @return the name of the token.
- fn name(&self) -> Result<string> {
+ fn name(&self) -> Result<String> {
Ok(decode_utf16(self.name.iter().copied())
.map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))
- .collect::<string>())
+ .collect::<String>())
}
/// @return the symbol of the token.
- fn symbol(&self) -> Result<string> {
- Ok(string::from_utf8_lossy(&self.token_prefix).into())
+ fn symbol(&self) -> Result<String> {
+ Ok(String::from_utf8_lossy(&self.token_prefix).into())
}
/// @dev Total number of tokens in existence
- fn total_supply(&self) -> Result<uint256> {
+ fn total_supply(&self) -> Result<U256> {
self.consume_store_reads(1)?;
Ok(<TotalSupply<T>>::get((self.id, self.1)).into())
}
/// @dev Not supported
- fn decimals(&self) -> Result<uint8> {
+ fn decimals(&self) -> Result<u8> {
// Decimals aren't supported for refungible tokens
Ok(0)
}
@@ -117,7 +118,7 @@
/// @dev Gets the balance of the specified address.
/// @param owner The address to query the balance of.
/// @return An uint256 representing the amount owned by the passed address.
- fn balance_of(&self, owner: address) -> Result<uint256> {
+ fn balance_of(&self, owner: Address) -> Result<U256> {
self.consume_store_reads(1)?;
let owner = T::CrossAccountId::from_eth(owner);
let balance = <Balance<T>>::get((self.id, self.1, owner));
@@ -128,7 +129,7 @@
/// @param to The address to transfer to.
/// @param amount The amount to be transferred.
#[weight(<CommonWeights<T>>::transfer())]
- fn transfer(&mut self, caller: caller, to: address, amount: uint256) -> Result<bool> {
+ fn transfer(&mut self, caller: Caller, to: Address, amount: U256) -> Result<bool> {
let caller = T::CrossAccountId::from_eth(caller);
let to = T::CrossAccountId::from_eth(to);
let amount = amount.try_into().map_err(|_| "amount overflow")?;
@@ -148,10 +149,10 @@
#[weight(<CommonWeights<T>>::transfer_from())]
fn transfer_from(
&mut self,
- caller: caller,
- from: address,
- to: address,
- amount: uint256,
+ caller: Caller,
+ from: Address,
+ to: Address,
+ amount: U256,
) -> Result<bool> {
let caller = T::CrossAccountId::from_eth(caller);
let from = T::CrossAccountId::from_eth(from);
@@ -174,7 +175,7 @@
/// @param spender The address which will spend the funds.
/// @param amount The amount of tokens to be spent.
#[weight(<SelfWeightOf<T>>::approve())]
- fn approve(&mut self, caller: caller, spender: address, amount: uint256) -> Result<bool> {
+ fn approve(&mut self, caller: Caller, spender: Address, amount: U256) -> Result<bool> {
let caller = T::CrossAccountId::from_eth(caller);
let spender = T::CrossAccountId::from_eth(spender);
let amount = amount.try_into().map_err(|_| "amount overflow")?;
@@ -188,7 +189,7 @@
/// @param owner address The address which owns the funds.
/// @param spender address The address which will spend the funds.
/// @return A uint256 specifying the amount of tokens still available for the spender.
- fn allowance(&self, owner: address, spender: address) -> Result<uint256> {
+ fn allowance(&self, owner: Address, spender: Address) -> Result<U256> {
self.consume_store_reads(1)?;
let owner = T::CrossAccountId::from_eth(owner);
let spender = T::CrossAccountId::from_eth(spender);
@@ -208,7 +209,7 @@
/// @param amount The amount that will be burnt.
#[weight(<SelfWeightOf<T>>::burn_from())]
#[solidity(hide)]
- fn burn_from(&mut self, caller: caller, from: address, amount: uint256) -> Result<bool> {
+ fn burn_from(&mut self, caller: Caller, from: Address, amount: U256) -> Result<bool> {
let caller = T::CrossAccountId::from_eth(caller);
let from = T::CrossAccountId::from_eth(from);
let amount = amount.try_into().map_err(|_| "amount overflow")?;
@@ -228,9 +229,9 @@
#[weight(<SelfWeightOf<T>>::burn_from())]
fn burn_from_cross(
&mut self,
- caller: caller,
+ caller: Caller,
from: pallet_common::eth::CrossAddress,
- amount: uint256,
+ amount: U256,
) -> Result<bool> {
let caller = T::CrossAccountId::from_eth(caller);
let from = from.into_sub_cross_account::<T>()?;
@@ -254,9 +255,9 @@
#[weight(<SelfWeightOf<T>>::approve())]
fn approve_cross(
&mut self,
- caller: caller,
+ caller: Caller,
spender: pallet_common::eth::CrossAddress,
- amount: uint256,
+ amount: U256,
) -> Result<bool> {
let caller = T::CrossAccountId::from_eth(caller);
let spender = spender.into_sub_cross_account::<T>()?;
@@ -270,7 +271,7 @@
/// Throws if `msg.sender` doesn't owns all of the tokens.
/// @param amount New total amount of the tokens.
#[weight(<SelfWeightOf<T>>::repartition_item())]
- fn repartition(&mut self, caller: caller, amount: uint256) -> Result<bool> {
+ fn repartition(&mut self, caller: Caller, amount: U256) -> Result<bool> {
let caller = T::CrossAccountId::from_eth(caller);
let amount = amount.try_into().map_err(|_| "amount overflow")?;
@@ -284,9 +285,9 @@
#[weight(<CommonWeights<T>>::transfer())]
fn transfer_cross(
&mut self,
- caller: caller,
+ caller: Caller,
to: pallet_common::eth::CrossAddress,
- amount: uint256,
+ amount: U256,
) -> Result<bool> {
let caller = T::CrossAccountId::from_eth(caller);
let to = to.into_sub_cross_account::<T>()?;
@@ -307,10 +308,10 @@
#[weight(<CommonWeights<T>>::transfer_from())]
fn transfer_from_cross(
&mut self,
- caller: caller,
+ caller: Caller,
from: pallet_common::eth::CrossAddress,
to: pallet_common::eth::CrossAddress,
- amount: uint256,
+ amount: U256,
) -> Result<bool> {
let caller = T::CrossAccountId::from_eth(caller);
let from = from.into_sub_cross_account::<T>()?;
pallets/refungible/src/stubs/UniqueRefungible.rawdiffbeforeafterbothbinary blob — no preview
pallets/refungible/src/stubs/UniqueRefungible.soldiffbeforeafterboth--- a/pallets/refungible/src/stubs/UniqueRefungible.sol
+++ b/pallets/refungible/src/stubs/UniqueRefungible.sol
@@ -416,11 +416,9 @@
/// Set the collection access method.
/// @param mode Access mode
- /// 0 for Normal
- /// 1 for AllowList
/// @dev EVM selector for this function is: 0x41835d4c,
/// or in textual repr: setCollectionAccess(uint8)
- function setCollectionAccess(uint8 mode) public {
+ function setCollectionAccess(AccessMode mode) public {
require(false, stub_error);
mode;
dummy = 0;
@@ -585,6 +583,14 @@
uint256 sub;
}
+/// Ethereum representation of `AccessMode` (see [`up_data_structs::AccessMode`]).
+enum AccessMode {
+ /// Access grant for owner and admins. Used as default.
+ Normal,
+ /// Like a [`Normal`](AccessMode::Normal) but also users in allow list.
+ AllowList
+}
+
/// Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) field.
struct CollectionNestingPermission {
CollectionPermissionField field;
pallets/unique/src/eth/mod.rsdiffbeforeafterboth--- a/pallets/unique/src/eth/mod.rs
+++ b/pallets/unique/src/eth/mod.rs
@@ -56,10 +56,10 @@
}
fn convert_data<T: Config>(
- caller: caller,
- name: string,
- description: string,
- token_prefix: string,
+ caller: Caller,
+ name: String,
+ description: String,
+ token_prefix: String,
) -> Result<(
T::CrossAccountId,
CollectionName,
@@ -87,13 +87,13 @@
#[inline(always)]
fn create_collection_internal<T: Config>(
- caller: caller,
- value: value,
- name: string,
+ caller: Caller,
+ value: Value,
+ name: String,
collection_mode: CollectionMode,
- description: string,
- token_prefix: string,
-) -> Result<address> {
+ description: String,
+ token_prefix: String,
+) -> Result<Address> {
let (caller, name, description, token_prefix) =
convert_data::<T>(caller, name, description, token_prefix)?;
let data = CreateCollectionData {
@@ -118,7 +118,7 @@
Ok(address)
}
-fn check_sent_amount_equals_collection_creation_price<T: Config>(value: value) -> Result<()> {
+fn check_sent_amount_equals_collection_creation_price<T: Config>(value: Value) -> Result<()> {
let value = value.as_u128();
let creation_price: u128 = T::CollectionCreationPrice::get()
.try_into()
@@ -149,12 +149,12 @@
#[solidity(rename_selector = "createNFTCollection")]
fn create_nft_collection(
&mut self,
- caller: caller,
- value: value,
- name: string,
- description: string,
- token_prefix: string,
- ) -> Result<address> {
+ caller: Caller,
+ value: Value,
+ name: String,
+ description: String,
+ token_prefix: String,
+ ) -> Result<Address> {
let (caller, name, description, token_prefix) =
convert_data::<T>(caller, name, description, token_prefix)?;
let data = CreateCollectionData {
@@ -188,12 +188,12 @@
#[solidity(hide)]
fn create_nonfungible_collection(
&mut self,
- caller: caller,
- value: value,
- name: string,
- description: string,
- token_prefix: string,
- ) -> Result<address> {
+ caller: Caller,
+ value: Value,
+ name: String,
+ description: String,
+ token_prefix: String,
+ ) -> Result<Address> {
create_collection_internal::<T>(
caller,
value,
@@ -208,12 +208,12 @@
#[solidity(rename_selector = "createRFTCollection")]
fn create_rft_collection(
&mut self,
- caller: caller,
- value: value,
- name: string,
- description: string,
- token_prefix: string,
- ) -> Result<address> {
+ caller: Caller,
+ value: Value,
+ name: String,
+ description: String,
+ token_prefix: String,
+ ) -> Result<Address> {
create_collection_internal::<T>(
caller,
value,
@@ -228,13 +228,13 @@
#[solidity(rename_selector = "createFTCollection")]
fn create_fungible_collection(
&mut self,
- caller: caller,
- value: value,
- name: string,
- decimals: uint8,
- description: string,
- token_prefix: string,
- ) -> Result<address> {
+ caller: Caller,
+ value: Value,
+ name: String,
+ decimals: u8,
+ description: String,
+ token_prefix: String,
+ ) -> Result<Address> {
create_collection_internal::<T>(
caller,
value,
@@ -248,9 +248,9 @@
#[solidity(rename_selector = "makeCollectionERC721MetadataCompatible")]
fn make_collection_metadata_compatible(
&mut self,
- caller: caller,
- collection: address,
- base_uri: string,
+ caller: Caller,
+ collection: Address,
+ base_uri: String,
) -> Result<()> {
let caller = T::CrossAccountId::from_eth(caller);
let collection =
@@ -334,7 +334,7 @@
}
#[weight(<SelfWeightOf<T>>::destroy_collection())]
- fn destroy_collection(&mut self, caller: caller, collection_address: address) -> Result<void> {
+ fn destroy_collection(&mut self, caller: Caller, collection_address: Address) -> Result<()> {
let caller = T::CrossAccountId::from_eth(caller);
let collection_id = pallet_common::eth::map_eth_to_id(&collection_address)
@@ -346,7 +346,7 @@
/// Check if a collection exists
/// @param collectionAddress Address of the collection in question
/// @return bool Does the collection exist?
- fn is_collection_exist(&self, _caller: caller, collection_address: address) -> Result<bool> {
+ fn is_collection_exist(&self, _caller: Caller, collection_address: Address) -> Result<bool> {
if let Some(id) = pallet_common::eth::map_eth_to_id(&collection_address) {
let collection_id = id;
return Ok(<CollectionById<T>>::contains_key(collection_id));
@@ -355,7 +355,7 @@
Ok(false)
}
- fn collection_creation_fee(&self) -> Result<value> {
+ fn collection_creation_fee(&self) -> Result<Value> {
let price: u128 = T::CollectionCreationPrice::get()
.try_into()
.map_err(|_| ()) // workaround for `expect` requiring `Debug` trait
@@ -366,14 +366,14 @@
/// Returns address of a collection.
/// @param collectionId - CollectionId of the collection
/// @return eth mirror address of the collection
- fn collection_address(&self, collection_id: uint32) -> Result<address> {
+ fn collection_address(&self, collection_id: u32) -> Result<Address> {
Ok(collection_id_to_address(collection_id.into()))
}
/// Returns collectionId of a collection.
/// @param collectionAddress - Eth address of the collection
/// @return collectionId of the collection
- fn collection_id(&self, collection_address: address) -> Result<uint32> {
+ fn collection_id(&self, collection_address: Address) -> Result<u32> {
map_eth_to_id(&collection_address)
.map(|id| id.0)
.ok_or(Error::Revert(format!(
runtime/tests/src/tests.rsdiffbeforeafterboth1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617// Tests to be written here18use crate::{Test, TestCrossAccountId, CollectionCreationPrice, RuntimeOrigin, Unique, new_test_ext};19use up_data_structs::{20 COLLECTION_NUMBER_LIMIT, CollectionId, CreateItemData, CreateFungibleData, CreateNftData,21 CreateReFungibleData, MAX_DECIMAL_POINTS, COLLECTION_ADMINS_LIMIT, TokenId,22 MAX_TOKEN_OWNERSHIP, CreateCollectionData, CollectionMode, AccessMode, CollectionPermissions,23 PropertyKeyPermission, PropertyPermission, Property, CollectionPropertiesVec,24 CollectionPropertiesPermissionsVec,25};26use frame_support::{assert_noop, assert_ok, assert_err};27use sp_std::convert::TryInto;28use pallet_evm::account::CrossAccountId;29use pallet_common::Error as CommonError;30use pallet_unique::Error as UniqueError;3132fn add_balance(user: u64, value: u64) {33 const DONOR_USER: u64 = 999;34 assert_ok!(<pallet_balances::Pallet<Test>>::set_balance(35 RuntimeOrigin::root(),36 DONOR_USER,37 value,38 039 ));40 assert_ok!(<pallet_balances::Pallet<Test>>::force_transfer(41 RuntimeOrigin::root(),42 DONOR_USER,43 user,44 value45 ));46}4748fn default_nft_data() -> CreateNftData {49 CreateNftData {50 properties: vec![Property {51 key: b"test-prop".to_vec().try_into().unwrap(),52 value: b"test-nft-prop".to_vec().try_into().unwrap(),53 }]54 .try_into()55 .unwrap(),56 }57}5859fn default_fungible_data() -> CreateFungibleData {60 CreateFungibleData { value: 5 }61}6263fn default_re_fungible_data() -> CreateReFungibleData {64 CreateReFungibleData {65 pieces: 1023,66 properties: vec![Property {67 key: b"test-prop".to_vec().try_into().unwrap(),68 value: b"test-nft-prop".to_vec().try_into().unwrap(),69 }]70 .try_into()71 .unwrap(),72 }73}7475fn create_test_collection_for_owner(76 mode: &CollectionMode,77 owner: u64,78 id: CollectionId,79) -> CollectionId {80 add_balance(owner, CollectionCreationPrice::get() as u64 + 1);8182 let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();83 let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();84 let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();85 let token_property_permissions: CollectionPropertiesPermissionsVec =86 vec![PropertyKeyPermission {87 key: b"test-prop".to_vec().try_into().unwrap(),88 permission: PropertyPermission {89 mutable: true,90 collection_admin: false,91 token_owner: true,92 },93 }]94 .try_into()95 .unwrap();96 let properties: CollectionPropertiesVec = vec![Property {97 key: b"test-collection-prop".to_vec().try_into().unwrap(),98 value: b"test-collection-value".to_vec().try_into().unwrap(),99 }]100 .try_into()101 .unwrap();102103 let data: CreateCollectionData<u64> = CreateCollectionData {104 name: col_name1.try_into().unwrap(),105 description: col_desc1.try_into().unwrap(),106 token_prefix: token_prefix1.try_into().unwrap(),107 mode: mode.clone(),108 token_property_permissions: token_property_permissions.clone(),109 properties: properties.clone(),110 ..Default::default()111 };112113 let origin1 = RuntimeOrigin::signed(owner);114 assert_ok!(Unique::create_collection_ex(origin1, data));115116 let saved_col_name: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();117 let saved_description: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();118 let saved_prefix: Vec<u8> = b"token_prefix1\0".to_vec();119 assert_eq!(120 <pallet_common::CollectionById<Test>>::get(id)121 .unwrap()122 .owner,123 owner124 );125 assert_eq!(126 <pallet_common::CollectionById<Test>>::get(id).unwrap().name,127 saved_col_name128 );129 assert_eq!(130 <pallet_common::CollectionById<Test>>::get(id).unwrap().mode,131 *mode132 );133 assert_eq!(134 <pallet_common::CollectionById<Test>>::get(id)135 .unwrap()136 .description,137 saved_description138 );139 assert_eq!(140 <pallet_common::CollectionById<Test>>::get(id)141 .unwrap()142 .token_prefix,143 saved_prefix144 );145 assert_eq!(146 get_collection_property_permissions(id).as_slice(),147 token_property_permissions.as_slice()148 );149 assert_eq!(150 get_collection_properties(id).as_slice(),151 properties.as_slice()152 );153 id154}155156fn get_collection_property_permissions(collection_id: CollectionId) -> Vec<PropertyKeyPermission> {157 <pallet_common::Pallet<Test>>::property_permissions(collection_id)158 .into_iter()159 .map(|(key, permission)| PropertyKeyPermission { key, permission })160 .collect()161}162163fn get_collection_properties(collection_id: CollectionId) -> Vec<Property> {164 <pallet_common::Pallet<Test>>::collection_properties(collection_id)165 .into_iter()166 .map(|(key, value)| Property { key, value })167 .collect()168}169170fn get_token_properties(collection_id: CollectionId, token_id: TokenId) -> Vec<Property> {171 <pallet_nonfungible::Pallet<Test>>::token_properties((collection_id, token_id))172 .into_iter()173 .map(|(key, value)| Property { key, value })174 .collect()175}176177fn create_test_collection(mode: &CollectionMode, id: CollectionId) -> CollectionId {178 create_test_collection_for_owner(&mode, 1, id)179}180181fn create_test_item(collection_id: CollectionId, data: &CreateItemData) {182 let origin1 = RuntimeOrigin::signed(1);183 assert_ok!(Unique::create_item(184 origin1,185 collection_id,186 account(1),187 data.clone()188 ));189}190191fn account(sub: u64) -> TestCrossAccountId {192 TestCrossAccountId::from_sub(sub)193}194195// Use cases tests region196// #region197198#[test]199fn check_not_sufficient_founds() {200 new_test_ext().execute_with(|| {201 let acc: u64 = 1;202 <pallet_balances::Pallet<Test>>::set_balance(RuntimeOrigin::root(), acc, 0, 0).unwrap();203204 let name: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();205 let description: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();206 let token_prefix: Vec<u8> = b"token_prefix1\0".to_vec();207208 let data: CreateCollectionData<<Test as frame_system::Config>::AccountId> =209 CreateCollectionData {210 name: name.try_into().unwrap(),211 description: description.try_into().unwrap(),212 token_prefix: token_prefix.try_into().unwrap(),213 mode: CollectionMode::NFT,214 ..Default::default()215 };216217 let result = Unique::create_collection_ex(RuntimeOrigin::signed(acc), data);218 assert_err!(result, <CommonError<Test>>::NotSufficientFounds);219 });220}221222#[test]223fn create_fungible_collection_fails_with_large_decimal_numbers() {224 new_test_ext().execute_with(|| {225 let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();226 let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();227 let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();228229 let data: CreateCollectionData<u64> = CreateCollectionData {230 name: col_name1.try_into().unwrap(),231 description: col_desc1.try_into().unwrap(),232 token_prefix: token_prefix1.try_into().unwrap(),233 mode: CollectionMode::Fungible(MAX_DECIMAL_POINTS + 1),234 ..Default::default()235 };236237 let origin1 = RuntimeOrigin::signed(1);238 assert_noop!(239 Unique::create_collection_ex(origin1, data),240 UniqueError::<Test>::CollectionDecimalPointLimitExceeded241 );242 });243}244245#[test]246fn create_nft_item() {247 new_test_ext().execute_with(|| {248 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));249250 let data = default_nft_data();251 create_test_item(collection_id, &data.clone().into());252253 assert_eq!(254 get_token_properties(collection_id, TokenId(1)).as_slice(),255 data.properties.as_slice(),256 );257 });258}259260// Use cases tests region261// #region262#[test]263fn create_nft_multiple_items() {264 new_test_ext().execute_with(|| {265 create_test_collection(&CollectionMode::NFT, CollectionId(1));266267 let origin1 = RuntimeOrigin::signed(1);268269 let items_data = vec![default_nft_data(), default_nft_data(), default_nft_data()];270271 assert_ok!(Unique::create_multiple_items(272 origin1,273 CollectionId(1),274 account(1),275 items_data276 .clone()277 .into_iter()278 .map(|d| { d.into() })279 .collect()280 ));281 for (index, data) in items_data.into_iter().enumerate() {282 assert_eq!(283 get_token_properties(CollectionId(1), TokenId(index as u32 + 1)).as_slice(),284 data.properties.as_slice()285 );286 }287 });288}289290#[test]291fn create_refungible_item() {292 new_test_ext().execute_with(|| {293 let collection_id = create_test_collection(&CollectionMode::ReFungible, CollectionId(1));294295 let data = default_re_fungible_data();296 create_test_item(collection_id, &data.clone().into());297 let balance =298 <pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(1)));299 assert_eq!(balance, 1023);300 });301}302303#[test]304fn create_multiple_refungible_items() {305 new_test_ext().execute_with(|| {306 create_test_collection(&CollectionMode::ReFungible, CollectionId(1));307308 let origin1 = RuntimeOrigin::signed(1);309310 let items_data = vec![311 default_re_fungible_data(),312 default_re_fungible_data(),313 default_re_fungible_data(),314 ];315316 assert_ok!(Unique::create_multiple_items(317 origin1,318 CollectionId(1),319 account(1),320 items_data321 .clone()322 .into_iter()323 .map(|d| { d.into() })324 .collect()325 ));326 for (index, data) in items_data.into_iter().enumerate() {327 let balance = <pallet_refungible::Balance<Test>>::get((328 CollectionId(1),329 TokenId((index + 1) as u32),330 account(1),331 ));332 assert_eq!(balance, 1023);333 }334 });335}336337#[test]338fn create_fungible_item() {339 new_test_ext().execute_with(|| {340 let collection_id = create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));341342 let data = default_fungible_data();343 create_test_item(collection_id, &data.into());344345 assert_eq!(346 <pallet_fungible::Balance<Test>>::get((collection_id, account(1))),347 5348 );349 });350}351352//#[test]353// fn create_multiple_fungible_items() {354// new_test_ext().execute_with(|| {355// default_limits();356357// create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));358359// let origin1 = RuntimeOrigin::signed(1);360361// let items_data = vec![default_fungible_data(), default_fungible_data(), default_fungible_data()];362363// assert_ok!(Unique::create_multiple_items(364// origin1.clone(),365// 1,366// 1,367// items_data.clone().into_iter().map(|d| { d.into() }).collect()368// ));369370// for (index, _) in items_data.iter().enumerate() {371// assert_eq!(Unique::fungible_item_id(1, (index + 1) as TokenId).value, 5);372// }373// assert_eq!(Unique::balance_count(1, 1), 3000);374// assert_eq!(Unique::address_tokens(1, 1), [1, 2, 3]);375// });376// }377378#[test]379fn transfer_fungible_item() {380 new_test_ext().execute_with(|| {381 let collection_id = create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));382383 let origin1 = RuntimeOrigin::signed(1);384 let origin2 = RuntimeOrigin::signed(2);385386 let data = default_fungible_data();387 create_test_item(collection_id, &data.into());388389 assert_eq!(390 <pallet_fungible::Balance<Test>>::get((CollectionId(1), account(1))),391 5392 );393394 // change owner scenario395 assert_ok!(Unique::transfer(396 origin1,397 account(2),398 CollectionId(1),399 TokenId(0),400 5401 ));402 assert_eq!(403 <pallet_fungible::Balance<Test>>::get((CollectionId(1), account(1))),404 0405 );406407 // split item scenario408 assert_ok!(Unique::transfer(409 origin2.clone(),410 account(3),411 CollectionId(1),412 TokenId(0),413 3414 ));415416 // split item and new owner has account scenario417 assert_ok!(Unique::transfer(418 origin2,419 account(3),420 CollectionId(1),421 TokenId(0),422 1423 ));424 assert_eq!(425 <pallet_fungible::Balance<Test>>::get((CollectionId(1), account(2))),426 1427 );428 assert_eq!(429 <pallet_fungible::Balance<Test>>::get((CollectionId(1), account(3))),430 4431 );432 });433}434435#[test]436fn transfer_refungible_item() {437 new_test_ext().execute_with(|| {438 let collection_id = create_test_collection(&CollectionMode::ReFungible, CollectionId(1));439440 // Create RFT 1 in 1023 pieces for account 1441 let data = default_re_fungible_data();442 create_test_item(collection_id, &data.clone().into());443 assert_eq!(444 <pallet_refungible::AccountBalance<Test>>::get((collection_id, account(1))),445 1446 );447 assert_eq!(448 <pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(1))),449 1023450 );451 assert_eq!(452 <pallet_refungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),453 true454 );455456 // Account 1 transfers all 1023 pieces of RFT 1 to account 2457 let origin1 = RuntimeOrigin::signed(1);458 let origin2 = RuntimeOrigin::signed(2);459 assert_ok!(Unique::transfer(460 origin1,461 account(2),462 CollectionId(1),463 TokenId(1),464 1023465 ));466 assert_eq!(467 <pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(2))),468 1023469 );470 assert_eq!(471 <pallet_refungible::AccountBalance<Test>>::get((collection_id, account(1))),472 0473 );474 assert_eq!(475 <pallet_refungible::AccountBalance<Test>>::get((collection_id, account(2))),476 1477 );478 assert_eq!(479 <pallet_refungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),480 false481 );482 assert_eq!(483 <pallet_refungible::Owned<Test>>::get((collection_id, account(2), TokenId(1))),484 true485 );486487 // Account 2 transfers 500 pieces of RFT 1 to account 3488 assert_ok!(Unique::transfer(489 origin2.clone(),490 account(3),491 CollectionId(1),492 TokenId(1),493 500494 ));495 assert_eq!(496 <pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(2))),497 523498 );499 assert_eq!(500 <pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(3))),501 500502 );503 assert_eq!(504 <pallet_refungible::AccountBalance<Test>>::get((collection_id, account(2))),505 1506 );507 assert_eq!(508 <pallet_refungible::AccountBalance<Test>>::get((collection_id, account(3))),509 1510 );511 assert_eq!(512 <pallet_refungible::Owned<Test>>::get((collection_id, account(2), TokenId(1))),513 true514 );515 assert_eq!(516 <pallet_refungible::Owned<Test>>::get((collection_id, account(3), TokenId(1))),517 true518 );519520 // Account 2 transfers 200 more pieces of RFT 1 to account 3 with pre-existing balance521 assert_ok!(Unique::transfer(522 origin2,523 account(3),524 CollectionId(1),525 TokenId(1),526 200527 ));528 assert_eq!(529 <pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(2))),530 323531 );532 assert_eq!(533 <pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(3))),534 700535 );536 assert_eq!(537 <pallet_refungible::AccountBalance<Test>>::get((collection_id, account(2))),538 1539 );540 assert_eq!(541 <pallet_refungible::AccountBalance<Test>>::get((collection_id, account(3))),542 1543 );544 assert_eq!(545 <pallet_refungible::Owned<Test>>::get((collection_id, account(2), TokenId(1))),546 true547 );548 assert_eq!(549 <pallet_refungible::Owned<Test>>::get((collection_id, account(3), TokenId(1))),550 true551 );552 });553}554555#[test]556fn transfer_nft_item() {557 new_test_ext().execute_with(|| {558 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));559560 let data = default_nft_data();561 create_test_item(collection_id, &data.into());562 assert_eq!(563 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),564 1565 );566 assert_eq!(567 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),568 true569 );570571 let origin1 = RuntimeOrigin::signed(1);572 // default scenario573 assert_ok!(Unique::transfer(574 origin1,575 account(2),576 CollectionId(1),577 TokenId(1),578 1579 ));580 assert_eq!(581 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),582 0583 );584 assert_eq!(585 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(2))),586 1587 );588 assert_eq!(589 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),590 false591 );592 assert_eq!(593 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(2), TokenId(1))),594 true595 );596 });597}598599#[test]600fn transfer_nft_item_wrong_value() {601 new_test_ext().execute_with(|| {602 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));603604 let data = default_nft_data();605 create_test_item(collection_id, &data.into());606 assert_eq!(607 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),608 1609 );610 assert_eq!(611 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),612 true613 );614615 let origin1 = RuntimeOrigin::signed(1);616617 assert_noop!(618 Unique::transfer(origin1, account(2), CollectionId(1), TokenId(1), 2)619 .map_err(|e| e.error),620 <pallet_nonfungible::Error::<Test>>::NonfungibleItemsHaveNoAmount621 );622 });623}624625#[test]626fn transfer_nft_item_zero_value() {627 new_test_ext().execute_with(|| {628 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));629630 let data = default_nft_data();631 create_test_item(collection_id, &data.into());632 assert_eq!(633 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),634 1635 );636 assert_eq!(637 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),638 true639 );640641 let origin1 = RuntimeOrigin::signed(1);642643 // Transferring 0 amount works on NFT...644 assert_ok!(Unique::transfer(645 origin1,646 account(2),647 CollectionId(1),648 TokenId(1),649 0650 ));651 // ... and results in no transfer652 assert_eq!(653 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),654 1655 );656 assert_eq!(657 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),658 true659 );660 });661}662663#[test]664fn nft_approve_and_transfer_from() {665 new_test_ext().execute_with(|| {666 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));667668 let data = default_nft_data();669 create_test_item(collection_id, &data.into());670671 let origin1 = RuntimeOrigin::signed(1);672 let origin2 = RuntimeOrigin::signed(2);673674 assert_eq!(675 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),676 1677 );678 assert_eq!(679 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),680 true681 );682683 // neg transfer_from684 assert_noop!(685 Unique::transfer_from(686 origin2.clone(),687 account(1),688 account(2),689 CollectionId(1),690 TokenId(1),691 1692 )693 .map_err(|e| e.error),694 CommonError::<Test>::ApprovedValueTooLow695 );696697 // do approve698 assert_ok!(Unique::approve(699 origin1,700 account(2),701 CollectionId(1),702 TokenId(1),703 1704 ));705 assert_eq!(706 <pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).unwrap(),707 account(2)708 );709710 assert_ok!(Unique::transfer_from(711 origin2,712 account(1),713 account(3),714 CollectionId(1),715 TokenId(1),716 1717 ));718 assert!(719 <pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).is_none()720 );721 });722}723724#[test]725fn nft_approve_and_transfer_from_allow_list() {726 new_test_ext().execute_with(|| {727 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));728729 let origin1 = RuntimeOrigin::signed(1);730 let origin2 = RuntimeOrigin::signed(2);731732 // Create NFT 1 for account 1733 let data = default_nft_data();734 create_test_item(collection_id, &data.clone().into());735 assert_eq!(736 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),737 1738 );739 assert_eq!(740 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),741 true742 );743744 // Allow allow-list users to mint and add accounts 1, 2, and 3 to allow-list745 assert_ok!(Unique::set_collection_permissions(746 origin1.clone(),747 CollectionId(1),748 CollectionPermissions {749 mint_mode: Some(true),750 access: Some(AccessMode::AllowList),751 nesting: None,752 }753 ));754 assert_ok!(Unique::add_to_allow_list(755 origin1.clone(),756 CollectionId(1),757 account(1)758 ));759 assert_ok!(Unique::add_to_allow_list(760 origin1.clone(),761 CollectionId(1),762 account(2)763 ));764 assert_ok!(Unique::add_to_allow_list(765 origin1.clone(),766 CollectionId(1),767 account(3)768 ));769770 // Account 1 approves account 2 for NFT 1771 assert_ok!(Unique::approve(772 origin1.clone(),773 account(2),774 CollectionId(1),775 TokenId(1),776 1777 ));778 assert_eq!(779 <pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).unwrap(),780 account(2)781 );782783 // Account 2 transfers NFT 1 from account 1 to account 3784 assert_ok!(Unique::transfer_from(785 origin2,786 account(1),787 account(3),788 CollectionId(1),789 TokenId(1),790 1791 ));792 assert!(793 <pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).is_none()794 );795 });796}797798#[test]799fn refungible_approve_and_transfer_from() {800 new_test_ext().execute_with(|| {801 let collection_id = create_test_collection(&CollectionMode::ReFungible, CollectionId(1));802803 let origin1 = RuntimeOrigin::signed(1);804 let origin2 = RuntimeOrigin::signed(2);805806 // Create RFT 1 in 1023 pieces for account 1807 let data = default_re_fungible_data();808 create_test_item(collection_id, &data.into());809810 assert_eq!(811 <pallet_refungible::AccountBalance<Test>>::get((collection_id, account(1))),812 1813 );814 assert_eq!(815 <pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(1))),816 1023817 );818 assert_eq!(819 <pallet_refungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),820 true821 );822823 // Allow public minting, enable allow-list and add accounts 1, 2, 3 to allow-list824 assert_ok!(Unique::set_collection_permissions(825 origin1.clone(),826 CollectionId(1),827 CollectionPermissions {828 mint_mode: Some(true),829 access: Some(AccessMode::AllowList),830 nesting: None,831 }832 ));833 assert_ok!(Unique::add_to_allow_list(834 origin1.clone(),835 CollectionId(1),836 account(1)837 ));838 assert_ok!(Unique::add_to_allow_list(839 origin1.clone(),840 CollectionId(1),841 account(2)842 ));843 assert_ok!(Unique::add_to_allow_list(844 origin1.clone(),845 CollectionId(1),846 account(3)847 ));848849 // Account 1 approves account 2 for 1023 pieces of RFT 1850 assert_ok!(Unique::approve(851 origin1,852 account(2),853 CollectionId(1),854 TokenId(1),855 1023856 ));857 assert_eq!(858 <pallet_refungible::Allowance<Test>>::get((859 CollectionId(1),860 TokenId(1),861 account(1),862 account(2)863 )),864 1023865 );866867 // Account 2 transfers 100 pieces of RFT 1 from account 1 to account 3868 assert_ok!(Unique::transfer_from(869 origin2,870 account(1),871 account(3),872 CollectionId(1),873 TokenId(1),874 100875 ));876 assert_eq!(877 <pallet_refungible::AccountBalance<Test>>::get((collection_id, account(1))),878 1879 );880 assert_eq!(881 <pallet_refungible::AccountBalance<Test>>::get((collection_id, account(3))),882 1883 );884 assert_eq!(885 <pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(1))),886 923887 );888 assert_eq!(889 <pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(3))),890 100891 );892 assert_eq!(893 <pallet_refungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),894 true895 );896 assert_eq!(897 <pallet_refungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),898 true899 );900 assert_eq!(901 <pallet_refungible::Allowance<Test>>::get((902 CollectionId(1),903 TokenId(1),904 account(1),905 account(2)906 )),907 923908 );909 });910}911912#[test]913fn fungible_approve_and_transfer_from() {914 new_test_ext().execute_with(|| {915 let collection_id = create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));916917 let data = default_fungible_data();918 create_test_item(collection_id, &data.into());919920 let origin1 = RuntimeOrigin::signed(1);921 let origin2 = RuntimeOrigin::signed(2);922923 assert_ok!(Unique::set_collection_permissions(924 origin1.clone(),925 CollectionId(1),926 CollectionPermissions {927 mint_mode: Some(true),928 access: Some(AccessMode::AllowList),929 nesting: None,930 }931 ));932 assert_ok!(Unique::add_to_allow_list(933 origin1.clone(),934 CollectionId(1),935 account(1)936 ));937 assert_ok!(Unique::add_to_allow_list(938 origin1.clone(),939 CollectionId(1),940 account(2)941 ));942 assert_ok!(Unique::add_to_allow_list(943 origin1.clone(),944 CollectionId(1),945 account(3)946 ));947948 // do approve949 assert_ok!(Unique::approve(950 origin1.clone(),951 account(2),952 CollectionId(1),953 TokenId(0),954 5955 ));956 assert_eq!(957 <pallet_fungible::Allowance<Test>>::get((CollectionId(1), account(1), account(2))),958 5959 );960 assert_ok!(Unique::approve(961 origin1,962 account(3),963 CollectionId(1),964 TokenId(0),965 5966 ));967 assert_eq!(968 <pallet_fungible::Allowance<Test>>::get((CollectionId(1), account(1), account(2))),969 5970 );971 assert_eq!(972 <pallet_fungible::Allowance<Test>>::get((CollectionId(1), account(1), account(3))),973 5974 );975976 assert_ok!(Unique::transfer_from(977 origin2.clone(),978 account(1),979 account(3),980 CollectionId(1),981 TokenId(0),982 4983 ));984985 assert_eq!(986 <pallet_fungible::Allowance<Test>>::get((CollectionId(1), account(1), account(2))),987 1988 );989990 assert_noop!(991 Unique::transfer_from(992 origin2,993 account(1),994 account(3),995 CollectionId(1),996 TokenId(0),997 4998 )999 .map_err(|e| e.error),1000 CommonError::<Test>::ApprovedValueTooLow1001 );1002 });1003}10041005#[test]1006fn change_collection_owner() {1007 new_test_ext().execute_with(|| {1008 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));10091010 let origin1 = RuntimeOrigin::signed(1);1011 assert_ok!(Unique::change_collection_owner(origin1, collection_id, 2));1012 assert_eq!(1013 <pallet_common::CollectionById<Test>>::get(collection_id)1014 .unwrap()1015 .owner,1016 21017 );1018 });1019}10201021#[test]1022fn destroy_collection() {1023 new_test_ext().execute_with(|| {1024 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));10251026 let origin1 = RuntimeOrigin::signed(1);1027 assert_ok!(Unique::destroy_collection(origin1, collection_id));1028 });1029}10301031#[test]1032fn burn_nft_item() {1033 new_test_ext().execute_with(|| {1034 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));10351036 let origin1 = RuntimeOrigin::signed(1);10371038 let data = default_nft_data();1039 create_test_item(collection_id, &data.into());10401041 // check balance (collection with id = 1, user id = 1)1042 assert_eq!(1043 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),1044 11045 );10461047 // burn item1048 assert_ok!(Unique::burn_item(1049 origin1.clone(),1050 collection_id,1051 TokenId(1),1052 11053 ));1054 assert_eq!(1055 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),1056 01057 );1058 });1059}10601061#[test]1062fn burn_same_nft_item_twice() {1063 new_test_ext().execute_with(|| {1064 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));10651066 let origin1 = RuntimeOrigin::signed(1);10671068 let data = default_nft_data();1069 create_test_item(collection_id, &data.into());10701071 // check balance (collection with id = 1, user id = 1)1072 assert_eq!(1073 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),1074 11075 );10761077 // burn item1078 assert_ok!(Unique::burn_item(1079 origin1.clone(),1080 collection_id,1081 TokenId(1),1082 11083 ));10841085 // burn item again1086 assert_noop!(1087 Unique::burn_item(origin1, collection_id, TokenId(1), 1).map_err(|e| e.error),1088 CommonError::<Test>::TokenNotFound1089 );10901091 assert_eq!(1092 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),1093 01094 );1095 });1096}10971098#[test]1099fn burn_fungible_item() {1100 new_test_ext().execute_with(|| {1101 let collection_id = create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));11021103 let origin1 = RuntimeOrigin::signed(1);1104 assert_ok!(Unique::add_collection_admin(1105 origin1.clone(),1106 collection_id,1107 account(2)1108 ));11091110 let data = default_fungible_data();1111 create_test_item(collection_id, &data.into());11121113 // check balance (collection with id = 1, user id = 1)1114 assert_eq!(1115 <pallet_fungible::Balance<Test>>::get((collection_id, account(1))),1116 51117 );11181119 // burn item1120 assert_ok!(Unique::burn_item(1121 origin1.clone(),1122 CollectionId(1),1123 TokenId(0),1124 51125 ));1126 assert_noop!(1127 Unique::burn_item(origin1, CollectionId(1), TokenId(0), 5).map_err(|e| e.error),1128 CommonError::<Test>::TokenValueTooLow1129 );11301131 assert_eq!(1132 <pallet_fungible::Balance<Test>>::get((collection_id, account(1))),1133 01134 );1135 });1136}11371138#[test]1139fn burn_fungible_item_with_token_id() {1140 new_test_ext().execute_with(|| {1141 let collection_id = create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));11421143 let origin1 = RuntimeOrigin::signed(1);1144 assert_ok!(Unique::add_collection_admin(1145 origin1.clone(),1146 collection_id,1147 account(2)1148 ));11491150 let data = default_fungible_data();1151 create_test_item(collection_id, &data.into());11521153 // check balance (collection with id = 1, user id = 1)1154 assert_eq!(1155 <pallet_fungible::Balance<Test>>::get((collection_id, account(1))),1156 51157 );11581159 // Try to burn item using Token ID1160 assert_noop!(1161 Unique::burn_item(origin1, CollectionId(1), TokenId(1), 5).map_err(|e| e.error),1162 <pallet_fungible::Error::<Test>>::FungibleItemsHaveNoId1163 );1164 });1165}1166#[test]1167fn burn_refungible_item() {1168 new_test_ext().execute_with(|| {1169 let collection_id = create_test_collection(&CollectionMode::ReFungible, CollectionId(1));1170 let origin1 = RuntimeOrigin::signed(1);11711172 assert_ok!(Unique::set_collection_permissions(1173 origin1.clone(),1174 collection_id,1175 CollectionPermissions {1176 mint_mode: Some(true),1177 access: Some(AccessMode::AllowList),1178 nesting: None,1179 }1180 ));1181 assert_ok!(Unique::add_to_allow_list(1182 origin1.clone(),1183 collection_id,1184 account(1)1185 ));11861187 assert_ok!(Unique::add_collection_admin(1188 origin1.clone(),1189 collection_id,1190 account(2)1191 ));11921193 let data = default_re_fungible_data();1194 create_test_item(collection_id, &data.into());11951196 // check balance (collection with id = 1, user id = 2)1197 assert_eq!(1198 <pallet_refungible::AccountBalance<Test>>::get((collection_id, account(1))),1199 11200 );1201 assert_eq!(1202 <pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(1))),1203 10231204 );12051206 // burn item1207 assert_ok!(Unique::burn_item(1208 origin1.clone(),1209 collection_id,1210 TokenId(1),1211 10231212 ));1213 assert_noop!(1214 Unique::burn_item(origin1, collection_id, TokenId(1), 1023).map_err(|e| e.error),1215 CommonError::<Test>::TokenValueTooLow1216 );12171218 assert_eq!(1219 <pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(1))),1220 01221 );1222 });1223}12241225#[test]1226fn add_collection_admin() {1227 new_test_ext().execute_with(|| {1228 let collection1_id =1229 create_test_collection_for_owner(&CollectionMode::NFT, 1, CollectionId(1));1230 let origin1 = RuntimeOrigin::signed(1);12311232 // Add collection admins1233 assert_ok!(Unique::add_collection_admin(1234 origin1.clone(),1235 collection1_id,1236 account(2)1237 ));1238 assert_ok!(Unique::add_collection_admin(1239 origin1,1240 collection1_id,1241 account(3)1242 ));12431244 // Owner is not an admin by default1245 assert_eq!(1246 <pallet_common::IsAdmin<Test>>::get((CollectionId(1), account(1))),1247 false1248 );1249 assert!(<pallet_common::IsAdmin<Test>>::get((1250 CollectionId(1),1251 account(2)1252 )));1253 assert!(<pallet_common::IsAdmin<Test>>::get((1254 CollectionId(1),1255 account(3)1256 )));1257 });1258}12591260#[test]1261fn remove_collection_admin() {1262 new_test_ext().execute_with(|| {1263 let collection1_id =1264 create_test_collection_for_owner(&CollectionMode::NFT, 1, CollectionId(1));1265 let origin1 = RuntimeOrigin::signed(1);12661267 // Add collection admins 2 and 31268 assert_ok!(Unique::add_collection_admin(1269 origin1.clone(),1270 collection1_id,1271 account(2)1272 ));1273 assert_ok!(Unique::add_collection_admin(1274 origin1.clone(),1275 collection1_id,1276 account(3)1277 ));12781279 assert!(<pallet_common::IsAdmin<Test>>::get((1280 CollectionId(1),1281 account(2)1282 )));1283 assert!(<pallet_common::IsAdmin<Test>>::get((1284 CollectionId(1),1285 account(3)1286 )));12871288 // remove admin 31289 assert_ok!(Unique::remove_collection_admin(1290 origin1,1291 CollectionId(1),1292 account(3)1293 ));12941295 // 2 is still admin, 3 is not an admin anymore1296 assert!(<pallet_common::IsAdmin<Test>>::get((1297 CollectionId(1),1298 account(2)1299 )));1300 assert_eq!(1301 <pallet_common::IsAdmin<Test>>::get((CollectionId(1), account(3))),1302 false1303 );1304 });1305}13061307#[test]1308fn balance_of() {1309 new_test_ext().execute_with(|| {1310 let nft_collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1311 let fungible_collection_id =1312 create_test_collection(&CollectionMode::Fungible(3), CollectionId(2));1313 let re_fungible_collection_id =1314 create_test_collection(&CollectionMode::ReFungible, CollectionId(3));13151316 // check balance before1317 assert_eq!(1318 <pallet_nonfungible::AccountBalance<Test>>::get((nft_collection_id, account(1))),1319 01320 );1321 assert_eq!(1322 <pallet_fungible::Balance<Test>>::get((fungible_collection_id, account(1))),1323 01324 );1325 assert_eq!(1326 <pallet_refungible::AccountBalance<Test>>::get((re_fungible_collection_id, account(1))),1327 01328 );13291330 let nft_data = default_nft_data();1331 create_test_item(nft_collection_id, &nft_data.into());13321333 let fungible_data = default_fungible_data();1334 create_test_item(fungible_collection_id, &fungible_data.into());13351336 let re_fungible_data = default_re_fungible_data();1337 create_test_item(re_fungible_collection_id, &re_fungible_data.into());13381339 // check balance (collection with id = 1, user id = 1)1340 assert_eq!(1341 <pallet_nonfungible::AccountBalance<Test>>::get((nft_collection_id, account(1))),1342 11343 );1344 assert_eq!(1345 <pallet_fungible::Balance<Test>>::get((fungible_collection_id, account(1))),1346 51347 );1348 assert_eq!(1349 <pallet_refungible::AccountBalance<Test>>::get((re_fungible_collection_id, account(1))),1350 11351 );13521353 assert_eq!(1354 <pallet_nonfungible::Owned<Test>>::get((nft_collection_id, account(1), TokenId(1))),1355 true1356 );1357 assert_eq!(1358 <pallet_refungible::Owned<Test>>::get((1359 re_fungible_collection_id,1360 account(1),1361 TokenId(1)1362 )),1363 true1364 );1365 });1366}13671368#[test]1369fn approve() {1370 new_test_ext().execute_with(|| {1371 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));13721373 let data = default_nft_data();1374 create_test_item(collection_id, &data.into());13751376 let origin1 = RuntimeOrigin::signed(1);13771378 // approve1379 assert_ok!(Unique::approve(1380 origin1,1381 account(2),1382 CollectionId(1),1383 TokenId(1),1384 11385 ));1386 assert_eq!(1387 <pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).unwrap(),1388 account(2)1389 );1390 });1391}13921393#[test]1394fn transfer_from() {1395 new_test_ext().execute_with(|| {1396 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1397 let origin1 = RuntimeOrigin::signed(1);1398 let origin2 = RuntimeOrigin::signed(2);13991400 let data = default_nft_data();1401 create_test_item(collection_id, &data.into());14021403 // approve1404 assert_ok!(Unique::approve(1405 origin1.clone(),1406 account(2),1407 CollectionId(1),1408 TokenId(1),1409 11410 ));1411 assert_eq!(1412 <pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).unwrap(),1413 account(2)1414 );14151416 assert_ok!(Unique::set_collection_permissions(1417 origin1.clone(),1418 CollectionId(1),1419 CollectionPermissions {1420 mint_mode: Some(true),1421 access: Some(AccessMode::AllowList),1422 nesting: None,1423 }1424 ));1425 assert_ok!(Unique::add_to_allow_list(1426 origin1.clone(),1427 CollectionId(1),1428 account(1)1429 ));1430 assert_ok!(Unique::add_to_allow_list(1431 origin1.clone(),1432 CollectionId(1),1433 account(2)1434 ));1435 assert_ok!(Unique::add_to_allow_list(1436 origin1,1437 CollectionId(1),1438 account(3)1439 ));14401441 assert_ok!(Unique::transfer_from(1442 origin2,1443 account(1),1444 account(2),1445 CollectionId(1),1446 TokenId(1),1447 11448 ));14491450 // after transfer1451 assert_eq!(1452 <pallet_nonfungible::AccountBalance<Test>>::get((CollectionId(1), account(1))),1453 01454 );1455 assert_eq!(1456 <pallet_nonfungible::AccountBalance<Test>>::get((CollectionId(1), account(2))),1457 11458 );1459 });1460}14611462// #endregion14631464// Coverage tests region1465// #region14661467#[test]1468fn owner_can_add_address_to_allow_list() {1469 new_test_ext().execute_with(|| {1470 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));14711472 let origin1 = RuntimeOrigin::signed(1);1473 assert_ok!(Unique::add_to_allow_list(1474 origin1,1475 collection_id,1476 account(2)1477 ));1478 assert!(<pallet_common::Allowlist<Test>>::get((1479 collection_id,1480 account(2)1481 )));1482 });1483}14841485#[test]1486fn admin_can_add_address_to_allow_list() {1487 new_test_ext().execute_with(|| {1488 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1489 let origin1 = RuntimeOrigin::signed(1);1490 let origin2 = RuntimeOrigin::signed(2);14911492 assert_ok!(Unique::add_collection_admin(1493 origin1,1494 collection_id,1495 account(2)1496 ));1497 assert_ok!(Unique::add_to_allow_list(1498 origin2,1499 collection_id,1500 account(3)1501 ));1502 assert!(<pallet_common::Allowlist<Test>>::get((1503 collection_id,1504 account(3)1505 )));1506 });1507}15081509#[test]1510fn nonprivileged_user_cannot_add_address_to_allow_list() {1511 new_test_ext().execute_with(|| {1512 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));15131514 let origin2 = RuntimeOrigin::signed(2);1515 assert_noop!(1516 Unique::add_to_allow_list(origin2, collection_id, account(3)),1517 CommonError::<Test>::NoPermission1518 );1519 });1520}15211522#[test]1523fn nobody_can_add_address_to_allow_list_of_nonexisting_collection() {1524 new_test_ext().execute_with(|| {1525 let origin1 = RuntimeOrigin::signed(1);15261527 assert_noop!(1528 Unique::add_to_allow_list(origin1, CollectionId(1), account(2)),1529 CommonError::<Test>::CollectionNotFound1530 );1531 });1532}15331534#[test]1535fn nobody_can_add_address_to_allow_list_of_deleted_collection() {1536 new_test_ext().execute_with(|| {1537 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));15381539 let origin1 = RuntimeOrigin::signed(1);1540 assert_ok!(Unique::destroy_collection(origin1.clone(), collection_id));1541 assert_noop!(1542 Unique::add_to_allow_list(origin1, collection_id, account(2)),1543 CommonError::<Test>::CollectionNotFound1544 );1545 });1546}15471548// If address is already added to allow list, nothing happens1549#[test]1550fn address_is_already_added_to_allow_list() {1551 new_test_ext().execute_with(|| {1552 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1553 let origin1 = RuntimeOrigin::signed(1);15541555 assert_ok!(Unique::add_to_allow_list(1556 origin1.clone(),1557 collection_id,1558 account(2)1559 ));1560 assert_ok!(Unique::add_to_allow_list(1561 origin1,1562 collection_id,1563 account(2)1564 ));1565 assert!(<pallet_common::Allowlist<Test>>::get((1566 collection_id,1567 account(2)1568 )));1569 });1570}15711572#[test]1573fn owner_can_remove_address_from_allow_list() {1574 new_test_ext().execute_with(|| {1575 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));15761577 let origin1 = RuntimeOrigin::signed(1);1578 assert_ok!(Unique::add_to_allow_list(1579 origin1.clone(),1580 collection_id,1581 account(2)1582 ));1583 assert_ok!(Unique::remove_from_allow_list(1584 origin1,1585 collection_id,1586 account(2)1587 ));1588 assert_eq!(1589 <pallet_common::Allowlist<Test>>::get((collection_id, account(2))),1590 false1591 );1592 });1593}15941595#[test]1596fn admin_can_remove_address_from_allow_list() {1597 new_test_ext().execute_with(|| {1598 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1599 let origin1 = RuntimeOrigin::signed(1);1600 let origin2 = RuntimeOrigin::signed(2);16011602 // Owner adds admin1603 assert_ok!(Unique::add_collection_admin(1604 origin1.clone(),1605 collection_id,1606 account(2)1607 ));16081609 // Owner adds address 3 to allow list1610 assert_ok!(Unique::add_to_allow_list(1611 origin1,1612 collection_id,1613 account(3)1614 ));16151616 // Admin removes address 3 from allow list1617 assert_ok!(Unique::remove_from_allow_list(1618 origin2,1619 collection_id,1620 account(3)1621 ));1622 assert_eq!(1623 <pallet_common::Allowlist<Test>>::get((collection_id, account(3))),1624 false1625 );1626 });1627}16281629#[test]1630fn nonprivileged_user_cannot_remove_address_from_allow_list() {1631 new_test_ext().execute_with(|| {1632 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1633 let origin1 = RuntimeOrigin::signed(1);1634 let origin2 = RuntimeOrigin::signed(2);16351636 assert_ok!(Unique::add_to_allow_list(1637 origin1,1638 collection_id,1639 account(2)1640 ));1641 assert_noop!(1642 Unique::remove_from_allow_list(origin2, collection_id, account(2)),1643 CommonError::<Test>::NoPermission1644 );1645 assert!(<pallet_common::Allowlist<Test>>::get((1646 collection_id,1647 account(2)1648 )));1649 });1650}16511652#[test]1653fn nobody_can_remove_address_from_allow_list_of_nonexisting_collection() {1654 new_test_ext().execute_with(|| {1655 let origin1 = RuntimeOrigin::signed(1);16561657 assert_noop!(1658 Unique::remove_from_allow_list(origin1, CollectionId(1), account(2)),1659 CommonError::<Test>::CollectionNotFound1660 );1661 });1662}16631664#[test]1665fn nobody_can_remove_address_from_allow_list_of_deleted_collection() {1666 new_test_ext().execute_with(|| {1667 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1668 let origin1 = RuntimeOrigin::signed(1);1669 let origin2 = RuntimeOrigin::signed(2);16701671 // Add account 2 to allow list1672 assert_ok!(Unique::add_to_allow_list(1673 origin1.clone(),1674 collection_id,1675 account(2)1676 ));16771678 // Account 2 is in collection allow-list1679 assert!(<pallet_common::Allowlist<Test>>::get((1680 collection_id,1681 account(2)1682 )));16831684 // Destroy collection1685 assert_ok!(Unique::destroy_collection(origin1, collection_id));16861687 // Attempt to remove account 2 from collection allow-list => error1688 assert_noop!(1689 Unique::remove_from_allow_list(origin2, collection_id, account(2)),1690 CommonError::<Test>::CollectionNotFound1691 );16921693 // Account 2 is not found in collection allow-list anyway1694 assert_eq!(1695 <pallet_common::Allowlist<Test>>::get((collection_id, account(2))),1696 false1697 );1698 });1699}17001701// If address is already removed from allow list, nothing happens1702#[test]1703fn address_is_already_removed_from_allow_list() {1704 new_test_ext().execute_with(|| {1705 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1706 let origin1 = RuntimeOrigin::signed(1);17071708 assert_ok!(Unique::add_to_allow_list(1709 origin1.clone(),1710 collection_id,1711 account(2)1712 ));1713 assert_ok!(Unique::remove_from_allow_list(1714 origin1.clone(),1715 collection_id,1716 account(2)1717 ));1718 assert_eq!(1719 <pallet_common::Allowlist<Test>>::get((collection_id, account(2))),1720 false1721 );1722 assert_ok!(Unique::remove_from_allow_list(1723 origin1,1724 collection_id,1725 account(2)1726 ));1727 assert_eq!(1728 <pallet_common::Allowlist<Test>>::get((collection_id, account(2))),1729 false1730 );1731 });1732}17331734// If Public Access mode is set to AllowList, tokens can’t be transferred from a non-allowlisted address with transfer or transferFrom (2 tests)1735#[test]1736fn allow_list_test_1() {1737 new_test_ext().execute_with(|| {1738 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));17391740 let origin1 = RuntimeOrigin::signed(1);17411742 let data = default_nft_data();1743 create_test_item(collection_id, &data.into());17441745 assert_ok!(Unique::set_collection_permissions(1746 origin1.clone(),1747 collection_id,1748 CollectionPermissions {1749 mint_mode: None,1750 access: Some(AccessMode::AllowList),1751 nesting: None,1752 }1753 ));1754 assert_ok!(Unique::add_to_allow_list(1755 origin1.clone(),1756 collection_id,1757 account(2)1758 ));17591760 assert_noop!(1761 Unique::transfer(origin1, account(3), CollectionId(1), TokenId(1), 1)1762 .map_err(|e| e.error),1763 CommonError::<Test>::AddressNotInAllowlist1764 );1765 });1766}17671768#[test]1769fn allow_list_test_2() {1770 new_test_ext().execute_with(|| {1771 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1772 let origin1 = RuntimeOrigin::signed(1);17731774 let data = default_nft_data();1775 create_test_item(collection_id, &data.into());17761777 assert_ok!(Unique::set_collection_permissions(1778 origin1.clone(),1779 collection_id,1780 CollectionPermissions {1781 mint_mode: None,1782 access: Some(AccessMode::AllowList),1783 nesting: None,1784 }1785 ));1786 assert_ok!(Unique::add_to_allow_list(1787 origin1.clone(),1788 collection_id,1789 account(1)1790 ));1791 assert_ok!(Unique::add_to_allow_list(1792 origin1.clone(),1793 collection_id,1794 account(2)1795 ));17961797 // do approve1798 assert_ok!(Unique::approve(1799 origin1.clone(),1800 account(1),1801 collection_id,1802 TokenId(1),1803 11804 ));1805 assert_eq!(1806 <pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).unwrap(),1807 account(1)1808 );18091810 assert_ok!(Unique::remove_from_allow_list(1811 origin1.clone(),1812 collection_id,1813 account(1)1814 ));18151816 assert_noop!(1817 Unique::transfer_from(1818 origin1,1819 account(1),1820 account(3),1821 CollectionId(1),1822 TokenId(1),1823 11824 )1825 .map_err(|e| e.error),1826 CommonError::<Test>::AddressNotInAllowlist1827 );1828 });1829}18301831// If Public Access mode is set to AllowList, tokens can’t be transferred to a non-allowlisted address with transfer or transferFrom (2 tests)1832#[test]1833fn allow_list_test_3() {1834 new_test_ext().execute_with(|| {1835 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));18361837 let origin1 = RuntimeOrigin::signed(1);18381839 let data = default_nft_data();1840 create_test_item(collection_id, &data.into());18411842 assert_ok!(Unique::set_collection_permissions(1843 origin1.clone(),1844 collection_id,1845 CollectionPermissions {1846 mint_mode: None,1847 access: Some(AccessMode::AllowList),1848 nesting: None,1849 }1850 ));1851 assert_ok!(Unique::add_to_allow_list(1852 origin1.clone(),1853 collection_id,1854 account(1)1855 ));18561857 assert_noop!(1858 Unique::transfer(origin1, account(3), collection_id, TokenId(1), 1)1859 .map_err(|e| e.error),1860 CommonError::<Test>::AddressNotInAllowlist1861 );1862 });1863}18641865#[test]1866fn allow_list_test_4() {1867 new_test_ext().execute_with(|| {1868 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));18691870 let origin1 = RuntimeOrigin::signed(1);18711872 let data = default_nft_data();1873 create_test_item(collection_id, &data.into());18741875 assert_ok!(Unique::set_collection_permissions(1876 origin1.clone(),1877 collection_id,1878 CollectionPermissions {1879 mint_mode: None,1880 access: Some(AccessMode::AllowList),1881 nesting: None,1882 }1883 ));1884 assert_ok!(Unique::add_to_allow_list(1885 origin1.clone(),1886 collection_id,1887 account(1)1888 ));1889 assert_ok!(Unique::add_to_allow_list(1890 origin1.clone(),1891 collection_id,1892 account(2)1893 ));18941895 // do approve1896 assert_ok!(Unique::approve(1897 origin1.clone(),1898 account(1),1899 collection_id,1900 TokenId(1),1901 11902 ));1903 assert_eq!(1904 <pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).unwrap(),1905 account(1)1906 );19071908 assert_ok!(Unique::remove_from_allow_list(1909 origin1.clone(),1910 collection_id,1911 account(2)1912 ));19131914 assert_noop!(1915 Unique::transfer_from(1916 origin1,1917 account(1),1918 account(3),1919 collection_id,1920 TokenId(1),1921 11922 )1923 .map_err(|e| e.error),1924 CommonError::<Test>::AddressNotInAllowlist1925 );1926 });1927}19281929// If Public Access mode is set to AllowList, tokens can’t be destroyed by a non-allowlisted address (even if it owned them before enabling AllowList mode)1930#[test]1931fn allow_list_test_5() {1932 new_test_ext().execute_with(|| {1933 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));19341935 let origin1 = RuntimeOrigin::signed(1);19361937 let data = default_nft_data();1938 create_test_item(collection_id, &data.into());19391940 assert_ok!(Unique::set_collection_permissions(1941 origin1.clone(),1942 collection_id,1943 CollectionPermissions {1944 mint_mode: None,1945 access: Some(AccessMode::AllowList),1946 nesting: None,1947 }1948 ));1949 assert_noop!(1950 Unique::burn_item(origin1.clone(), CollectionId(1), TokenId(1), 1).map_err(|e| e.error),1951 CommonError::<Test>::AddressNotInAllowlist1952 );1953 });1954}19551956// If Public Access mode is set to AllowList, token transfers can’t be Approved by a non-allowlisted address (see Approve method).1957#[test]1958fn allow_list_test_6() {1959 new_test_ext().execute_with(|| {1960 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));19611962 let origin1 = RuntimeOrigin::signed(1);19631964 let data = default_nft_data();1965 create_test_item(collection_id, &data.into());19661967 assert_ok!(Unique::set_collection_permissions(1968 origin1.clone(),1969 collection_id,1970 CollectionPermissions {1971 mint_mode: None,1972 access: Some(AccessMode::AllowList),1973 nesting: None,1974 }1975 ));19761977 // do approve1978 assert_noop!(1979 Unique::approve(origin1, account(1), CollectionId(1), TokenId(1), 1)1980 .map_err(|e| e.error),1981 CommonError::<Test>::AddressNotInAllowlist1982 );1983 });1984}19851986// If Public Access mode is set to AllowList, tokens can be transferred from a allowlisted address with transfer or transferFrom (2 tests) and1987// tokens can be transferred from a allowlisted address with transfer or transferFrom (2 tests)1988#[test]1989fn allow_list_test_7() {1990 new_test_ext().execute_with(|| {1991 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));19921993 let data = default_nft_data();1994 create_test_item(collection_id, &data.into());19951996 let origin1 = RuntimeOrigin::signed(1);19971998 assert_ok!(Unique::set_collection_permissions(1999 origin1.clone(),2000 collection_id,2001 CollectionPermissions {2002 mint_mode: None,2003 access: Some(AccessMode::AllowList),2004 nesting: None,2005 }2006 ));2007 assert_ok!(Unique::add_to_allow_list(2008 origin1.clone(),2009 collection_id,2010 account(1)2011 ));2012 assert_ok!(Unique::add_to_allow_list(2013 origin1.clone(),2014 collection_id,2015 account(2)2016 ));20172018 assert_ok!(Unique::transfer(2019 origin1,2020 account(2),2021 CollectionId(1),2022 TokenId(1),2023 12024 ));2025 });2026}20272028#[test]2029fn allow_list_test_8() {2030 new_test_ext().execute_with(|| {2031 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));20322033 // Create NFT for account 12034 let data = default_nft_data();2035 create_test_item(collection_id, &data.into());20362037 let origin1 = RuntimeOrigin::signed(1);20382039 // Toggle Allow List mode and add accounts 1 and 22040 assert_ok!(Unique::set_collection_permissions(2041 origin1.clone(),2042 collection_id,2043 CollectionPermissions {2044 mint_mode: None,2045 access: Some(AccessMode::AllowList),2046 nesting: None,2047 }2048 ));2049 assert_ok!(Unique::add_to_allow_list(2050 origin1.clone(),2051 collection_id,2052 account(1)2053 ));2054 assert_ok!(Unique::add_to_allow_list(2055 origin1.clone(),2056 collection_id,2057 account(2)2058 ));20592060 // Sself-approve account 1 for NFT 12061 assert_ok!(Unique::approve(2062 origin1.clone(),2063 account(1),2064 CollectionId(1),2065 TokenId(1),2066 12067 ));2068 assert_eq!(2069 <pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).unwrap(),2070 account(1)2071 );20722073 // Transfer from 1 to 22074 assert_ok!(Unique::transfer_from(2075 origin1,2076 account(1),2077 account(2),2078 CollectionId(1),2079 TokenId(1),2080 12081 ));2082 });2083}20842085// If Public Access mode is set to AllowList, and Mint Permission is set to false, tokens can be created by owner.2086#[test]2087fn allow_list_test_9() {2088 new_test_ext().execute_with(|| {2089 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));2090 let origin1 = RuntimeOrigin::signed(1);20912092 assert_ok!(Unique::set_collection_permissions(2093 origin1.clone(),2094 collection_id,2095 CollectionPermissions {2096 mint_mode: Some(false),2097 access: Some(AccessMode::AllowList),2098 nesting: None,2099 }2100 ));21012102 let data = default_nft_data();2103 create_test_item(collection_id, &data.into());2104 });2105}21062107// If Public Access mode is set to AllowList, and Mint Permission is set to false, tokens can be created by admin.2108#[test]2109fn allow_list_test_10() {2110 new_test_ext().execute_with(|| {2111 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));21122113 let origin1 = RuntimeOrigin::signed(1);2114 let origin2 = RuntimeOrigin::signed(2);21152116 assert_ok!(Unique::set_collection_permissions(2117 origin1.clone(),2118 collection_id,2119 CollectionPermissions {2120 mint_mode: Some(false),2121 access: Some(AccessMode::AllowList),2122 nesting: None,2123 }2124 ));21252126 assert_ok!(Unique::add_collection_admin(2127 origin1,2128 collection_id,2129 account(2)2130 ));21312132 assert_ok!(Unique::create_item(2133 origin2,2134 collection_id,2135 account(2),2136 default_nft_data().into()2137 ));2138 });2139}21402141// If Public Access mode is set to AllowList, and Mint Permission is set to false, tokens cannot be created by non-privileged and allow listed address.2142#[test]2143fn allow_list_test_11() {2144 new_test_ext().execute_with(|| {2145 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));21462147 let origin1 = RuntimeOrigin::signed(1);2148 let origin2 = RuntimeOrigin::signed(2);21492150 assert_ok!(Unique::set_collection_permissions(2151 origin1.clone(),2152 collection_id,2153 CollectionPermissions {2154 mint_mode: Some(false),2155 access: Some(AccessMode::AllowList),2156 nesting: None,2157 }2158 ));2159 assert_ok!(Unique::add_to_allow_list(2160 origin1,2161 collection_id,2162 account(2)2163 ));21642165 assert_noop!(2166 Unique::create_item(2167 origin2,2168 CollectionId(1),2169 account(2),2170 default_nft_data().into()2171 )2172 .map_err(|e| e.error),2173 CommonError::<Test>::PublicMintingNotAllowed2174 );2175 });2176}21772178// If Public Access mode is set to AllowList, and Mint Permission is set to false, tokens cannot be created by non-privileged and non-allow listed address.2179#[test]2180fn allow_list_test_12() {2181 new_test_ext().execute_with(|| {2182 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));21832184 let origin1 = RuntimeOrigin::signed(1);2185 let origin2 = RuntimeOrigin::signed(2);21862187 assert_ok!(Unique::set_collection_permissions(2188 origin1.clone(),2189 collection_id,2190 CollectionPermissions {2191 mint_mode: Some(false),2192 access: Some(AccessMode::AllowList),2193 nesting: None,2194 }2195 ));21962197 assert_noop!(2198 Unique::create_item(2199 origin2,2200 CollectionId(1),2201 account(2),2202 default_nft_data().into()2203 )2204 .map_err(|e| e.error),2205 CommonError::<Test>::PublicMintingNotAllowed2206 );2207 });2208}22092210// If Public Access mode is set to AllowList, and Mint Permission is set to true, tokens can be created by owner.2211#[test]2212fn allow_list_test_13() {2213 new_test_ext().execute_with(|| {2214 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));22152216 let origin1 = RuntimeOrigin::signed(1);22172218 assert_ok!(Unique::set_collection_permissions(2219 origin1.clone(),2220 collection_id,2221 CollectionPermissions {2222 mint_mode: Some(true),2223 access: Some(AccessMode::AllowList),2224 nesting: None,2225 }2226 ));22272228 let data = default_nft_data();2229 create_test_item(collection_id, &data.into());2230 });2231}22322233// If Public Access mode is set to AllowList, and Mint Permission is set to true, tokens can be created by admin.2234#[test]2235fn allow_list_test_14() {2236 new_test_ext().execute_with(|| {2237 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));22382239 let origin1 = RuntimeOrigin::signed(1);2240 let origin2 = RuntimeOrigin::signed(2);22412242 assert_ok!(Unique::set_collection_permissions(2243 origin1.clone(),2244 collection_id,2245 CollectionPermissions {2246 mint_mode: Some(true),2247 access: Some(AccessMode::AllowList),2248 nesting: None,2249 }2250 ));22512252 assert_ok!(Unique::add_collection_admin(2253 origin1,2254 collection_id,2255 account(2)2256 ));22572258 assert_ok!(Unique::create_item(2259 origin2,2260 collection_id,2261 account(2),2262 default_nft_data().into()2263 ));2264 });2265}22662267// If Public Access mode is set to AllowList, and Mint Permission is set to true, tokens cannot be created by non-privileged and non-allow listed address.2268#[test]2269fn allow_list_test_15() {2270 new_test_ext().execute_with(|| {2271 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));22722273 let origin1 = RuntimeOrigin::signed(1);2274 let origin2 = RuntimeOrigin::signed(2);22752276 assert_ok!(Unique::set_collection_permissions(2277 origin1.clone(),2278 collection_id,2279 CollectionPermissions {2280 mint_mode: Some(true),2281 access: Some(AccessMode::AllowList),2282 nesting: None,2283 }2284 ));22852286 assert_noop!(2287 Unique::create_item(2288 origin2,2289 collection_id,2290 account(2),2291 default_nft_data().into()2292 )2293 .map_err(|e| e.error),2294 CommonError::<Test>::AddressNotInAllowlist2295 );2296 });2297}22982299// If Public Access mode is set to AllowList, and Mint Permission is set to true, tokens can be created by non-privileged and allow listed address.2300#[test]2301fn allow_list_test_16() {2302 new_test_ext().execute_with(|| {2303 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));23042305 let origin1 = RuntimeOrigin::signed(1);2306 let origin2 = RuntimeOrigin::signed(2);23072308 assert_ok!(Unique::set_collection_permissions(2309 origin1.clone(),2310 collection_id,2311 CollectionPermissions {2312 mint_mode: Some(true),2313 access: Some(AccessMode::AllowList),2314 nesting: None,2315 }2316 ));2317 assert_ok!(Unique::add_to_allow_list(2318 origin1,2319 collection_id,2320 account(2)2321 ));23222323 assert_ok!(Unique::create_item(2324 origin2,2325 collection_id,2326 account(2),2327 default_nft_data().into()2328 ));2329 });2330}23312332// Total number of collections. Positive test2333#[test]2334fn total_number_collections_bound() {2335 new_test_ext().execute_with(|| {2336 create_test_collection(&CollectionMode::NFT, CollectionId(1));2337 });2338}23392340#[test]2341fn create_max_collections() {2342 new_test_ext().execute_with(|| {2343 for i in 1..COLLECTION_NUMBER_LIMIT {2344 create_test_collection(&CollectionMode::NFT, CollectionId(i));2345 }2346 });2347}23482349// Total number of collections. Negative test2350#[test]2351fn total_number_collections_bound_neg() {2352 new_test_ext().execute_with(|| {2353 let origin1 = RuntimeOrigin::signed(1);23542355 for i in 1..=COLLECTION_NUMBER_LIMIT {2356 create_test_collection(&CollectionMode::NFT, CollectionId(i));2357 }23582359 let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();2360 let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();2361 let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();23622363 let data: CreateCollectionData<u64> = CreateCollectionData {2364 name: col_name1.try_into().unwrap(),2365 description: col_desc1.try_into().unwrap(),2366 token_prefix: token_prefix1.try_into().unwrap(),2367 mode: CollectionMode::NFT,2368 ..Default::default()2369 };23702371 // 11-th collection in chain. Expects error2372 assert_noop!(2373 Unique::create_collection_ex(origin1, data),2374 CommonError::<Test>::TotalCollectionsLimitExceeded2375 );2376 });2377}23782379// Owned tokens by a single address. Positive test2380#[test]2381fn owned_tokens_bound() {2382 new_test_ext().execute_with(|| {2383 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));23842385 let data = default_nft_data();2386 create_test_item(collection_id, &data.clone().into());2387 create_test_item(collection_id, &data.into());2388 });2389}23902391// Owned tokens by a single address. Negotive test2392#[test]2393fn owned_tokens_bound_neg() {2394 new_test_ext().execute_with(|| {2395 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));23962397 let origin1 = RuntimeOrigin::signed(1);23982399 for _ in 1..=MAX_TOKEN_OWNERSHIP {2400 let data = default_nft_data();2401 create_test_item(collection_id, &data.clone().into());2402 }24032404 let data = default_nft_data();2405 assert_noop!(2406 Unique::create_item(origin1, CollectionId(1), account(1), data.into())2407 .map_err(|e| e.error),2408 CommonError::<Test>::AccountTokenLimitExceeded2409 );2410 });2411}24122413// Number of collection admins. Positive test2414#[test]2415fn collection_admins_bound() {2416 new_test_ext().execute_with(|| {2417 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));24182419 let origin1 = RuntimeOrigin::signed(1);24202421 assert_ok!(Unique::add_collection_admin(2422 origin1.clone(),2423 collection_id,2424 account(2)2425 ));2426 assert_ok!(Unique::add_collection_admin(2427 origin1,2428 collection_id,2429 account(3)2430 ));2431 });2432}24332434// Number of collection admins. Negotive test2435#[test]2436fn collection_admins_bound_neg() {2437 new_test_ext().execute_with(|| {2438 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));24392440 let origin1 = RuntimeOrigin::signed(1);24412442 for i in 0..COLLECTION_ADMINS_LIMIT {2443 assert_ok!(Unique::add_collection_admin(2444 origin1.clone(),2445 collection_id,2446 account((2 + i).into())2447 ));2448 }2449 assert_noop!(2450 Unique::add_collection_admin(2451 origin1,2452 collection_id,2453 account((3 + COLLECTION_ADMINS_LIMIT).into())2454 ),2455 CommonError::<Test>::CollectionAdminCountExceeded2456 );2457 });2458}2459// #endregion24602461#[test]2462fn collection_transfer_flag_works() {2463 new_test_ext().execute_with(|| {2464 let origin1 = RuntimeOrigin::signed(1);24652466 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));2467 assert_ok!(Unique::set_transfers_enabled_flag(2468 origin1,2469 collection_id,2470 true2471 ));24722473 let data = default_nft_data();2474 create_test_item(collection_id, &data.into());2475 assert_eq!(2476 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),2477 12478 );2479 assert_eq!(2480 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),2481 true2482 );24832484 let origin1 = RuntimeOrigin::signed(1);24852486 // default scenario2487 assert_ok!(Unique::transfer(2488 origin1,2489 account(2),2490 collection_id,2491 TokenId(1),2492 12493 ));2494 assert_eq!(2495 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),2496 false2497 );2498 assert_eq!(2499 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(2), TokenId(1))),2500 true2501 );2502 assert_eq!(2503 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),2504 02505 );2506 assert_eq!(2507 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(2))),2508 12509 );2510 });2511}25122513#[test]2514fn collection_transfer_flag_works_neg() {2515 new_test_ext().execute_with(|| {2516 let origin1 = RuntimeOrigin::signed(1);25172518 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));2519 assert_ok!(Unique::set_transfers_enabled_flag(2520 origin1,2521 collection_id,2522 false2523 ));25242525 let data = default_nft_data();2526 create_test_item(collection_id, &data.into());2527 assert_eq!(2528 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),2529 12530 );2531 assert_eq!(2532 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),2533 true2534 );25352536 let origin1 = RuntimeOrigin::signed(1);25372538 // default scenario2539 assert_noop!(2540 Unique::transfer(origin1, account(2), CollectionId(1), TokenId(1), 1)2541 .map_err(|e| e.error),2542 CommonError::<Test>::TransferNotAllowed2543 );2544 assert_eq!(2545 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),2546 12547 );2548 assert_eq!(2549 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(2))),2550 02551 );2552 assert_eq!(2553 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),2554 true2555 );2556 assert_eq!(2557 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(2), TokenId(1))),2558 false2559 );2560 });2561}25622563#[test]2564fn collection_sponsoring() {2565 new_test_ext().execute_with(|| {2566 // default_limits();2567 let user1 = 1_u64;2568 let user2 = 777_u64;2569 let origin1 = RuntimeOrigin::signed(user1);2570 let origin2 = RuntimeOrigin::signed(user2);2571 let account2 = account(user2);25722573 let collection_id =2574 create_test_collection_for_owner(&CollectionMode::NFT, user1, CollectionId(1));2575 assert_ok!(Unique::set_collection_sponsor(2576 origin1.clone(),2577 collection_id,2578 user12579 ));2580 assert_ok!(Unique::confirm_sponsorship(origin1.clone(), collection_id));25812582 // Expect error while have no permissions2583 assert!(Unique::create_item(2584 origin2.clone(),2585 collection_id,2586 account2.clone(),2587 default_nft_data().into()2588 )2589 .is_err());25902591 assert_ok!(Unique::set_collection_permissions(2592 origin1.clone(),2593 collection_id,2594 CollectionPermissions {2595 mint_mode: Some(true),2596 access: Some(AccessMode::AllowList),2597 nesting: None,2598 }2599 ));2600 assert_ok!(Unique::add_to_allow_list(2601 origin1.clone(),2602 collection_id,2603 account2.clone()2604 ));26052606 assert_ok!(Unique::create_item(2607 origin2,2608 collection_id,2609 account2,2610 default_nft_data().into()2611 ));2612 });2613}1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617// Tests to be written here18use crate::{Test, TestCrossAccountId, CollectionCreationPrice, RuntimeOrigin, Unique, new_test_ext};19use up_data_structs::{20 COLLECTION_NUMBER_LIMIT, CollectionId, CreateItemData, CreateFungibleData, CreateNftData,21 CreateReFungibleData, MAX_DECIMAL_POINTS, COLLECTION_ADMINS_LIMIT, TokenId,22 MAX_TOKEN_OWNERSHIP, CreateCollectionData, CollectionMode, AccessMode, CollectionPermissions,23 PropertyKeyPermission, PropertyPermission, Property, CollectionPropertiesVec,24 CollectionPropertiesPermissionsVec,25};26use frame_support::{assert_noop, assert_ok, assert_err};27use sp_std::convert::TryInto;28use pallet_evm::account::CrossAccountId;29use pallet_common::Error as CommonError;30use pallet_unique::Error as UniqueError;3132fn add_balance(user: u64, value: u64) {33 const DONOR_USER: u64 = 999;34 assert_ok!(<pallet_balances::Pallet<Test>>::set_balance(35 RuntimeOrigin::root(),36 DONOR_USER,37 value,38 039 ));40 assert_ok!(<pallet_balances::Pallet<Test>>::force_transfer(41 RuntimeOrigin::root(),42 DONOR_USER,43 user,44 value45 ));46}4748fn default_nft_data() -> CreateNftData {49 CreateNftData {50 properties: vec![Property {51 key: b"test-prop".to_vec().try_into().unwrap(),52 value: b"test-nft-prop".to_vec().try_into().unwrap(),53 }]54 .try_into()55 .unwrap(),56 }57}5859fn default_fungible_data() -> CreateFungibleData {60 CreateFungibleData { value: 5 }61}6263fn default_re_fungible_data() -> CreateReFungibleData {64 CreateReFungibleData {65 pieces: 1023,66 properties: vec![Property {67 key: b"test-prop".to_vec().try_into().unwrap(),68 value: b"test-nft-prop".to_vec().try_into().unwrap(),69 }]70 .try_into()71 .unwrap(),72 }73}7475fn create_test_collection_for_owner(76 mode: &CollectionMode,77 owner: u64,78 id: CollectionId,79) -> CollectionId {80 add_balance(owner, CollectionCreationPrice::get() as u64 + 1);8182 let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();83 let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();84 let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();85 let token_property_permissions: CollectionPropertiesPermissionsVec =86 vec![PropertyKeyPermission {87 key: b"test-prop".to_vec().try_into().unwrap(),88 permission: PropertyPermission {89 mutable: true,90 collection_admin: false,91 token_owner: true,92 },93 }]94 .try_into()95 .unwrap();96 let properties: CollectionPropertiesVec = vec![Property {97 key: b"test-collection-prop".to_vec().try_into().unwrap(),98 value: b"test-collection-value".to_vec().try_into().unwrap(),99 }]100 .try_into()101 .unwrap();102103 let data: CreateCollectionData<u64> = CreateCollectionData {104 name: col_name1.try_into().unwrap(),105 description: col_desc1.try_into().unwrap(),106 token_prefix: token_prefix1.try_into().unwrap(),107 mode: mode.clone(),108 token_property_permissions: token_property_permissions.clone(),109 properties: properties.clone(),110 ..Default::default()111 };112113 let origin1 = RuntimeOrigin::signed(owner);114 assert_ok!(Unique::create_collection_ex(origin1, data));115116 let saved_col_name: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();117 let saved_description: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();118 let saved_prefix: Vec<u8> = b"token_prefix1\0".to_vec();119 assert_eq!(120 <pallet_common::CollectionById<Test>>::get(id)121 .unwrap()122 .owner,123 owner124 );125 assert_eq!(126 <pallet_common::CollectionById<Test>>::get(id).unwrap().name,127 saved_col_name128 );129 assert_eq!(130 <pallet_common::CollectionById<Test>>::get(id).unwrap().mode,131 *mode132 );133 assert_eq!(134 <pallet_common::CollectionById<Test>>::get(id)135 .unwrap()136 .description,137 saved_description138 );139 assert_eq!(140 <pallet_common::CollectionById<Test>>::get(id)141 .unwrap()142 .token_prefix,143 saved_prefix144 );145 assert_eq!(146 get_collection_property_permissions(id).as_slice(),147 token_property_permissions.as_slice()148 );149 assert_eq!(150 get_collection_properties(id).as_slice(),151 properties.as_slice()152 );153 id154}155156fn get_collection_property_permissions(collection_id: CollectionId) -> Vec<PropertyKeyPermission> {157 <pallet_common::Pallet<Test>>::property_permissions(collection_id)158 .into_iter()159 .map(|(key, permission)| PropertyKeyPermission { key, permission })160 .collect()161}162163fn get_collection_properties(collection_id: CollectionId) -> Vec<Property> {164 <pallet_common::Pallet<Test>>::collection_properties(collection_id)165 .into_iter()166 .map(|(key, value)| Property { key, value })167 .collect()168}169170fn get_token_properties(collection_id: CollectionId, token_id: TokenId) -> Vec<Property> {171 <pallet_nonfungible::Pallet<Test>>::token_properties((collection_id, token_id))172 .into_iter()173 .map(|(key, value)| Property { key, value })174 .collect()175}176177fn create_test_collection(mode: &CollectionMode, id: CollectionId) -> CollectionId {178 create_test_collection_for_owner(&mode, 1, id)179}180181fn create_test_item(collection_id: CollectionId, data: &CreateItemData) {182 let origin1 = RuntimeOrigin::signed(1);183 assert_ok!(Unique::create_item(184 origin1,185 collection_id,186 account(1),187 data.clone()188 ));189}190191fn account(sub: u64) -> TestCrossAccountId {192 TestCrossAccountId::from_sub(sub)193}194195// Use cases tests region196// #region197198#[test]199fn check_not_sufficient_founds() {200 new_test_ext().execute_with(|| {201 let acc: u64 = 1;202 <pallet_balances::Pallet<Test>>::set_balance(RuntimeOrigin::root(), acc, 0, 0).unwrap();203204 let name: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();205 let description: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();206 let token_prefix: Vec<u8> = b"token_prefix1\0".to_vec();207208 let data: CreateCollectionData<<Test as frame_system::Config>::AccountId> =209 CreateCollectionData {210 name: name.try_into().unwrap(),211 description: description.try_into().unwrap(),212 token_prefix: token_prefix.try_into().unwrap(),213 mode: CollectionMode::NFT,214 ..Default::default()215 };216217 let result = Unique::create_collection_ex(RuntimeOrigin::signed(acc), data);218 assert_err!(result, <CommonError<Test>>::NotSufficientFounds);219 });220}221222#[test]223fn create_fungible_collection_fails_with_large_decimal_numbers() {224 new_test_ext().execute_with(|| {225 let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();226 let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();227 let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();228229 let data: CreateCollectionData<u64> = CreateCollectionData {230 name: col_name1.try_into().unwrap(),231 description: col_desc1.try_into().unwrap(),232 token_prefix: token_prefix1.try_into().unwrap(),233 mode: CollectionMode::Fungible(MAX_DECIMAL_POINTS + 1),234 ..Default::default()235 };236237 let origin1 = RuntimeOrigin::signed(1);238 assert_noop!(239 Unique::create_collection_ex(origin1, data),240 UniqueError::<Test>::CollectionDecimalPointLimitExceeded241 );242 });243}244245#[test]246fn create_nft_item() {247 new_test_ext().execute_with(|| {248 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));249250 let data = default_nft_data();251 create_test_item(collection_id, &data.clone().into());252253 assert_eq!(254 get_token_properties(collection_id, TokenId(1)).as_slice(),255 data.properties.as_slice(),256 );257 });258}259260// Use cases tests region261// #region262#[test]263fn create_nft_multiple_items() {264 new_test_ext().execute_with(|| {265 create_test_collection(&CollectionMode::NFT, CollectionId(1));266267 let origin1 = RuntimeOrigin::signed(1);268269 let items_data = vec![default_nft_data(), default_nft_data(), default_nft_data()];270271 assert_ok!(Unique::create_multiple_items(272 origin1,273 CollectionId(1),274 account(1),275 items_data276 .clone()277 .into_iter()278 .map(|d| { d.into() })279 .collect()280 ));281 for (index, data) in items_data.into_iter().enumerate() {282 assert_eq!(283 get_token_properties(CollectionId(1), TokenId(index as u32 + 1)).as_slice(),284 data.properties.as_slice()285 );286 }287 });288}289290#[test]291fn create_refungible_item() {292 new_test_ext().execute_with(|| {293 let collection_id = create_test_collection(&CollectionMode::ReFungible, CollectionId(1));294295 let data = default_re_fungible_data();296 create_test_item(collection_id, &data.clone().into());297 let balance =298 <pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(1)));299 assert_eq!(balance, 1023);300 });301}302303#[test]304fn create_multiple_refungible_items() {305 new_test_ext().execute_with(|| {306 create_test_collection(&CollectionMode::ReFungible, CollectionId(1));307308 let origin1 = RuntimeOrigin::signed(1);309310 let items_data = vec![311 default_re_fungible_data(),312 default_re_fungible_data(),313 default_re_fungible_data(),314 ];315316 assert_ok!(Unique::create_multiple_items(317 origin1,318 CollectionId(1),319 account(1),320 items_data321 .clone()322 .into_iter()323 .map(|d| { d.into() })324 .collect()325 ));326 for (index, _data) in items_data.into_iter().enumerate() {327 let balance = <pallet_refungible::Balance<Test>>::get((328 CollectionId(1),329 TokenId((index + 1) as u32),330 account(1),331 ));332 assert_eq!(balance, 1023);333 }334 });335}336337#[test]338fn create_fungible_item() {339 new_test_ext().execute_with(|| {340 let collection_id = create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));341342 let data = default_fungible_data();343 create_test_item(collection_id, &data.into());344345 assert_eq!(346 <pallet_fungible::Balance<Test>>::get((collection_id, account(1))),347 5348 );349 });350}351352//#[test]353// fn create_multiple_fungible_items() {354// new_test_ext().execute_with(|| {355// default_limits();356357// create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));358359// let origin1 = RuntimeOrigin::signed(1);360361// let items_data = vec![default_fungible_data(), default_fungible_data(), default_fungible_data()];362363// assert_ok!(Unique::create_multiple_items(364// origin1.clone(),365// 1,366// 1,367// items_data.clone().into_iter().map(|d| { d.into() }).collect()368// ));369370// for (index, _) in items_data.iter().enumerate() {371// assert_eq!(Unique::fungible_item_id(1, (index + 1) as TokenId).value, 5);372// }373// assert_eq!(Unique::balance_count(1, 1), 3000);374// assert_eq!(Unique::address_tokens(1, 1), [1, 2, 3]);375// });376// }377378#[test]379fn transfer_fungible_item() {380 new_test_ext().execute_with(|| {381 let collection_id = create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));382383 let origin1 = RuntimeOrigin::signed(1);384 let origin2 = RuntimeOrigin::signed(2);385386 let data = default_fungible_data();387 create_test_item(collection_id, &data.into());388389 assert_eq!(390 <pallet_fungible::Balance<Test>>::get((CollectionId(1), account(1))),391 5392 );393394 // change owner scenario395 assert_ok!(Unique::transfer(396 origin1,397 account(2),398 CollectionId(1),399 TokenId(0),400 5401 ));402 assert_eq!(403 <pallet_fungible::Balance<Test>>::get((CollectionId(1), account(1))),404 0405 );406407 // split item scenario408 assert_ok!(Unique::transfer(409 origin2.clone(),410 account(3),411 CollectionId(1),412 TokenId(0),413 3414 ));415416 // split item and new owner has account scenario417 assert_ok!(Unique::transfer(418 origin2,419 account(3),420 CollectionId(1),421 TokenId(0),422 1423 ));424 assert_eq!(425 <pallet_fungible::Balance<Test>>::get((CollectionId(1), account(2))),426 1427 );428 assert_eq!(429 <pallet_fungible::Balance<Test>>::get((CollectionId(1), account(3))),430 4431 );432 });433}434435#[test]436fn transfer_refungible_item() {437 new_test_ext().execute_with(|| {438 let collection_id = create_test_collection(&CollectionMode::ReFungible, CollectionId(1));439440 // Create RFT 1 in 1023 pieces for account 1441 let data = default_re_fungible_data();442 create_test_item(collection_id, &data.clone().into());443 assert_eq!(444 <pallet_refungible::AccountBalance<Test>>::get((collection_id, account(1))),445 1446 );447 assert_eq!(448 <pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(1))),449 1023450 );451 assert_eq!(452 <pallet_refungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),453 true454 );455456 // Account 1 transfers all 1023 pieces of RFT 1 to account 2457 let origin1 = RuntimeOrigin::signed(1);458 let origin2 = RuntimeOrigin::signed(2);459 assert_ok!(Unique::transfer(460 origin1,461 account(2),462 CollectionId(1),463 TokenId(1),464 1023465 ));466 assert_eq!(467 <pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(2))),468 1023469 );470 assert_eq!(471 <pallet_refungible::AccountBalance<Test>>::get((collection_id, account(1))),472 0473 );474 assert_eq!(475 <pallet_refungible::AccountBalance<Test>>::get((collection_id, account(2))),476 1477 );478 assert_eq!(479 <pallet_refungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),480 false481 );482 assert_eq!(483 <pallet_refungible::Owned<Test>>::get((collection_id, account(2), TokenId(1))),484 true485 );486487 // Account 2 transfers 500 pieces of RFT 1 to account 3488 assert_ok!(Unique::transfer(489 origin2.clone(),490 account(3),491 CollectionId(1),492 TokenId(1),493 500494 ));495 assert_eq!(496 <pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(2))),497 523498 );499 assert_eq!(500 <pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(3))),501 500502 );503 assert_eq!(504 <pallet_refungible::AccountBalance<Test>>::get((collection_id, account(2))),505 1506 );507 assert_eq!(508 <pallet_refungible::AccountBalance<Test>>::get((collection_id, account(3))),509 1510 );511 assert_eq!(512 <pallet_refungible::Owned<Test>>::get((collection_id, account(2), TokenId(1))),513 true514 );515 assert_eq!(516 <pallet_refungible::Owned<Test>>::get((collection_id, account(3), TokenId(1))),517 true518 );519520 // Account 2 transfers 200 more pieces of RFT 1 to account 3 with pre-existing balance521 assert_ok!(Unique::transfer(522 origin2,523 account(3),524 CollectionId(1),525 TokenId(1),526 200527 ));528 assert_eq!(529 <pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(2))),530 323531 );532 assert_eq!(533 <pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(3))),534 700535 );536 assert_eq!(537 <pallet_refungible::AccountBalance<Test>>::get((collection_id, account(2))),538 1539 );540 assert_eq!(541 <pallet_refungible::AccountBalance<Test>>::get((collection_id, account(3))),542 1543 );544 assert_eq!(545 <pallet_refungible::Owned<Test>>::get((collection_id, account(2), TokenId(1))),546 true547 );548 assert_eq!(549 <pallet_refungible::Owned<Test>>::get((collection_id, account(3), TokenId(1))),550 true551 );552 });553}554555#[test]556fn transfer_nft_item() {557 new_test_ext().execute_with(|| {558 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));559560 let data = default_nft_data();561 create_test_item(collection_id, &data.into());562 assert_eq!(563 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),564 1565 );566 assert_eq!(567 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),568 true569 );570571 let origin1 = RuntimeOrigin::signed(1);572 // default scenario573 assert_ok!(Unique::transfer(574 origin1,575 account(2),576 CollectionId(1),577 TokenId(1),578 1579 ));580 assert_eq!(581 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),582 0583 );584 assert_eq!(585 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(2))),586 1587 );588 assert_eq!(589 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),590 false591 );592 assert_eq!(593 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(2), TokenId(1))),594 true595 );596 });597}598599#[test]600fn transfer_nft_item_wrong_value() {601 new_test_ext().execute_with(|| {602 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));603604 let data = default_nft_data();605 create_test_item(collection_id, &data.into());606 assert_eq!(607 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),608 1609 );610 assert_eq!(611 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),612 true613 );614615 let origin1 = RuntimeOrigin::signed(1);616617 assert_noop!(618 Unique::transfer(origin1, account(2), CollectionId(1), TokenId(1), 2)619 .map_err(|e| e.error),620 <pallet_nonfungible::Error::<Test>>::NonfungibleItemsHaveNoAmount621 );622 });623}624625#[test]626fn transfer_nft_item_zero_value() {627 new_test_ext().execute_with(|| {628 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));629630 let data = default_nft_data();631 create_test_item(collection_id, &data.into());632 assert_eq!(633 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),634 1635 );636 assert_eq!(637 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),638 true639 );640641 let origin1 = RuntimeOrigin::signed(1);642643 // Transferring 0 amount works on NFT...644 assert_ok!(Unique::transfer(645 origin1,646 account(2),647 CollectionId(1),648 TokenId(1),649 0650 ));651 // ... and results in no transfer652 assert_eq!(653 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),654 1655 );656 assert_eq!(657 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),658 true659 );660 });661}662663#[test]664fn nft_approve_and_transfer_from() {665 new_test_ext().execute_with(|| {666 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));667668 let data = default_nft_data();669 create_test_item(collection_id, &data.into());670671 let origin1 = RuntimeOrigin::signed(1);672 let origin2 = RuntimeOrigin::signed(2);673674 assert_eq!(675 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),676 1677 );678 assert_eq!(679 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),680 true681 );682683 // neg transfer_from684 assert_noop!(685 Unique::transfer_from(686 origin2.clone(),687 account(1),688 account(2),689 CollectionId(1),690 TokenId(1),691 1692 )693 .map_err(|e| e.error),694 CommonError::<Test>::ApprovedValueTooLow695 );696697 // do approve698 assert_ok!(Unique::approve(699 origin1,700 account(2),701 CollectionId(1),702 TokenId(1),703 1704 ));705 assert_eq!(706 <pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).unwrap(),707 account(2)708 );709710 assert_ok!(Unique::transfer_from(711 origin2,712 account(1),713 account(3),714 CollectionId(1),715 TokenId(1),716 1717 ));718 assert!(719 <pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).is_none()720 );721 });722}723724#[test]725fn nft_approve_and_transfer_from_allow_list() {726 new_test_ext().execute_with(|| {727 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));728729 let origin1 = RuntimeOrigin::signed(1);730 let origin2 = RuntimeOrigin::signed(2);731732 // Create NFT 1 for account 1733 let data = default_nft_data();734 create_test_item(collection_id, &data.clone().into());735 assert_eq!(736 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),737 1738 );739 assert_eq!(740 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),741 true742 );743744 // Allow allow-list users to mint and add accounts 1, 2, and 3 to allow-list745 assert_ok!(Unique::set_collection_permissions(746 origin1.clone(),747 CollectionId(1),748 CollectionPermissions {749 mint_mode: Some(true),750 access: Some(AccessMode::AllowList),751 nesting: None,752 }753 ));754 assert_ok!(Unique::add_to_allow_list(755 origin1.clone(),756 CollectionId(1),757 account(1)758 ));759 assert_ok!(Unique::add_to_allow_list(760 origin1.clone(),761 CollectionId(1),762 account(2)763 ));764 assert_ok!(Unique::add_to_allow_list(765 origin1.clone(),766 CollectionId(1),767 account(3)768 ));769770 // Account 1 approves account 2 for NFT 1771 assert_ok!(Unique::approve(772 origin1.clone(),773 account(2),774 CollectionId(1),775 TokenId(1),776 1777 ));778 assert_eq!(779 <pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).unwrap(),780 account(2)781 );782783 // Account 2 transfers NFT 1 from account 1 to account 3784 assert_ok!(Unique::transfer_from(785 origin2,786 account(1),787 account(3),788 CollectionId(1),789 TokenId(1),790 1791 ));792 assert!(793 <pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).is_none()794 );795 });796}797798#[test]799fn refungible_approve_and_transfer_from() {800 new_test_ext().execute_with(|| {801 let collection_id = create_test_collection(&CollectionMode::ReFungible, CollectionId(1));802803 let origin1 = RuntimeOrigin::signed(1);804 let origin2 = RuntimeOrigin::signed(2);805806 // Create RFT 1 in 1023 pieces for account 1807 let data = default_re_fungible_data();808 create_test_item(collection_id, &data.into());809810 assert_eq!(811 <pallet_refungible::AccountBalance<Test>>::get((collection_id, account(1))),812 1813 );814 assert_eq!(815 <pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(1))),816 1023817 );818 assert_eq!(819 <pallet_refungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),820 true821 );822823 // Allow public minting, enable allow-list and add accounts 1, 2, 3 to allow-list824 assert_ok!(Unique::set_collection_permissions(825 origin1.clone(),826 CollectionId(1),827 CollectionPermissions {828 mint_mode: Some(true),829 access: Some(AccessMode::AllowList),830 nesting: None,831 }832 ));833 assert_ok!(Unique::add_to_allow_list(834 origin1.clone(),835 CollectionId(1),836 account(1)837 ));838 assert_ok!(Unique::add_to_allow_list(839 origin1.clone(),840 CollectionId(1),841 account(2)842 ));843 assert_ok!(Unique::add_to_allow_list(844 origin1.clone(),845 CollectionId(1),846 account(3)847 ));848849 // Account 1 approves account 2 for 1023 pieces of RFT 1850 assert_ok!(Unique::approve(851 origin1,852 account(2),853 CollectionId(1),854 TokenId(1),855 1023856 ));857 assert_eq!(858 <pallet_refungible::Allowance<Test>>::get((859 CollectionId(1),860 TokenId(1),861 account(1),862 account(2)863 )),864 1023865 );866867 // Account 2 transfers 100 pieces of RFT 1 from account 1 to account 3868 assert_ok!(Unique::transfer_from(869 origin2,870 account(1),871 account(3),872 CollectionId(1),873 TokenId(1),874 100875 ));876 assert_eq!(877 <pallet_refungible::AccountBalance<Test>>::get((collection_id, account(1))),878 1879 );880 assert_eq!(881 <pallet_refungible::AccountBalance<Test>>::get((collection_id, account(3))),882 1883 );884 assert_eq!(885 <pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(1))),886 923887 );888 assert_eq!(889 <pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(3))),890 100891 );892 assert_eq!(893 <pallet_refungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),894 true895 );896 assert_eq!(897 <pallet_refungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),898 true899 );900 assert_eq!(901 <pallet_refungible::Allowance<Test>>::get((902 CollectionId(1),903 TokenId(1),904 account(1),905 account(2)906 )),907 923908 );909 });910}911912#[test]913fn fungible_approve_and_transfer_from() {914 new_test_ext().execute_with(|| {915 let collection_id = create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));916917 let data = default_fungible_data();918 create_test_item(collection_id, &data.into());919920 let origin1 = RuntimeOrigin::signed(1);921 let origin2 = RuntimeOrigin::signed(2);922923 assert_ok!(Unique::set_collection_permissions(924 origin1.clone(),925 CollectionId(1),926 CollectionPermissions {927 mint_mode: Some(true),928 access: Some(AccessMode::AllowList),929 nesting: None,930 }931 ));932 assert_ok!(Unique::add_to_allow_list(933 origin1.clone(),934 CollectionId(1),935 account(1)936 ));937 assert_ok!(Unique::add_to_allow_list(938 origin1.clone(),939 CollectionId(1),940 account(2)941 ));942 assert_ok!(Unique::add_to_allow_list(943 origin1.clone(),944 CollectionId(1),945 account(3)946 ));947948 // do approve949 assert_ok!(Unique::approve(950 origin1.clone(),951 account(2),952 CollectionId(1),953 TokenId(0),954 5955 ));956 assert_eq!(957 <pallet_fungible::Allowance<Test>>::get((CollectionId(1), account(1), account(2))),958 5959 );960 assert_ok!(Unique::approve(961 origin1,962 account(3),963 CollectionId(1),964 TokenId(0),965 5966 ));967 assert_eq!(968 <pallet_fungible::Allowance<Test>>::get((CollectionId(1), account(1), account(2))),969 5970 );971 assert_eq!(972 <pallet_fungible::Allowance<Test>>::get((CollectionId(1), account(1), account(3))),973 5974 );975976 assert_ok!(Unique::transfer_from(977 origin2.clone(),978 account(1),979 account(3),980 CollectionId(1),981 TokenId(0),982 4983 ));984985 assert_eq!(986 <pallet_fungible::Allowance<Test>>::get((CollectionId(1), account(1), account(2))),987 1988 );989990 assert_noop!(991 Unique::transfer_from(992 origin2,993 account(1),994 account(3),995 CollectionId(1),996 TokenId(0),997 4998 )999 .map_err(|e| e.error),1000 CommonError::<Test>::ApprovedValueTooLow1001 );1002 });1003}10041005#[test]1006fn change_collection_owner() {1007 new_test_ext().execute_with(|| {1008 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));10091010 let origin1 = RuntimeOrigin::signed(1);1011 assert_ok!(Unique::change_collection_owner(origin1, collection_id, 2));1012 assert_eq!(1013 <pallet_common::CollectionById<Test>>::get(collection_id)1014 .unwrap()1015 .owner,1016 21017 );1018 });1019}10201021#[test]1022fn destroy_collection() {1023 new_test_ext().execute_with(|| {1024 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));10251026 let origin1 = RuntimeOrigin::signed(1);1027 assert_ok!(Unique::destroy_collection(origin1, collection_id));1028 });1029}10301031#[test]1032fn burn_nft_item() {1033 new_test_ext().execute_with(|| {1034 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));10351036 let origin1 = RuntimeOrigin::signed(1);10371038 let data = default_nft_data();1039 create_test_item(collection_id, &data.into());10401041 // check balance (collection with id = 1, user id = 1)1042 assert_eq!(1043 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),1044 11045 );10461047 // burn item1048 assert_ok!(Unique::burn_item(1049 origin1.clone(),1050 collection_id,1051 TokenId(1),1052 11053 ));1054 assert_eq!(1055 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),1056 01057 );1058 });1059}10601061#[test]1062fn burn_same_nft_item_twice() {1063 new_test_ext().execute_with(|| {1064 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));10651066 let origin1 = RuntimeOrigin::signed(1);10671068 let data = default_nft_data();1069 create_test_item(collection_id, &data.into());10701071 // check balance (collection with id = 1, user id = 1)1072 assert_eq!(1073 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),1074 11075 );10761077 // burn item1078 assert_ok!(Unique::burn_item(1079 origin1.clone(),1080 collection_id,1081 TokenId(1),1082 11083 ));10841085 // burn item again1086 assert_noop!(1087 Unique::burn_item(origin1, collection_id, TokenId(1), 1).map_err(|e| e.error),1088 CommonError::<Test>::TokenNotFound1089 );10901091 assert_eq!(1092 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),1093 01094 );1095 });1096}10971098#[test]1099fn burn_fungible_item() {1100 new_test_ext().execute_with(|| {1101 let collection_id = create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));11021103 let origin1 = RuntimeOrigin::signed(1);1104 assert_ok!(Unique::add_collection_admin(1105 origin1.clone(),1106 collection_id,1107 account(2)1108 ));11091110 let data = default_fungible_data();1111 create_test_item(collection_id, &data.into());11121113 // check balance (collection with id = 1, user id = 1)1114 assert_eq!(1115 <pallet_fungible::Balance<Test>>::get((collection_id, account(1))),1116 51117 );11181119 // burn item1120 assert_ok!(Unique::burn_item(1121 origin1.clone(),1122 CollectionId(1),1123 TokenId(0),1124 51125 ));1126 assert_noop!(1127 Unique::burn_item(origin1, CollectionId(1), TokenId(0), 5).map_err(|e| e.error),1128 CommonError::<Test>::TokenValueTooLow1129 );11301131 assert_eq!(1132 <pallet_fungible::Balance<Test>>::get((collection_id, account(1))),1133 01134 );1135 });1136}11371138#[test]1139fn burn_fungible_item_with_token_id() {1140 new_test_ext().execute_with(|| {1141 let collection_id = create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));11421143 let origin1 = RuntimeOrigin::signed(1);1144 assert_ok!(Unique::add_collection_admin(1145 origin1.clone(),1146 collection_id,1147 account(2)1148 ));11491150 let data = default_fungible_data();1151 create_test_item(collection_id, &data.into());11521153 // check balance (collection with id = 1, user id = 1)1154 assert_eq!(1155 <pallet_fungible::Balance<Test>>::get((collection_id, account(1))),1156 51157 );11581159 // Try to burn item using Token ID1160 assert_noop!(1161 Unique::burn_item(origin1, CollectionId(1), TokenId(1), 5).map_err(|e| e.error),1162 <pallet_fungible::Error::<Test>>::FungibleItemsHaveNoId1163 );1164 });1165}1166#[test]1167fn burn_refungible_item() {1168 new_test_ext().execute_with(|| {1169 let collection_id = create_test_collection(&CollectionMode::ReFungible, CollectionId(1));1170 let origin1 = RuntimeOrigin::signed(1);11711172 assert_ok!(Unique::set_collection_permissions(1173 origin1.clone(),1174 collection_id,1175 CollectionPermissions {1176 mint_mode: Some(true),1177 access: Some(AccessMode::AllowList),1178 nesting: None,1179 }1180 ));1181 assert_ok!(Unique::add_to_allow_list(1182 origin1.clone(),1183 collection_id,1184 account(1)1185 ));11861187 assert_ok!(Unique::add_collection_admin(1188 origin1.clone(),1189 collection_id,1190 account(2)1191 ));11921193 let data = default_re_fungible_data();1194 create_test_item(collection_id, &data.into());11951196 // check balance (collection with id = 1, user id = 2)1197 assert_eq!(1198 <pallet_refungible::AccountBalance<Test>>::get((collection_id, account(1))),1199 11200 );1201 assert_eq!(1202 <pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(1))),1203 10231204 );12051206 // burn item1207 assert_ok!(Unique::burn_item(1208 origin1.clone(),1209 collection_id,1210 TokenId(1),1211 10231212 ));1213 assert_noop!(1214 Unique::burn_item(origin1, collection_id, TokenId(1), 1023).map_err(|e| e.error),1215 CommonError::<Test>::TokenValueTooLow1216 );12171218 assert_eq!(1219 <pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(1))),1220 01221 );1222 });1223}12241225#[test]1226fn add_collection_admin() {1227 new_test_ext().execute_with(|| {1228 let collection1_id =1229 create_test_collection_for_owner(&CollectionMode::NFT, 1, CollectionId(1));1230 let origin1 = RuntimeOrigin::signed(1);12311232 // Add collection admins1233 assert_ok!(Unique::add_collection_admin(1234 origin1.clone(),1235 collection1_id,1236 account(2)1237 ));1238 assert_ok!(Unique::add_collection_admin(1239 origin1,1240 collection1_id,1241 account(3)1242 ));12431244 // Owner is not an admin by default1245 assert_eq!(1246 <pallet_common::IsAdmin<Test>>::get((CollectionId(1), account(1))),1247 false1248 );1249 assert!(<pallet_common::IsAdmin<Test>>::get((1250 CollectionId(1),1251 account(2)1252 )));1253 assert!(<pallet_common::IsAdmin<Test>>::get((1254 CollectionId(1),1255 account(3)1256 )));1257 });1258}12591260#[test]1261fn remove_collection_admin() {1262 new_test_ext().execute_with(|| {1263 let collection1_id =1264 create_test_collection_for_owner(&CollectionMode::NFT, 1, CollectionId(1));1265 let origin1 = RuntimeOrigin::signed(1);12661267 // Add collection admins 2 and 31268 assert_ok!(Unique::add_collection_admin(1269 origin1.clone(),1270 collection1_id,1271 account(2)1272 ));1273 assert_ok!(Unique::add_collection_admin(1274 origin1.clone(),1275 collection1_id,1276 account(3)1277 ));12781279 assert!(<pallet_common::IsAdmin<Test>>::get((1280 CollectionId(1),1281 account(2)1282 )));1283 assert!(<pallet_common::IsAdmin<Test>>::get((1284 CollectionId(1),1285 account(3)1286 )));12871288 // remove admin 31289 assert_ok!(Unique::remove_collection_admin(1290 origin1,1291 CollectionId(1),1292 account(3)1293 ));12941295 // 2 is still admin, 3 is not an admin anymore1296 assert!(<pallet_common::IsAdmin<Test>>::get((1297 CollectionId(1),1298 account(2)1299 )));1300 assert_eq!(1301 <pallet_common::IsAdmin<Test>>::get((CollectionId(1), account(3))),1302 false1303 );1304 });1305}13061307#[test]1308fn balance_of() {1309 new_test_ext().execute_with(|| {1310 let nft_collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1311 let fungible_collection_id =1312 create_test_collection(&CollectionMode::Fungible(3), CollectionId(2));1313 let re_fungible_collection_id =1314 create_test_collection(&CollectionMode::ReFungible, CollectionId(3));13151316 // check balance before1317 assert_eq!(1318 <pallet_nonfungible::AccountBalance<Test>>::get((nft_collection_id, account(1))),1319 01320 );1321 assert_eq!(1322 <pallet_fungible::Balance<Test>>::get((fungible_collection_id, account(1))),1323 01324 );1325 assert_eq!(1326 <pallet_refungible::AccountBalance<Test>>::get((re_fungible_collection_id, account(1))),1327 01328 );13291330 let nft_data = default_nft_data();1331 create_test_item(nft_collection_id, &nft_data.into());13321333 let fungible_data = default_fungible_data();1334 create_test_item(fungible_collection_id, &fungible_data.into());13351336 let re_fungible_data = default_re_fungible_data();1337 create_test_item(re_fungible_collection_id, &re_fungible_data.into());13381339 // check balance (collection with id = 1, user id = 1)1340 assert_eq!(1341 <pallet_nonfungible::AccountBalance<Test>>::get((nft_collection_id, account(1))),1342 11343 );1344 assert_eq!(1345 <pallet_fungible::Balance<Test>>::get((fungible_collection_id, account(1))),1346 51347 );1348 assert_eq!(1349 <pallet_refungible::AccountBalance<Test>>::get((re_fungible_collection_id, account(1))),1350 11351 );13521353 assert_eq!(1354 <pallet_nonfungible::Owned<Test>>::get((nft_collection_id, account(1), TokenId(1))),1355 true1356 );1357 assert_eq!(1358 <pallet_refungible::Owned<Test>>::get((1359 re_fungible_collection_id,1360 account(1),1361 TokenId(1)1362 )),1363 true1364 );1365 });1366}13671368#[test]1369fn approve() {1370 new_test_ext().execute_with(|| {1371 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));13721373 let data = default_nft_data();1374 create_test_item(collection_id, &data.into());13751376 let origin1 = RuntimeOrigin::signed(1);13771378 // approve1379 assert_ok!(Unique::approve(1380 origin1,1381 account(2),1382 CollectionId(1),1383 TokenId(1),1384 11385 ));1386 assert_eq!(1387 <pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).unwrap(),1388 account(2)1389 );1390 });1391}13921393#[test]1394fn transfer_from() {1395 new_test_ext().execute_with(|| {1396 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1397 let origin1 = RuntimeOrigin::signed(1);1398 let origin2 = RuntimeOrigin::signed(2);13991400 let data = default_nft_data();1401 create_test_item(collection_id, &data.into());14021403 // approve1404 assert_ok!(Unique::approve(1405 origin1.clone(),1406 account(2),1407 CollectionId(1),1408 TokenId(1),1409 11410 ));1411 assert_eq!(1412 <pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).unwrap(),1413 account(2)1414 );14151416 assert_ok!(Unique::set_collection_permissions(1417 origin1.clone(),1418 CollectionId(1),1419 CollectionPermissions {1420 mint_mode: Some(true),1421 access: Some(AccessMode::AllowList),1422 nesting: None,1423 }1424 ));1425 assert_ok!(Unique::add_to_allow_list(1426 origin1.clone(),1427 CollectionId(1),1428 account(1)1429 ));1430 assert_ok!(Unique::add_to_allow_list(1431 origin1.clone(),1432 CollectionId(1),1433 account(2)1434 ));1435 assert_ok!(Unique::add_to_allow_list(1436 origin1,1437 CollectionId(1),1438 account(3)1439 ));14401441 assert_ok!(Unique::transfer_from(1442 origin2,1443 account(1),1444 account(2),1445 CollectionId(1),1446 TokenId(1),1447 11448 ));14491450 // after transfer1451 assert_eq!(1452 <pallet_nonfungible::AccountBalance<Test>>::get((CollectionId(1), account(1))),1453 01454 );1455 assert_eq!(1456 <pallet_nonfungible::AccountBalance<Test>>::get((CollectionId(1), account(2))),1457 11458 );1459 });1460}14611462// #endregion14631464// Coverage tests region1465// #region14661467#[test]1468fn owner_can_add_address_to_allow_list() {1469 new_test_ext().execute_with(|| {1470 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));14711472 let origin1 = RuntimeOrigin::signed(1);1473 assert_ok!(Unique::add_to_allow_list(1474 origin1,1475 collection_id,1476 account(2)1477 ));1478 assert!(<pallet_common::Allowlist<Test>>::get((1479 collection_id,1480 account(2)1481 )));1482 });1483}14841485#[test]1486fn admin_can_add_address_to_allow_list() {1487 new_test_ext().execute_with(|| {1488 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1489 let origin1 = RuntimeOrigin::signed(1);1490 let origin2 = RuntimeOrigin::signed(2);14911492 assert_ok!(Unique::add_collection_admin(1493 origin1,1494 collection_id,1495 account(2)1496 ));1497 assert_ok!(Unique::add_to_allow_list(1498 origin2,1499 collection_id,1500 account(3)1501 ));1502 assert!(<pallet_common::Allowlist<Test>>::get((1503 collection_id,1504 account(3)1505 )));1506 });1507}15081509#[test]1510fn nonprivileged_user_cannot_add_address_to_allow_list() {1511 new_test_ext().execute_with(|| {1512 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));15131514 let origin2 = RuntimeOrigin::signed(2);1515 assert_noop!(1516 Unique::add_to_allow_list(origin2, collection_id, account(3)),1517 CommonError::<Test>::NoPermission1518 );1519 });1520}15211522#[test]1523fn nobody_can_add_address_to_allow_list_of_nonexisting_collection() {1524 new_test_ext().execute_with(|| {1525 let origin1 = RuntimeOrigin::signed(1);15261527 assert_noop!(1528 Unique::add_to_allow_list(origin1, CollectionId(1), account(2)),1529 CommonError::<Test>::CollectionNotFound1530 );1531 });1532}15331534#[test]1535fn nobody_can_add_address_to_allow_list_of_deleted_collection() {1536 new_test_ext().execute_with(|| {1537 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));15381539 let origin1 = RuntimeOrigin::signed(1);1540 assert_ok!(Unique::destroy_collection(origin1.clone(), collection_id));1541 assert_noop!(1542 Unique::add_to_allow_list(origin1, collection_id, account(2)),1543 CommonError::<Test>::CollectionNotFound1544 );1545 });1546}15471548// If address is already added to allow list, nothing happens1549#[test]1550fn address_is_already_added_to_allow_list() {1551 new_test_ext().execute_with(|| {1552 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1553 let origin1 = RuntimeOrigin::signed(1);15541555 assert_ok!(Unique::add_to_allow_list(1556 origin1.clone(),1557 collection_id,1558 account(2)1559 ));1560 assert_ok!(Unique::add_to_allow_list(1561 origin1,1562 collection_id,1563 account(2)1564 ));1565 assert!(<pallet_common::Allowlist<Test>>::get((1566 collection_id,1567 account(2)1568 )));1569 });1570}15711572#[test]1573fn owner_can_remove_address_from_allow_list() {1574 new_test_ext().execute_with(|| {1575 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));15761577 let origin1 = RuntimeOrigin::signed(1);1578 assert_ok!(Unique::add_to_allow_list(1579 origin1.clone(),1580 collection_id,1581 account(2)1582 ));1583 assert_ok!(Unique::remove_from_allow_list(1584 origin1,1585 collection_id,1586 account(2)1587 ));1588 assert_eq!(1589 <pallet_common::Allowlist<Test>>::get((collection_id, account(2))),1590 false1591 );1592 });1593}15941595#[test]1596fn admin_can_remove_address_from_allow_list() {1597 new_test_ext().execute_with(|| {1598 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1599 let origin1 = RuntimeOrigin::signed(1);1600 let origin2 = RuntimeOrigin::signed(2);16011602 // Owner adds admin1603 assert_ok!(Unique::add_collection_admin(1604 origin1.clone(),1605 collection_id,1606 account(2)1607 ));16081609 // Owner adds address 3 to allow list1610 assert_ok!(Unique::add_to_allow_list(1611 origin1,1612 collection_id,1613 account(3)1614 ));16151616 // Admin removes address 3 from allow list1617 assert_ok!(Unique::remove_from_allow_list(1618 origin2,1619 collection_id,1620 account(3)1621 ));1622 assert_eq!(1623 <pallet_common::Allowlist<Test>>::get((collection_id, account(3))),1624 false1625 );1626 });1627}16281629#[test]1630fn nonprivileged_user_cannot_remove_address_from_allow_list() {1631 new_test_ext().execute_with(|| {1632 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1633 let origin1 = RuntimeOrigin::signed(1);1634 let origin2 = RuntimeOrigin::signed(2);16351636 assert_ok!(Unique::add_to_allow_list(1637 origin1,1638 collection_id,1639 account(2)1640 ));1641 assert_noop!(1642 Unique::remove_from_allow_list(origin2, collection_id, account(2)),1643 CommonError::<Test>::NoPermission1644 );1645 assert!(<pallet_common::Allowlist<Test>>::get((1646 collection_id,1647 account(2)1648 )));1649 });1650}16511652#[test]1653fn nobody_can_remove_address_from_allow_list_of_nonexisting_collection() {1654 new_test_ext().execute_with(|| {1655 let origin1 = RuntimeOrigin::signed(1);16561657 assert_noop!(1658 Unique::remove_from_allow_list(origin1, CollectionId(1), account(2)),1659 CommonError::<Test>::CollectionNotFound1660 );1661 });1662}16631664#[test]1665fn nobody_can_remove_address_from_allow_list_of_deleted_collection() {1666 new_test_ext().execute_with(|| {1667 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1668 let origin1 = RuntimeOrigin::signed(1);1669 let origin2 = RuntimeOrigin::signed(2);16701671 // Add account 2 to allow list1672 assert_ok!(Unique::add_to_allow_list(1673 origin1.clone(),1674 collection_id,1675 account(2)1676 ));16771678 // Account 2 is in collection allow-list1679 assert!(<pallet_common::Allowlist<Test>>::get((1680 collection_id,1681 account(2)1682 )));16831684 // Destroy collection1685 assert_ok!(Unique::destroy_collection(origin1, collection_id));16861687 // Attempt to remove account 2 from collection allow-list => error1688 assert_noop!(1689 Unique::remove_from_allow_list(origin2, collection_id, account(2)),1690 CommonError::<Test>::CollectionNotFound1691 );16921693 // Account 2 is not found in collection allow-list anyway1694 assert_eq!(1695 <pallet_common::Allowlist<Test>>::get((collection_id, account(2))),1696 false1697 );1698 });1699}17001701// If address is already removed from allow list, nothing happens1702#[test]1703fn address_is_already_removed_from_allow_list() {1704 new_test_ext().execute_with(|| {1705 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1706 let origin1 = RuntimeOrigin::signed(1);17071708 assert_ok!(Unique::add_to_allow_list(1709 origin1.clone(),1710 collection_id,1711 account(2)1712 ));1713 assert_ok!(Unique::remove_from_allow_list(1714 origin1.clone(),1715 collection_id,1716 account(2)1717 ));1718 assert_eq!(1719 <pallet_common::Allowlist<Test>>::get((collection_id, account(2))),1720 false1721 );1722 assert_ok!(Unique::remove_from_allow_list(1723 origin1,1724 collection_id,1725 account(2)1726 ));1727 assert_eq!(1728 <pallet_common::Allowlist<Test>>::get((collection_id, account(2))),1729 false1730 );1731 });1732}17331734// If Public Access mode is set to AllowList, tokens can’t be transferred from a non-allowlisted address with transfer or transferFrom (2 tests)1735#[test]1736fn allow_list_test_1() {1737 new_test_ext().execute_with(|| {1738 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));17391740 let origin1 = RuntimeOrigin::signed(1);17411742 let data = default_nft_data();1743 create_test_item(collection_id, &data.into());17441745 assert_ok!(Unique::set_collection_permissions(1746 origin1.clone(),1747 collection_id,1748 CollectionPermissions {1749 mint_mode: None,1750 access: Some(AccessMode::AllowList),1751 nesting: None,1752 }1753 ));1754 assert_ok!(Unique::add_to_allow_list(1755 origin1.clone(),1756 collection_id,1757 account(2)1758 ));17591760 assert_noop!(1761 Unique::transfer(origin1, account(3), CollectionId(1), TokenId(1), 1)1762 .map_err(|e| e.error),1763 CommonError::<Test>::AddressNotInAllowlist1764 );1765 });1766}17671768#[test]1769fn allow_list_test_2() {1770 new_test_ext().execute_with(|| {1771 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1772 let origin1 = RuntimeOrigin::signed(1);17731774 let data = default_nft_data();1775 create_test_item(collection_id, &data.into());17761777 assert_ok!(Unique::set_collection_permissions(1778 origin1.clone(),1779 collection_id,1780 CollectionPermissions {1781 mint_mode: None,1782 access: Some(AccessMode::AllowList),1783 nesting: None,1784 }1785 ));1786 assert_ok!(Unique::add_to_allow_list(1787 origin1.clone(),1788 collection_id,1789 account(1)1790 ));1791 assert_ok!(Unique::add_to_allow_list(1792 origin1.clone(),1793 collection_id,1794 account(2)1795 ));17961797 // do approve1798 assert_ok!(Unique::approve(1799 origin1.clone(),1800 account(1),1801 collection_id,1802 TokenId(1),1803 11804 ));1805 assert_eq!(1806 <pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).unwrap(),1807 account(1)1808 );18091810 assert_ok!(Unique::remove_from_allow_list(1811 origin1.clone(),1812 collection_id,1813 account(1)1814 ));18151816 assert_noop!(1817 Unique::transfer_from(1818 origin1,1819 account(1),1820 account(3),1821 CollectionId(1),1822 TokenId(1),1823 11824 )1825 .map_err(|e| e.error),1826 CommonError::<Test>::AddressNotInAllowlist1827 );1828 });1829}18301831// If Public Access mode is set to AllowList, tokens can’t be transferred to a non-allowlisted address with transfer or transferFrom (2 tests)1832#[test]1833fn allow_list_test_3() {1834 new_test_ext().execute_with(|| {1835 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));18361837 let origin1 = RuntimeOrigin::signed(1);18381839 let data = default_nft_data();1840 create_test_item(collection_id, &data.into());18411842 assert_ok!(Unique::set_collection_permissions(1843 origin1.clone(),1844 collection_id,1845 CollectionPermissions {1846 mint_mode: None,1847 access: Some(AccessMode::AllowList),1848 nesting: None,1849 }1850 ));1851 assert_ok!(Unique::add_to_allow_list(1852 origin1.clone(),1853 collection_id,1854 account(1)1855 ));18561857 assert_noop!(1858 Unique::transfer(origin1, account(3), collection_id, TokenId(1), 1)1859 .map_err(|e| e.error),1860 CommonError::<Test>::AddressNotInAllowlist1861 );1862 });1863}18641865#[test]1866fn allow_list_test_4() {1867 new_test_ext().execute_with(|| {1868 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));18691870 let origin1 = RuntimeOrigin::signed(1);18711872 let data = default_nft_data();1873 create_test_item(collection_id, &data.into());18741875 assert_ok!(Unique::set_collection_permissions(1876 origin1.clone(),1877 collection_id,1878 CollectionPermissions {1879 mint_mode: None,1880 access: Some(AccessMode::AllowList),1881 nesting: None,1882 }1883 ));1884 assert_ok!(Unique::add_to_allow_list(1885 origin1.clone(),1886 collection_id,1887 account(1)1888 ));1889 assert_ok!(Unique::add_to_allow_list(1890 origin1.clone(),1891 collection_id,1892 account(2)1893 ));18941895 // do approve1896 assert_ok!(Unique::approve(1897 origin1.clone(),1898 account(1),1899 collection_id,1900 TokenId(1),1901 11902 ));1903 assert_eq!(1904 <pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).unwrap(),1905 account(1)1906 );19071908 assert_ok!(Unique::remove_from_allow_list(1909 origin1.clone(),1910 collection_id,1911 account(2)1912 ));19131914 assert_noop!(1915 Unique::transfer_from(1916 origin1,1917 account(1),1918 account(3),1919 collection_id,1920 TokenId(1),1921 11922 )1923 .map_err(|e| e.error),1924 CommonError::<Test>::AddressNotInAllowlist1925 );1926 });1927}19281929// If Public Access mode is set to AllowList, tokens can’t be destroyed by a non-allowlisted address (even if it owned them before enabling AllowList mode)1930#[test]1931fn allow_list_test_5() {1932 new_test_ext().execute_with(|| {1933 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));19341935 let origin1 = RuntimeOrigin::signed(1);19361937 let data = default_nft_data();1938 create_test_item(collection_id, &data.into());19391940 assert_ok!(Unique::set_collection_permissions(1941 origin1.clone(),1942 collection_id,1943 CollectionPermissions {1944 mint_mode: None,1945 access: Some(AccessMode::AllowList),1946 nesting: None,1947 }1948 ));1949 assert_noop!(1950 Unique::burn_item(origin1.clone(), CollectionId(1), TokenId(1), 1).map_err(|e| e.error),1951 CommonError::<Test>::AddressNotInAllowlist1952 );1953 });1954}19551956// If Public Access mode is set to AllowList, token transfers can’t be Approved by a non-allowlisted address (see Approve method).1957#[test]1958fn allow_list_test_6() {1959 new_test_ext().execute_with(|| {1960 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));19611962 let origin1 = RuntimeOrigin::signed(1);19631964 let data = default_nft_data();1965 create_test_item(collection_id, &data.into());19661967 assert_ok!(Unique::set_collection_permissions(1968 origin1.clone(),1969 collection_id,1970 CollectionPermissions {1971 mint_mode: None,1972 access: Some(AccessMode::AllowList),1973 nesting: None,1974 }1975 ));19761977 // do approve1978 assert_noop!(1979 Unique::approve(origin1, account(1), CollectionId(1), TokenId(1), 1)1980 .map_err(|e| e.error),1981 CommonError::<Test>::AddressNotInAllowlist1982 );1983 });1984}19851986// If Public Access mode is set to AllowList, tokens can be transferred from a allowlisted address with transfer or transferFrom (2 tests) and1987// tokens can be transferred from a allowlisted address with transfer or transferFrom (2 tests)1988#[test]1989fn allow_list_test_7() {1990 new_test_ext().execute_with(|| {1991 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));19921993 let data = default_nft_data();1994 create_test_item(collection_id, &data.into());19951996 let origin1 = RuntimeOrigin::signed(1);19971998 assert_ok!(Unique::set_collection_permissions(1999 origin1.clone(),2000 collection_id,2001 CollectionPermissions {2002 mint_mode: None,2003 access: Some(AccessMode::AllowList),2004 nesting: None,2005 }2006 ));2007 assert_ok!(Unique::add_to_allow_list(2008 origin1.clone(),2009 collection_id,2010 account(1)2011 ));2012 assert_ok!(Unique::add_to_allow_list(2013 origin1.clone(),2014 collection_id,2015 account(2)2016 ));20172018 assert_ok!(Unique::transfer(2019 origin1,2020 account(2),2021 CollectionId(1),2022 TokenId(1),2023 12024 ));2025 });2026}20272028#[test]2029fn allow_list_test_8() {2030 new_test_ext().execute_with(|| {2031 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));20322033 // Create NFT for account 12034 let data = default_nft_data();2035 create_test_item(collection_id, &data.into());20362037 let origin1 = RuntimeOrigin::signed(1);20382039 // Toggle Allow List mode and add accounts 1 and 22040 assert_ok!(Unique::set_collection_permissions(2041 origin1.clone(),2042 collection_id,2043 CollectionPermissions {2044 mint_mode: None,2045 access: Some(AccessMode::AllowList),2046 nesting: None,2047 }2048 ));2049 assert_ok!(Unique::add_to_allow_list(2050 origin1.clone(),2051 collection_id,2052 account(1)2053 ));2054 assert_ok!(Unique::add_to_allow_list(2055 origin1.clone(),2056 collection_id,2057 account(2)2058 ));20592060 // Sself-approve account 1 for NFT 12061 assert_ok!(Unique::approve(2062 origin1.clone(),2063 account(1),2064 CollectionId(1),2065 TokenId(1),2066 12067 ));2068 assert_eq!(2069 <pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).unwrap(),2070 account(1)2071 );20722073 // Transfer from 1 to 22074 assert_ok!(Unique::transfer_from(2075 origin1,2076 account(1),2077 account(2),2078 CollectionId(1),2079 TokenId(1),2080 12081 ));2082 });2083}20842085// If Public Access mode is set to AllowList, and Mint Permission is set to false, tokens can be created by owner.2086#[test]2087fn allow_list_test_9() {2088 new_test_ext().execute_with(|| {2089 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));2090 let origin1 = RuntimeOrigin::signed(1);20912092 assert_ok!(Unique::set_collection_permissions(2093 origin1.clone(),2094 collection_id,2095 CollectionPermissions {2096 mint_mode: Some(false),2097 access: Some(AccessMode::AllowList),2098 nesting: None,2099 }2100 ));21012102 let data = default_nft_data();2103 create_test_item(collection_id, &data.into());2104 });2105}21062107// If Public Access mode is set to AllowList, and Mint Permission is set to false, tokens can be created by admin.2108#[test]2109fn allow_list_test_10() {2110 new_test_ext().execute_with(|| {2111 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));21122113 let origin1 = RuntimeOrigin::signed(1);2114 let origin2 = RuntimeOrigin::signed(2);21152116 assert_ok!(Unique::set_collection_permissions(2117 origin1.clone(),2118 collection_id,2119 CollectionPermissions {2120 mint_mode: Some(false),2121 access: Some(AccessMode::AllowList),2122 nesting: None,2123 }2124 ));21252126 assert_ok!(Unique::add_collection_admin(2127 origin1,2128 collection_id,2129 account(2)2130 ));21312132 assert_ok!(Unique::create_item(2133 origin2,2134 collection_id,2135 account(2),2136 default_nft_data().into()2137 ));2138 });2139}21402141// If Public Access mode is set to AllowList, and Mint Permission is set to false, tokens cannot be created by non-privileged and allow listed address.2142#[test]2143fn allow_list_test_11() {2144 new_test_ext().execute_with(|| {2145 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));21462147 let origin1 = RuntimeOrigin::signed(1);2148 let origin2 = RuntimeOrigin::signed(2);21492150 assert_ok!(Unique::set_collection_permissions(2151 origin1.clone(),2152 collection_id,2153 CollectionPermissions {2154 mint_mode: Some(false),2155 access: Some(AccessMode::AllowList),2156 nesting: None,2157 }2158 ));2159 assert_ok!(Unique::add_to_allow_list(2160 origin1,2161 collection_id,2162 account(2)2163 ));21642165 assert_noop!(2166 Unique::create_item(2167 origin2,2168 CollectionId(1),2169 account(2),2170 default_nft_data().into()2171 )2172 .map_err(|e| e.error),2173 CommonError::<Test>::PublicMintingNotAllowed2174 );2175 });2176}21772178// If Public Access mode is set to AllowList, and Mint Permission is set to false, tokens cannot be created by non-privileged and non-allow listed address.2179#[test]2180fn allow_list_test_12() {2181 new_test_ext().execute_with(|| {2182 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));21832184 let origin1 = RuntimeOrigin::signed(1);2185 let origin2 = RuntimeOrigin::signed(2);21862187 assert_ok!(Unique::set_collection_permissions(2188 origin1.clone(),2189 collection_id,2190 CollectionPermissions {2191 mint_mode: Some(false),2192 access: Some(AccessMode::AllowList),2193 nesting: None,2194 }2195 ));21962197 assert_noop!(2198 Unique::create_item(2199 origin2,2200 CollectionId(1),2201 account(2),2202 default_nft_data().into()2203 )2204 .map_err(|e| e.error),2205 CommonError::<Test>::PublicMintingNotAllowed2206 );2207 });2208}22092210// If Public Access mode is set to AllowList, and Mint Permission is set to true, tokens can be created by owner.2211#[test]2212fn allow_list_test_13() {2213 new_test_ext().execute_with(|| {2214 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));22152216 let origin1 = RuntimeOrigin::signed(1);22172218 assert_ok!(Unique::set_collection_permissions(2219 origin1.clone(),2220 collection_id,2221 CollectionPermissions {2222 mint_mode: Some(true),2223 access: Some(AccessMode::AllowList),2224 nesting: None,2225 }2226 ));22272228 let data = default_nft_data();2229 create_test_item(collection_id, &data.into());2230 });2231}22322233// If Public Access mode is set to AllowList, and Mint Permission is set to true, tokens can be created by admin.2234#[test]2235fn allow_list_test_14() {2236 new_test_ext().execute_with(|| {2237 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));22382239 let origin1 = RuntimeOrigin::signed(1);2240 let origin2 = RuntimeOrigin::signed(2);22412242 assert_ok!(Unique::set_collection_permissions(2243 origin1.clone(),2244 collection_id,2245 CollectionPermissions {2246 mint_mode: Some(true),2247 access: Some(AccessMode::AllowList),2248 nesting: None,2249 }2250 ));22512252 assert_ok!(Unique::add_collection_admin(2253 origin1,2254 collection_id,2255 account(2)2256 ));22572258 assert_ok!(Unique::create_item(2259 origin2,2260 collection_id,2261 account(2),2262 default_nft_data().into()2263 ));2264 });2265}22662267// If Public Access mode is set to AllowList, and Mint Permission is set to true, tokens cannot be created by non-privileged and non-allow listed address.2268#[test]2269fn allow_list_test_15() {2270 new_test_ext().execute_with(|| {2271 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));22722273 let origin1 = RuntimeOrigin::signed(1);2274 let origin2 = RuntimeOrigin::signed(2);22752276 assert_ok!(Unique::set_collection_permissions(2277 origin1.clone(),2278 collection_id,2279 CollectionPermissions {2280 mint_mode: Some(true),2281 access: Some(AccessMode::AllowList),2282 nesting: None,2283 }2284 ));22852286 assert_noop!(2287 Unique::create_item(2288 origin2,2289 collection_id,2290 account(2),2291 default_nft_data().into()2292 )2293 .map_err(|e| e.error),2294 CommonError::<Test>::AddressNotInAllowlist2295 );2296 });2297}22982299// If Public Access mode is set to AllowList, and Mint Permission is set to true, tokens can be created by non-privileged and allow listed address.2300#[test]2301fn allow_list_test_16() {2302 new_test_ext().execute_with(|| {2303 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));23042305 let origin1 = RuntimeOrigin::signed(1);2306 let origin2 = RuntimeOrigin::signed(2);23072308 assert_ok!(Unique::set_collection_permissions(2309 origin1.clone(),2310 collection_id,2311 CollectionPermissions {2312 mint_mode: Some(true),2313 access: Some(AccessMode::AllowList),2314 nesting: None,2315 }2316 ));2317 assert_ok!(Unique::add_to_allow_list(2318 origin1,2319 collection_id,2320 account(2)2321 ));23222323 assert_ok!(Unique::create_item(2324 origin2,2325 collection_id,2326 account(2),2327 default_nft_data().into()2328 ));2329 });2330}23312332// Total number of collections. Positive test2333#[test]2334fn total_number_collections_bound() {2335 new_test_ext().execute_with(|| {2336 create_test_collection(&CollectionMode::NFT, CollectionId(1));2337 });2338}23392340#[test]2341fn create_max_collections() {2342 new_test_ext().execute_with(|| {2343 for i in 1..COLLECTION_NUMBER_LIMIT {2344 create_test_collection(&CollectionMode::NFT, CollectionId(i));2345 }2346 });2347}23482349// Total number of collections. Negative test2350#[test]2351fn total_number_collections_bound_neg() {2352 new_test_ext().execute_with(|| {2353 let origin1 = RuntimeOrigin::signed(1);23542355 for i in 1..=COLLECTION_NUMBER_LIMIT {2356 create_test_collection(&CollectionMode::NFT, CollectionId(i));2357 }23582359 let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();2360 let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();2361 let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();23622363 let data: CreateCollectionData<u64> = CreateCollectionData {2364 name: col_name1.try_into().unwrap(),2365 description: col_desc1.try_into().unwrap(),2366 token_prefix: token_prefix1.try_into().unwrap(),2367 mode: CollectionMode::NFT,2368 ..Default::default()2369 };23702371 // 11-th collection in chain. Expects error2372 assert_noop!(2373 Unique::create_collection_ex(origin1, data),2374 CommonError::<Test>::TotalCollectionsLimitExceeded2375 );2376 });2377}23782379// Owned tokens by a single address. Positive test2380#[test]2381fn owned_tokens_bound() {2382 new_test_ext().execute_with(|| {2383 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));23842385 let data = default_nft_data();2386 create_test_item(collection_id, &data.clone().into());2387 create_test_item(collection_id, &data.into());2388 });2389}23902391// Owned tokens by a single address. Negotive test2392#[test]2393fn owned_tokens_bound_neg() {2394 new_test_ext().execute_with(|| {2395 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));23962397 let origin1 = RuntimeOrigin::signed(1);23982399 for _ in 1..=MAX_TOKEN_OWNERSHIP {2400 let data = default_nft_data();2401 create_test_item(collection_id, &data.clone().into());2402 }24032404 let data = default_nft_data();2405 assert_noop!(2406 Unique::create_item(origin1, CollectionId(1), account(1), data.into())2407 .map_err(|e| e.error),2408 CommonError::<Test>::AccountTokenLimitExceeded2409 );2410 });2411}24122413// Number of collection admins. Positive test2414#[test]2415fn collection_admins_bound() {2416 new_test_ext().execute_with(|| {2417 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));24182419 let origin1 = RuntimeOrigin::signed(1);24202421 assert_ok!(Unique::add_collection_admin(2422 origin1.clone(),2423 collection_id,2424 account(2)2425 ));2426 assert_ok!(Unique::add_collection_admin(2427 origin1,2428 collection_id,2429 account(3)2430 ));2431 });2432}24332434// Number of collection admins. Negotive test2435#[test]2436fn collection_admins_bound_neg() {2437 new_test_ext().execute_with(|| {2438 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));24392440 let origin1 = RuntimeOrigin::signed(1);24412442 for i in 0..COLLECTION_ADMINS_LIMIT {2443 assert_ok!(Unique::add_collection_admin(2444 origin1.clone(),2445 collection_id,2446 account((2 + i).into())2447 ));2448 }2449 assert_noop!(2450 Unique::add_collection_admin(2451 origin1,2452 collection_id,2453 account((3 + COLLECTION_ADMINS_LIMIT).into())2454 ),2455 CommonError::<Test>::CollectionAdminCountExceeded2456 );2457 });2458}2459// #endregion24602461#[test]2462fn collection_transfer_flag_works() {2463 new_test_ext().execute_with(|| {2464 let origin1 = RuntimeOrigin::signed(1);24652466 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));2467 assert_ok!(Unique::set_transfers_enabled_flag(2468 origin1,2469 collection_id,2470 true2471 ));24722473 let data = default_nft_data();2474 create_test_item(collection_id, &data.into());2475 assert_eq!(2476 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),2477 12478 );2479 assert_eq!(2480 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),2481 true2482 );24832484 let origin1 = RuntimeOrigin::signed(1);24852486 // default scenario2487 assert_ok!(Unique::transfer(2488 origin1,2489 account(2),2490 collection_id,2491 TokenId(1),2492 12493 ));2494 assert_eq!(2495 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),2496 false2497 );2498 assert_eq!(2499 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(2), TokenId(1))),2500 true2501 );2502 assert_eq!(2503 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),2504 02505 );2506 assert_eq!(2507 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(2))),2508 12509 );2510 });2511}25122513#[test]2514fn collection_transfer_flag_works_neg() {2515 new_test_ext().execute_with(|| {2516 let origin1 = RuntimeOrigin::signed(1);25172518 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));2519 assert_ok!(Unique::set_transfers_enabled_flag(2520 origin1,2521 collection_id,2522 false2523 ));25242525 let data = default_nft_data();2526 create_test_item(collection_id, &data.into());2527 assert_eq!(2528 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),2529 12530 );2531 assert_eq!(2532 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),2533 true2534 );25352536 let origin1 = RuntimeOrigin::signed(1);25372538 // default scenario2539 assert_noop!(2540 Unique::transfer(origin1, account(2), CollectionId(1), TokenId(1), 1)2541 .map_err(|e| e.error),2542 CommonError::<Test>::TransferNotAllowed2543 );2544 assert_eq!(2545 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),2546 12547 );2548 assert_eq!(2549 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(2))),2550 02551 );2552 assert_eq!(2553 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),2554 true2555 );2556 assert_eq!(2557 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(2), TokenId(1))),2558 false2559 );2560 });2561}25622563#[test]2564fn collection_sponsoring() {2565 new_test_ext().execute_with(|| {2566 // default_limits();2567 let user1 = 1_u64;2568 let user2 = 777_u64;2569 let origin1 = RuntimeOrigin::signed(user1);2570 let origin2 = RuntimeOrigin::signed(user2);2571 let account2 = account(user2);25722573 let collection_id =2574 create_test_collection_for_owner(&CollectionMode::NFT, user1, CollectionId(1));2575 assert_ok!(Unique::set_collection_sponsor(2576 origin1.clone(),2577 collection_id,2578 user12579 ));2580 assert_ok!(Unique::confirm_sponsorship(origin1.clone(), collection_id));25812582 // Expect error while have no permissions2583 assert!(Unique::create_item(2584 origin2.clone(),2585 collection_id,2586 account2.clone(),2587 default_nft_data().into()2588 )2589 .is_err());25902591 assert_ok!(Unique::set_collection_permissions(2592 origin1.clone(),2593 collection_id,2594 CollectionPermissions {2595 mint_mode: Some(true),2596 access: Some(AccessMode::AllowList),2597 nesting: None,2598 }2599 ));2600 assert_ok!(Unique::add_to_allow_list(2601 origin1.clone(),2602 collection_id,2603 account2.clone()2604 ));26052606 assert_ok!(Unique::create_item(2607 origin2,2608 collection_id,2609 account2,2610 default_nft_data().into()2611 ));2612 });2613}tests/src/eth/abi/fungible.jsondiffbeforeafterboth--- a/tests/src/eth/abi/fungible.json
+++ b/tests/src/eth/abi/fungible.json
@@ -488,7 +488,9 @@
"type": "function"
},
{
- "inputs": [{ "internalType": "uint8", "name": "mode", "type": "uint8" }],
+ "inputs": [
+ { "internalType": "enum AccessMode", "name": "mode", "type": "uint8" }
+ ],
"name": "setCollectionAccess",
"outputs": [],
"stateMutability": "nonpayable",
tests/src/eth/abi/nonFungible.jsondiffbeforeafterboth--- a/tests/src/eth/abi/nonFungible.json
+++ b/tests/src/eth/abi/nonFungible.json
@@ -630,7 +630,9 @@
"type": "function"
},
{
- "inputs": [{ "internalType": "uint8", "name": "mode", "type": "uint8" }],
+ "inputs": [
+ { "internalType": "enum AccessMode", "name": "mode", "type": "uint8" }
+ ],
"name": "setCollectionAccess",
"outputs": [],
"stateMutability": "nonpayable",
tests/src/eth/abi/reFungible.jsondiffbeforeafterboth--- a/tests/src/eth/abi/reFungible.json
+++ b/tests/src/eth/abi/reFungible.json
@@ -612,7 +612,9 @@
"type": "function"
},
{
- "inputs": [{ "internalType": "uint8", "name": "mode", "type": "uint8" }],
+ "inputs": [
+ { "internalType": "enum AccessMode", "name": "mode", "type": "uint8" }
+ ],
"name": "setCollectionAccess",
"outputs": [],
"stateMutability": "nonpayable",
tests/src/eth/api/UniqueFungible.soldiffbeforeafterboth--- a/tests/src/eth/api/UniqueFungible.sol
+++ b/tests/src/eth/api/UniqueFungible.sol
@@ -175,11 +175,9 @@
/// Set the collection access method.
/// @param mode Access mode
- /// 0 for Normal
- /// 1 for AllowList
/// @dev EVM selector for this function is: 0x41835d4c,
/// or in textual repr: setCollectionAccess(uint8)
- function setCollectionAccess(uint8 mode) external;
+ function setCollectionAccess(AccessMode mode) external;
/// Checks that user allowed to operate with collection.
///
@@ -285,6 +283,14 @@
uint256 sub;
}
+/// Ethereum representation of `AccessMode` (see [`up_data_structs::AccessMode`]).
+enum AccessMode {
+ /// Access grant for owner and admins. Used as default.
+ Normal,
+ /// Like a [`Normal`](AccessMode::Normal) but also users in allow list.
+ AllowList
+}
+
/// Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) field.
struct CollectionNestingPermission {
CollectionPermissionField field;
tests/src/eth/api/UniqueNFT.soldiffbeforeafterboth--- a/tests/src/eth/api/UniqueNFT.sol
+++ b/tests/src/eth/api/UniqueNFT.sol
@@ -275,11 +275,9 @@
/// Set the collection access method.
/// @param mode Access mode
- /// 0 for Normal
- /// 1 for AllowList
/// @dev EVM selector for this function is: 0x41835d4c,
/// or in textual repr: setCollectionAccess(uint8)
- function setCollectionAccess(uint8 mode) external;
+ function setCollectionAccess(AccessMode mode) external;
/// Checks that user allowed to operate with collection.
///
@@ -385,6 +383,14 @@
uint256 sub;
}
+/// Ethereum representation of `AccessMode` (see [`up_data_structs::AccessMode`]).
+enum AccessMode {
+ /// Access grant for owner and admins. Used as default.
+ Normal,
+ /// Like a [`Normal`](AccessMode::Normal) but also users in allow list.
+ AllowList
+}
+
/// Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) field.
struct CollectionNestingPermission {
CollectionPermissionField field;
tests/src/eth/api/UniqueRefungible.soldiffbeforeafterboth--- a/tests/src/eth/api/UniqueRefungible.sol
+++ b/tests/src/eth/api/UniqueRefungible.sol
@@ -275,11 +275,9 @@
/// Set the collection access method.
/// @param mode Access mode
- /// 0 for Normal
- /// 1 for AllowList
/// @dev EVM selector for this function is: 0x41835d4c,
/// or in textual repr: setCollectionAccess(uint8)
- function setCollectionAccess(uint8 mode) external;
+ function setCollectionAccess(AccessMode mode) external;
/// Checks that user allowed to operate with collection.
///
@@ -385,6 +383,14 @@
uint256 sub;
}
+/// Ethereum representation of `AccessMode` (see [`up_data_structs::AccessMode`]).
+enum AccessMode {
+ /// Access grant for owner and admins. Used as default.
+ Normal,
+ /// Like a [`Normal`](AccessMode::Normal) but also users in allow list.
+ AllowList
+}
+
/// Ethereum representation of `NestingPermissions` (see [`up_data_structs::NestingPermissions`]) field.
struct CollectionNestingPermission {
CollectionPermissionField field;