git.delta.rocks / unique-network / refs/commits / 9efdf3945665

difftreelog

Merge branch 'develop' into tests/require-await

Max Andreev2022-10-27parents: #9a3b012 #1c71798.patch.diff
in: master

91 files changed

modifiedCargo.lockdiffbeforeafterboth
746source = "registry+https://github.com/rust-lang/crates.io-index"746source = "registry+https://github.com/rust-lang/crates.io-index"
747checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223"747checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223"
748dependencies = [748dependencies = [
749 "lazy_static",
749 "memchr",750 "memchr",
751 "regex-automata",
750]752]
751753
752[[package]]754[[package]]
1054 "unicode-width",1056 "unicode-width",
1055]1057]
1058
1059[[package]]
1060name = "concat-idents"
1061version = "1.1.3"
1062source = "registry+https://github.com/rust-lang/crates.io-index"
1063checksum = "4b6f90860248d75014b7b103db8fee4f291c07bfb41306cdf77a0a5ab7a10d2f"
1064dependencies = [
1065 "quote",
1066 "syn",
1067]
10561068
1057[[package]]1069[[package]]
1058name = "concurrent-queue"1070name = "concurrent-queue"
1063 "cache-padded",1075 "cache-padded",
1064]1076]
1077
1078[[package]]
1079name = "console"
1080version = "0.15.2"
1081source = "registry+https://github.com/rust-lang/crates.io-index"
1082checksum = "c050367d967ced717c04b65d8c619d863ef9292ce0c5760028655a2fb298718c"
1083dependencies = [
1084 "encode_unicode",
1085 "lazy_static",
1086 "libc",
1087 "terminal_size",
1088 "winapi",
1089]
10651090
1066[[package]]1091[[package]]
1067name = "const-oid"1092name = "const-oid"
18461871
1847[[package]]1872[[package]]
1848name = "cxx"1873name = "cxx"
1849version = "1.0.79"1874version = "1.0.78"
1850source = "registry+https://github.com/rust-lang/crates.io-index"1875source = "registry+https://github.com/rust-lang/crates.io-index"
1851checksum = "3f83d0ebf42c6eafb8d7c52f7e5f2d3003b89c7aa4fd2b79229209459a849af8"1876checksum = "19f39818dcfc97d45b03953c1292efc4e80954e1583c4aa770bac1383e2310a4"
1852dependencies = [1877dependencies = [
1853 "cc",1878 "cc",
1854 "cxxbridge-flags",1879 "cxxbridge-flags",
18581883
1859[[package]]1884[[package]]
1860name = "cxx-build"1885name = "cxx-build"
1861version = "1.0.79"1886version = "1.0.78"
1862source = "registry+https://github.com/rust-lang/crates.io-index"1887source = "registry+https://github.com/rust-lang/crates.io-index"
1863checksum = "07d050484b55975889284352b0ffc2ecbda25c0c55978017c132b29ba0818a86"1888checksum = "3e580d70777c116df50c390d1211993f62d40302881e54d4b79727acb83d0199"
1864dependencies = [1889dependencies = [
1865 "cc",1890 "cc",
1866 "codespan-reporting",1891 "codespan-reporting",
18731898
1874[[package]]1899[[package]]
1875name = "cxxbridge-flags"1900name = "cxxbridge-flags"
1876version = "1.0.79"1901version = "1.0.78"
1877source = "registry+https://github.com/rust-lang/crates.io-index"1902source = "registry+https://github.com/rust-lang/crates.io-index"
1878checksum = "99d2199b00553eda8012dfec8d3b1c75fce747cf27c169a270b3b99e3448ab78"1903checksum = "56a46460b88d1cec95112c8c363f0e2c39afdb237f60583b0b36343bf627ea9c"
18791904
1880[[package]]1905[[package]]
1881name = "cxxbridge-macro"1906name = "cxxbridge-macro"
1882version = "1.0.79"1907version = "1.0.78"
1883source = "registry+https://github.com/rust-lang/crates.io-index"1908source = "registry+https://github.com/rust-lang/crates.io-index"
1884checksum = "dcb67a6de1f602736dd7eaead0080cf3435df806c61b24b13328db128c58868f"1909checksum = "747b608fecf06b0d72d440f27acc99288207324b793be2c17991839f3d4995ea"
1885dependencies = [1910dependencies = [
1886 "proc-macro2",1911 "proc-macro2",
1887 "quote",1912 "quote",
2139 "zeroize",2164 "zeroize",
2140]2165]
2166
2167[[package]]
2168name = "encode_unicode"
2169version = "0.3.6"
2170source = "registry+https://github.com/rust-lang/crates.io-index"
2171checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
21412172
2142[[package]]2173[[package]]
2143name = "enum-as-inner"2174name = "enum-as-inner"
2302name = "evm-coder"2333name = "evm-coder"
2303version = "0.1.3"2334version = "0.1.3"
2304dependencies = [2335dependencies = [
2336 "concat-idents",
2305 "ethereum",2337 "ethereum",
2306 "evm-coder-procedural",2338 "evm-coder-procedural",
2307 "evm-core",2339 "evm-core",
2310 "hex-literal",2342 "hex-literal",
2311 "impl-trait-for-tuples",2343 "impl-trait-for-tuples",
2312 "primitive-types",2344 "primitive-types",
2345 "similar-asserts",
2313 "sp-std",2346 "sp-std",
2314]2347]
23152348
35283561
3529[[package]]3562[[package]]
3530name = "iana-time-zone-haiku"3563name = "iana-time-zone-haiku"
3531version = "0.1.1"3564version = "0.1.0"
3532source = "registry+https://github.com/rust-lang/crates.io-index"3565source = "registry+https://github.com/rust-lang/crates.io-index"
3533checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca"3566checksum = "fde6edd6cef363e9359ed3c98ba64590ba9eecba2293eb5a723ab32aee8926aa"
3534dependencies = [3567dependencies = [
3535 "cxx",3568 "cxx",
3536 "cxx-build",3569 "cxx-build",
5345 "pallet-structure",5378 "pallet-structure",
5346 "pallet-sudo",5379 "pallet-sudo",
5347 "pallet-template-transaction-payment",5380 "pallet-template-transaction-payment",
5381 "pallet-test-utils",
5348 "pallet-timestamp",5382 "pallet-timestamp",
5349 "pallet-transaction-payment",5383 "pallet-transaction-payment",
5350 "pallet-transaction-payment-rpc-runtime-api",5384 "pallet-transaction-payment-rpc-runtime-api",
5351 "pallet-treasury",5385 "pallet-treasury",
5352 "pallet-unique",5386 "pallet-unique",
5353 "pallet-unique-scheduler",5387 "pallet-unique-scheduler",
5388 "pallet-unique-scheduler-v2",
5354 "pallet-xcm",5389 "pallet-xcm",
5355 "parachain-info",5390 "parachain-info",
5356 "parity-scale-codec 3.2.1",5391 "parity-scale-codec 3.2.1",
57925827
5793[[package]]5828[[package]]
5794name = "pallet-common"5829name = "pallet-common"
5795version = "0.1.8"5830version = "0.1.9"
5796dependencies = [5831dependencies = [
5797 "ethereum",5832 "ethereum",
5798 "evm-coder",5833 "evm-coder",
63256360
6326[[package]]6361[[package]]
6327name = "pallet-nonfungible"6362name = "pallet-nonfungible"
6328version = "0.1.5"6363version = "0.1.6"
6329dependencies = [6364dependencies = [
6330 "ethereum",6365 "ethereum",
6331 "evm-coder",6366 "evm-coder",
64476482
6448[[package]]6483[[package]]
6449name = "pallet-refungible"6484name = "pallet-refungible"
6450version = "0.2.4"6485version = "0.2.5"
6451dependencies = [6486dependencies = [
6452 "derivative",6487 "derivative",
6453 "ethereum",6488 "ethereum",
6668 "up-sponsorship",6703 "up-sponsorship",
6669]6704]
6705
6706[[package]]
6707name = "pallet-test-utils"
6708version = "0.1.0"
6709dependencies = [
6710 "frame-support",
6711 "frame-system",
6712 "pallet-unique-scheduler-v2",
6713 "parity-scale-codec 3.2.1",
6714 "scale-info",
6715]
66706716
6671[[package]]6717[[package]]
6672name = "pallet-timestamp"6718name = "pallet-timestamp"
67666812
6767[[package]]6813[[package]]
6768name = "pallet-unique"6814name = "pallet-unique"
6769version = "0.2.0"6815version = "0.2.1"
6770dependencies = [6816dependencies = [
6771 "ethereum",6817 "ethereum",
6772 "evm-coder",6818 "evm-coder",
6807 "up-sponsorship",6853 "up-sponsorship",
6808]6854]
6855
6856[[package]]
6857name = "pallet-unique-scheduler-v2"
6858version = "0.1.0"
6859dependencies = [
6860 "frame-benchmarking",
6861 "frame-support",
6862 "frame-system",
6863 "log",
6864 "pallet-preimage",
6865 "parity-scale-codec 3.2.1",
6866 "scale-info",
6867 "sp-core",
6868 "sp-io",
6869 "sp-runtime",
6870 "sp-std",
6871 "substrate-test-utils",
6872]
68096873
6810[[package]]6874[[package]]
6811name = "pallet-utility"6875name = "pallet-utility"
1074110805
10742[[package]]10806[[package]]
10743name = "serde_json"10807name = "serde_json"
10744version = "1.0.87"10808version = "1.0.86"
10745source = "registry+https://github.com/rust-lang/crates.io-index"10809source = "registry+https://github.com/rust-lang/crates.io-index"
10746checksum = "6ce777b7b150d76b9cf60d28b55f5847135a003f7d7350c6be7a773508ce7d45"10810checksum = "41feea4228a6f1cd09ec7a3593a682276702cd67b5273544757dae23c096f074"
10747dependencies = [10811dependencies = [
10748 "itoa",10812 "itoa",
10749 "ryu",10813 "ryu",
10885 "paste",10949 "paste",
10886]10950]
10951
10952[[package]]
10953name = "similar"
10954version = "2.2.0"
10955source = "registry+https://github.com/rust-lang/crates.io-index"
10956checksum = "62ac7f900db32bf3fd12e0117dd3dc4da74bc52ebaac97f39668446d89694803"
10957dependencies = [
10958 "bstr",
10959 "unicode-segmentation",
10960]
10961
10962[[package]]
10963name = "similar-asserts"
10964version = "1.4.2"
10965source = "registry+https://github.com/rust-lang/crates.io-index"
10966checksum = "bbf644ad016b75129f01a34a355dcb8d66a5bc803e417c7a77cc5d5ee9fa0f18"
10967dependencies = [
10968 "console",
10969 "similar",
10970]
1088710971
10888[[package]]10972[[package]]
10889name = "slab"10973name = "slab"
1200212086
12003[[package]]12087[[package]]
12004name = "syn"12088name = "syn"
12005version = "1.0.103"12089version = "1.0.102"
12006source = "registry+https://github.com/rust-lang/crates.io-index"12090source = "registry+https://github.com/rust-lang/crates.io-index"
12007checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d"12091checksum = "3fcd952facd492f9be3ef0d0b7032a6e442ee9b361d4acc2b1d0c4aaa5f613a1"
12008dependencies = [12092dependencies = [
12009 "proc-macro2",12093 "proc-macro2",
12010 "quote",12094 "quote",
12079 "winapi-util",12163 "winapi-util",
12080]12164]
12165
12166[[package]]
12167name = "terminal_size"
12168version = "0.1.17"
12169source = "registry+https://github.com/rust-lang/crates.io-index"
12170checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df"
12171dependencies = [
12172 "libc",
12173 "winapi",
12174]
1208112175
12082[[package]]12176[[package]]
12083name = "test-runtime-constants"12177name = "test-runtime-constants"
12659 "tinyvec",12753 "tinyvec",
12660]12754]
12755
12756[[package]]
12757name = "unicode-segmentation"
12758version = "1.10.0"
12759source = "registry+https://github.com/rust-lang/crates.io-index"
12760checksum = "0fdbf052a0783de01e944a6ce7a8cb939e295b1e7be835a1112c3b9a7f047a5a"
1266112761
12662[[package]]12762[[package]]
12663name = "unicode-width"12763name = "unicode-width"
modifiedCargo.tomldiffbeforeafterboth

no syntactic changes

modifiedclient/rpc/src/lib.rsdiffbeforeafterboth
558 pass_method!(allowed(collection: CollectionId, user: CrossAccountId) -> bool, unique_api);558 pass_method!(allowed(collection: CollectionId, user: CrossAccountId) -> bool, unique_api);
559 pass_method!(last_token_id(collection: CollectionId) -> TokenId, unique_api);559 pass_method!(last_token_id(collection: CollectionId) -> TokenId, unique_api);
560 pass_method!(collection_by_id(collection: CollectionId) -> Option<RpcCollection<AccountId>>, unique_api);560 pass_method!(
561 collection_by_id(collection: CollectionId) -> Option<RpcCollection<AccountId>>, unique_api;
562 changed_in 3, collection_by_id_before_version_3(collection) => |value| value.map(|coll| coll.into())
563 );
561 pass_method!(collection_stats() -> CollectionStats, unique_api);564 pass_method!(collection_stats() -> CollectionStats, unique_api);
562 pass_method!(next_sponsored(collection: CollectionId, account: CrossAccountId, token: TokenId) -> Option<u64>, unique_api);565 pass_method!(next_sponsored(collection: CollectionId, account: CrossAccountId, token: TokenId) -> Option<u64>, unique_api);
modifiedcrates/evm-coder/Cargo.tomldiffbeforeafterboth
22# We want to assert some large binary blobs equality in tests22# We want to assert some large binary blobs equality in tests
23hex = "0.4.3"23hex = "0.4.3"
24hex-literal = "0.3.4"24hex-literal = "0.3.4"
25similar-asserts = "1.4.2"
26concat-idents = "1.1.3"
2527
26[features]28[features]
27default = ["std"]29default = ["std"]
modifiedcrates/evm-coder/src/abi.rsdiffbeforeafterboth
2525
26use crate::{26use crate::{
27 execution::{Error, ResultWithPostInfo, WithPostDispatchInfo},27 execution::{Error, ResultWithPostInfo, WithPostDispatchInfo},
28 types::{string, self},28 types::*,
29};29};
30use crate::execution::Result;30use crate::execution::Result;
3131
32const ABI_ALIGNMENT: usize = 32;32const ABI_ALIGNMENT: usize = 32;
3333
34trait TypeHelper {34trait TypeHelper {
35 /// Is type dynamic sized.
35 fn is_dynamic() -> bool;36 fn is_dynamic() -> bool;
37
38 /// Size for type aligned to [`ABI_ALIGNMENT`].
39 fn size() -> usize;
36}40}
3741
38/// View into RLP data, which provides method to read typed items from it42/// View into RLP data, which provides method to read typed items from it
52 }56 }
53 }57 }
54 /// Start reading RLP buffer, parsing first 4 bytes as selector58 /// Start reading RLP buffer, parsing first 4 bytes as selector
55 pub fn new_call(buf: &'i [u8]) -> Result<(types::bytes4, Self)> {59 pub fn new_call(buf: &'i [u8]) -> Result<(bytes4, Self)> {
56 if buf.len() < 4 {60 if buf.len() < 4 {
57 return Err(Error::Error(ExitError::OutOfOffset));61 return Err(Error::Error(ExitError::OutOfOffset));
58 }62 }
218 static_part: Vec<u8>,222 static_part: Vec<u8>,
219 dynamic_part: Vec<(usize, AbiWriter)>,223 dynamic_part: Vec<(usize, AbiWriter)>,
220 had_call: bool,224 had_call: bool,
225 is_dynamic: bool,
221}226}
222impl AbiWriter {227impl AbiWriter {
223 /// Initialize internal buffers for output data, assuming no padding required228 /// Initialize internal buffers for output data, assuming no padding required
224 pub fn new() -> Self {229 pub fn new() -> Self {
225 Self::default()230 Self::default()
226 }231 }
232
233 /// Initialize internal buffers with data size
234 pub fn new_dynamic(is_dynamic: bool) -> Self {
235 Self {
236 is_dynamic,
237 ..Default::default()
238 }
239 }
227 /// Initialize internal buffers, inserting method selector at beginning240 /// Initialize internal buffers, inserting method selector at beginning
228 pub fn new_call(method_id: u32) -> Self {241 pub fn new_call(method_id: u32) -> Self {
229 let mut val = Self::new();242 let mut val = Self::new();
239 self.static_part.extend(block);252 self.static_part.extend(block);
240 }253 }
241254
242 fn write_padright(&mut self, bytes: &[u8]) {255 fn write_padright(&mut self, block: &[u8]) {
243 assert!(bytes.len() <= ABI_ALIGNMENT);256 assert!(block.len() <= ABI_ALIGNMENT);
244 self.static_part.extend(bytes);257 self.static_part.extend(block);
245 self.static_part258 self.static_part
246 .extend(&[0; ABI_ALIGNMENT][0..ABI_ALIGNMENT - bytes.len()]);259 .extend(&[0; ABI_ALIGNMENT][0..ABI_ALIGNMENT - block.len()]);
247 }260 }
248261
249 /// Write [`H160`] to end of buffer262 /// Write [`H160`] to end of buffer
315 for (static_offset, part) in self.dynamic_part {328 for (static_offset, part) in self.dynamic_part {
316 let part_offset = self.static_part.len() - if self.had_call { 4 } else { 0 };329 let part_offset = self.static_part.len()
330 - if self.had_call { 4 } else { 0 }
331 - if self.is_dynamic { ABI_ALIGNMENT } else { 0 };
317332
318 let encoded_dynamic_offset = usize::to_be_bytes(part_offset);333 let encoded_dynamic_offset = usize::to_be_bytes(part_offset);
334 let start = static_offset + ABI_ALIGNMENT - encoded_dynamic_offset.len();
335 let stop = static_offset + ABI_ALIGNMENT;
319 self.static_part[static_offset + ABI_ALIGNMENT - encoded_dynamic_offset.len()336 self.static_part[start..stop].copy_from_slice(&encoded_dynamic_offset);
320 ..static_offset + ABI_ALIGNMENT]
321 .copy_from_slice(&encoded_dynamic_offset);
322 self.static_part.extend(part.finish())337 self.static_part.extend(part.finish())
323 }338 }
334 /// Read item from current position, advanding decoder349 /// Read item from current position, advanding decoder
335 fn abi_read(&mut self) -> Result<T>;350 fn abi_read(&mut self) -> Result<T>;
336
337 /// Size for type aligned to [`ABI_ALIGNMENT`].
338 fn size() -> usize;
339}351}
340352
341macro_rules! impl_abi_readable {353macro_rules! impl_abi_readable {
345 $dynamic357 $dynamic
346 }358 }
359
360 fn size() -> usize {
361 ABI_ALIGNMENT
362 }
347 }363 }
348 impl AbiRead<$ty> for AbiReader<'_> {364 impl AbiRead<$ty> for AbiReader<'_> {
349 fn abi_read(&mut self) -> Result<$ty> {365 fn abi_read(&mut self) -> Result<$ty> {
350 self.$method()366 self.$method()
351 }367 }
352
353 fn size() -> usize {
354 ABI_ALIGNMENT
355 }
356 }368 }
357 };369 };
358}370}
359371
372impl_abi_readable!(bool, bool, false);
360impl_abi_readable!(u8, uint8, false);373impl_abi_readable!(uint8, uint8, false);
361impl_abi_readable!(u32, uint32, false);374impl_abi_readable!(uint32, uint32, false);
362impl_abi_readable!(u64, uint64, false);375impl_abi_readable!(uint64, uint64, false);
363impl_abi_readable!(u128, uint128, false);376impl_abi_readable!(uint128, uint128, false);
364impl_abi_readable!(U256, uint256, false);377impl_abi_readable!(uint256, uint256, false);
365impl_abi_readable!([u8; 4], bytes4, false);378impl_abi_readable!(bytes4, bytes4, false);
366impl_abi_readable!(H160, address, false);379impl_abi_readable!(address, address, false);
367impl_abi_readable!(Vec<u8>, bytes, true);
368impl_abi_readable!(bool, bool, true);
369impl_abi_readable!(string, string, true);380impl_abi_readable!(string, string, true);
381// impl_abi_readable!(bytes, bytes, true);
382
383impl TypeHelper for bytes {
384 fn is_dynamic() -> bool {
385 true
386 }
387 fn size() -> usize {
388 ABI_ALIGNMENT
389 }
390}
391impl AbiRead<bytes> for AbiReader<'_> {
392 fn abi_read(&mut self) -> Result<bytes> {
393 Ok(bytes(self.bytes()?))
394 }
395}
370396
371mod sealed {397mod sealed {
372 /// Not all types can be placed in vec, i.e `Vec<u8>` is restricted, `bytes` should be used instead398 /// Not all types can be placed in vec, i.e `Vec<u8>` is restricted, `bytes` should be used instead
392 Ok(out)418 Ok(out)
393 }419 }
394
395 fn size() -> usize {
396 ABI_ALIGNMENT
397 }
398}420}
399421
400macro_rules! impl_tuples {422macro_rules! impl_tuples {
401 ($($ident:ident)+) => {423 ($($ident:ident)+) => {
402 impl<$($ident: TypeHelper,)+> TypeHelper for ($($ident,)+) {424 impl<$($ident: TypeHelper,)+> TypeHelper for ($($ident,)+)
425 where
426 $(
427 $ident: TypeHelper,
428 )+
429 {
403 fn is_dynamic() -> bool {430 fn is_dynamic() -> bool {
404 false431 false
407 )*434 )*
408 }435 }
436
437 fn size() -> usize {
438 0 $(+ <$ident>::size())+
439 }
409 }440 }
410 impl<$($ident),+> sealed::CanBePlacedInVec for ($($ident,)+) {}441 impl<$($ident),+> sealed::CanBePlacedInVec for ($($ident,)+) {}
411 impl<$($ident),+> AbiRead<($($ident,)+)> for AbiReader<'_>442 impl<$($ident),+> AbiRead<($($ident,)+)> for AbiReader<'_>
416 ($($ident,)+): TypeHelper,447 ($($ident,)+): TypeHelper,
417 {448 {
418 fn abi_read(&mut self) -> Result<($($ident,)+)> {449 fn abi_read(&mut self) -> Result<($($ident,)+)> {
419 let size = if !<($($ident,)+)>::is_dynamic() { Some(<Self as AbiRead<($($ident,)+)>>::size()) } else { None };450 let size = if !<($($ident,)+)>::is_dynamic() { Some(<($($ident,)+)>::size()) } else { None };
420 let mut subresult = self.subresult(size)?;451 let mut subresult = self.subresult(size)?;
421 Ok((452 Ok((
422 $(<Self as AbiRead<$ident>>::abi_read(&mut subresult)?,)+453 $(<Self as AbiRead<$ident>>::abi_read(&mut subresult)?,)+
423 ))454 ))
424 }455 }
425
426 fn size() -> usize {
427 0 $(+ <AbiReader<'_> as AbiRead<$ident>>::size())+
428 }
429 }456 }
430 #[allow(non_snake_case)]457 #[allow(non_snake_case)]
431 impl<$($ident),+> AbiWrite for &($($ident,)+)458 impl<$($ident),+> AbiWrite for ($($ident,)+)
432 where459 where
433 $($ident: AbiWrite,)+460 $($ident: AbiWrite,)+
434 {461 {
435 fn abi_write(&self, writer: &mut AbiWriter) {462 fn abi_write(&self, writer: &mut AbiWriter) {
436 let ($($ident,)+) = self;463 let ($($ident,)+) = self;
464 if writer.is_dynamic {
465 let mut sub = AbiWriter::new();
466 $($ident.abi_write(&mut sub);)+
467 writer.write_subresult(sub);
468 } else {
437 $($ident.abi_write(writer);)+469 $($ident.abi_write(writer);)+
470 }
438 }471 }
439 }472 }
440 };473 };
506impl_abi_writeable!(bool, bool);539impl_abi_writeable!(bool, bool);
507impl_abi_writeable!(&str, string);540impl_abi_writeable!(&str, string);
541
508impl AbiWrite for &string {542impl AbiWrite for string {
509 fn abi_write(&self, writer: &mut AbiWriter) {543 fn abi_write(&self, writer: &mut AbiWriter) {
510 writer.string(self)544 writer.string(self)
511 }545 }
512}546}
547
548impl AbiWrite for bytes {
549 fn abi_write(&self, writer: &mut AbiWriter) {
550 writer.bytes(self.0.as_slice())
551 }
552}
553
513impl AbiWrite for &Vec<u8> {554impl<T: AbiWrite + TypeHelper> AbiWrite for Vec<T> {
514 fn abi_write(&self, writer: &mut AbiWriter) {555 fn abi_write(&self, writer: &mut AbiWriter) {
556 let is_dynamic = T::is_dynamic();
557 let mut sub = if is_dynamic {
558 AbiWriter::new_dynamic(is_dynamic)
559 } else {
560 AbiWriter::new()
561 };
562
563 // Write items count
564 (self.len() as u32).abi_write(&mut sub);
565
566 for item in self {
567 item.abi_write(&mut sub);
568 }
515 writer.bytes(self)569 writer.write_subresult(sub);
516 }570 }
517}571}
518572
556#[cfg(test)]610#[cfg(test)]
557pub mod test {611pub mod test {
558 use crate::{612 use crate::{
559 abi::AbiRead,613 abi::{AbiRead, AbiWrite},
560 types::{string, uint256},614 types::*,
561 };615 };
562616
563 use super::{AbiReader, AbiWriter};617 use super::{AbiReader, AbiWriter};
564 use hex_literal::hex;618 use hex_literal::hex;
619 use primitive_types::{H160, U256};
620 use concat_idents::concat_idents;
621
622 macro_rules! test_impl {
623 ($name:ident, $type:ty, $function_identifier:expr, $decoded_data:expr, $encoded_data:expr) => {
624 concat_idents!(test_name = encode_decode_, $name {
625 #[test]
626 fn test_name() {
627 let function_identifier: u32 = $function_identifier;
628 let decoded_data = $decoded_data;
629 let encoded_data = $encoded_data;
630
631 let (call, mut decoder) = AbiReader::new_call(encoded_data).unwrap();
632 assert_eq!(call, u32::to_be_bytes(function_identifier));
633 let data = <AbiReader<'_> as AbiRead<$type>>::abi_read(&mut decoder).unwrap();
634 assert_eq!(data, decoded_data);
635
636 let mut writer = AbiWriter::new_call(function_identifier);
637 decoded_data.abi_write(&mut writer);
638 let ed = writer.finish();
639 similar_asserts::assert_eq!(encoded_data, ed.as_slice());
640 }
641 });
642 };
643 }
644
645 macro_rules! test_impl_uint {
646 ($type:ident) => {
647 test_impl!(
648 $type,
649 $type,
650 0xdeadbeef,
651 255 as $type,
652 &hex!(
653 "
654 deadbeef
655 00000000000000000000000000000000000000000000000000000000000000ff
656 "
657 )
658 );
659 };
660 }
661
662 test_impl_uint!(uint8);
663 test_impl_uint!(uint32);
664 test_impl_uint!(uint128);
665
666 test_impl!(
667 uint256,
668 uint256,
669 0xdeadbeef,
670 U256([255, 0, 0, 0]),
671 &hex!(
672 "
673 deadbeef
674 00000000000000000000000000000000000000000000000000000000000000ff
675 "
676 )
677 );
678
679 test_impl!(
680 vec_tuple_address_uint256,
681 Vec<(address, uint256)>,
682 0x1ACF2D55,
683 vec![
684 (
685 H160(hex!("2D2FF76104B7BACB2E8F6731D5BFC184EBECDDBC")),
686 U256([10, 0, 0, 0]),
687 ),
688 (
689 H160(hex!("AB8E3D9134955566483B11E6825C9223B6737B10")),
690 U256([20, 0, 0, 0]),
691 ),
692 (
693 H160(hex!("8C582BDF2953046705FC56F189385255EFC1BE18")),
694 U256([30, 0, 0, 0]),
695 ),
696 ],
697 &hex!(
698 "
699 1ACF2D55
700 0000000000000000000000000000000000000000000000000000000000000020 // offset of (address, uint256)[]
701 0000000000000000000000000000000000000000000000000000000000000003 // length of (address, uint256)[]
702
703 0000000000000000000000002D2FF76104B7BACB2E8F6731D5BFC184EBECDDBC // address
704 000000000000000000000000000000000000000000000000000000000000000A // uint256
705
706 000000000000000000000000AB8E3D9134955566483B11E6825C9223B6737B10 // address
707 0000000000000000000000000000000000000000000000000000000000000014 // uint256
708
709 0000000000000000000000008C582BDF2953046705FC56F189385255EFC1BE18 // address
710 000000000000000000000000000000000000000000000000000000000000001E // uint256
711 "
712 )
713 );
714
715 test_impl!(
716 vec_tuple_uint256_string,
717 Vec<(uint256, string)>,
718 0xdeadbeef,
719 vec![
720 (1.into(), "Test URI 0".to_string()),
721 (11.into(), "Test URI 1".to_string()),
722 (12.into(), "Test URI 2".to_string()),
723 ],
724 &hex!(
725 "
726 deadbeef
727 0000000000000000000000000000000000000000000000000000000000000020 // offset of (uint256, string)[]
728 0000000000000000000000000000000000000000000000000000000000000003 // length of (uint256, string)[]
729
730 0000000000000000000000000000000000000000000000000000000000000060 // offset of first elem
731 00000000000000000000000000000000000000000000000000000000000000e0 // offset of second elem
732 0000000000000000000000000000000000000000000000000000000000000160 // offset of third elem
733
734 0000000000000000000000000000000000000000000000000000000000000001 // first token id? #60
735 0000000000000000000000000000000000000000000000000000000000000040 // offset of string
736 000000000000000000000000000000000000000000000000000000000000000a // size of string
737 5465737420555249203000000000000000000000000000000000000000000000 // string
738
739 000000000000000000000000000000000000000000000000000000000000000b // second token id? Why ==11? #e0
740 0000000000000000000000000000000000000000000000000000000000000040 // offset of string
741 000000000000000000000000000000000000000000000000000000000000000a // size of string
742 5465737420555249203100000000000000000000000000000000000000000000 // string
743
744 000000000000000000000000000000000000000000000000000000000000000c // third token id? Why ==12? #160
745 0000000000000000000000000000000000000000000000000000000000000040 // offset of string
746 000000000000000000000000000000000000000000000000000000000000000a // size of string
747 5465737420555249203200000000000000000000000000000000000000000000 // string
748 "
749 )
750 );
565751
566 #[test]752 #[test]
567 fn dynamic_after_static() {753 fn dynamic_after_static() {
609 }795 }
610796
611 #[test]797 #[test]
612 fn mint_bulk() {798 fn parse_vec_with_dynamic_type() {
799 let decoded_data = (
800 0x36543006,
801 vec![
802 (1.into(), "Test URI 0".to_string()),
803 (11.into(), "Test URI 1".to_string()),
804 (12.into(), "Test URI 2".to_string()),
805 ],
806 );
807
808 let encoded_data = &hex!(
809 "
810 36543006
811 00000000000000000000000053744e6da587ba10b32a2554d2efdcd985bc27a3 // address
812 0000000000000000000000000000000000000000000000000000000000000040 // offset of (uint256, string)[]
813 0000000000000000000000000000000000000000000000000000000000000003 // length of (uint256, string)[]
814
815 0000000000000000000000000000000000000000000000000000000000000060 // offset of first elem
816 00000000000000000000000000000000000000000000000000000000000000e0 // offset of second elem
817 0000000000000000000000000000000000000000000000000000000000000160 // offset of third elem
818
819 0000000000000000000000000000000000000000000000000000000000000001 // first token id? #60
820 0000000000000000000000000000000000000000000000000000000000000040 // offset of string
821 000000000000000000000000000000000000000000000000000000000000000a // size of string
822 5465737420555249203000000000000000000000000000000000000000000000 // string
823
824 000000000000000000000000000000000000000000000000000000000000000b // second token id? Why ==11? #e0
825 0000000000000000000000000000000000000000000000000000000000000040 // offset of string
826 000000000000000000000000000000000000000000000000000000000000000a // size of string
827 5465737420555249203100000000000000000000000000000000000000000000 // string
828
829 000000000000000000000000000000000000000000000000000000000000000c // third token id? Why ==12? #160
830 0000000000000000000000000000000000000000000000000000000000000040 // offset of string
831 000000000000000000000000000000000000000000000000000000000000000a // size of string
832 5465737420555249203200000000000000000000000000000000000000000000 // string
833 "
834 );
835
613 let (call, mut decoder) = AbiReader::new_call(&hex!(836 let (call, mut decoder) = AbiReader::new_call(encoded_data).unwrap();
614 "
615 36543006
616 00000000000000000000000053744e6da587ba10b32a2554d2efdcd985bc27a3 // address
617 0000000000000000000000000000000000000000000000000000000000000040 // offset of (uint256, string)[]
618 0000000000000000000000000000000000000000000000000000000000000003 // length of (uint256, string)[]
619
620 0000000000000000000000000000000000000000000000000000000000000060 // offset of first elem
621 00000000000000000000000000000000000000000000000000000000000000e0 // offset of second elem
622 0000000000000000000000000000000000000000000000000000000000000160 // offset of third elem
623
624 0000000000000000000000000000000000000000000000000000000000000001 // first token id? #60
625 0000000000000000000000000000000000000000000000000000000000000040 // offset of string
626 000000000000000000000000000000000000000000000000000000000000000a // size of string
627 5465737420555249203000000000000000000000000000000000000000000000 // string
628
629 000000000000000000000000000000000000000000000000000000000000000b // second token id? Why ==11? #e0
630 0000000000000000000000000000000000000000000000000000000000000040 // offset of string
631 000000000000000000000000000000000000000000000000000000000000000a // size of string
632 5465737420555249203100000000000000000000000000000000000000000000 // string
633
634 000000000000000000000000000000000000000000000000000000000000000c // third token id? Why ==12? #160
635 0000000000000000000000000000000000000000000000000000000000000040 // offset of string
636 000000000000000000000000000000000000000000000000000000000000000a // size of string
637 5465737420555249203200000000000000000000000000000000000000000000 // string
638 "
639 ))
640 .unwrap();
641 assert_eq!(call, u32::to_be_bytes(0x36543006));837 assert_eq!(call, u32::to_be_bytes(decoded_data.0));
642 let _ = decoder.address().unwrap();838 let address = decoder.address().unwrap();
643 let data =839 let data =
644 <AbiReader<'_> as AbiRead<Vec<(uint256, string)>>>::abi_read(&mut decoder).unwrap();840 <AbiReader<'_> as AbiRead<Vec<(uint256, string)>>>::abi_read(&mut decoder).unwrap();
645 assert_eq!(841 assert_eq!(data, decoded_data.1);
646 data,842
647 vec![843 let mut writer = AbiWriter::new_call(decoded_data.0);
648 (1.into(), "Test URI 0".to_string()),844 address.abi_write(&mut writer);
649 (11.into(), "Test URI 1".to_string()),845 decoded_data.1.abi_write(&mut writer);
650 (12.into(), "Test URI 2".to_string())846 let ed = writer.finish();
651 ]847 similar_asserts::assert_eq!(encoded_data, ed.as_slice());
652 );
653 }848 }
654
655 #[test]
656 fn parse_vec_with_simple_type() {
657 use crate::types::address;
658 use primitive_types::{H160, U256};
659
660 let (call, mut decoder) = AbiReader::new_call(&hex!(
661 "
662 1ACF2D55
663 0000000000000000000000000000000000000000000000000000000000000020 // offset of (address, uint256)[]
664 0000000000000000000000000000000000000000000000000000000000000003 // length of (address, uint256)[]
665
666 0000000000000000000000002D2FF76104B7BACB2E8F6731D5BFC184EBECDDBC // address
667 000000000000000000000000000000000000000000000000000000000000000A // uint256
668
669 000000000000000000000000AB8E3D9134955566483B11E6825C9223B6737B10 // address
670 0000000000000000000000000000000000000000000000000000000000000014 // uint256
671
672 0000000000000000000000008C582BDF2953046705FC56F189385255EFC1BE18 // address
673 000000000000000000000000000000000000000000000000000000000000001E // uint256
674 "
675 ))
676 .unwrap();
677 assert_eq!(call, u32::to_be_bytes(0x1ACF2D55));
678 let data =
679 <AbiReader<'_> as AbiRead<Vec<(address, uint256)>>>::abi_read(&mut decoder).unwrap();
680 assert_eq!(data.len(), 3);
681 assert_eq!(
682 data,
683 vec![
684 (
685 H160(hex!("2D2FF76104B7BACB2E8F6731D5BFC184EBECDDBC")),
686 U256([10, 0, 0, 0])
687 ),
688 (
689 H160(hex!("AB8E3D9134955566483B11E6825C9223B6737B10")),
690 U256([20, 0, 0, 0])
691 ),
692 (
693 H160(hex!("8C582BDF2953046705FC56F189385255EFC1BE18")),
694 U256([30, 0, 0, 0])
695 ),
696 ]
697 );
698 }
699}849}
700850
modifiedcrates/evm-coder/src/lib.rsdiffbeforeafterboth
134 #[cfg(feature = "std")]134 #[cfg(feature = "std")]
135 pub type string = ::std::string::String;135 pub type string = ::std::string::String;
136
137 #[derive(Default, Debug)]
136 pub type bytes = Vec<u8>;138 pub struct bytes(pub Vec<u8>);
137139
138 /// Solidity doesn't have `void` type, however we have special implementation140 /// Solidity doesn't have `void` type, however we have special implementation
139 /// for empty tuple return type141 /// for empty tuple return type
158 pub value: U256,160 pub value: U256,
159 }161 }
162
163 impl From<Vec<u8>> for bytes {
164 fn from(src: Vec<u8>) -> Self {
165 Self(src)
166 }
167 }
168
169 impl Into<Vec<u8>> for bytes {
170 fn into(self) -> Vec<u8> {
171 self.0
172 }
173 }
174
175 impl bytes {
176 #[must_use]
177 pub fn len(&self) -> usize {
178 self.0.len()
179 }
180
181 #[must_use]
182 pub fn is_empty(&self) -> bool {
183 self.len() == 0
184 }
185 }
160}186}
161187
162/// Parseable EVM call, this trait should be implemented with [`solidity_interface`] macro188/// Parseable EVM call, this trait should be implemented with [`solidity_interface`] macro
modifiedcrates/evm-coder/src/solidity.rsdiffbeforeafterboth
154 fn is_simple() -> bool {154 fn is_simple() -> bool {
155 false155 false
156 }156 }
157 fn solidity_default(writer: &mut impl fmt::Write, _tc: &TypeCollector) -> fmt::Result {157 fn solidity_default(writer: &mut impl fmt::Write, tc: &TypeCollector) -> fmt::Result {
158 write!(writer, "new ")?;
159 T::solidity_name(writer, tc)?;
158 write!(writer, "[]")160 write!(writer, "[](0)")
159 }161 }
160}162}
161163
modifiednode/cli/src/command.rsdiffbeforeafterboth
3434
35use crate::{35use crate::{
36 chain_spec::{36 chain_spec::{self, RuntimeId, RuntimeIdentification, ServiceId, ServiceIdentification},
37 self, RuntimeId, RuntimeIdentification, ServiceId, ServiceIdentification, default_runtime,
38 },
39 cli::{Cli, RelayChainCli, Subcommand},37 cli::{Cli, RelayChainCli, Subcommand},
40 service::{new_partial, start_node, start_dev_node},38 service::{new_partial, start_node, start_dev_node},
41};39};
40#[cfg(feature = "runtime-benchmarks")]
41use crate::chain_spec::default_runtime;
4242
43#[cfg(feature = "unique-runtime")]43#[cfg(feature = "unique-runtime")]
44use crate::service::UniqueRuntimeExecutor;44use crate::service::UniqueRuntimeExecutor;
4545
46#[cfg(feature = "quartz-runtime")]46#[cfg(feature = "quartz-runtime")]
47use crate::service::QuartzRuntimeExecutor;47use crate::service::QuartzRuntimeExecutor;
4848
49use crate::service::{OpalRuntimeExecutor, DefaultRuntimeExecutor};49use crate::service::OpalRuntimeExecutor;
50
51#[cfg(feature = "runtime-benchmarks")]
52use crate::service::DefaultRuntimeExecutor;
5053
51use codec::Encode;54use codec::Encode;
52use cumulus_primitives_core::ParaId;55use cumulus_primitives_core::ParaId;
modifiednode/cli/src/service.rsdiffbeforeafterboth
46use cumulus_relay_chain_rpc_interface::{RelayChainRpcInterface, create_client_and_start_worker};46use cumulus_relay_chain_rpc_interface::{RelayChainRpcInterface, create_client_and_start_worker};
4747
48// Substrate Imports48// Substrate Imports
49use sc_client_api::ExecutorProvider;
50use sc_executor::NativeElseWasmExecutor;49use sc_executor::NativeElseWasmExecutor;
51use sc_executor::NativeExecutionDispatch;50use sc_executor::NativeExecutionDispatch;
52use sc_network::{NetworkService, NetworkBlock};51use sc_network::{NetworkService, NetworkBlock};
84/// Opal native executor instance.83/// Opal native executor instance.
85pub struct OpalRuntimeExecutor;84pub struct OpalRuntimeExecutor;
8685
87#[cfg(feature = "unique-runtime")]86#[cfg(all(feature = "unique-runtime", feature = "runtime-benchmarks"))]
88pub type DefaultRuntimeExecutor = UniqueRuntimeExecutor;87pub type DefaultRuntimeExecutor = UniqueRuntimeExecutor;
8988
90#[cfg(all(not(feature = "unique-runtime"), feature = "quartz-runtime"))]89#[cfg(all(
90 not(feature = "unique-runtime"),
91 feature = "quartz-runtime",
92 feature = "runtime-benchmarks"
93))]
91pub type DefaultRuntimeExecutor = QuartzRuntimeExecutor;94pub type DefaultRuntimeExecutor = QuartzRuntimeExecutor;
9295
93#[cfg(all(not(feature = "unique-runtime"), not(feature = "quartz-runtime")))]96#[cfg(all(
97 not(feature = "unique-runtime"),
98 not(feature = "quartz-runtime"),
99 feature = "runtime-benchmarks"
100))]
94pub type DefaultRuntimeExecutor = OpalRuntimeExecutor;101pub type DefaultRuntimeExecutor = OpalRuntimeExecutor;
95102
modifiedpallets/common/CHANGELOG.mddiffbeforeafterboth
22
3All notable changes to this project will be documented in this file.3All notable changes to this project will be documented in this file.
44
5## [0.1.9] - 2022-10-13
6
7## Added
8
9- EVM event for `destroy_collection`.
10
5## [0.1.8] - 2022-08-2411## [0.1.8] - 2022-08-24
612
7## Added13## Added
14
8 - Eth methods for collection15- Eth methods for collection
9 + set_collection_sponsor_substrate16 - set_collection_sponsor_substrate
10 + has_collection_pending_sponsor17 - has_collection_pending_sponsor
11 + remove_collection_sponsor18 - remove_collection_sponsor
12 + get_collection_sponsor19 - get_collection_sponsor
13- Add convert function from `uint256` to `CrossAccountId`.20- Add convert function from `uint256` to `CrossAccountId`.
1421
15## [0.1.7] - 2022-08-1922## [0.1.7] - 2022-08-19
1623
17### Added24### Added
1825
19 - Add convert funtion from `CrossAccountId` to eth `uint256`.26- Add convert funtion from `CrossAccountId` to eth `uint256`.
2027
21
22## [0.1.6] - 2022-08-1628## [0.1.6] - 2022-08-16
2329
24### Added30### Added
25- New Ethereum API methods: changeOwner, changeOwner(Substrate) and verifyOwnerOrAdmin(Substrate).
2631
32- New Ethereum API methods: changeOwner, changeOwner(Substrate) and verifyOwnerOrAdmin(Substrate).
33
27<!-- bureaucrate goes here -->34<!-- bureaucrate goes here -->
35
28## [v0.1.5] 2022-08-1636## [v0.1.5] 2022-08-16
2937
30### Other changes38### Other changes
45- build: Upgrade polkadot to v0.9.25 cdfb9bdc7b205ff1b5134f034ef9973d769e5e6b53- build: Upgrade polkadot to v0.9.25 cdfb9bdc7b205ff1b5134f034ef9973d769e5e6b
4654
47## [0.1.3] - 2022-07-2555## [0.1.3] - 2022-07-25
56
48### Add57### Add
58
49- Some static property keys and values.59- Some static property keys and values.
5060
51## [0.1.2] - 2022-07-2061## [0.1.2] - 2022-07-20
5262
53### Fixed63### Fixed
5464
55- Some methods in `#[solidity_interface]` for `CollectionHandle` had invalid65- Some methods in `#[solidity_interface]` for `CollectionHandle` had invalid
56 mutability modifiers, causing invalid stub/abi generation.66 mutability modifiers, causing invalid stub/abi generation.
5767
58## [0.1.1] - 2022-07-1468## [0.1.1] - 2022-07-14
5969
60### Added70### Added
6171
62 - Implementation of RPC method `token_owners` returning 10 owners in no particular order.72- Implementation of RPC method `token_owners` returning 10 owners in no particular order.
63 This was an internal request to improve the web interface and support fractionalization event.73 This was an internal request to improve the web interface and support fractionalization event.
6474
modifiedpallets/common/Cargo.tomldiffbeforeafterboth
1[package]1[package]
2name = "pallet-common"2name = "pallet-common"
3version = "0.1.8"3version = "0.1.9"
4license = "GPLv3"4license = "GPLv3"
5edition = "2021"5edition = "2021"
66
modifiedpallets/common/src/erc.rsdiffbeforeafterboth
34use crate::{34use crate::{
35 Pallet, CollectionHandle, Config, CollectionProperties, SelfWeightOf,35 Pallet, CollectionHandle, Config, CollectionProperties, SelfWeightOf,
36 eth::{36 eth::{
37 convert_cross_account_to_uint256, convert_uint256_to_cross_account,37 convert_cross_account_to_uint256, convert_cross_account_to_tuple,
38 convert_cross_account_to_tuple,38 convert_tuple_to_cross_account,
39 },39 },
40 weights::WeightInfo,40 weights::WeightInfo,
41};41};
53 #[indexed]53 #[indexed]
54 collection_id: address,54 collection_id: address,
55 },55 },
56 /// The collection has been destroyed.
57 CollectionDestroyed {
58 /// Collection ID.
59 #[indexed]
60 collection_id: address,
61 },
56}62}
5763
58/// Does not always represent a full collection, for RFT it is either64/// Does not always represent a full collection, for RFT it is either
85 let key = <Vec<u8>>::from(key)91 let key = <Vec<u8>>::from(key)
86 .try_into()92 .try_into()
87 .map_err(|_| "key too large")?;93 .map_err(|_| "key too large")?;
88 let value = value.try_into().map_err(|_| "value too large")?;94 let value = value.0.try_into().map_err(|_| "value too large")?;
8995
90 <Pallet<T>>::set_collection_property(self, &caller, Property { key, value })96 <Pallet<T>>::set_collection_property(self, &caller, Property { key, value })
91 .map_err(dispatch_to_evm::<T>)97 .map_err(dispatch_to_evm::<T>)
92 }98 }
99
100 /// Set collection properties.
101 ///
102 /// @param properties Vector of properties key/value pair.
103 #[weight(<SelfWeightOf<T>>::set_collection_properties(properties.len() as u32))]
104 fn set_collection_properties(
105 &mut self,
106 caller: caller,
107 properties: Vec<(string, bytes)>,
108 ) -> Result<void> {
109 let caller = T::CrossAccountId::from_eth(caller);
110
111 let properties = properties
112 .into_iter()
113 .map(|(key, value)| {
114 let key = <Vec<u8>>::from(key)
115 .try_into()
116 .map_err(|_| "key too large")?;
117
118 let value = value.0.try_into().map_err(|_| "value too large")?;
119
120 Ok(Property { key, value })
121 })
122 .collect::<Result<Vec<_>>>()?;
123
124 <Pallet<T>>::set_collection_properties(self, &caller, properties)
125 .map_err(dispatch_to_evm::<T>)
126 }
93127
94 /// Delete collection property.128 /// Delete collection property.
95 ///129 ///
96 /// @param key Property key.130 /// @param key Property key.
97 #[weight(<SelfWeightOf<T>>::delete_collection_properties(1))]131 #[weight(<SelfWeightOf<T>>::delete_collection_properties(1))]
98 fn delete_collection_property(&mut self, caller: caller, key: string) -> Result<()> {132 fn delete_collection_property(&mut self, caller: caller, key: string) -> Result<()> {
99 self.consume_store_reads_and_writes(1, 1)?;
100
101 let caller = T::CrossAccountId::from_eth(caller);133 let caller = T::CrossAccountId::from_eth(caller);
102 let key = <Vec<u8>>::from(key)134 let key = <Vec<u8>>::from(key)
106 <Pallet<T>>::delete_collection_property(self, &caller, key).map_err(dispatch_to_evm::<T>)138 <Pallet<T>>::delete_collection_property(self, &caller, key).map_err(dispatch_to_evm::<T>)
107 }139 }
140
141 /// Delete collection properties.
142 ///
143 /// @param keys Properties keys.
144 #[weight(<SelfWeightOf<T>>::delete_collection_properties(keys.len() as u32))]
145 fn delete_collection_properties(&mut self, caller: caller, keys: Vec<string>) -> Result<()> {
146 let caller = T::CrossAccountId::from_eth(caller);
147 let keys = keys
148 .into_iter()
149 .map(|key| {
150 <Vec<u8>>::from(key)
151 .try_into()
152 .map_err(|_| Error::Revert("key too large".into()))
153 })
154 .collect::<Result<Vec<_>>>()?;
155
156 <Pallet<T>>::delete_collection_properties(self, &caller, keys).map_err(dispatch_to_evm::<T>)
157 }
108158
109 /// Get collection property.159 /// Get collection property.
110 ///160 ///
117 .try_into()167 .try_into()
118 .map_err(|_| "key too large")?;168 .map_err(|_| "key too large")?;
119169
120 let props = <CollectionProperties<T>>::get(self.id);170 let props = CollectionProperties::<T>::get(self.id);
121 let prop = props.get(&key).ok_or("key not found")?;171 let prop = props.get(&key).ok_or("key not found")?;
122172
123 Ok(prop.to_vec())173 Ok(bytes(prop.to_vec()))
124 }174 }
175
176 /// Get collection properties.
177 ///
178 /// @param keys Properties keys. Empty keys for all propertyes.
179 /// @return Vector of properties key/value pairs.
180 fn collection_properties(&self, keys: Vec<string>) -> Result<Vec<(string, bytes)>> {
181 let keys = keys
182 .into_iter()
183 .map(|key| {
184 <Vec<u8>>::from(key)
185 .try_into()
186 .map_err(|_| Error::Revert("key too large".into()))
187 })
188 .collect::<Result<Vec<_>>>()?;
189
190 let properties = Pallet::<T>::filter_collection_properties(
191 self.id,
192 if keys.is_empty() { None } else { Some(keys) },
193 )
194 .map_err(dispatch_to_evm::<T>)?;
195
196 let properties = properties
197 .into_iter()
198 .map(|p| {
199 let key =
200 string::from_utf8(p.key.into()).map_err(|e| Error::Revert(format!("{}", e)))?;
201 let value = bytes(p.value.to_vec());
202 Ok((key, value))
203 })
204 .collect::<Result<Vec<_>>>()?;
205 Ok(properties)
206 }
125207
126 /// Set the sponsor of the collection.208 /// Set the sponsor of the collection.
127 ///209 ///
139 save(self)221 save(self)
140 }222 }
141223
142 // TODO: Temprorary off. Need refactor
143 // /// Set the substrate sponsor of the collection.224 /// Set the sponsor of the collection.
144 // ///225 ///
145 // /// @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.226 /// @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.
146 // ///227 ///
147 // /// @param sponsor Substrate address of the sponsor from whose account funds will be debited for operations with the contract.228 /// @param sponsor Cross account address of the sponsor from whose account funds will be debited for operations with the contract.
148 // fn set_collection_sponsor_substrate(229 fn set_collection_sponsor_cross(
149 // &mut self,230 &mut self,
150 // caller: caller,231 caller: caller,
151 // sponsor: uint256,232 sponsor: (address, uint256),
152 // ) -> Result<void> {233 ) -> Result<void> {
153 // self.consume_store_reads_and_writes(1, 1)?;234 self.consume_store_reads_and_writes(1, 1)?;
154235
155 // check_is_owner_or_admin(caller, self)?;236 check_is_owner_or_admin(caller, self)?;
156237
157 // let sponsor = convert_uint256_to_cross_account::<T>(sponsor);238 let sponsor = convert_tuple_to_cross_account::<T>(sponsor)?;
158 // self.set_sponsor(sponsor.as_sub().clone())239 self.set_sponsor(sponsor.as_sub().clone())
159 // .map_err(dispatch_to_evm::<T>)?;240 .map_err(dispatch_to_evm::<T>)?;
160 // save(self)241 save(self)
161 // }242 }
162243
163 /// Whether there is a pending sponsor.244 /// Whether there is a pending sponsor.
164 fn has_collection_pending_sponsor(&self) -> Result<bool> {245 fn has_collection_pending_sponsor(&self) -> Result<bool> {
300 Ok(crate::eth::collection_id_to_address(self.id))381 Ok(crate::eth::collection_id_to_address(self.id))
301 }382 }
302383
303 // TODO: Temprorary off. Need refactor
304 // /// Add collection admin by substrate address.384 /// Add collection admin.
305 // /// @param newAdmin Substrate administrator address.385 /// @param newAdmin Cross account administrator address.
306 // fn add_collection_admin_substrate(386 fn add_collection_admin_cross(
307 // &mut self,387 &mut self,
308 // caller: caller,388 caller: caller,
309 // new_admin: uint256,389 new_admin: (address, uint256),
310 // ) -> Result<void> {390 ) -> Result<void> {
311 // self.consume_store_writes(2)?;391 self.consume_store_writes(2)?;
312392
313 // let caller = T::CrossAccountId::from_eth(caller);393 let caller = T::CrossAccountId::from_eth(caller);
314 // let new_admin = convert_uint256_to_cross_account::<T>(new_admin);394 let new_admin = convert_tuple_to_cross_account::<T>(new_admin)?;
315 // <Pallet<T>>::toggle_admin(self, &caller, &new_admin, true).map_err(dispatch_to_evm::<T>)?;395 <Pallet<T>>::toggle_admin(self, &caller, &new_admin, true).map_err(dispatch_to_evm::<T>)?;
316 // Ok(())396 Ok(())
317 // }397 }
318398
319 // TODO: Temprorary off. Need refactor
320 // /// Remove collection admin by substrate address.399 /// Remove collection admin.
321 // /// @param admin Substrate administrator address.400 /// @param admin Cross account administrator address.
322 // fn remove_collection_admin_substrate(401 fn remove_collection_admin_cross(
323 // &mut self,402 &mut self,
324 // caller: caller,403 caller: caller,
325 // admin: uint256,404 admin: (address, uint256),
326 // ) -> Result<void> {405 ) -> Result<void> {
327 // self.consume_store_writes(2)?;406 self.consume_store_writes(2)?;
328407
329 // let caller = T::CrossAccountId::from_eth(caller);408 let caller = T::CrossAccountId::from_eth(caller);
330 // let admin = convert_uint256_to_cross_account::<T>(admin);409 let admin = convert_tuple_to_cross_account::<T>(admin)?;
331 // <Pallet<T>>::toggle_admin(self, &caller, &admin, false).map_err(dispatch_to_evm::<T>)?;410 <Pallet<T>>::toggle_admin(self, &caller, &admin, false).map_err(dispatch_to_evm::<T>)?;
332 // Ok(())411 Ok(())
333 // }412 }
334413
335 /// Add collection admin.414 /// Add collection admin.
336 /// @param newAdmin Address of the added administrator.415 /// @param newAdmin Address of the added administrator.
479 Ok(())558 Ok(())
480 }559 }
481560
482 // TODO: Temprorary off. Need refactor
483 // /// Add substrate user to allowed list.561 /// Add user to allowed list.
484 // ///562 ///
485 // /// @param user User substrate address.563 /// @param user User cross account address.
486 // fn add_to_collection_allow_list_substrate(564 fn add_to_collection_allow_list_cross(
487 // &mut self,565 &mut self,
488 // caller: caller,566 caller: caller,
489 // user: uint256,567 user: (address, uint256),
490 // ) -> Result<void> {568 ) -> Result<void> {
491 // self.consume_store_writes(1)?;569 self.consume_store_writes(1)?;
492570
493 // let caller = T::CrossAccountId::from_eth(caller);571 let caller = T::CrossAccountId::from_eth(caller);
494 // let user = convert_uint256_to_cross_account::<T>(user);572 let user = convert_tuple_to_cross_account::<T>(user)?;
495 // Pallet::<T>::toggle_allowlist(self, &caller, &user, true).map_err(dispatch_to_evm::<T>)?;573 Pallet::<T>::toggle_allowlist(self, &caller, &user, true).map_err(dispatch_to_evm::<T>)?;
496 // Ok(())574 Ok(())
497 // }575 }
498576
499 /// Remove the user from the allowed list.577 /// Remove the user from the allowed list.
500 ///578 ///
508 Ok(())586 Ok(())
509 }587 }
510588
511 // TODO: Temprorary off. Need refactor
512 // /// Remove substrate user from allowed list.589 /// Remove user from allowed list.
513 // ///590 ///
514 // /// @param user User substrate address.591 /// @param user User cross account address.
515 // fn remove_from_collection_allow_list_substrate(592 fn remove_from_collection_allow_list_cross(
516 // &mut self,593 &mut self,
517 // caller: caller,594 caller: caller,
518 // user: uint256,595 user: (address, uint256),
519 // ) -> Result<void> {596 ) -> Result<void> {
520 // self.consume_store_writes(1)?;597 self.consume_store_writes(1)?;
521598
522 // let caller = T::CrossAccountId::from_eth(caller);599 let caller = T::CrossAccountId::from_eth(caller);
523 // let user = convert_uint256_to_cross_account::<T>(user);600 let user = convert_tuple_to_cross_account::<T>(user)?;
524 // Pallet::<T>::toggle_allowlist(self, &caller, &user, false).map_err(dispatch_to_evm::<T>)?;601 Pallet::<T>::toggle_allowlist(self, &caller, &user, false).map_err(dispatch_to_evm::<T>)?;
525 // Ok(())602 Ok(())
526 // }603 }
527604
528 /// Switch permission for minting.605 /// Switch permission for minting.
529 ///606 ///
556 Ok(self.is_owner_or_admin(&user))633 Ok(self.is_owner_or_admin(&user))
557 }634 }
558635
559 // TODO: Temprorary off. Need refactor
560 // /// Check that substrate account is the owner or admin of the collection636 /// Check that account is the owner or admin of the collection
561 // ///637 ///
562 // /// @param user account to verify638 /// @param user User cross account to verify
563 // /// @return "true" if account is the owner or admin639 /// @return "true" if account is the owner or admin
564 // fn is_owner_or_admin_substrate(&self, user: uint256) -> Result<bool> {640 fn is_owner_or_admin_cross(&self, user: (address, uint256)) -> Result<bool> {
565 // let user = convert_uint256_to_cross_account::<T>(user);641 let user = convert_tuple_to_cross_account::<T>(user)?;
566 // Ok(self.is_owner_or_admin(&user))642 Ok(self.is_owner_or_admin(&user))
567 // }643 }
568644
569 /// Returns collection type645 /// Returns collection type
570 ///646 ///
580656
581 /// Get collection owner.657 /// Get collection owner.
582 ///658 ///
583 /// @return Tuble with sponsor address and his substrate mirror.659 /// @return Tuple with sponsor address and his substrate mirror.
584 /// If address is canonical then substrate mirror is zero and vice versa.660 /// If address is canonical then substrate mirror is zero and vice versa.
585 fn collection_owner(&self) -> Result<(address, uint256)> {661 fn collection_owner(&self) -> Result<(address, uint256)> {
586 Ok(convert_cross_account_to_tuple::<T>(662 Ok(convert_cross_account_to_tuple::<T>(
602 .map_err(dispatch_to_evm::<T>)678 .map_err(dispatch_to_evm::<T>)
603 }679 }
604680
605 // TODO: Temprorary off. Need refactor681 /// Get collection administrators
682 ///
683 /// @return Vector of tuples with admins address and his substrate mirror.
684 /// If address is canonical then substrate mirror is zero and vice versa.
685 fn collection_admins(&self) -> Result<Vec<(address, uint256)>> {
686 let result = crate::IsAdmin::<T>::iter_prefix((self.id,))
687 .map(|(admin, _)| crate::eth::convert_cross_account_to_tuple::<T>(&admin))
688 .collect();
689 Ok(result)
690 }
691
606 // /// Changes collection owner to another substrate account692 /// Changes collection owner to another account
607 // ///693 ///
608 // /// @dev Owner can be changed only by current owner694 /// @dev Owner can be changed only by current owner
609 // /// @param newOwner new owner substrate account695 /// @param newOwner new owner cross account
610 // fn set_owner_substrate(&mut self, caller: caller, new_owner: uint256) -> Result<void> {696 fn set_owner_cross(&mut self, caller: caller, new_owner: (address, uint256)) -> Result<void> {
611 // self.consume_store_writes(1)?;697 self.consume_store_writes(1)?;
612698
613 // let caller = T::CrossAccountId::from_eth(caller);699 let caller = T::CrossAccountId::from_eth(caller);
614 // let new_owner = convert_uint256_to_cross_account::<T>(new_owner);700 let new_owner = convert_tuple_to_cross_account::<T>(new_owner)?;
615 // self.set_owner_internal(caller, new_owner)701 self.set_owner_internal(caller, new_owner)
616 // .map_err(dispatch_to_evm::<T>)702 .map_err(dispatch_to_evm::<T>)
617 // }703 }
618
619 // TODO: need implement AbiWriter for &Vec<T>
620 // fn collection_admins(&self) -> Result<Vec<(address, uint256)>> {
621 // let result = pallet_common::IsAdmin::<T>::iter_prefix((self.id,))
622 // .map(|(admin, _)| pallet_common::eth::convert_cross_account_to_tuple::<T>(&admin))
623 // .collect();
624 // Ok(result)
625 // }
626}704}
627705
628/// ### Note706/// ### Note
modifiedpallets/common/src/eth.rsdiffbeforeafterboth
86 }86 }
87}87}
88
89/// Convert tuple `(address, uint256)` to `CrossAccountId`.
90///
91/// If `address` in the tuple has *default* value, then the canonical form is substrate,
92/// if `uint256` has *default* value, then the ethereum form is canonical,
93/// if both values are *default* or *non default*, then this is considered an invalid address and `Error` is returned.
94pub fn convert_tuple_to_cross_account<T: Config>(
95 eth_cross_account_id: (address, uint256),
96) -> evm_coder::execution::Result<T::CrossAccountId>
97where
98 T::AccountId: From<[u8; 32]>,
99{
100 if eth_cross_account_id == Default::default() {
101 Err("All fields of cross account is zeroed".into())
102 } else if eth_cross_account_id.0 == Default::default() {
103 Ok(convert_uint256_to_cross_account::<T>(
104 eth_cross_account_id.1,
105 ))
106 } else if eth_cross_account_id.1 == Default::default() {
107 Ok(T::CrossAccountId::from_eth(eth_cross_account_id.0))
108 } else {
109 Err("All fields of cross account is non zeroed".into())
110 }
111}
88112
modifiedpallets/common/src/lib.rsdiffbeforeafterboth
10001000
1001 <Pallet<T>>::deposit_event(Event::CollectionDestroyed(collection.id));1001 <Pallet<T>>::deposit_event(Event::CollectionDestroyed(collection.id));
1002
1003 <PalletEvm<T>>::deposit_log(
1004 erc::CollectionHelpersEvents::CollectionDestroyed {
1005 collection_id: eth::collection_id_to_address(collection.id),
1006 }
1007 .to_log(T::ContractAddress::get()),
1008 );
1002 Ok(())1009 Ok(())
1003 }1010 }
10041011
modifiedpallets/evm-contract-helpers/src/stubs/ContractHelpers.rawdiffbeforeafterboth

binary blob — no preview

modifiedpallets/fungible/src/erc.rsdiffbeforeafterboth
19use core::char::{REPLACEMENT_CHARACTER, decode_utf16};19use core::char::{REPLACEMENT_CHARACTER, decode_utf16};
20use core::convert::TryInto;20use core::convert::TryInto;
21use evm_coder::{ToLog, execution::*, generate_stubgen, solidity_interface, types::*, weight};21use evm_coder::{ToLog, execution::*, generate_stubgen, solidity_interface, types::*, weight};
22use pallet_common::eth::convert_tuple_to_cross_account;
22use up_data_structs::CollectionMode;23use up_data_structs::CollectionMode;
23use pallet_common::erc::{CommonEvmHandler, PrecompileResult};24use pallet_common::erc::{CommonEvmHandler, PrecompileResult};
24use sp_std::vec::Vec;25use sp_std::vec::Vec;
150151
151#[solidity_interface(name = ERC20UniqueExtensions)]152#[solidity_interface(name = ERC20UniqueExtensions)]
152impl<T: Config> FungibleHandle<T> {153impl<T: Config> FungibleHandle<T>
154where
155 T::AccountId: From<[u8; 32]>,
156{
157 #[weight(<SelfWeightOf<T>>::approve())]
158 fn approve_cross(
159 &mut self,
160 caller: caller,
161 spender: (address, uint256),
162 amount: uint256,
163 ) -> Result<bool> {
164 let caller = T::CrossAccountId::from_eth(caller);
165 let spender = convert_tuple_to_cross_account::<T>(spender)?;
166 let amount = amount.try_into().map_err(|_| "amount overflow")?;
167
168 <Pallet<T>>::set_allowance(self, &caller, &spender, amount)
169 .map_err(dispatch_to_evm::<T>)?;
170 Ok(true)
171 }
172
153 /// Burn tokens from account173 /// Burn tokens from account
154 /// @dev Function that burns an `amount` of the tokens of a given account,174 /// @dev Function that burns an `amount` of the tokens of a given account,
169 Ok(true)189 Ok(true)
170 }190 }
191
192 /// Burn tokens from account
193 /// @dev Function that burns an `amount` of the tokens of a given account,
194 /// deducting from the sender's allowance for said account.
195 /// @param from The account whose tokens will be burnt.
196 /// @param amount The amount that will be burnt.
197 #[weight(<SelfWeightOf<T>>::burn_from())]
198 fn burn_from_cross(
199 &mut self,
200 caller: caller,
201 from: (address, uint256),
202 amount: uint256,
203 ) -> Result<bool> {
204 let caller = T::CrossAccountId::from_eth(caller);
205 let from = convert_tuple_to_cross_account::<T>(from)?;
206 let amount = amount.try_into().map_err(|_| "amount overflow")?;
207 let budget = self
208 .recorder
209 .weight_calls_budget(<StructureWeight<T>>::find_parent());
210
211 <Pallet<T>>::burn_from(self, &caller, &from, amount, &budget)
212 .map_err(dispatch_to_evm::<T>)?;
213 Ok(true)
214 }
171215
172 /// Mint tokens for multiple accounts.216 /// Mint tokens for multiple accounts.
173 /// @param amounts array of pairs of account address and amount217 /// @param amounts array of pairs of account address and amount
192 Ok(true)236 Ok(true)
193 }237 }
238
239 #[weight(<SelfWeightOf<T>>::transfer_from())]
240 fn transfer_from_cross(
241 &mut self,
242 caller: caller,
243 from: (address, uint256),
244 to: (address, uint256),
245 amount: uint256,
246 ) -> Result<bool> {
247 let caller = T::CrossAccountId::from_eth(caller);
248 let from = convert_tuple_to_cross_account::<T>(from)?;
249 let to = convert_tuple_to_cross_account::<T>(to)?;
250 let amount = amount.try_into().map_err(|_| "amount overflow")?;
251 let budget = self
252 .recorder
253 .weight_calls_budget(<StructureWeight<T>>::find_parent());
254
255 <Pallet<T>>::transfer_from(self, &caller, &from, &to, amount, &budget)
256 .map_err(dispatch_to_evm::<T>)?;
257 Ok(true)
258 }
194}259}
195260
196#[solidity_interface(261#[solidity_interface(
modifiedpallets/fungible/src/stubs/UniqueFungible.rawdiffbeforeafterboth

binary blob — no preview

modifiedpallets/fungible/src/stubs/UniqueFungible.soldiffbeforeafterboth
18}18}
1919
20/// @title A contract that allows you to work with collections.20/// @title A contract that allows you to work with collections.
21/// @dev the ERC-165 identifier for this interface is 0x62e2229021/// @dev the ERC-165 identifier for this interface is 0xb3152af3
22contract Collection is Dummy, ERC165 {22contract Collection is Dummy, ERC165 {
23 /// Set collection property.23 /// Set collection property.
24 ///24 ///
33 dummy = 0;33 dummy = 0;
34 }34 }
35
36 /// Set collection properties.
37 ///
38 /// @param properties Vector of properties key/value pair.
39 /// @dev EVM selector for this function is: 0x50b26b2a,
40 /// or in textual repr: setCollectionProperties((string,bytes)[])
41 function setCollectionProperties(Tuple10[] memory properties) public {
42 require(false, stub_error);
43 properties;
44 dummy = 0;
45 }
3546
36 /// Delete collection property.47 /// Delete collection property.
37 ///48 ///
44 dummy = 0;55 dummy = 0;
45 }56 }
57
58 /// Delete collection properties.
59 ///
60 /// @param keys Properties keys.
61 /// @dev EVM selector for this function is: 0xee206ee3,
62 /// or in textual repr: deleteCollectionProperties(string[])
63 function deleteCollectionProperties(string[] memory keys) public {
64 require(false, stub_error);
65 keys;
66 dummy = 0;
67 }
4668
47 /// Get collection property.69 /// Get collection property.
48 ///70 ///
59 return hex"";81 return hex"";
60 }82 }
83
84 /// Get collection properties.
85 ///
86 /// @param keys Properties keys. Empty keys for all propertyes.
87 /// @return Vector of properties key/value pairs.
88 /// @dev EVM selector for this function is: 0x285fb8e6,
89 /// or in textual repr: collectionProperties(string[])
90 function collectionProperties(string[] memory keys) public view returns (Tuple10[] memory) {
91 require(false, stub_error);
92 keys;
93 dummy;
94 return new Tuple10[](0);
95 }
6196
62 /// Set the sponsor of the collection.97 /// Set the sponsor of the collection.
63 ///98 ///
72 dummy = 0;107 dummy = 0;
73 }108 }
109
110 /// Set the sponsor of the collection.
111 ///
112 /// @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.
113 ///
114 /// @param sponsor Cross account address of the sponsor from whose account funds will be debited for operations with the contract.
115 /// @dev EVM selector for this function is: 0x84a1d5a8,
116 /// or in textual repr: setCollectionSponsorCross((address,uint256))
117 function setCollectionSponsorCross(Tuple6 memory sponsor) public {
118 require(false, stub_error);
119 sponsor;
120 dummy = 0;
121 }
74122
75 /// Whether there is a pending sponsor.123 /// Whether there is a pending sponsor.
76 /// @dev EVM selector for this function is: 0x058ac185,124 /// @dev EVM selector for this function is: 0x058ac185,
154 return 0x0000000000000000000000000000000000000000;202 return 0x0000000000000000000000000000000000000000;
155 }203 }
204
205 /// Add collection admin.
206 /// @param newAdmin Cross account administrator address.
207 /// @dev EVM selector for this function is: 0x859aa7d6,
208 /// or in textual repr: addCollectionAdminCross((address,uint256))
209 function addCollectionAdminCross(Tuple6 memory newAdmin) public {
210 require(false, stub_error);
211 newAdmin;
212 dummy = 0;
213 }
214
215 /// Remove collection admin.
216 /// @param admin Cross account administrator address.
217 /// @dev EVM selector for this function is: 0x6c0cd173,
218 /// or in textual repr: removeCollectionAdminCross((address,uint256))
219 function removeCollectionAdminCross(Tuple6 memory admin) public {
220 require(false, stub_error);
221 admin;
222 dummy = 0;
223 }
156224
157 /// Add collection admin.225 /// Add collection admin.
158 /// @param newAdmin Address of the added administrator.226 /// @param newAdmin Address of the added administrator.
234 dummy = 0;302 dummy = 0;
235 }303 }
304
305 /// Add user to allowed list.
306 ///
307 /// @param user User cross account address.
308 /// @dev EVM selector for this function is: 0xa0184a3a,
309 /// or in textual repr: addToCollectionAllowListCross((address,uint256))
310 function addToCollectionAllowListCross(Tuple6 memory user) public {
311 require(false, stub_error);
312 user;
313 dummy = 0;
314 }
236315
237 /// Remove the user from the allowed list.316 /// Remove the user from the allowed list.
238 ///317 ///
245 dummy = 0;324 dummy = 0;
246 }325 }
326
327 /// Remove user from allowed list.
328 ///
329 /// @param user User cross account address.
330 /// @dev EVM selector for this function is: 0x09ba452a,
331 /// or in textual repr: removeFromCollectionAllowListCross((address,uint256))
332 function removeFromCollectionAllowListCross(Tuple6 memory user) public {
333 require(false, stub_error);
334 user;
335 dummy = 0;
336 }
247337
248 /// Switch permission for minting.338 /// Switch permission for minting.
249 ///339 ///
269 return false;359 return false;
270 }360 }
361
362 /// Check that account is the owner or admin of the collection
363 ///
364 /// @param user User cross account to verify
365 /// @return "true" if account is the owner or admin
366 /// @dev EVM selector for this function is: 0x3e75a905,
367 /// or in textual repr: isOwnerOrAdminCross((address,uint256))
368 function isOwnerOrAdminCross(Tuple6 memory user) public view returns (bool) {
369 require(false, stub_error);
370 user;
371 dummy;
372 return false;
373 }
271374
272 /// Returns collection type375 /// Returns collection type
273 ///376 ///
282385
283 /// Get collection owner.386 /// Get collection owner.
284 ///387 ///
285 /// @return Tuble with sponsor address and his substrate mirror.388 /// @return Tuple with sponsor address and his substrate mirror.
286 /// If address is canonical then substrate mirror is zero and vice versa.389 /// If address is canonical then substrate mirror is zero and vice versa.
287 /// @dev EVM selector for this function is: 0xdf727d3b,390 /// @dev EVM selector for this function is: 0xdf727d3b,
288 /// or in textual repr: collectionOwner()391 /// or in textual repr: collectionOwner()
304 dummy = 0;407 dummy = 0;
305 }408 }
409
410 /// Get collection administrators
411 ///
412 /// @return Vector of tuples with admins address and his substrate mirror.
413 /// If address is canonical then substrate mirror is zero and vice versa.
414 /// @dev EVM selector for this function is: 0x5813216b,
415 /// or in textual repr: collectionAdmins()
416 function collectionAdmins() public view returns (Tuple6[] memory) {
417 require(false, stub_error);
418 dummy;
419 return new Tuple6[](0);
420 }
421
422 /// Changes collection owner to another account
423 ///
424 /// @dev Owner can be changed only by current owner
425 /// @param newOwner new owner cross account
426 /// @dev EVM selector for this function is: 0xe5c9913f,
427 /// or in textual repr: setOwnerCross((address,uint256))
428 function setOwnerCross(Tuple6 memory newOwner) public {
429 require(false, stub_error);
430 newOwner;
431 dummy = 0;
432 }
306}433}
434
435/// @dev anonymous struct
436struct Tuple10 {
437 string field_0;
438 bytes field_1;
439}
307440
308/// @dev the ERC-165 identifier for this interface is 0x63034ac5441/// @dev the ERC-165 identifier for this interface is 0x032e5926
309contract ERC20UniqueExtensions is Dummy, ERC165 {442contract ERC20UniqueExtensions is Dummy, ERC165 {
443 /// @dev EVM selector for this function is: 0x0ecd0ab0,
444 /// or in textual repr: approveCross((address,uint256),uint256)
445 function approveCross(Tuple6 memory spender, uint256 amount) public returns (bool) {
446 require(false, stub_error);
447 spender;
448 amount;
449 dummy = 0;
450 return false;
451 }
452
310 /// Burn tokens from account453 /// Burn tokens from account
311 /// @dev Function that burns an `amount` of the tokens of a given account,454 /// @dev Function that burns an `amount` of the tokens of a given account,
322 return false;465 return false;
323 }466 }
467
468 /// Burn tokens from account
469 /// @dev Function that burns an `amount` of the tokens of a given account,
470 /// deducting from the sender's allowance for said account.
471 /// @param from The account whose tokens will be burnt.
472 /// @param amount The amount that will be burnt.
473 /// @dev EVM selector for this function is: 0xbb2f5a58,
474 /// or in textual repr: burnFromCross((address,uint256),uint256)
475 function burnFromCross(Tuple6 memory from, uint256 amount) public returns (bool) {
476 require(false, stub_error);
477 from;
478 amount;
479 dummy = 0;
480 return false;
481 }
324482
325 /// Mint tokens for multiple accounts.483 /// Mint tokens for multiple accounts.
326 /// @param amounts array of pairs of account address and amount484 /// @param amounts array of pairs of account address and amount
333 return false;491 return false;
334 }492 }
493
494 /// @dev EVM selector for this function is: 0xd5cf430b,
495 /// or in textual repr: transferFromCross((address,uint256),(address,uint256),uint256)
496 function transferFromCross(
497 Tuple6 memory from,
498 Tuple6 memory to,
499 uint256 amount
500 ) public returns (bool) {
501 require(false, stub_error);
502 from;
503 to;
504 amount;
505 dummy = 0;
506 return false;
507 }
335}508}
336509
337/// @dev anonymous struct510/// @dev anonymous struct
modifiedpallets/nonfungible/CHANGELOG.mddiffbeforeafterboth
22
3All notable changes to this project will be documented in this file.3All notable changes to this project will be documented in this file.
44
5<!-- bureaucrate goes here -->
6
7## [v0.1.6] - 2022-20-10
8
9### Change
10
11- Added `set_properties` method for `TokenProperties` interface.
12
5## [v0.1.5] - 2022-08-2413## [v0.1.5] - 2022-08-24
614
7### Change15### Change
8 - Add bound `AsRef<[u8; 32]>` to `T::CrossAccountId`.
916
10<!-- bureaucrate goes here -->17- Add bound `AsRef<[u8; 32]>` to `T::CrossAccountId`.
18
11## [v0.1.4] 2022-08-1619## [v0.1.4] 2022-08-16
1220
28- build: Upgrade polkadot to v0.9.25 cdfb9bdc7b205ff1b5134f034ef9973d769e5e6b36- build: Upgrade polkadot to v0.9.25 cdfb9bdc7b205ff1b5134f034ef9973d769e5e6b
2937
30## [0.1.2] - 2022-07-2538## [0.1.2] - 2022-07-25
39
31### Changed40### Changed
41
32- New `token_uri` retrieval logic:42- New `token_uri` retrieval logic:
3343
34 If the collection has a `url` property and it is not empty, it is returned.44 If the collection has a `url` property and it is not empty, it is returned.
39 otherwise, return concatenation of `baseURI` and stringified token id (decimal stringifying, without paddings).49 otherwise, return concatenation of `baseURI` and stringified token id (decimal stringifying, without paddings).
4050
41## [0.1.1] - 2022-07-1451## [0.1.1] - 2022-07-14
52
42### Added53### Added
4354
44- Implementation of RPC method `token_owners`.55- Implementation of RPC method `token_owners`.
45 For reasons of compatibility with this pallet, returns only one owner if token exists.56 For reasons of compatibility with this pallet, returns only one owner if token exists.
46 This was an internal request to improve the web interface and support fractionalization event.57 This was an internal request to improve the web interface and support fractionalization event.
4758
modifiedpallets/nonfungible/Cargo.tomldiffbeforeafterboth
1[package]1[package]
2name = "pallet-nonfungible"2name = "pallet-nonfungible"
3version = "0.1.5"3version = "0.1.6"
4license = "GPLv3"4license = "GPLv3"
5edition = "2021"5edition = "2021"
66
modifiedpallets/nonfungible/src/erc.rsdiffbeforeafterboth
35use pallet_common::{35use pallet_common::{
36 erc::{CommonEvmHandler, PrecompileResult, CollectionCall, static_property::key},36 erc::{CommonEvmHandler, PrecompileResult, CollectionCall, static_property::key},
37 CollectionHandle, CollectionPropertyPermissions,37 CollectionHandle, CollectionPropertyPermissions,
38 eth::convert_tuple_to_cross_account,
38};39};
39use pallet_evm::{account::CrossAccountId, PrecompileHandle};40use pallet_evm::{account::CrossAccountId, PrecompileHandle};
40use pallet_evm_coder_substrate::call;41use pallet_evm_coder_substrate::call;
97 let key = <Vec<u8>>::from(key)98 let key = <Vec<u8>>::from(key)
98 .try_into()99 .try_into()
99 .map_err(|_| "key too long")?;100 .map_err(|_| "key too long")?;
100 let value = value.try_into().map_err(|_| "value too long")?;101 let value = value.0.try_into().map_err(|_| "value too long")?;
101102
102 let nesting_budget = self103 let nesting_budget = self
103 .recorder104 .recorder
113 .map_err(dispatch_to_evm::<T>)114 .map_err(dispatch_to_evm::<T>)
114 }115 }
116
117 /// @notice Set token properties value.
118 /// @dev Throws error if `msg.sender` has no permission to edit the property.
119 /// @param tokenId ID of the token.
120 /// @param properties settable properties
121 #[weight(<SelfWeightOf<T>>::set_token_properties(properties.len() as u32))]
122 fn set_properties(
123 &mut self,
124 caller: caller,
125 token_id: uint256,
126 properties: Vec<(string, bytes)>,
127 ) -> Result<()> {
128 let caller = T::CrossAccountId::from_eth(caller);
129 let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;
130
131 let nesting_budget = self
132 .recorder
133 .weight_calls_budget(<StructureWeight<T>>::find_parent());
134
135 let properties = properties
136 .into_iter()
137 .map(|(key, value)| {
138 let key = <Vec<u8>>::from(key)
139 .try_into()
140 .map_err(|_| "key too large")?;
141
142 let value = value.0.try_into().map_err(|_| "value too large")?;
143
144 Ok(Property { key, value })
145 })
146 .collect::<Result<Vec<_>>>()?;
147
148 <Pallet<T>>::set_token_properties(
149 self,
150 &caller,
151 TokenId(token_id),
152 properties.into_iter(),
153 <Pallet<T>>::token_exists(&self, TokenId(token_id)),
154 &nesting_budget,
155 )
156 .map_err(dispatch_to_evm::<T>)
157 }
115158
116 /// @notice Delete token property value.159 /// @notice Delete token property value.
117 /// @dev Throws error if `msg.sender` has no permission to edit the property.160 /// @dev Throws error if `msg.sender` has no permission to edit the property.
146 let props = <TokenProperties<T>>::get((self.id, token_id));189 let props = <TokenProperties<T>>::get((self.id, token_id));
147 let prop = props.get(&key).ok_or("key not found")?;190 let prop = props.get(&key).ok_or("key not found")?;
148191
149 Ok(prop.to_vec())192 Ok(prop.to_vec().into())
150 }193 }
151}194}
152195
199/// @dev See https://eips.ethereum.org/EIPS/eip-721242/// @dev See https://eips.ethereum.org/EIPS/eip-721
200#[solidity_interface(name = ERC721Metadata, expect_selector = 0x5b5e139f)]243#[solidity_interface(name = ERC721Metadata, expect_selector = 0x5b5e139f)]
201impl<T: Config> NonfungibleHandle<T> {244impl<T: Config> NonfungibleHandle<T>
245where
246 T::AccountId: From<[u8; 32]>,
247{
202 /// @notice A descriptive name for a collection of NFTs in this contract248 /// @notice A descriptive name for a collection of NFTs in this contract
203 /// @dev real implementation of this function lies in `ERC721UniqueExtensions`249 /// @dev real implementation of this function lies in `ERC721UniqueExtensions`
604/// @title Unique extensions for ERC721.650/// @title Unique extensions for ERC721.
605#[solidity_interface(name = ERC721UniqueExtensions)]651#[solidity_interface(name = ERC721UniqueExtensions)]
606impl<T: Config> NonfungibleHandle<T> {652impl<T: Config> NonfungibleHandle<T>
653where
654 T::AccountId: From<[u8; 32]>,
655{
607 /// @notice A descriptive name for a collection of NFTs in this contract656 /// @notice A descriptive name for a collection of NFTs in this contract
608 fn name(&self) -> Result<string> {657 fn name(&self) -> Result<string> {
616 Ok(string::from_utf8_lossy(&self.token_prefix).into())665 Ok(string::from_utf8_lossy(&self.token_prefix).into())
617 }666 }
667
668 /// @notice Set or reaffirm the approved address for an NFT
669 /// @dev The zero address indicates there is no approved address.
670 /// @dev Throws unless `msg.sender` is the current NFT owner, or an authorized
671 /// operator of the current owner.
672 /// @param approved The new substrate address approved NFT controller
673 /// @param tokenId The NFT to approve
674 #[weight(<SelfWeightOf<T>>::approve())]
675 fn approve_cross(
676 &mut self,
677 caller: caller,
678 approved: (address, uint256),
679 token_id: uint256,
680 ) -> Result<void> {
681 let caller = T::CrossAccountId::from_eth(caller);
682 let approved = convert_tuple_to_cross_account::<T>(approved)?;
683 let token = token_id.try_into()?;
684
685 <Pallet<T>>::set_allowance(self, &caller, token, Some(&approved))
686 .map_err(dispatch_to_evm::<T>)?;
687 Ok(())
688 }
618689
619 /// @notice Transfer ownership of an NFT690 /// @notice Transfer ownership of an NFT
620 /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`691 /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`
634 Ok(())705 Ok(())
635 }706 }
707
708 /// @notice Transfer ownership of an NFT from cross account address to cross account address
709 /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`
710 /// is the zero address. Throws if `tokenId` is not a valid NFT.
711 /// @param from Cross acccount address of current owner
712 /// @param to Cross acccount address of new owner
713 /// @param tokenId The NFT to transfer
714 #[weight(<SelfWeightOf<T>>::transfer())]
715 fn transfer_from_cross(
716 &mut self,
717 caller: caller,
718 from: (address, uint256),
719 to: (address, uint256),
720 token_id: uint256,
721 ) -> Result<void> {
722 let caller = T::CrossAccountId::from_eth(caller);
723 let from = convert_tuple_to_cross_account::<T>(from)?;
724 let to = convert_tuple_to_cross_account::<T>(to)?;
725 let token_id = token_id.try_into()?;
726 let budget = self
727 .recorder
728 .weight_calls_budget(<StructureWeight<T>>::find_parent());
729 Pallet::<T>::transfer_from(self, &caller, &from, &to, token_id, &budget)
730 .map_err(dispatch_to_evm::<T>)?;
731 Ok(())
732 }
636733
637 /// @notice Burns a specific ERC721 token.734 /// @notice Burns a specific ERC721 token.
638 /// @dev Throws unless `msg.sender` is the current owner or an authorized735 /// @dev Throws unless `msg.sender` is the current owner or an authorized
654 Ok(())751 Ok(())
655 }752 }
753
754 /// @notice Burns a specific ERC721 token.
755 /// @dev Throws unless `msg.sender` is the current owner or an authorized
756 /// operator for this NFT. Throws if `from` is not the current owner. Throws
757 /// if `to` is the zero address. Throws if `tokenId` is not a valid NFT.
758 /// @param from The current owner of the NFT
759 /// @param tokenId The NFT to transfer
760 #[weight(<SelfWeightOf<T>>::burn_from())]
761 fn burn_from_cross(
762 &mut self,
763 caller: caller,
764 from: (address, uint256),
765 token_id: uint256,
766 ) -> Result<void> {
767 let caller = T::CrossAccountId::from_eth(caller);
768 let from = convert_tuple_to_cross_account::<T>(from)?;
769 let token = token_id.try_into()?;
770 let budget = self
771 .recorder
772 .weight_calls_budget(<StructureWeight<T>>::find_parent());
773
774 <Pallet<T>>::burn_from(self, &caller, &from, token, &budget)
775 .map_err(dispatch_to_evm::<T>)?;
776 Ok(())
777 }
656778
657 /// @notice Returns next free NFT ID.779 /// @notice Returns next free NFT ID.
658 fn next_token_id(&self) -> Result<uint256> {780 fn next_token_id(&self) -> Result<uint256> {
modifiedpallets/nonfungible/src/stubs/UniqueNFT.rawdiffbeforeafterboth

binary blob — no preview

modifiedpallets/nonfungible/src/stubs/UniqueNFT.soldiffbeforeafterboth
18}18}
1919
20/// @title A contract that allows to set and delete token properties and change token property permissions.20/// @title A contract that allows to set and delete token properties and change token property permissions.
21/// @dev the ERC-165 identifier for this interface is 0x4136937721/// @dev the ERC-165 identifier for this interface is 0x55dba919
22contract TokenProperties is Dummy, ERC165 {22contract TokenProperties is Dummy, ERC165 {
23 /// @notice Set permissions for token property.23 /// @notice Set permissions for token property.
24 /// @dev Throws error if `msg.sender` is not admin or owner of the collection.24 /// @dev Throws error if `msg.sender` is not admin or owner of the collection.
61 dummy = 0;61 dummy = 0;
62 }62 }
63
64 /// @notice Set token properties value.
65 /// @dev Throws error if `msg.sender` has no permission to edit the property.
66 /// @param tokenId ID of the token.
67 /// @param properties settable properties
68 /// @dev EVM selector for this function is: 0x14ed3a6e,
69 /// or in textual repr: setProperties(uint256,(string,bytes)[])
70 function setProperties(uint256 tokenId, Tuple19[] memory properties) public {
71 require(false, stub_error);
72 tokenId;
73 properties;
74 dummy = 0;
75 }
6376
64 /// @notice Delete token property value.77 /// @notice Delete token property value.
65 /// @dev Throws error if `msg.sender` has no permission to edit the property.78 /// @dev Throws error if `msg.sender` has no permission to edit the property.
91}104}
92105
93/// @title A contract that allows you to work with collections.106/// @title A contract that allows you to work with collections.
94/// @dev the ERC-165 identifier for this interface is 0x62e22290107/// @dev the ERC-165 identifier for this interface is 0xb3152af3
95contract Collection is Dummy, ERC165 {108contract Collection is Dummy, ERC165 {
96 /// Set collection property.109 /// Set collection property.
97 ///110 ///
106 dummy = 0;119 dummy = 0;
107 }120 }
121
122 /// Set collection properties.
123 ///
124 /// @param properties Vector of properties key/value pair.
125 /// @dev EVM selector for this function is: 0x50b26b2a,
126 /// or in textual repr: setCollectionProperties((string,bytes)[])
127 function setCollectionProperties(Tuple19[] memory properties) public {
128 require(false, stub_error);
129 properties;
130 dummy = 0;
131 }
108132
109 /// Delete collection property.133 /// Delete collection property.
110 ///134 ///
117 dummy = 0;141 dummy = 0;
118 }142 }
143
144 /// Delete collection properties.
145 ///
146 /// @param keys Properties keys.
147 /// @dev EVM selector for this function is: 0xee206ee3,
148 /// or in textual repr: deleteCollectionProperties(string[])
149 function deleteCollectionProperties(string[] memory keys) public {
150 require(false, stub_error);
151 keys;
152 dummy = 0;
153 }
119154
120 /// Get collection property.155 /// Get collection property.
121 ///156 ///
132 return hex"";167 return hex"";
133 }168 }
169
170 /// Get collection properties.
171 ///
172 /// @param keys Properties keys. Empty keys for all propertyes.
173 /// @return Vector of properties key/value pairs.
174 /// @dev EVM selector for this function is: 0x285fb8e6,
175 /// or in textual repr: collectionProperties(string[])
176 function collectionProperties(string[] memory keys) public view returns (Tuple19[] memory) {
177 require(false, stub_error);
178 keys;
179 dummy;
180 return new Tuple19[](0);
181 }
134182
135 /// Set the sponsor of the collection.183 /// Set the sponsor of the collection.
136 ///184 ///
145 dummy = 0;193 dummy = 0;
146 }194 }
195
196 /// Set the sponsor of the collection.
197 ///
198 /// @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.
199 ///
200 /// @param sponsor Cross account address of the sponsor from whose account funds will be debited for operations with the contract.
201 /// @dev EVM selector for this function is: 0x84a1d5a8,
202 /// or in textual repr: setCollectionSponsorCross((address,uint256))
203 function setCollectionSponsorCross(Tuple6 memory sponsor) public {
204 require(false, stub_error);
205 sponsor;
206 dummy = 0;
207 }
147208
148 /// Whether there is a pending sponsor.209 /// Whether there is a pending sponsor.
149 /// @dev EVM selector for this function is: 0x058ac185,210 /// @dev EVM selector for this function is: 0x058ac185,
177 /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.238 /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.
178 /// @dev EVM selector for this function is: 0x6ec0a9f1,239 /// @dev EVM selector for this function is: 0x6ec0a9f1,
179 /// or in textual repr: collectionSponsor()240 /// or in textual repr: collectionSponsor()
180 function collectionSponsor() public view returns (Tuple17 memory) {241 function collectionSponsor() public view returns (Tuple6 memory) {
181 require(false, stub_error);242 require(false, stub_error);
182 dummy;243 dummy;
183 return Tuple17(0x0000000000000000000000000000000000000000, 0);244 return Tuple6(0x0000000000000000000000000000000000000000, 0);
184 }245 }
185246
186 /// Set limits for the collection.247 /// Set limits for the collection.
227 return 0x0000000000000000000000000000000000000000;288 return 0x0000000000000000000000000000000000000000;
228 }289 }
290
291 /// Add collection admin.
292 /// @param newAdmin Cross account administrator address.
293 /// @dev EVM selector for this function is: 0x859aa7d6,
294 /// or in textual repr: addCollectionAdminCross((address,uint256))
295 function addCollectionAdminCross(Tuple6 memory newAdmin) public {
296 require(false, stub_error);
297 newAdmin;
298 dummy = 0;
299 }
300
301 /// Remove collection admin.
302 /// @param admin Cross account administrator address.
303 /// @dev EVM selector for this function is: 0x6c0cd173,
304 /// or in textual repr: removeCollectionAdminCross((address,uint256))
305 function removeCollectionAdminCross(Tuple6 memory admin) public {
306 require(false, stub_error);
307 admin;
308 dummy = 0;
309 }
229310
230 /// Add collection admin.311 /// Add collection admin.
231 /// @param newAdmin Address of the added administrator.312 /// @param newAdmin Address of the added administrator.
307 dummy = 0;388 dummy = 0;
308 }389 }
390
391 /// Add user to allowed list.
392 ///
393 /// @param user User cross account address.
394 /// @dev EVM selector for this function is: 0xa0184a3a,
395 /// or in textual repr: addToCollectionAllowListCross((address,uint256))
396 function addToCollectionAllowListCross(Tuple6 memory user) public {
397 require(false, stub_error);
398 user;
399 dummy = 0;
400 }
309401
310 /// Remove the user from the allowed list.402 /// Remove the user from the allowed list.
311 ///403 ///
318 dummy = 0;410 dummy = 0;
319 }411 }
412
413 /// Remove user from allowed list.
414 ///
415 /// @param user User cross account address.
416 /// @dev EVM selector for this function is: 0x09ba452a,
417 /// or in textual repr: removeFromCollectionAllowListCross((address,uint256))
418 function removeFromCollectionAllowListCross(Tuple6 memory user) public {
419 require(false, stub_error);
420 user;
421 dummy = 0;
422 }
320423
321 /// Switch permission for minting.424 /// Switch permission for minting.
322 ///425 ///
342 return false;445 return false;
343 }446 }
447
448 /// Check that account is the owner or admin of the collection
449 ///
450 /// @param user User cross account to verify
451 /// @return "true" if account is the owner or admin
452 /// @dev EVM selector for this function is: 0x3e75a905,
453 /// or in textual repr: isOwnerOrAdminCross((address,uint256))
454 function isOwnerOrAdminCross(Tuple6 memory user) public view returns (bool) {
455 require(false, stub_error);
456 user;
457 dummy;
458 return false;
459 }
344460
345 /// Returns collection type461 /// Returns collection type
346 ///462 ///
355471
356 /// Get collection owner.472 /// Get collection owner.
357 ///473 ///
358 /// @return Tuble with sponsor address and his substrate mirror.474 /// @return Tuple with sponsor address and his substrate mirror.
359 /// If address is canonical then substrate mirror is zero and vice versa.475 /// If address is canonical then substrate mirror is zero and vice versa.
360 /// @dev EVM selector for this function is: 0xdf727d3b,476 /// @dev EVM selector for this function is: 0xdf727d3b,
361 /// or in textual repr: collectionOwner()477 /// or in textual repr: collectionOwner()
362 function collectionOwner() public view returns (Tuple17 memory) {478 function collectionOwner() public view returns (Tuple6 memory) {
363 require(false, stub_error);479 require(false, stub_error);
364 dummy;480 dummy;
365 return Tuple17(0x0000000000000000000000000000000000000000, 0);481 return Tuple6(0x0000000000000000000000000000000000000000, 0);
366 }482 }
367483
368 /// Changes collection owner to another account484 /// Changes collection owner to another account
377 dummy = 0;493 dummy = 0;
378 }494 }
495
496 /// Get collection administrators
497 ///
498 /// @return Vector of tuples with admins address and his substrate mirror.
499 /// If address is canonical then substrate mirror is zero and vice versa.
500 /// @dev EVM selector for this function is: 0x5813216b,
501 /// or in textual repr: collectionAdmins()
502 function collectionAdmins() public view returns (Tuple6[] memory) {
503 require(false, stub_error);
504 dummy;
505 return new Tuple6[](0);
506 }
507
508 /// Changes collection owner to another account
509 ///
510 /// @dev Owner can be changed only by current owner
511 /// @param newOwner new owner cross account
512 /// @dev EVM selector for this function is: 0xe5c9913f,
513 /// or in textual repr: setOwnerCross((address,uint256))
514 function setOwnerCross(Tuple6 memory newOwner) public {
515 require(false, stub_error);
516 newOwner;
517 dummy = 0;
518 }
379}519}
380520
381/// @dev anonymous struct521/// @dev anonymous struct
382struct Tuple17 {522struct Tuple19 {
383 address field_0;523 string field_0;
384 uint256 field_1;524 bytes field_1;
385}525}
386526
387/// @title ERC-721 Non-Fungible Token Standard, optional metadata extension527/// @title ERC-721 Non-Fungible Token Standard, optional metadata extension
528}668}
529669
530/// @title Unique extensions for ERC721.670/// @title Unique extensions for ERC721.
531/// @dev the ERC-165 identifier for this interface is 0x4468500d671/// @dev the ERC-165 identifier for this interface is 0x244543ee
532contract ERC721UniqueExtensions is Dummy, ERC165 {672contract ERC721UniqueExtensions is Dummy, ERC165 {
533 /// @notice A descriptive name for a collection of NFTs in this contract673 /// @notice A descriptive name for a collection of NFTs in this contract
534 /// @dev EVM selector for this function is: 0x06fdde03,674 /// @dev EVM selector for this function is: 0x06fdde03,
548 return "";688 return "";
549 }689 }
690
691 /// @notice Set or reaffirm the approved address for an NFT
692 /// @dev The zero address indicates there is no approved address.
693 /// @dev Throws unless `msg.sender` is the current NFT owner, or an authorized
694 /// operator of the current owner.
695 /// @param approved The new substrate address approved NFT controller
696 /// @param tokenId The NFT to approve
697 /// @dev EVM selector for this function is: 0x0ecd0ab0,
698 /// or in textual repr: approveCross((address,uint256),uint256)
699 function approveCross(Tuple6 memory approved, uint256 tokenId) public {
700 require(false, stub_error);
701 approved;
702 tokenId;
703 dummy = 0;
704 }
550705
551 /// @notice Transfer ownership of an NFT706 /// @notice Transfer ownership of an NFT
552 /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`707 /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`
562 dummy = 0;717 dummy = 0;
563 }718 }
719
720 /// @notice Transfer ownership of an NFT from cross account address to cross account address
721 /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`
722 /// is the zero address. Throws if `tokenId` is not a valid NFT.
723 /// @param from Cross acccount address of current owner
724 /// @param to Cross acccount address of new owner
725 /// @param tokenId The NFT to transfer
726 /// @dev EVM selector for this function is: 0xd5cf430b,
727 /// or in textual repr: transferFromCross((address,uint256),(address,uint256),uint256)
728 function transferFromCross(
729 Tuple6 memory from,
730 Tuple6 memory to,
731 uint256 tokenId
732 ) public {
733 require(false, stub_error);
734 from;
735 to;
736 tokenId;
737 dummy = 0;
738 }
564739
565 /// @notice Burns a specific ERC721 token.740 /// @notice Burns a specific ERC721 token.
566 /// @dev Throws unless `msg.sender` is the current owner or an authorized741 /// @dev Throws unless `msg.sender` is the current owner or an authorized
577 dummy = 0;752 dummy = 0;
578 }753 }
754
755 /// @notice Burns a specific ERC721 token.
756 /// @dev Throws unless `msg.sender` is the current owner or an authorized
757 /// operator for this NFT. Throws if `from` is not the current owner. Throws
758 /// if `to` is the zero address. Throws if `tokenId` is not a valid NFT.
759 /// @param from The current owner of the NFT
760 /// @param tokenId The NFT to transfer
761 /// @dev EVM selector for this function is: 0xbb2f5a58,
762 /// or in textual repr: burnFromCross((address,uint256),uint256)
763 function burnFromCross(Tuple6 memory from, uint256 tokenId) public {
764 require(false, stub_error);
765 from;
766 tokenId;
767 dummy = 0;
768 }
579769
580 /// @notice Returns next free NFT ID.770 /// @notice Returns next free NFT ID.
581 /// @dev EVM selector for this function is: 0x75794a3c,771 /// @dev EVM selector for this function is: 0x75794a3c,
607 // /// @param tokens array of pairs of token ID and token URI for minted tokens797 // /// @param tokens array of pairs of token ID and token URI for minted tokens
608 // /// @dev EVM selector for this function is: 0x36543006,798 // /// @dev EVM selector for this function is: 0x36543006,
609 // /// or in textual repr: mintBulkWithTokenURI(address,(uint256,string)[])799 // /// or in textual repr: mintBulkWithTokenURI(address,(uint256,string)[])
610 // function mintBulkWithTokenURI(address to, Tuple6[] memory tokens) public returns (bool) {800 // function mintBulkWithTokenURI(address to, Tuple8[] memory tokens) public returns (bool) {
611 // require(false, stub_error);801 // require(false, stub_error);
612 // to;802 // to;
613 // tokens;803 // tokens;
618}808}
619809
620/// @dev anonymous struct810/// @dev anonymous struct
621struct Tuple6 {811struct Tuple8 {
622 uint256 field_0;812 uint256 field_0;
623 string field_1;813 string field_1;
624}814}
815
816/// @dev anonymous struct
817struct Tuple6 {
818 address field_0;
819 uint256 field_1;
820}
625821
626/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension822/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
627/// @dev See https://eips.ethereum.org/EIPS/eip-721823/// @dev See https://eips.ethereum.org/EIPS/eip-721
modifiedpallets/refungible/CHANGELOG.mddiffbeforeafterboth
22
3All notable changes to this project will be documented in this file.3All notable changes to this project will be documented in this file.
44
5## [v0.2.5] - 2022-20-10
6
7### Change
8
9- Added `set_properties` method for `TokenProperties` interface.
10
5## [v0.2.4] - 2022-08-2411## [v0.2.4] - 2022-08-24
612
7### Change13### Change
8 - Add bound `AsRef<[u8; 32]>` to `T::CrossAccountId`.
914
15- Add bound `AsRef<[u8; 32]>` to `T::CrossAccountId`.
16
10<!-- bureaucrate goes here -->17<!-- bureaucrate goes here -->
18
11## [v0.2.3] 2022-08-1619## [v0.2.3] 2022-08-16
1220
13### Other changes21### Other changes
modifiedpallets/refungible/Cargo.tomldiffbeforeafterboth
1[package]1[package]
2name = "pallet-refungible"2name = "pallet-refungible"
3version = "0.2.4"3version = "0.2.5"
4license = "GPLv3"4license = "GPLv3"
5edition = "2021"5edition = "2021"
66
modifiedpallets/refungible/src/erc.rsdiffbeforeafterboth
30use pallet_common::{30use pallet_common::{
31 CollectionHandle, CollectionPropertyPermissions,31 CollectionHandle, CollectionPropertyPermissions,
32 erc::{CommonEvmHandler, CollectionCall, static_property::key},32 erc::{CommonEvmHandler, CollectionCall, static_property::key},
33 eth::convert_tuple_to_cross_account,
33};34};
34use pallet_evm::{account::CrossAccountId, PrecompileHandle};35use pallet_evm::{account::CrossAccountId, PrecompileHandle};
35use pallet_evm_coder_substrate::{call, dispatch_to_evm};36use pallet_evm_coder_substrate::{call, dispatch_to_evm};
100 let key = <Vec<u8>>::from(key)101 let key = <Vec<u8>>::from(key)
101 .try_into()102 .try_into()
102 .map_err(|_| "key too long")?;103 .map_err(|_| "key too long")?;
103 let value = value.try_into().map_err(|_| "value too long")?;104 let value = value.0.try_into().map_err(|_| "value too long")?;
104105
105 let nesting_budget = self106 let nesting_budget = self
106 .recorder107 .recorder
116 .map_err(dispatch_to_evm::<T>)117 .map_err(dispatch_to_evm::<T>)
117 }118 }
119
120 /// @notice Set token properties value.
121 /// @dev Throws error if `msg.sender` has no permission to edit the property.
122 /// @param tokenId ID of the token.
123 /// @param properties settable properties
124 fn set_properties(
125 &mut self,
126 caller: caller,
127 token_id: uint256,
128 properties: Vec<(string, bytes)>,
129 ) -> Result<()> {
130 let caller = T::CrossAccountId::from_eth(caller);
131 let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;
132
133 let nesting_budget = self
134 .recorder
135 .weight_calls_budget(<StructureWeight<T>>::find_parent());
136
137 let properties = properties
138 .into_iter()
139 .map(|(key, value)| {
140 let key = <Vec<u8>>::from(key)
141 .try_into()
142 .map_err(|_| "key too large")?;
143
144 let value = value.0.try_into().map_err(|_| "value too large")?;
145
146 Ok(Property { key, value })
147 })
148 .collect::<Result<Vec<_>>>()?;
149
150 <Pallet<T>>::set_token_properties(
151 self,
152 &caller,
153 TokenId(token_id),
154 properties.into_iter(),
155 <Pallet<T>>::token_exists(&self, TokenId(token_id)),
156 &nesting_budget,
157 )
158 .map_err(dispatch_to_evm::<T>)
159 }
118160
119 /// @notice Delete token property value.161 /// @notice Delete token property value.
120 /// @dev Throws error if `msg.sender` has no permission to edit the property.162 /// @dev Throws error if `msg.sender` has no permission to edit the property.
149 let props = <TokenProperties<T>>::get((self.id, token_id));191 let props = <TokenProperties<T>>::get((self.id, token_id));
150 let prop = props.get(&key).ok_or("key not found")?;192 let prop = props.get(&key).ok_or("key not found")?;
151193
152 Ok(prop.to_vec())194 Ok(prop.to_vec().into())
153 }195 }
154}196}
155197
195237
196#[solidity_interface(name = ERC721Metadata)]238#[solidity_interface(name = ERC721Metadata)]
197impl<T: Config> RefungibleHandle<T> {239impl<T: Config> RefungibleHandle<T>
240where
241 T::AccountId: From<[u8; 32]>,
242{
198 /// @notice A descriptive name for a collection of NFTs in this contract243 /// @notice A descriptive name for a collection of NFTs in this contract
199 /// @dev real implementation of this function lies in `ERC721UniqueExtensions`244 /// @dev real implementation of this function lies in `ERC721UniqueExtensions`
632/// @title Unique extensions for ERC721.677/// @title Unique extensions for ERC721.
633#[solidity_interface(name = ERC721UniqueExtensions)]678#[solidity_interface(name = ERC721UniqueExtensions)]
634impl<T: Config> RefungibleHandle<T> {679impl<T: Config> RefungibleHandle<T>
680where
681 T::AccountId: From<[u8; 32]>,
682{
635 /// @notice A descriptive name for a collection of NFTs in this contract683 /// @notice A descriptive name for a collection of NFTs in this contract
636 fn name(&self) -> Result<string> {684 fn name(&self) -> Result<string> {
659 .recorder707 .recorder
660 .weight_calls_budget(<StructureWeight<T>>::find_parent());708 .weight_calls_budget(<StructureWeight<T>>::find_parent());
661709
662 let balance = balance(&self, token, &caller)?;710 let balance = balance(self, token, &caller)?;
663 ensure_single_owner(&self, token, balance)?;711 ensure_single_owner(self, token, balance)?;
664712
665 <Pallet<T>>::transfer(self, &caller, &to, token, balance, &budget)713 <Pallet<T>>::transfer(self, &caller, &to, token, balance, &budget)
666 .map_err(dispatch_to_evm::<T>)?;714 .map_err(dispatch_to_evm::<T>)?;
667 Ok(())715 Ok(())
668 }716 }
717
718 /// @notice Transfer ownership of an RFT
719 /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`
720 /// is the zero address. Throws if `tokenId` is not a valid RFT.
721 /// Throws if RFT pieces have multiple owners.
722 /// @param to The new owner
723 /// @param tokenId The RFT to transfer
724 #[weight(<SelfWeightOf<T>>::transfer_creating_removing())]
725 fn transfer_from_cross(
726 &mut self,
727 caller: caller,
728 from: (address, uint256),
729 to: (address, uint256),
730 token_id: uint256,
731 ) -> Result<void> {
732 let caller = T::CrossAccountId::from_eth(caller);
733 let from = convert_tuple_to_cross_account::<T>(from)?;
734 let to = convert_tuple_to_cross_account::<T>(to)?;
735 let token_id = token_id.try_into()?;
736 let budget = self
737 .recorder
738 .weight_calls_budget(<StructureWeight<T>>::find_parent());
739
740 let balance = balance(self, token_id, &from)?;
741 ensure_single_owner(self, token_id, balance)?;
742
743 Pallet::<T>::transfer_from(self, &caller, &from, &to, token_id, balance, &budget)
744 .map_err(dispatch_to_evm::<T>)?;
745 Ok(())
746 }
669747
670 /// @notice Burns a specific ERC721 token.748 /// @notice Burns a specific ERC721 token.
671 /// @dev Throws unless `msg.sender` is the current owner or an authorized749 /// @dev Throws unless `msg.sender` is the current owner or an authorized
683 .recorder761 .recorder
684 .weight_calls_budget(<StructureWeight<T>>::find_parent());762 .weight_calls_budget(<StructureWeight<T>>::find_parent());
685763
686 let balance = balance(&self, token, &caller)?;764 let balance = balance(self, token, &from)?;
687 ensure_single_owner(&self, token, balance)?;765 ensure_single_owner(self, token, balance)?;
688766
689 <Pallet<T>>::burn_from(self, &caller, &from, token, balance, &budget)767 <Pallet<T>>::burn_from(self, &caller, &from, token, balance, &budget)
690 .map_err(dispatch_to_evm::<T>)?;768 .map_err(dispatch_to_evm::<T>)?;
691 Ok(())769 Ok(())
692 }770 }
771
772 /// @notice Burns a specific ERC721 token.
773 /// @dev Throws unless `msg.sender` is the current owner or an authorized
774 /// operator for this RFT. Throws if `from` is not the current owner. Throws
775 /// if `to` is the zero address. Throws if `tokenId` is not a valid RFT.
776 /// Throws if RFT pieces have multiple owners.
777 /// @param from The current owner of the RFT
778 /// @param tokenId The RFT to transfer
779 #[weight(<SelfWeightOf<T>>::burn_from())]
780 fn burn_from_cross(
781 &mut self,
782 caller: caller,
783 from: (address, uint256),
784 token_id: uint256,
785 ) -> Result<void> {
786 let caller = T::CrossAccountId::from_eth(caller);
787 let from = convert_tuple_to_cross_account::<T>(from)?;
788 let token = token_id.try_into()?;
789 let budget = self
790 .recorder
791 .weight_calls_budget(<StructureWeight<T>>::find_parent());
792
793 let balance = balance(self, token, &from)?;
794 ensure_single_owner(self, token, balance)?;
795
796 <Pallet<T>>::burn_from(self, &caller, &from, token, balance, &budget)
797 .map_err(dispatch_to_evm::<T>)?;
798 Ok(())
799 }
693800
694 /// @notice Returns next free RFT ID.801 /// @notice Returns next free RFT ID.
695 fn next_token_id(&self) -> Result<uint256> {802 fn next_token_id(&self) -> Result<uint256> {
modifiedpallets/refungible/src/stubs/UniqueRefungible.rawdiffbeforeafterboth

binary blob — no preview

modifiedpallets/refungible/src/stubs/UniqueRefungible.soldiffbeforeafterboth
18}18}
1919
20/// @title A contract that allows to set and delete token properties and change token property permissions.20/// @title A contract that allows to set and delete token properties and change token property permissions.
21/// @dev the ERC-165 identifier for this interface is 0x4136937721/// @dev the ERC-165 identifier for this interface is 0x55dba919
22contract TokenProperties is Dummy, ERC165 {22contract TokenProperties is Dummy, ERC165 {
23 /// @notice Set permissions for token property.23 /// @notice Set permissions for token property.
24 /// @dev Throws error if `msg.sender` is not admin or owner of the collection.24 /// @dev Throws error if `msg.sender` is not admin or owner of the collection.
61 dummy = 0;61 dummy = 0;
62 }62 }
63
64 /// @notice Set token properties value.
65 /// @dev Throws error if `msg.sender` has no permission to edit the property.
66 /// @param tokenId ID of the token.
67 /// @param properties settable properties
68 /// @dev EVM selector for this function is: 0x14ed3a6e,
69 /// or in textual repr: setProperties(uint256,(string,bytes)[])
70 function setProperties(uint256 tokenId, Tuple19[] memory properties) public {
71 require(false, stub_error);
72 tokenId;
73 properties;
74 dummy = 0;
75 }
6376
64 /// @notice Delete token property value.77 /// @notice Delete token property value.
65 /// @dev Throws error if `msg.sender` has no permission to edit the property.78 /// @dev Throws error if `msg.sender` has no permission to edit the property.
91}104}
92105
93/// @title A contract that allows you to work with collections.106/// @title A contract that allows you to work with collections.
94/// @dev the ERC-165 identifier for this interface is 0x62e22290107/// @dev the ERC-165 identifier for this interface is 0xb3152af3
95contract Collection is Dummy, ERC165 {108contract Collection is Dummy, ERC165 {
96 /// Set collection property.109 /// Set collection property.
97 ///110 ///
106 dummy = 0;119 dummy = 0;
107 }120 }
121
122 /// Set collection properties.
123 ///
124 /// @param properties Vector of properties key/value pair.
125 /// @dev EVM selector for this function is: 0x50b26b2a,
126 /// or in textual repr: setCollectionProperties((string,bytes)[])
127 function setCollectionProperties(Tuple19[] memory properties) public {
128 require(false, stub_error);
129 properties;
130 dummy = 0;
131 }
108132
109 /// Delete collection property.133 /// Delete collection property.
110 ///134 ///
117 dummy = 0;141 dummy = 0;
118 }142 }
143
144 /// Delete collection properties.
145 ///
146 /// @param keys Properties keys.
147 /// @dev EVM selector for this function is: 0xee206ee3,
148 /// or in textual repr: deleteCollectionProperties(string[])
149 function deleteCollectionProperties(string[] memory keys) public {
150 require(false, stub_error);
151 keys;
152 dummy = 0;
153 }
119154
120 /// Get collection property.155 /// Get collection property.
121 ///156 ///
132 return hex"";167 return hex"";
133 }168 }
169
170 /// Get collection properties.
171 ///
172 /// @param keys Properties keys. Empty keys for all propertyes.
173 /// @return Vector of properties key/value pairs.
174 /// @dev EVM selector for this function is: 0x285fb8e6,
175 /// or in textual repr: collectionProperties(string[])
176 function collectionProperties(string[] memory keys) public view returns (Tuple19[] memory) {
177 require(false, stub_error);
178 keys;
179 dummy;
180 return new Tuple19[](0);
181 }
134182
135 /// Set the sponsor of the collection.183 /// Set the sponsor of the collection.
136 ///184 ///
145 dummy = 0;193 dummy = 0;
146 }194 }
195
196 /// Set the sponsor of the collection.
197 ///
198 /// @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.
199 ///
200 /// @param sponsor Cross account address of the sponsor from whose account funds will be debited for operations with the contract.
201 /// @dev EVM selector for this function is: 0x84a1d5a8,
202 /// or in textual repr: setCollectionSponsorCross((address,uint256))
203 function setCollectionSponsorCross(Tuple6 memory sponsor) public {
204 require(false, stub_error);
205 sponsor;
206 dummy = 0;
207 }
147208
148 /// Whether there is a pending sponsor.209 /// Whether there is a pending sponsor.
149 /// @dev EVM selector for this function is: 0x058ac185,210 /// @dev EVM selector for this function is: 0x058ac185,
177 /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.238 /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.
178 /// @dev EVM selector for this function is: 0x6ec0a9f1,239 /// @dev EVM selector for this function is: 0x6ec0a9f1,
179 /// or in textual repr: collectionSponsor()240 /// or in textual repr: collectionSponsor()
180 function collectionSponsor() public view returns (Tuple17 memory) {241 function collectionSponsor() public view returns (Tuple6 memory) {
181 require(false, stub_error);242 require(false, stub_error);
182 dummy;243 dummy;
183 return Tuple17(0x0000000000000000000000000000000000000000, 0);244 return Tuple6(0x0000000000000000000000000000000000000000, 0);
184 }245 }
185246
186 /// Set limits for the collection.247 /// Set limits for the collection.
227 return 0x0000000000000000000000000000000000000000;288 return 0x0000000000000000000000000000000000000000;
228 }289 }
290
291 /// Add collection admin.
292 /// @param newAdmin Cross account administrator address.
293 /// @dev EVM selector for this function is: 0x859aa7d6,
294 /// or in textual repr: addCollectionAdminCross((address,uint256))
295 function addCollectionAdminCross(Tuple6 memory newAdmin) public {
296 require(false, stub_error);
297 newAdmin;
298 dummy = 0;
299 }
300
301 /// Remove collection admin.
302 /// @param admin Cross account administrator address.
303 /// @dev EVM selector for this function is: 0x6c0cd173,
304 /// or in textual repr: removeCollectionAdminCross((address,uint256))
305 function removeCollectionAdminCross(Tuple6 memory admin) public {
306 require(false, stub_error);
307 admin;
308 dummy = 0;
309 }
229310
230 /// Add collection admin.311 /// Add collection admin.
231 /// @param newAdmin Address of the added administrator.312 /// @param newAdmin Address of the added administrator.
307 dummy = 0;388 dummy = 0;
308 }389 }
390
391 /// Add user to allowed list.
392 ///
393 /// @param user User cross account address.
394 /// @dev EVM selector for this function is: 0xa0184a3a,
395 /// or in textual repr: addToCollectionAllowListCross((address,uint256))
396 function addToCollectionAllowListCross(Tuple6 memory user) public {
397 require(false, stub_error);
398 user;
399 dummy = 0;
400 }
309401
310 /// Remove the user from the allowed list.402 /// Remove the user from the allowed list.
311 ///403 ///
318 dummy = 0;410 dummy = 0;
319 }411 }
412
413 /// Remove user from allowed list.
414 ///
415 /// @param user User cross account address.
416 /// @dev EVM selector for this function is: 0x09ba452a,
417 /// or in textual repr: removeFromCollectionAllowListCross((address,uint256))
418 function removeFromCollectionAllowListCross(Tuple6 memory user) public {
419 require(false, stub_error);
420 user;
421 dummy = 0;
422 }
320423
321 /// Switch permission for minting.424 /// Switch permission for minting.
322 ///425 ///
342 return false;445 return false;
343 }446 }
447
448 /// Check that account is the owner or admin of the collection
449 ///
450 /// @param user User cross account to verify
451 /// @return "true" if account is the owner or admin
452 /// @dev EVM selector for this function is: 0x3e75a905,
453 /// or in textual repr: isOwnerOrAdminCross((address,uint256))
454 function isOwnerOrAdminCross(Tuple6 memory user) public view returns (bool) {
455 require(false, stub_error);
456 user;
457 dummy;
458 return false;
459 }
344460
345 /// Returns collection type461 /// Returns collection type
346 ///462 ///
355471
356 /// Get collection owner.472 /// Get collection owner.
357 ///473 ///
358 /// @return Tuble with sponsor address and his substrate mirror.474 /// @return Tuple with sponsor address and his substrate mirror.
359 /// If address is canonical then substrate mirror is zero and vice versa.475 /// If address is canonical then substrate mirror is zero and vice versa.
360 /// @dev EVM selector for this function is: 0xdf727d3b,476 /// @dev EVM selector for this function is: 0xdf727d3b,
361 /// or in textual repr: collectionOwner()477 /// or in textual repr: collectionOwner()
362 function collectionOwner() public view returns (Tuple17 memory) {478 function collectionOwner() public view returns (Tuple6 memory) {
363 require(false, stub_error);479 require(false, stub_error);
364 dummy;480 dummy;
365 return Tuple17(0x0000000000000000000000000000000000000000, 0);481 return Tuple6(0x0000000000000000000000000000000000000000, 0);
366 }482 }
367483
368 /// Changes collection owner to another account484 /// Changes collection owner to another account
377 dummy = 0;493 dummy = 0;
378 }494 }
495
496 /// Get collection administrators
497 ///
498 /// @return Vector of tuples with admins address and his substrate mirror.
499 /// If address is canonical then substrate mirror is zero and vice versa.
500 /// @dev EVM selector for this function is: 0x5813216b,
501 /// or in textual repr: collectionAdmins()
502 function collectionAdmins() public view returns (Tuple6[] memory) {
503 require(false, stub_error);
504 dummy;
505 return new Tuple6[](0);
506 }
507
508 /// Changes collection owner to another account
509 ///
510 /// @dev Owner can be changed only by current owner
511 /// @param newOwner new owner cross account
512 /// @dev EVM selector for this function is: 0xe5c9913f,
513 /// or in textual repr: setOwnerCross((address,uint256))
514 function setOwnerCross(Tuple6 memory newOwner) public {
515 require(false, stub_error);
516 newOwner;
517 dummy = 0;
518 }
379}519}
380520
381/// @dev anonymous struct521/// @dev anonymous struct
382struct Tuple17 {522struct Tuple19 {
383 address field_0;523 string field_0;
384 uint256 field_1;524 bytes field_1;
385}525}
386526
387/// @dev the ERC-165 identifier for this interface is 0x5b5e139f527/// @dev the ERC-165 identifier for this interface is 0x5b5e139f
526}666}
527667
528/// @title Unique extensions for ERC721.668/// @title Unique extensions for ERC721.
529/// @dev the ERC-165 identifier for this interface is 0xef1eaacb669/// @dev the ERC-165 identifier for this interface is 0x81feb398
530contract ERC721UniqueExtensions is Dummy, ERC165 {670contract ERC721UniqueExtensions is Dummy, ERC165 {
531 /// @notice A descriptive name for a collection of NFTs in this contract671 /// @notice A descriptive name for a collection of NFTs in this contract
532 /// @dev EVM selector for this function is: 0x06fdde03,672 /// @dev EVM selector for this function is: 0x06fdde03,
561 dummy = 0;701 dummy = 0;
562 }702 }
703
704 /// @notice Transfer ownership of an RFT
705 /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`
706 /// is the zero address. Throws if `tokenId` is not a valid RFT.
707 /// Throws if RFT pieces have multiple owners.
708 /// @param to The new owner
709 /// @param tokenId The RFT to transfer
710 /// @dev EVM selector for this function is: 0xd5cf430b,
711 /// or in textual repr: transferFromCross((address,uint256),(address,uint256),uint256)
712 function transferFromCross(
713 Tuple6 memory from,
714 Tuple6 memory to,
715 uint256 tokenId
716 ) public {
717 require(false, stub_error);
718 from;
719 to;
720 tokenId;
721 dummy = 0;
722 }
563723
564 /// @notice Burns a specific ERC721 token.724 /// @notice Burns a specific ERC721 token.
565 /// @dev Throws unless `msg.sender` is the current owner or an authorized725 /// @dev Throws unless `msg.sender` is the current owner or an authorized
577 dummy = 0;737 dummy = 0;
578 }738 }
739
740 /// @notice Burns a specific ERC721 token.
741 /// @dev Throws unless `msg.sender` is the current owner or an authorized
742 /// operator for this RFT. Throws if `from` is not the current owner. Throws
743 /// if `to` is the zero address. Throws if `tokenId` is not a valid RFT.
744 /// Throws if RFT pieces have multiple owners.
745 /// @param from The current owner of the RFT
746 /// @param tokenId The RFT to transfer
747 /// @dev EVM selector for this function is: 0xbb2f5a58,
748 /// or in textual repr: burnFromCross((address,uint256),uint256)
749 function burnFromCross(Tuple6 memory from, uint256 tokenId) public {
750 require(false, stub_error);
751 from;
752 tokenId;
753 dummy = 0;
754 }
579755
580 /// @notice Returns next free RFT ID.756 /// @notice Returns next free RFT ID.
581 /// @dev EVM selector for this function is: 0x75794a3c,757 /// @dev EVM selector for this function is: 0x75794a3c,
608 // /// @param tokens array of pairs of token ID and token URI for minted tokens784 // /// @param tokens array of pairs of token ID and token URI for minted tokens
609 // /// @dev EVM selector for this function is: 0x36543006,785 // /// @dev EVM selector for this function is: 0x36543006,
610 // /// or in textual repr: mintBulkWithTokenURI(address,(uint256,string)[])786 // /// or in textual repr: mintBulkWithTokenURI(address,(uint256,string)[])
611 // function mintBulkWithTokenURI(address to, Tuple6[] memory tokens) public returns (bool) {787 // function mintBulkWithTokenURI(address to, Tuple8[] memory tokens) public returns (bool) {
612 // require(false, stub_error);788 // require(false, stub_error);
613 // to;789 // to;
614 // tokens;790 // tokens;
630}806}
631807
632/// @dev anonymous struct808/// @dev anonymous struct
633struct Tuple6 {809struct Tuple8 {
634 uint256 field_0;810 uint256 field_0;
635 string field_1;811 string field_1;
636}812}
813
814/// @dev anonymous struct
815struct Tuple6 {
816 address field_0;
817 uint256 field_1;
818}
637819
638/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension820/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
639/// @dev See https://eips.ethereum.org/EIPS/eip-721821/// @dev See https://eips.ethereum.org/EIPS/eip-721
modifiedpallets/refungible/src/stubs/UniqueRefungibleToken.rawdiffbeforeafterboth

binary blob — no preview

addedpallets/scheduler-v2/Cargo.tomldiffbeforeafterboth

no changes

addedpallets/scheduler-v2/src/benchmarking.rsdiffbeforeafterboth

no changes

addedpallets/scheduler-v2/src/lib.rsdiffbeforeafterboth

no changes

addedpallets/scheduler-v2/src/mock.rsdiffbeforeafterboth

no changes

addedpallets/scheduler-v2/src/tests.rsdiffbeforeafterboth

no changes

addedpallets/scheduler-v2/src/weights.rsdiffbeforeafterboth

no changes

modifiedpallets/scheduler/src/benchmarking.rsdiffbeforeafterboth
5050
51const BLOCK_NUMBER: u32 = 2;51const BLOCK_NUMBER: u32 = 2;
52
53fn make_scheduled_id(src: u32) -> ScheduledId {
54 let slice_id: [u8; 4] = src.encode().try_into().unwrap();
55 let mut id: [u8; 16] = [0; 16];
56 id[..4].clone_from_slice(&slice_id);
57 id
58}
5259
53/// Add `n` named items to the schedule.60/// Add `n` named items to the schedule.
54///61///
79 false => None,86 false => None,
80 };87 };
8188
82 let slice_id: [u8; 4] = i.encode().try_into().unwrap();89 let id = make_scheduled_id(i);
83 let mut id: [u8; 16] = [0; 16];
84 id[..4].clone_from_slice(&slice_id);
85
86 let origin = frame_system::RawOrigin::Signed(caller.clone()).into();90 let origin = frame_system::RawOrigin::Signed(caller.clone()).into();
87 Scheduler::<T>::do_schedule_named(id, t, period, 0, origin, call_or_hash)?;91 Scheduler::<T>::do_schedule_named(id, t, period, 0, origin, call_or_hash)?;
202 id[..4].clone_from_slice(&slice_id);206 id[..4].clone_from_slice(&slice_id);
203 let when = BLOCK_NUMBER.into();207 let when = BLOCK_NUMBER.into();
204 let periodic = Some((T::BlockNumber::one(), 100));208 let periodic = Some((T::BlockNumber::one(), 100));
205 let priority = 0;209 let priority = None;
206 // Essentially a no-op call.210 // Essentially a no-op call.
207 let inner_call = frame_system::Call::set_storage { items: vec![] }.into();211 let inner_call = frame_system::Call::set_storage { items: vec![] }.into();
208 let call = Box::new(CallOrHashOf::<T>::Value(inner_call));212 let call = Box::new(CallOrHashOf::<T>::Value(inner_call));
220 let origin: RawOrigin<T::AccountId> = frame_system::RawOrigin::Signed(caller.clone());224 let origin: RawOrigin<T::AccountId> = frame_system::RawOrigin::Signed(caller.clone());
221 let s in 1 .. T::MaxScheduledPerBlock::get();225 let s in 1 .. T::MaxScheduledPerBlock::get();
222 let when = BLOCK_NUMBER.into();226 let when = BLOCK_NUMBER.into();
227 let idx = s - 1;
223 let id = 0.encode().try_into().unwrap_or([0; MAX_TASK_ID_LENGTH_IN_BYTES as usize]);228 let id = make_scheduled_id(idx);
224 fill_schedule::<T>(when, s, true, Some(false))?;229 fill_schedule::<T>(when, s, true, Some(false))?;
225 }: _(origin, id)230 }: _(origin, id)
226 verify {231 verify {
230 );235 );
231 // Removed schedule is NONE236 // Removed schedule is NONE
232 ensure!(237 ensure!(
233 Agenda::<T>::get(when)[0].is_none(),238 Agenda::<T>::get(when)[idx as usize].is_none(),
234 "didn't remove from schedule"239 "didn't remove from schedule"
235 );240 );
236 }241 }
242
243 change_named_priority {
244 let origin: RawOrigin<T::AccountId> = frame_system::RawOrigin::Root;
245 let s in 1 .. T::MaxScheduledPerBlock::get();
246 let when = BLOCK_NUMBER.into();
247 let idx = s - 1;
248 let id = make_scheduled_id(idx);
249 let priority = 42;
250 fill_schedule::<T>(when, s, true, Some(false))?;
251 }: _(origin, id, priority)
252 verify {
253 ensure!(
254 Agenda::<T>::get(when)[idx as usize].clone().unwrap().priority == priority,
255 "didn't change the priority"
256 );
257 }
237258
238 impl_benchmark_test_suite!(Scheduler, crate::mock::new_test_ext(), crate::mock::Test);259 impl_benchmark_test_suite!(Scheduler, crate::mock::new_test_ext(), crate::mock::Test);
239}260}
modifiedpallets/scheduler/src/lib.rsdiffbeforeafterboth
8787
88use frame_support::{88use frame_support::{
89 dispatch::{DispatchError, DispatchResult, Dispatchable, Parameter, GetDispatchInfo},89 dispatch::{
90 DispatchError, DispatchResult, Dispatchable, UnfilteredDispatchable, Parameter,
91 GetDispatchInfo,
92 },
90 traits::{93 traits::{
91 schedule::{self, DispatchTime, MaybeHashed},94 schedule::{self, DispatchTime, MaybeHashed},
97100
98pub use weights::WeightInfo;101pub use weights::WeightInfo;
99102
100/// Just a simple index for naming period tasks.
101pub type PeriodicIndex = u32;
102/// The location of a scheduled task that can be used to remove it.103/// The location of a scheduled task that can be used to remove it.
103pub type TaskAddress<BlockNumber> = (BlockNumber, u32);104pub type TaskAddress<BlockNumber> = (BlockNumber, u32);
104pub const MAX_TASK_ID_LENGTH_IN_BYTES: u8 = 16;105pub const MAX_TASK_ID_LENGTH_IN_BYTES: u8 = 16;
105106
106type ScheduledId = [u8; MAX_TASK_ID_LENGTH_IN_BYTES as usize];107pub type ScheduledId = [u8; MAX_TASK_ID_LENGTH_IN_BYTES as usize];
107pub type CallOrHashOf<T> =108pub type CallOrHashOf<T> =
108 MaybeHashed<<T as Config>::RuntimeCall, <T as frame_system::Config>::Hash>;109 MaybeHashed<<T as Config>::RuntimeCall, <T as frame_system::Config>::Hash>;
109110
137pub type Scheduled<Call, BlockNumber, PalletsOrigin, AccountId> =138pub type Scheduled<Call, BlockNumber, PalletsOrigin, AccountId> =
138 ScheduledV3<Call, BlockNumber, PalletsOrigin, AccountId>;139 ScheduledV3<Call, BlockNumber, PalletsOrigin, AccountId>;
140
141pub enum ScheduledEnsureOriginSuccess<AccountId> {
142 Root,
143 Signed(AccountId),
144}
139145
140#[cfg(feature = "runtime-benchmarks")]146#[cfg(feature = "runtime-benchmarks")]
141mod preimage_provider {147mod preimage_provider {
194 dispatch::PostDispatchInfo,200 dispatch::PostDispatchInfo,
195 pallet_prelude::*,201 pallet_prelude::*,
196 traits::{schedule::LookupError, PreimageProvider},202 traits::{
203 schedule::{LookupError, LOWEST_PRIORITY},
204 PreimageProvider,
205 },
197 };206 };
198 use frame_system::pallet_prelude::*;207 use frame_system::pallet_prelude::*;
227 + Dispatchable<236 + Dispatchable<
228 RuntimeOrigin = <Self as Config>::RuntimeOrigin,237 RuntimeOrigin = <Self as Config>::RuntimeOrigin,
229 PostInfo = PostDispatchInfo,238 PostInfo = PostDispatchInfo,
230 > + GetDispatchInfo239 > + UnfilteredDispatchable<RuntimeOrigin = <Self as system::Config>::RuntimeOrigin>
240 + GetDispatchInfo
231 + From<system::Call<Self>>;241 + From<system::Call<Self>>;
232242
237247
238 /// Required origin to schedule or cancel calls.248 /// Required origin to schedule or cancel calls.
239 type ScheduleOrigin: EnsureOrigin<<Self as system::Config>::RuntimeOrigin>;249 type ScheduleOrigin: EnsureOrigin<
250 <Self as system::Config>::RuntimeOrigin,
251 Success = ScheduledEnsureOriginSuccess<Self::AccountId>,
252 >;
253
254 /// Required origin to set/change calls' priority.
255 type PrioritySetOrigin: EnsureOrigin<<Self as system::Config>::RuntimeOrigin>;
240256
241 /// Compare the privileges of origins.257 /// Compare the privileges of origins.
242 ///258 ///
287303
288 /// Resolve the call dispatch, including any post-dispatch operations.304 /// Resolve the call dispatch, including any post-dispatch operations.
289 fn dispatch_call(305 fn dispatch_call(
290 signer: T::AccountId,306 signer: Option<T::AccountId>,
291 function: <T as Config>::RuntimeCall,307 function: <T as Config>::RuntimeCall,
292 ) -> Result<308 ) -> Result<
293 Result<PostDispatchInfo, DispatchErrorWithPostInfo<PostDispatchInfo>>,309 Result<PostDispatchInfo, DispatchErrorWithPostInfo<PostDispatchInfo>>,
319 Scheduled { when: T::BlockNumber, index: u32 },335 Scheduled { when: T::BlockNumber, index: u32 },
320 /// Canceled some task.336 /// Canceled some task.
321 Canceled { when: T::BlockNumber, index: u32 },337 Canceled { when: T::BlockNumber, index: u32 },
338 /// Scheduled task's priority has changed
339 PriorityChanged {
340 when: T::BlockNumber,
341 index: u32,
342 priority: schedule::Priority,
343 },
322 /// Dispatched some task.344 /// Dispatched some task.
323 Dispatched {345 Dispatched {
324 task: TaskAddress<T::BlockNumber>,346 task: TaskAddress<T::BlockNumber>,
371393
372 let mut total_weight: Weight = T::WeightInfo::on_initialize(0);394 let mut total_weight: Weight = T::WeightInfo::on_initialize(0);
373 for (order, (index, mut s)) in queued.into_iter().enumerate() {395 for (order, (index, mut s)) in queued.into_iter().enumerate() {
374 let named = if let Some(ref id) = s.maybe_id {396 let named = s.maybe_id.is_some();
375 Lookup::<T>::remove(id);
376 true
377 } else {
378 false
379 };
380397
381 let (call, maybe_completed) = s.call.resolved::<T::PreimageProvider>();398 let (call, maybe_completed) = s.call.resolved::<T::PreimageProvider>();
382 s.call = call;399 s.call = call;
399 Lookup::<T>::insert(id, (until, index as u32));416 Lookup::<T>::insert(id, (until, index as u32));
400 }417 }
401 Agenda::<T>::append(until, Some(s));418 Agenda::<T>::append(until, Some(s));
402 }419 } else if let Some(ref id) = s.maybe_id {
420 Lookup::<T>::remove(id);
421 }
403 continue;422 continue;
404 }423 }
405 };424 };
439 continue;458 continue;
440 }459 }
441460
442 let sender = ensure_signed(461 let scheduled_origin =
443 <<T as Config>::RuntimeOrigin as From<T::PalletsOrigin>>::from(462 <<T as Config>::RuntimeOrigin as From<T::PalletsOrigin>>::from(
444 s.origin.clone(),463 s.origin.clone(),
445 )464 );
446 .into(),465 let ensured_origin = T::ScheduleOrigin::ensure_origin(scheduled_origin.into());
447 )466
448 .unwrap();
449
450 // // if call have id it was be reserved
451 // if s.maybe_id.is_some() {
452 // let _ = T::CallExecutor::pay_for_call(
453 // s.maybe_id.unwrap(),
454 // sender.clone(),
455 // call.clone(),
456 // );
457 // }
458
459 // Execute transaction via chain default pipeline
460 // That means dispatch will be processed like any user's extrinsic e.g. transaction fees will be taken
461 let r = T::CallExecutor::dispatch_call(sender, call.clone());467 let r = match ensured_origin {
468 Ok(ScheduledEnsureOriginSuccess::Root) => {
469 Ok(call.dispatch_bypass_filter(frame_system::RawOrigin::Root.into()))
470 }
471 Ok(ScheduledEnsureOriginSuccess::Signed(sender)) => {
472 // Execute transaction via chain default pipeline
473 // That means dispatch will be processed like any user's extrinsic e.g. transaction fees will be taken
474 T::CallExecutor::dispatch_call(Some(sender), call.clone())
475 }
476 Err(e) => Ok(Err(e.into())),
477 };
462478
463 let mut actual_call_weight: Weight = item_weight;479 let mut actual_call_weight: Weight = item_weight;
464 let result: Result<_, DispatchError> = match r {480 let result: Result<_, DispatchError> = match r {
494 s.maybe_periodic = None;510 s.maybe_periodic = None;
495 }511 }
496 let wake = now + period;512 let wake = now + period;
513 let is_canceled;
514
497 // If scheduled is named, place its information in `Lookup`515 // If scheduled is named, place its information in `Lookup`
498 if let Some(ref id) = s.maybe_id {516 if let Some(ref id) = s.maybe_id {
517 is_canceled = Lookup::<T>::get(id).is_none();
499 let wake_index = Agenda::<T>::decode_len(wake).unwrap_or(0);518 let wake_index = Agenda::<T>::decode_len(wake).unwrap_or(0);
519
520 if !is_canceled {
500 Lookup::<T>::insert(id, (wake, wake_index as u32));521 Lookup::<T>::insert(id, (wake, wake_index as u32));
522 }
501 }523 } else {
524 is_canceled = false;
525 }
526
527 if !is_canceled {
502 Agenda::<T>::append(wake, Some(s));528 Agenda::<T>::append(wake, Some(s));
529 }
503 }530 } else if let Some(ref id) = s.maybe_id {
531 Lookup::<T>::remove(id);
532 }
504 }533 }
505 // Total weight should be 0, because the transaction is already paid for534 total_weight
506 Weight::zero()
507 }535 }
508 }536 }
509537
516 id: ScheduledId,544 id: ScheduledId,
517 when: T::BlockNumber,545 when: T::BlockNumber,
518 maybe_periodic: Option<schedule::Period<T::BlockNumber>>,546 maybe_periodic: Option<schedule::Period<T::BlockNumber>>,
519 priority: schedule::Priority,547 priority: Option<schedule::Priority>,
520 call: Box<CallOrHashOf<T>>,548 call: Box<CallOrHashOf<T>>,
521 ) -> DispatchResult {549 ) -> DispatchResult {
522 T::ScheduleOrigin::ensure_origin(origin.clone())?;550 T::ScheduleOrigin::ensure_origin(origin.clone())?;
551
552 if priority.is_some() {
553 T::PrioritySetOrigin::ensure_origin(origin.clone())?;
554 }
555
523 let origin = <T as Config>::RuntimeOrigin::from(origin);556 let origin = <T as Config>::RuntimeOrigin::from(origin);
524 Self::do_schedule_named(557 Self::do_schedule_named(
525 id,558 id,
526 DispatchTime::At(when),559 DispatchTime::At(when),
527 maybe_periodic,560 maybe_periodic,
528 priority,561 priority.unwrap_or(LOWEST_PRIORITY),
529 origin.caller().clone(),562 origin.caller().clone(),
530 *call,563 *call,
531 )?;564 )?;
552 id: ScheduledId,585 id: ScheduledId,
553 after: T::BlockNumber,586 after: T::BlockNumber,
554 maybe_periodic: Option<schedule::Period<T::BlockNumber>>,587 maybe_periodic: Option<schedule::Period<T::BlockNumber>>,
555 priority: schedule::Priority,588 priority: Option<schedule::Priority>,
556 call: Box<CallOrHashOf<T>>,589 call: Box<CallOrHashOf<T>>,
557 ) -> DispatchResult {590 ) -> DispatchResult {
558 T::ScheduleOrigin::ensure_origin(origin.clone())?;591 T::ScheduleOrigin::ensure_origin(origin.clone())?;
592
593 if priority.is_some() {
594 T::PrioritySetOrigin::ensure_origin(origin.clone())?;
595 }
596
559 let origin = <T as Config>::RuntimeOrigin::from(origin);597 let origin = <T as Config>::RuntimeOrigin::from(origin);
560 Self::do_schedule_named(598 Self::do_schedule_named(
561 id,599 id,
562 DispatchTime::After(after),600 DispatchTime::After(after),
563 maybe_periodic,601 maybe_periodic,
564 priority,602 priority.unwrap_or(LOWEST_PRIORITY),
565 origin.caller().clone(),603 origin.caller().clone(),
566 *call,604 *call,
567 )?;605 )?;
568 Ok(())606 Ok(())
569 }607 }
608
609 #[pallet::weight(<T as Config>::WeightInfo::change_named_priority(T::MaxScheduledPerBlock::get()))]
610 pub fn change_named_priority(
611 origin: OriginFor<T>,
612 id: ScheduledId,
613 priority: schedule::Priority,
614 ) -> DispatchResult {
615 T::PrioritySetOrigin::ensure_origin(origin.clone())?;
616 let origin = <T as Config>::RuntimeOrigin::from(origin);
617 Self::do_change_named_priority(origin.caller().clone(), id, priority)
618 }
570 }619 }
571}620}
572621
720 })769 })
721 }770 }
771
772 fn do_change_named_priority(
773 origin: T::PalletsOrigin,
774 id: ScheduledId,
775 priority: schedule::Priority,
776 ) -> DispatchResult {
777 match Lookup::<T>::get(id) {
778 Some((when, index)) => {
779 let i = index as usize;
780 Agenda::<T>::try_mutate(when, |agenda| {
781 if let Some(Some(s)) = agenda.get_mut(i) {
782 if matches!(
783 T::OriginPrivilegeCmp::cmp_privilege(&origin, &s.origin),
784 Some(Ordering::Less) | None
785 ) {
786 return Err(BadOrigin.into());
787 }
788
789 s.priority = priority;
790 Self::deposit_event(Event::PriorityChanged {
791 when,
792 index,
793 priority,
794 });
795 }
796 Ok(())
797 })
798 }
799 None => Err(Error::<T>::NotFound.into()),
800 }
801 }
722}802}
723803
modifiedpallets/scheduler/src/weights.rsdiffbeforeafterboth
3//! Autogenerated weights for pallet_unique_scheduler3//! Autogenerated weights for pallet_unique_scheduler
4//!4//!
5//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev5//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
6//! DATE: 2022-08-15, STEPS: `50`, REPEAT: 80, LOW RANGE: `[]`, HIGH RANGE: `[]`6//! DATE: 2022-09-14, STEPS: `50`, REPEAT: 80, LOW RANGE: `[]`, HIGH RANGE: `[]`
7//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 10247//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024
88
9// Executed Command:9// Executed Command:
26#![cfg_attr(rustfmt, rustfmt_skip)]26#![cfg_attr(rustfmt, rustfmt_skip)]
27#![allow(unused_parens)]27#![allow(unused_parens)]
28#![allow(unused_imports)]28#![allow(unused_imports)]
29#![allow(missing_docs)]
29#![allow(clippy::unnecessary_cast)]30#![allow(clippy::unnecessary_cast)]
3031
31use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};32use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
44 fn on_initialize_resolved(s: u32, ) -> Weight;45 fn on_initialize_resolved(s: u32, ) -> Weight;
45 fn schedule_named(s: u32, ) -> Weight;46 fn schedule_named(s: u32, ) -> Weight;
46 fn cancel_named(s: u32, ) -> Weight;47 fn cancel_named(s: u32, ) -> Weight;
48 fn change_named_priority(s: u32, ) -> Weight;
47}49}
4850
49/// Weights for pallet_unique_scheduler using the Substrate node and recommended hardware.51/// Weights for pallet_unique_scheduler using the Substrate node and recommended hardware.
53 // Storage: System Account (r:1 w:1)55 // Storage: System Account (r:1 w:1)
54 // Storage: System AllExtrinsicsLen (r:1 w:1)56 // Storage: System AllExtrinsicsLen (r:1 w:1)
55 // Storage: System BlockWeight (r:1 w:1)57 // Storage: System BlockWeight (r:1 w:1)
58 // Storage: Configuration WeightToFeeCoefficientOverride (r:1 w:0)
59 // Storage: TransactionPayment NextFeeMultiplier (r:1 w:0)
56 // Storage: Scheduler Lookup (r:0 w:1)60 // Storage: Scheduler Lookup (r:1 w:1)
57 fn on_initialize_periodic_named_resolved(s: u32, ) -> Weight {61 fn on_initialize_periodic_named_resolved(s: u32, ) -> Weight {
58 Weight::from_ref_time(26_641_000)62 Weight::from_ref_time(26_641_000)
59 // Standard Error: 9_00063 // Standard Error: 9_000
67 // Storage: System Account (r:1 w:1)71 // Storage: System Account (r:1 w:1)
68 // Storage: System AllExtrinsicsLen (r:1 w:1)72 // Storage: System AllExtrinsicsLen (r:1 w:1)
69 // Storage: System BlockWeight (r:1 w:1)73 // Storage: System BlockWeight (r:1 w:1)
74 // Storage: Configuration WeightToFeeCoefficientOverride (r:1 w:0)
75 // Storage: TransactionPayment NextFeeMultiplier (r:1 w:0)
70 // Storage: Scheduler Lookup (r:0 w:1)76 // Storage: Scheduler Lookup (r:0 w:1)
71 fn on_initialize_named_resolved(s: u32, ) -> Weight {77 fn on_initialize_named_resolved(s: u32, ) -> Weight {
72 Weight::from_ref_time(23_941_000)78 Weight::from_ref_time(23_941_000)
80 // Storage: System Account (r:1 w:1)86 // Storage: System Account (r:1 w:1)
81 // Storage: System AllExtrinsicsLen (r:1 w:1)87 // Storage: System AllExtrinsicsLen (r:1 w:1)
82 // Storage: System BlockWeight (r:1 w:1)88 // Storage: System BlockWeight (r:1 w:1)
89 // Storage: Configuration WeightToFeeCoefficientOverride (r:1 w:0)
90 // Storage: TransactionPayment NextFeeMultiplier (r:1 w:0)
83 // Storage: Scheduler Lookup (r:0 w:1)91 // Storage: Scheduler Lookup (r:1 w:1)
84 fn on_initialize_periodic(s: u32, ) -> Weight {92 fn on_initialize_periodic(s: u32, ) -> Weight {
85 Weight::from_ref_time(24_858_000)93 Weight::from_ref_time(24_858_000)
86 // Standard Error: 7_00094 // Standard Error: 7_000
94 // Storage: System Account (r:1 w:1)102 // Storage: System Account (r:1 w:1)
95 // Storage: System AllExtrinsicsLen (r:1 w:1)103 // Storage: System AllExtrinsicsLen (r:1 w:1)
96 // Storage: System BlockWeight (r:1 w:1)104 // Storage: System BlockWeight (r:1 w:1)
105 // Storage: Configuration WeightToFeeCoefficientOverride (r:1 w:0)
106 // Storage: TransactionPayment NextFeeMultiplier (r:1 w:0)
97 // Storage: Scheduler Lookup (r:0 w:1)107 // Storage: Scheduler Lookup (r:1 w:1)
98 fn on_initialize_periodic_resolved(s: u32, ) -> Weight {108 fn on_initialize_periodic_resolved(s: u32, ) -> Weight {
99 Weight::from_ref_time(25_515_000)109 Weight::from_ref_time(25_515_000)
100 // Standard Error: 14_000110 // Standard Error: 14_000
118 // Storage: System Account (r:1 w:1)128 // Storage: System Account (r:1 w:1)
119 // Storage: System AllExtrinsicsLen (r:1 w:1)129 // Storage: System AllExtrinsicsLen (r:1 w:1)
120 // Storage: System BlockWeight (r:1 w:1)130 // Storage: System BlockWeight (r:1 w:1)
131 // Storage: Configuration WeightToFeeCoefficientOverride (r:1 w:0)
132 // Storage: TransactionPayment NextFeeMultiplier (r:1 w:0)
121 // Storage: Scheduler Lookup (r:0 w:1)133 // Storage: Scheduler Lookup (r:0 w:1)
122 fn on_initialize_named_aborted(s: u32, ) -> Weight {134 fn on_initialize_named_aborted(s: u32, ) -> Weight {
123 Weight::from_ref_time(25_552_000)135 Weight::from_ref_time(25_552_000)
141 // Storage: System Account (r:1 w:1)153 // Storage: System Account (r:1 w:1)
142 // Storage: System AllExtrinsicsLen (r:1 w:1)154 // Storage: System AllExtrinsicsLen (r:1 w:1)
143 // Storage: System BlockWeight (r:1 w:1)155 // Storage: System BlockWeight (r:1 w:1)
156 // Storage: Configuration WeightToFeeCoefficientOverride (r:1 w:0)
157 // Storage: TransactionPayment NextFeeMultiplier (r:1 w:0)
144 // Storage: Scheduler Lookup (r:0 w:1)158 // Storage: Scheduler Lookup (r:0 w:1)
145 fn on_initialize(s: u32, ) -> Weight {159 fn on_initialize(s: u32, ) -> Weight {
146 Weight::from_ref_time(24_482_000)160 Weight::from_ref_time(24_482_000)
154 // Storage: System Account (r:1 w:1)168 // Storage: System Account (r:1 w:1)
155 // Storage: System AllExtrinsicsLen (r:1 w:1)169 // Storage: System AllExtrinsicsLen (r:1 w:1)
156 // Storage: System BlockWeight (r:1 w:1)170 // Storage: System BlockWeight (r:1 w:1)
171 // Storage: Configuration WeightToFeeCoefficientOverride (r:1 w:0)
172 // Storage: TransactionPayment NextFeeMultiplier (r:1 w:0)
157 // Storage: Scheduler Lookup (r:0 w:1)173 // Storage: Scheduler Lookup (r:0 w:1)
158 fn on_initialize_resolved(s: u32, ) -> Weight {174 fn on_initialize_resolved(s: u32, ) -> Weight {
159 Weight::from_ref_time(25_187_000)175 Weight::from_ref_time(25_187_000)
181 .saturating_add(T::DbWeight::get().reads(2 as u64))197 .saturating_add(T::DbWeight::get().reads(2 as u64))
182 .saturating_add(T::DbWeight::get().writes(2 as u64))198 .saturating_add(T::DbWeight::get().writes(2 as u64))
183 }199 }
200 // Storage: Scheduler Lookup (r:1 w:1)
201 // Storage: Scheduler Agenda (r:1 w:1)
202 fn change_named_priority(s: u32, ) -> Weight {
203 Weight::from_ref_time(8_642_000)
204 // Standard Error: 0
205 .saturating_add(Weight::from_ref_time(431_000).saturating_mul(s as u64))
206 .saturating_add(T::DbWeight::get().reads(2 as u64))
207 .saturating_add(T::DbWeight::get().writes(2 as u64))
208 }
184}209}
185210
186// For backwards compatibility and tests211// For backwards compatibility and tests
189 // Storage: System Account (r:1 w:1)214 // Storage: System Account (r:1 w:1)
190 // Storage: System AllExtrinsicsLen (r:1 w:1)215 // Storage: System AllExtrinsicsLen (r:1 w:1)
191 // Storage: System BlockWeight (r:1 w:1)216 // Storage: System BlockWeight (r:1 w:1)
217 // Storage: Configuration WeightToFeeCoefficientOverride (r:1 w:0)
218 // Storage: TransactionPayment NextFeeMultiplier (r:1 w:0)
192 // Storage: Scheduler Lookup (r:0 w:1)219 // Storage: Scheduler Lookup (r:1 w:1)
193 fn on_initialize_periodic_named_resolved(s: u32, ) -> Weight {220 fn on_initialize_periodic_named_resolved(s: u32, ) -> Weight {
194 Weight::from_ref_time(26_641_000)221 Weight::from_ref_time(26_641_000)
195 // Standard Error: 9_000222 // Standard Error: 9_000
203 // Storage: System Account (r:1 w:1)230 // Storage: System Account (r:1 w:1)
204 // Storage: System AllExtrinsicsLen (r:1 w:1)231 // Storage: System AllExtrinsicsLen (r:1 w:1)
205 // Storage: System BlockWeight (r:1 w:1)232 // Storage: System BlockWeight (r:1 w:1)
233 // Storage: Configuration WeightToFeeCoefficientOverride (r:1 w:0)
234 // Storage: TransactionPayment NextFeeMultiplier (r:1 w:0)
206 // Storage: Scheduler Lookup (r:0 w:1)235 // Storage: Scheduler Lookup (r:0 w:1)
207 fn on_initialize_named_resolved(s: u32, ) -> Weight {236 fn on_initialize_named_resolved(s: u32, ) -> Weight {
208 Weight::from_ref_time(23_941_000)237 Weight::from_ref_time(23_941_000)
216 // Storage: System Account (r:1 w:1)245 // Storage: System Account (r:1 w:1)
217 // Storage: System AllExtrinsicsLen (r:1 w:1)246 // Storage: System AllExtrinsicsLen (r:1 w:1)
218 // Storage: System BlockWeight (r:1 w:1)247 // Storage: System BlockWeight (r:1 w:1)
248 // Storage: Configuration WeightToFeeCoefficientOverride (r:1 w:0)
249 // Storage: TransactionPayment NextFeeMultiplier (r:1 w:0)
219 // Storage: Scheduler Lookup (r:0 w:1)250 // Storage: Scheduler Lookup (r:1 w:1)
220 fn on_initialize_periodic(s: u32, ) -> Weight {251 fn on_initialize_periodic(s: u32, ) -> Weight {
221 Weight::from_ref_time(24_858_000)252 Weight::from_ref_time(24_858_000)
222 // Standard Error: 7_000253 // Standard Error: 7_000
230 // Storage: System Account (r:1 w:1)261 // Storage: System Account (r:1 w:1)
231 // Storage: System AllExtrinsicsLen (r:1 w:1)262 // Storage: System AllExtrinsicsLen (r:1 w:1)
232 // Storage: System BlockWeight (r:1 w:1)263 // Storage: System BlockWeight (r:1 w:1)
264 // Storage: Configuration WeightToFeeCoefficientOverride (r:1 w:0)
265 // Storage: TransactionPayment NextFeeMultiplier (r:1 w:0)
233 // Storage: Scheduler Lookup (r:0 w:1)266 // Storage: Scheduler Lookup (r:1 w:1)
234 fn on_initialize_periodic_resolved(s: u32, ) -> Weight {267 fn on_initialize_periodic_resolved(s: u32, ) -> Weight {
235 Weight::from_ref_time(25_515_000)268 Weight::from_ref_time(25_515_000)
236 // Standard Error: 14_000269 // Standard Error: 14_000
254 // Storage: System Account (r:1 w:1)287 // Storage: System Account (r:1 w:1)
255 // Storage: System AllExtrinsicsLen (r:1 w:1)288 // Storage: System AllExtrinsicsLen (r:1 w:1)
256 // Storage: System BlockWeight (r:1 w:1)289 // Storage: System BlockWeight (r:1 w:1)
290 // Storage: Configuration WeightToFeeCoefficientOverride (r:1 w:0)
291 // Storage: TransactionPayment NextFeeMultiplier (r:1 w:0)
257 // Storage: Scheduler Lookup (r:0 w:1)292 // Storage: Scheduler Lookup (r:0 w:1)
258 fn on_initialize_named_aborted(s: u32, ) -> Weight {293 fn on_initialize_named_aborted(s: u32, ) -> Weight {
259 Weight::from_ref_time(25_552_000)294 Weight::from_ref_time(25_552_000)
277 // Storage: System Account (r:1 w:1)312 // Storage: System Account (r:1 w:1)
278 // Storage: System AllExtrinsicsLen (r:1 w:1)313 // Storage: System AllExtrinsicsLen (r:1 w:1)
279 // Storage: System BlockWeight (r:1 w:1)314 // Storage: System BlockWeight (r:1 w:1)
315 // Storage: Configuration WeightToFeeCoefficientOverride (r:1 w:0)
316 // Storage: TransactionPayment NextFeeMultiplier (r:1 w:0)
280 // Storage: Scheduler Lookup (r:0 w:1)317 // Storage: Scheduler Lookup (r:0 w:1)
281 fn on_initialize(s: u32, ) -> Weight {318 fn on_initialize(s: u32, ) -> Weight {
282 Weight::from_ref_time(24_482_000)319 Weight::from_ref_time(24_482_000)
290 // Storage: System Account (r:1 w:1)327 // Storage: System Account (r:1 w:1)
291 // Storage: System AllExtrinsicsLen (r:1 w:1)328 // Storage: System AllExtrinsicsLen (r:1 w:1)
292 // Storage: System BlockWeight (r:1 w:1)329 // Storage: System BlockWeight (r:1 w:1)
330 // Storage: Configuration WeightToFeeCoefficientOverride (r:1 w:0)
331 // Storage: TransactionPayment NextFeeMultiplier (r:1 w:0)
293 // Storage: Scheduler Lookup (r:0 w:1)332 // Storage: Scheduler Lookup (r:0 w:1)
294 fn on_initialize_resolved(s: u32, ) -> Weight {333 fn on_initialize_resolved(s: u32, ) -> Weight {
295 Weight::from_ref_time(25_187_000)334 Weight::from_ref_time(25_187_000)
318 .saturating_add(RocksDbWeight::get().writes(2 as u64))357 .saturating_add(RocksDbWeight::get().writes(2 as u64))
319 }358 }
359
360 // Storage: Scheduler Lookup (r:1 w:1)
361 // Storage: Scheduler Agenda (r:1 w:1)
362 fn change_named_priority(s: u32, ) -> Weight {
363 Weight::from_ref_time(8_642_000)
364 // Standard Error: 0
365 .saturating_add(Weight::from_ref_time(431_000).saturating_mul(s as u64))
366 .saturating_add(RocksDbWeight::get().reads(2 as u64))
367 .saturating_add(RocksDbWeight::get().writes(2 as u64))
368 }
320}369}
321370
modifiedpallets/unique/CHANGELOG.mddiffbeforeafterboth
44
5<!-- bureaucrate goes here -->5<!-- bureaucrate goes here -->
66
7## [v0.2.1] 2022-10-10
8
9### Changes
10
11- Added `destroyCollection` and `createFTCollection` methods to **CollectionHelpers**.
12
7## [v0.2.0] 2022-09-1313## [v0.2.0] 2022-09-13
814
9### Changes15### Changes
16
10- Change **collectionHelper** method `createRefungibleCollection` to `createRFTCollection`,17- Change **collectionHelper** method `createRefungibleCollection` to `createRFTCollection`,
1118
12## [v0.1.4] 2022-09-0519## [v0.1.4] 2022-09-05
1320
14### Added21### Added
1522
16- Methods `force_set_sponsor` , `force_remove_collection_sponsor` to be able to administer sponsorships with other pallets. Added to implement `AppPromotion` pallet logic.23- Methods `force_set_sponsor` , `force_remove_collection_sponsor` to be able to administer sponsorships with other pallets. Added to implement `AppPromotion` pallet logic.
1724
18## [v0.1.3] 2022-08-1625## [v0.1.3] 2022-08-16
1926
20### Other changes27### Other changes
2128
22- build: Upgrade polkadot to v0.9.27 2c498572636f2b34d53b1c51b7283a761a7dc90a29- build: Upgrade polkadot to v0.9.27 2c498572636f2b34d53b1c51b7283a761a7dc90a
2330
24- build: Upgrade polkadot to v0.9.26 85515e54c4ca1b82a2630034e55dcc804c643bf831- build: Upgrade polkadot to v0.9.26 85515e54c4ca1b82a2630034e55dcc804c643bf8
2532
26- refactor: Remove `#[transactional]` from extrinsics 7fd36cea2f6e00c02c67ccc1de9649ae404efd3133- refactor: Remove `#[transactional]` from extrinsics 7fd36cea2f6e00c02c67ccc1de9649ae404efd31
2734
28Every extrinsic now runs in transaction implicitly, and35Every extrinsic now runs in transaction implicitly, and
29`#[transactional]` on pallet dispatchable is now meaningless36`#[transactional]` on pallet dispatchable is now meaningless
3037
31Upstream-Change: https://github.com/paritytech/substrate/issues/1080638Upstream-Change: https://github.com/paritytech/substrate/issues/10806
3239
33- refactor: Switch to new prefix removal methods 26734e9567589d75cdd99e404eabf11d5a97d97540- refactor: Switch to new prefix removal methods 26734e9567589d75cdd99e404eabf11d5a97d975
3441
35New methods allows to call `remove_prefix` with limit multiple times42New methods allows to call `remove_prefix` with limit multiple times
36in the same block43in the same block
3946
40Upstream-Change: https://github.com/paritytech/substrate/pull/1149047Upstream-Change: https://github.com/paritytech/substrate/pull/11490
4148
42- build: Upgrade polkadot to v0.9.25 cdfb9bdc7b205ff1b5134f034ef9973d769e5e6b49- build: Upgrade polkadot to v0.9.25 cdfb9bdc7b205ff1b5134f034ef9973d769e5e6b
4350
44## [v0.1.1] - 2022-07-2551## [v0.1.1] - 2022-07-25
4552
46### Added53### Added
4754
48- Method for creating `ERC721Metadata` compatible NFT collection.55- Method for creating `ERC721Metadata` compatible NFT collection.
49- Method for creating `ERC721Metadata` compatible ReFungible collection.56- Method for creating `ERC721Metadata` compatible ReFungible collection.
50- Method for creating ReFungible collection.57- Method for creating ReFungible collection.
5158
modifiedpallets/unique/Cargo.tomldiffbeforeafterboth
9license = 'GPLv3'9license = 'GPLv3'
10name = 'pallet-unique'10name = 'pallet-unique'
11repository = 'https://github.com/UniqueNetwork/unique-chain'11repository = 'https://github.com/UniqueNetwork/unique-chain'
12version = "0.2.0"12version = "0.2.1"
1313
14[package.metadata.docs.rs]14[package.metadata.docs.rs]
15targets = ['x86_64-unknown-linux-gnu']15targets = ['x86_64-unknown-linux-gnu']
modifiedpallets/unique/src/eth/mod.rsdiffbeforeafterboth
1818
19use core::marker::PhantomData;19use core::marker::PhantomData;
20use ethereum as _;20use ethereum as _;
21use evm_coder::{execution::*, generate_stubgen, solidity_interface, solidity, weight, types::*};21use evm_coder::{execution::*, generate_stubgen, solidity, solidity_interface, types::*, weight};
22use frame_support::traits::Get;22use frame_support::traits::Get;
23
24use crate::Pallet;
25
23use pallet_common::{26use pallet_common::{
24 CollectionById,27 CollectionById,
25 dispatch::CollectionDispatch,28 dispatch::CollectionDispatch,
26 erc::{29 erc::{static_property::key, CollectionHelpersEvents},
27 CollectionHelpersEvents,
28 static_property::{key},
29 },
30 Pallet as PalletCommon,30 Pallet as PalletCommon,
31};31};
32use pallet_evm::{account::CrossAccountId, OnMethodCall, PrecompileHandle, PrecompileResult};
32use pallet_evm_coder_substrate::{dispatch_to_evm, SubstrateRecorder, WithRecorder};33use pallet_evm_coder_substrate::{dispatch_to_evm, SubstrateRecorder, WithRecorder};
33use pallet_evm::{account::CrossAccountId, OnMethodCall, PrecompileHandle, PrecompileResult};
34use sp_std::vec;34use sp_std::vec;
35use up_data_structs::{35use up_data_structs::{
36 CollectionName, CollectionDescription, CollectionTokenPrefix, CreateCollectionData,36 CollectionDescription, CollectionMode, CollectionName, CollectionTokenPrefix,
37 CollectionMode, PropertyValue, CollectionFlags,37 CreateCollectionData,
38};38};
3939
40use crate::{Config, SelfWeightOf, weights::WeightInfo};40use crate::{weights::WeightInfo, Config, SelfWeightOf};
4141
42use alloc::format;
42use sp_std::vec::Vec;43use sp_std::vec::Vec;
43use alloc::format;
4444
45/// See [`CollectionHelpersCall`]45/// See [`CollectionHelpersCall`]
46pub struct EvmCollectionHelpers<T: Config>(SubstrateRecorder<T>);46pub struct EvmCollectionHelpers<T: Config>(SubstrateRecorder<T>);
84 Ok((caller, name, description, token_prefix))84 Ok((caller, name, description, token_prefix))
85}85}
8686
87#[inline(always)]
87fn create_refungible_collection_internal<88fn create_collection_internal<T: Config>(
88 T: Config + pallet_nonfungible::Config + pallet_refungible::Config,
89>(
90 caller: caller,89 caller: caller,
91 value: value,90 value: value,
92 name: string,91 name: string,
92 collection_mode: CollectionMode,
93 description: string,93 description: string,
94 token_prefix: string,94 token_prefix: string,
95) -> Result<address> {95) -> Result<address> {
96 let (caller, name, description, token_prefix) =96 let (caller, name, description, token_prefix) =
97 convert_data::<T>(caller, name, description, token_prefix)?;97 convert_data::<T>(caller, name, description, token_prefix)?;
98 let data = CreateCollectionData {98 let data = CreateCollectionData {
99 name,99 name,
100 mode: CollectionMode::ReFungible,100 mode: collection_mode,
101 description,101 description,
102 token_prefix,102 token_prefix,
103 ..Default::default()103 ..Default::default()
193 description: string,193 description: string,
194 token_prefix: string,194 token_prefix: string,
195 ) -> Result<address> {195 ) -> Result<address> {
196 self.create_nft_collection(caller, value, name, description, token_prefix)196 create_collection_internal::<T>(
197 caller,
198 value,
199 name,
200 CollectionMode::NFT,
201 description,
202 token_prefix,
203 )
197 }204 }
198205
206 description: string,213 description: string,
207 token_prefix: string,214 token_prefix: string,
208 ) -> Result<address> {215 ) -> Result<address> {
209 create_refungible_collection_internal::<T>(caller, value, name, description, token_prefix)216 create_collection_internal::<T>(
217 caller,
218 value,
219 name,
220 CollectionMode::ReFungible,
221 description,
222 token_prefix,
223 )
210 }224 }
225
226 #[weight(<SelfWeightOf<T>>::create_collection())]
227 #[solidity(rename_selector = "createFTCollection")]
228 fn create_fungible_collection(
229 &mut self,
230 caller: caller,
231 value: value,
232 name: string,
233 decimals: uint8,
234 description: string,
235 token_prefix: string,
236 ) -> Result<address> {
237 create_collection_internal::<T>(
238 caller,
239 value,
240 name,
241 CollectionMode::Fungible(decimals),
242 description,
243 token_prefix,
244 )
245 }
211246
212 #[solidity(rename_selector = "makeCollectionERC721MetadataCompatible")]247 #[solidity(rename_selector = "makeCollectionERC721MetadataCompatible")]
213 fn make_collection_metadata_compatible(248 fn make_collection_metadata_compatible(
296 Ok(())331 Ok(())
297 }332 }
333
334 #[weight(<SelfWeightOf<T>>::destroy_collection())]
335 fn destroy_collection(&mut self, caller: caller, collection_address: address) -> Result<void> {
336 let caller = T::CrossAccountId::from_eth(caller);
337
338 let collection_id = pallet_common::eth::map_eth_to_id(&collection_address)
339 .ok_or("Invalid collection address format")?;
340 <Pallet<T>>::destroy_collection_internal(caller, collection_id)
341 .map_err(pallet_evm_coder_substrate::dispatch_to_evm::<T>)
342 }
298343
299 /// Check if a collection exists344 /// Check if a collection exists
300 /// @param collectionAddress Address of the collection in question345 /// @param collectionAddress Address of the collection in question
modifiedpallets/unique/src/eth/stubs/CollectionHelpers.rawdiffbeforeafterboth

binary blob — no preview

modifiedpallets/unique/src/eth/stubs/CollectionHelpers.soldiffbeforeafterboth
20/// @dev inlined interface20/// @dev inlined interface
21contract CollectionHelpersEvents {21contract CollectionHelpersEvents {
22 event CollectionCreated(address indexed owner, address indexed collectionId);22 event CollectionCreated(address indexed owner, address indexed collectionId);
23 event CollectionDestroyed(address indexed collectionId);
23}24}
2425
25/// @title Contract, which allows users to operate with collections26/// @title Contract, which allows users to operate with collections
26/// @dev the ERC-165 identifier for this interface is 0x5891863127/// @dev the ERC-165 identifier for this interface is 0x7dea03b1
27contract CollectionHelpers is Dummy, ERC165, CollectionHelpersEvents {28contract CollectionHelpers is Dummy, ERC165, CollectionHelpersEvents {
28 /// Create an NFT collection29 /// Create an NFT collection
29 /// @param name Name of the collection30 /// @param name Name of the collection
76 return 0x0000000000000000000000000000000000000000;77 return 0x0000000000000000000000000000000000000000;
77 }78 }
79
80 /// @dev EVM selector for this function is: 0x7335b79f,
81 /// or in textual repr: createFTCollection(string,uint8,string,string)
82 function createFTCollection(
83 string memory name,
84 uint8 decimals,
85 string memory description,
86 string memory tokenPrefix
87 ) public payable returns (address) {
88 require(false, stub_error);
89 name;
90 decimals;
91 description;
92 tokenPrefix;
93 dummy = 0;
94 return 0x0000000000000000000000000000000000000000;
95 }
7896
79 /// @dev EVM selector for this function is: 0x85624258,97 /// @dev EVM selector for this function is: 0x85624258,
80 /// or in textual repr: makeCollectionERC721MetadataCompatible(address,string)98 /// or in textual repr: makeCollectionERC721MetadataCompatible(address,string)
85 dummy = 0;103 dummy = 0;
86 }104 }
105
106 /// @dev EVM selector for this function is: 0x564e321f,
107 /// or in textual repr: destroyCollection(address)
108 function destroyCollection(address collectionAddress) public {
109 require(false, stub_error);
110 collectionAddress;
111 dummy = 0;
112 }
87113
88 /// Check if a collection exists114 /// Check if a collection exists
89 /// @param collectionAddress Address of the collection in question115 /// @param collectionAddress Address of the collection in question
modifiedpallets/unique/src/lib.rsdiffbeforeafterboth
363 pub fn destroy_collection(origin, collection_id: CollectionId) -> DispatchResult {363 pub fn destroy_collection(origin, collection_id: CollectionId) -> DispatchResult {
364 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);364 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
365
365 let collection = <CollectionHandle<T>>::try_get(collection_id)?;366 Self::destroy_collection_internal(sender, collection_id)
366 collection.check_is_internal()?;
367
368 // =========
369
370 T::CollectionDispatch::destroy(sender, collection)?;
371
372 // TODO: basket cleanup should be moved elsewhere
373 // Maybe runtime dispatch.rs should perform it?
374
375 let _ = <NftTransferBasket<T>>::clear_prefix(collection_id, u32::MAX, None);
376 let _ = <FungibleTransferBasket<T>>::clear_prefix(collection_id, u32::MAX, None);
377 let _ = <ReFungibleTransferBasket<T>>::clear_prefix((collection_id,), u32::MAX, None);
378
379 let _ = <NftApproveBasket<T>>::clear_prefix(collection_id, u32::MAX, None);
380 let _ = <FungibleApproveBasket<T>>::clear_prefix(collection_id, u32::MAX, None);
381 let _ = <RefungibleApproveBasket<T>>::clear_prefix((collection_id,), u32::MAX, None);
382
383 Ok(())
384 }367 }
385368
386 /// Add an address to allow list.369 /// Add an address to allow list.
1152 target_collection.save()1135 target_collection.save()
1153 }1136 }
1137
1138 #[inline(always)]
1139 pub(crate) fn destroy_collection_internal(
1140 sender: T::CrossAccountId,
1141 collection_id: CollectionId,
1142 ) -> DispatchResult {
1143 let collection = <CollectionHandle<T>>::try_get(collection_id)?;
1144 collection.check_is_internal()?;
1145
1146 T::CollectionDispatch::destroy(sender, collection)?;
1147
1148 // TODO: basket cleanup should be moved elsewhere
1149 // Maybe runtime dispatch.rs should perform it?
1150
1151 let _ = <NftTransferBasket<T>>::clear_prefix(collection_id, u32::MAX, None);
1152 let _ = <FungibleTransferBasket<T>>::clear_prefix(collection_id, u32::MAX, None);
1153 let _ = <ReFungibleTransferBasket<T>>::clear_prefix((collection_id,), u32::MAX, None);
1154
1155 let _ = <NftApproveBasket<T>>::clear_prefix(collection_id, u32::MAX, None);
1156 let _ = <FungibleApproveBasket<T>>::clear_prefix(collection_id, u32::MAX, None);
1157 let _ = <RefungibleApproveBasket<T>>::clear_prefix((collection_id,), u32::MAX, None);
1158
1159 Ok(())
1160 }
1154}1161}
11551162
modifiedprimitives/data-structs/src/lib.rsdiffbeforeafterboth
447}447}
448448
449/// Collection parameters, used in RPC calls (see [`Collection`] for the storage version).449/// Collection parameters, used in RPC calls (see [`Collection`] for the storage version).
450#[struct_versioning::versioned(version = 2, upper)]
450#[derive(Encode, Decode, Clone, PartialEq, TypeInfo)]451#[derive(Encode, Decode, Clone, PartialEq, TypeInfo)]
451#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]452#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]
452pub struct RpcCollection<AccountId> {453pub struct RpcCollection<AccountId> {
484 pub read_only: bool,485 pub read_only: bool,
485486
486 /// Extra collection flags487 /// Extra collection flags
488 #[version(2.., upper(RpcCollectionFlags {foreign: false, erc721metadata: false}))]
487 pub flags: RpcCollectionFlags,489 pub flags: RpcCollectionFlags,
488}490}
489491
modifiedprimitives/rpc/src/lib.rsdiffbeforeafterboth
1616
17#![cfg_attr(not(feature = "std"), no_std)]17#![cfg_attr(not(feature = "std"), no_std)]
18
19extern crate alloc;
1820
19use up_data_structs::{21use up_data_structs::{
20 CollectionId, TokenId, RpcCollection, CollectionStats, CollectionLimits, Property,22 CollectionId, TokenId, RpcCollection, CollectionStats, CollectionLimits, Property,
21 PropertyKeyPermission, TokenData, TokenChild,23 PropertyKeyPermission, TokenData, TokenChild, RpcCollectionVersion1,
22};24};
2325
24use sp_std::vec::Vec;26use sp_std::vec::Vec;
28type Result<T> = core::result::Result<T, DispatchError>;30type Result<T> = core::result::Result<T, DispatchError>;
2931
30sp_api::decl_runtime_apis! {32sp_api::decl_runtime_apis! {
31 #[api_version(2)]33 #[api_version(3)]
32 /// Trait for generate rpc.34 /// Trait for generate rpc.
33 pub trait UniqueApi<CrossAccountId, AccountId> where35 pub trait UniqueApi<CrossAccountId, AccountId> where
34 AccountId: Decode,36 AccountId: Decode,
35 CrossAccountId: pallet_evm::account::CrossAccountId<AccountId>,37 CrossAccountId: pallet_evm::account::CrossAccountId<AccountId>,
36 {38 {
37 #[changed_in(2)]
38 fn token_owner(collection: CollectionId, token: TokenId) -> Result<CrossAccountId>;
39
40 /// Get number of tokens in collection owned by account.39 /// Get number of tokens in collection owned by account.
41 fn account_tokens(collection: CollectionId, account: CrossAccountId) -> Result<Vec<TokenId>>;40 fn account_tokens(collection: CollectionId, account: CrossAccountId) -> Result<Vec<TokenId>>;
110 /// Get collection by id.109 /// Get collection by id.
111 fn collection_by_id(collection: CollectionId) -> Result<Option<RpcCollection<AccountId>>>;110 fn collection_by_id(collection: CollectionId) -> Result<Option<RpcCollection<AccountId>>>;
111
112 #[changed_in(3)]
113 fn collection_by_id(collection: CollectionId) -> Result<Option<RpcCollectionVersion1<AccountId>>>;
112114
113 /// Get collection stats.115 /// Get collection stats.
114 fn collection_stats() -> Result<CollectionStats>;116 fn collection_stats() -> Result<CollectionStats>;
modifiedruntime/common/config/mod.rsdiffbeforeafterboth
22pub mod substrate;22pub mod substrate;
23pub mod xcm;23pub mod xcm;
24
25#[cfg(feature = "pallet-test-utils")]
26pub mod test_pallets;
2427
modifiedruntime/common/config/pallets/scheduler.rsdiffbeforeafterboth
15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
1616
17use frame_support::{traits::PrivilegeCmp, weights::Weight, parameter_types};17use frame_support::{
18 traits::{PrivilegeCmp, EnsureOrigin},
19 weights::Weight,
20 parameter_types,
21};
18use frame_system::EnsureSigned;22use frame_system::{EnsureRoot, RawOrigin};
19use sp_runtime::Perbill;23use sp_runtime::Perbill;
20use sp_std::cmp::Ordering;24use core::cmp::Ordering;
25use codec::Decode;
21use crate::{26use crate::{
22 runtime_common::{scheduler::SchedulerPaymentExecutor, config::substrate::RuntimeBlockWeights},27 runtime_common::{scheduler::SchedulerPaymentExecutor, config::substrate::RuntimeBlockWeights},
23 Runtime, Call, Event, Origin, OriginCaller, Balances,28 Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, OriginCaller, Balances,
24};29};
30use pallet_unique_scheduler_v2::ScheduledEnsureOriginSuccess;
25use up_common::types::AccountId;31use up_common::types::AccountId;
2632
27parameter_types! {33parameter_types! {
33 pub const Preimage: Option<u32> = Some(10);39 pub const Preimage: Option<u32> = Some(10);
34}40}
3541
36/// Used the compare the privilege of an origin inside the scheduler.
37pub struct OriginPrivilegeCmp;42pub struct EnsureSignedOrRoot<AccountId>(sp_std::marker::PhantomData<AccountId>);
3843impl<O: Into<Result<RawOrigin<AccountId>, O>> + From<RawOrigin<AccountId>>, AccountId: Decode>
44 EnsureOrigin<O> for EnsureSignedOrRoot<AccountId>
45{
46 type Success = ScheduledEnsureOriginSuccess<AccountId>;
47 fn try_origin(o: O) -> Result<Self::Success, O> {
48 o.into().and_then(|o| match o {
49 RawOrigin::Root => Ok(ScheduledEnsureOriginSuccess::Root),
50 RawOrigin::Signed(who) => Ok(ScheduledEnsureOriginSuccess::Signed(who)),
51 r => Err(O::from(r)),
52 })
53 }
54}
55
56pub struct EqualOrRootOnly;
39impl PrivilegeCmp<OriginCaller> for OriginPrivilegeCmp {57impl PrivilegeCmp<OriginCaller> for EqualOrRootOnly {
40 fn cmp_privilege(_left: &OriginCaller, _right: &OriginCaller) -> Option<Ordering> {58 fn cmp_privilege(left: &OriginCaller, right: &OriginCaller) -> Option<Ordering> {
59 use RawOrigin::*;
60
61 let left = left.clone().try_into().ok()?;
62 let right = right.clone().try_into().ok()?;
63
64 match (left, right) {
41 Some(Ordering::Equal)65 (Root, Root) => Some(Ordering::Equal),
66 (Root, _) => Some(Ordering::Greater),
67 (_, Root) => Some(Ordering::Less),
68 lr @ _ => (lr.0 == lr.1).then(|| Ordering::Equal),
69 }
42 }70 }
43}71}
72
73// impl pallet_unique_scheduler::Config for Runtime {
74// type RuntimeEvent = RuntimeEvent;
75// type RuntimeOrigin = RuntimeOrigin;
76// type Currency = Balances;
77// type PalletsOrigin = OriginCaller;
78// type RuntimeCall = RuntimeCall;
79// type MaximumWeight = MaximumSchedulerWeight;
80// type ScheduleOrigin = EnsureSignedOrRoot<AccountId>;
81// type PrioritySetOrigin = EnsureRoot<AccountId>;
82// type MaxScheduledPerBlock = MaxScheduledPerBlock;
83// type WeightInfo = ();
84// type CallExecutor = SchedulerPaymentExecutor;
85// type OriginPrivilegeCmp = EqualOrRootOnly;
86// type PreimageProvider = ();
87// type NoPreimagePostponement = NoPreimagePostponement;
88// }
4489
45impl pallet_unique_scheduler::Config for Runtime {90impl pallet_unique_scheduler_v2::Config for Runtime {
46 type RuntimeEvent = RuntimeEvent;91 type RuntimeEvent = RuntimeEvent;
47 type RuntimeOrigin = RuntimeOrigin;92 type RuntimeOrigin = RuntimeOrigin;
48 type Currency = Balances;
49 type PalletsOrigin = OriginCaller;93 type PalletsOrigin = OriginCaller;
50 type RuntimeCall = RuntimeCall;94 type RuntimeCall = RuntimeCall;
51 type MaximumWeight = MaximumSchedulerWeight;95 type MaximumWeight = MaximumSchedulerWeight;
52 type ScheduleOrigin = EnsureSigned<AccountId>;96 type ScheduleOrigin = EnsureSignedOrRoot<AccountId>;
97 type OriginPrivilegeCmp = EqualOrRootOnly;
53 type MaxScheduledPerBlock = MaxScheduledPerBlock;98 type MaxScheduledPerBlock = MaxScheduledPerBlock;
54 type WeightInfo = ();99 type WeightInfo = ();
55 type CallExecutor = SchedulerPaymentExecutor;100 type Preimages = ();
56 type OriginPrivilegeCmp = OriginPrivilegeCmp;101 type CallExecutor = SchedulerPaymentExecutor;
57 type PreimageProvider = ();102 type PrioritySetOrigin = EnsureRoot<AccountId>;
58 type NoPreimagePostponement = NoPreimagePostponement;
59}103}
60104
addedruntime/common/config/test_pallets.rsdiffbeforeafterboth

no changes

modifiedruntime/common/construct_runtime/mod.rsdiffbeforeafterboth
94 EvmTransactionPayment: pallet_evm_transaction_payment::{Pallet} = 152,94 EvmTransactionPayment: pallet_evm_transaction_payment::{Pallet} = 152,
95 EvmMigration: pallet_evm_migration::{Pallet, Call, Storage} = 153,95 EvmMigration: pallet_evm_migration::{Pallet, Call, Storage} = 153,
96
97 #[runtimes(opal)]
98 Scheduler: pallet_unique_scheduler_v2::{Pallet, Call, Storage, Event<T>} = 154,
99
100 #[runtimes(opal)]
101 TestUtils: pallet_test_utils = 255,
96 }102 }
97 }103 }
98 }104 }
modifiedruntime/common/scheduler.rsdiffbeforeafterboth
1616
17use frame_support::{17use frame_support::{
18 traits::NamedReservableCurrency,18 traits::NamedReservableCurrency,
19 weights::{GetDispatchInfo, PostDispatchInfo, DispatchInfo},19 dispatch::{GetDispatchInfo, PostDispatchInfo, DispatchInfo},
20};20};
21use sp_runtime::{21use sp_runtime::{
22 traits::{Dispatchable, Applyable, Member},22 traits::{Dispatchable, Applyable, Member},
23 generic::Era,23 generic::Era,
24 transaction_validity::TransactionValidityError,24 transaction_validity::TransactionValidityError,
25 DispatchErrorWithPostInfo, DispatchError,25 DispatchErrorWithPostInfo, DispatchError,
26};26};
27use codec::Encode;
27use crate::{Runtime, Call, Origin, Balances, ChargeTransactionPayment};28use crate::{Runtime, RuntimeCall, RuntimeOrigin, Balances};
28use up_common::types::{AccountId, Balance};29use up_common::types::{AccountId, Balance};
29use fp_self_contained::SelfContainedCall;30use fp_self_contained::SelfContainedCall;
30use pallet_unique_scheduler::DispatchCall;31use pallet_unique_scheduler_v2::DispatchCall;
32use pallet_transaction_payment::ChargeTransactionPayment;
33
34// type SponsorshipChargeTransactionPayment =
35// pallet_charge_transaction::ChargeTransactionPayment<Runtime>;
3136
32/// The SignedExtension to the basic transaction logic.37/// The SignedExtension to the basic transaction logic.
33pub type SignedExtraScheduler = (38pub type SignedExtraScheduler = (
36 frame_system::CheckEra<Runtime>,41 frame_system::CheckEra<Runtime>,
37 frame_system::CheckNonce<Runtime>,42 frame_system::CheckNonce<Runtime>,
38 frame_system::CheckWeight<Runtime>,43 frame_system::CheckWeight<Runtime>,
44 ChargeTransactionPayment<Runtime>,
39);45);
4046
41fn get_signed_extras(from: <Runtime as frame_system::Config>::AccountId) -> SignedExtraScheduler {47fn get_signed_extras(from: <Runtime as frame_system::Config>::AccountId) -> SignedExtraScheduler {
47 from,53 from,
48 )),54 )),
49 frame_system::CheckWeight::<Runtime>::new(),55 frame_system::CheckWeight::<Runtime>::new(),
50 // sponsoring transaction logic56 ChargeTransactionPayment::<Runtime>::from(0),
51 // pallet_charge_transaction::ChargeTransactionPayment::<Runtime>::new(0),
52 )57 )
53}58}
5459
55pub struct SchedulerPaymentExecutor;60pub struct SchedulerPaymentExecutor;
5661
57impl<T: frame_system::Config + pallet_unique_scheduler::Config, SelfContainedSignedInfo>62impl<T: frame_system::Config + pallet_unique_scheduler_v2::Config, SelfContainedSignedInfo>
58 DispatchCall<T, SelfContainedSignedInfo> for SchedulerPaymentExecutor63 DispatchCall<T, SelfContainedSignedInfo> for SchedulerPaymentExecutor
59where64where
60 <T as frame_system::Config>::Call: Member65 <T as frame_system::Config>::RuntimeCall: Member
61 + Dispatchable<Origin = Origin, Info = DispatchInfo>66 + Dispatchable<RuntimeOrigin = RuntimeOrigin, Info = DispatchInfo>
62 + SelfContainedCall<SignedInfo = SelfContainedSignedInfo>67 + SelfContainedCall<SignedInfo = SelfContainedSignedInfo>
63 + GetDispatchInfo68 + GetDispatchInfo
64 + From<frame_system::Call<Runtime>>,69 + From<frame_system::Call<Runtime>>,
65 SelfContainedSignedInfo: Send + Sync + 'static,70 SelfContainedSignedInfo: Send + Sync + 'static,
66 Call: From<<T as frame_system::Config>::Call>71 RuntimeCall: From<<T as frame_system::Config>::RuntimeCall>
67 + From<<T as pallet_unique_scheduler::Config>::Call>72 + From<<T as pallet_unique_scheduler_v2::Config>::RuntimeCall>
68 + SelfContainedCall<SignedInfo = SelfContainedSignedInfo>,73 + SelfContainedCall<SignedInfo = SelfContainedSignedInfo>,
69 sp_runtime::AccountId32: From<<T as frame_system::Config>::AccountId>,74 sp_runtime::AccountId32: From<<T as frame_system::Config>::AccountId>,
70{75{
71 fn dispatch_call(76 fn dispatch_call(
72 signer: <T as frame_system::Config>::AccountId,77 signer: Option<<T as frame_system::Config>::AccountId>,
73 call: <T as pallet_unique_scheduler::Config>::Call,78 call: <T as pallet_unique_scheduler_v2::Config>::RuntimeCall,
74 ) -> Result<79 ) -> Result<
75 Result<PostDispatchInfo, DispatchErrorWithPostInfo<PostDispatchInfo>>,80 Result<PostDispatchInfo, DispatchErrorWithPostInfo<PostDispatchInfo>>,
76 TransactionValidityError,81 TransactionValidityError,
77 > {82 > {
78 let dispatch_info = call.get_dispatch_info();83 let dispatch_info = call.get_dispatch_info();
84 let len = call.encoded_size();
85
79 let extrinsic = fp_self_contained::CheckedExtrinsic::<86 let signed = match signer {
80 AccountId,
81 Call,
82 SignedExtraScheduler,
83 SelfContainedSignedInfo,
84 > {
85 signed: fp_self_contained::CheckedSignature::<87 Some(signer) => fp_self_contained::CheckedSignature::Signed(
86 AccountId,
87 SignedExtraScheduler,
88 SelfContainedSignedInfo,
89 >::Signed(signer.clone().into(), get_signed_extras(signer.into())),88 signer.clone().into(),
90 function: call.into(),89 get_signed_extras(signer.into()),
90 ),
91 None => fp_self_contained::CheckedSignature::Unsigned,
91 };92 };
93
94 let extrinsic = fp_self_contained::CheckedExtrinsic::<
95 AccountId,
96 RuntimeCall,
97 SignedExtraScheduler,
98 SelfContainedSignedInfo,
99 > {
100 signed,
101 function: call.into(),
102 };
92103
93 extrinsic.apply::<Runtime>(&dispatch_info, 0)104 extrinsic.apply::<Runtime>(&dispatch_info, len)
94 }105 }
95
96 fn reserve_balance(
97 id: [u8; 16],
98 sponsor: <T as frame_system::Config>::AccountId,
99 call: <T as pallet_unique_scheduler::Config>::Call,
100 count: u32,
101 ) -> Result<(), DispatchError> {
102 let dispatch_info = call.get_dispatch_info();
103 let weight: Balance = ChargeTransactionPayment::traditional_fee(0, &dispatch_info, 0)
104 .saturating_mul(count.into());
105
106 <Balances as NamedReservableCurrency<AccountId>>::reserve_named(
107 &id,
108 &(sponsor.into()),
109 weight,
110 )
111 }
112
113 fn pay_for_call(
114 id: [u8; 16],
115 sponsor: <T as frame_system::Config>::AccountId,
116 call: <T as pallet_unique_scheduler::Config>::Call,
117 ) -> Result<u128, DispatchError> {
118 let dispatch_info = call.get_dispatch_info();
119 let weight: Balance = ChargeTransactionPayment::traditional_fee(0, &dispatch_info, 0);
120 Ok(
121 <Balances as NamedReservableCurrency<AccountId>>::unreserve_named(
122 &id,
123 &(sponsor.into()),
124 weight,
125 ),
126 )
127 }
128
129 fn cancel_reserve(
130 id: [u8; 16],
131 sponsor: <T as frame_system::Config>::AccountId,
132 ) -> Result<u128, DispatchError> {
133 Ok(
134 <Balances as NamedReservableCurrency<AccountId>>::unreserve_named(
135 &id,
136 &(sponsor.into()),
137 u128::MAX,
138 ),
139 )
140 }
141}106}
107
108// impl<T: frame_system::Config + pallet_unique_scheduler::Config, SelfContainedSignedInfo>
109// DispatchCall<T, SelfContainedSignedInfo> for SchedulerPaymentExecutor
110// where
111// <T as frame_system::Config>::Call: Member
112// + Dispatchable<Origin = Origin, Info = DispatchInfo>
113// + SelfContainedCall<SignedInfo = SelfContainedSignedInfo>
114// + GetDispatchInfo
115// + From<frame_system::Call<Runtime>>,
116// SelfContainedSignedInfo: Send + Sync + 'static,
117// Call: From<<T as frame_system::Config>::Call>
118// + From<<T as pallet_unique_scheduler::Config>::Call>
119// + SelfContainedCall<SignedInfo = SelfContainedSignedInfo>,
120// sp_runtime::AccountId32: From<<T as frame_system::Config>::AccountId>,
121// {
122// fn dispatch_call(
123// signer: Option<<T as frame_system::Config>::AccountId>,
124// call: <T as pallet_unique_scheduler::Config>::Call,
125// ) -> Result<
126// Result<PostDispatchInfo, DispatchErrorWithPostInfo<PostDispatchInfo>>,
127// TransactionValidityError,
128// > {
129// let dispatch_info = call.get_dispatch_info();
130// let len = call.encoded_size();
131
132// let signed = match signer {
133// Some(signer) => fp_self_contained::CheckedSignature::Signed(
134// signer.clone().into(),
135// get_signed_extras(signer.into()),
136// ),
137// None => fp_self_contained::CheckedSignature::Unsigned,
138// };
139
140// let extrinsic = fp_self_contained::CheckedExtrinsic::<
141// AccountId,
142// Call,
143// SignedExtraScheduler,
144// SelfContainedSignedInfo,
145// > {
146// signed,
147// function: call.into(),
148// };
149
150// extrinsic.apply::<Runtime>(&dispatch_info, len)
151// }
152
153// fn reserve_balance(
154// id: [u8; 16],
155// sponsor: <T as frame_system::Config>::AccountId,
156// call: <T as pallet_unique_scheduler::Config>::Call,
157// count: u32,
158// ) -> Result<(), DispatchError> {
159// let dispatch_info = call.get_dispatch_info();
160// let weight: Balance =
161// SponsorshipChargeTransactionPayment::traditional_fee(0, &dispatch_info, 0)
162// .saturating_mul(count.into());
163
164// <Balances as NamedReservableCurrency<AccountId>>::reserve_named(
165// &id,
166// &(sponsor.into()),
167// weight,
168// )
169// }
170
171// fn pay_for_call(
172// id: [u8; 16],
173// sponsor: <T as frame_system::Config>::AccountId,
174// call: <T as pallet_unique_scheduler::Config>::Call,
175// ) -> Result<u128, DispatchError> {
176// let dispatch_info = call.get_dispatch_info();
177// let weight: Balance =
178// SponsorshipChargeTransactionPayment::traditional_fee(0, &dispatch_info, 0);
179// Ok(
180// <Balances as NamedReservableCurrency<AccountId>>::unreserve_named(
181// &id,
182// &(sponsor.into()),
183// weight,
184// ),
185// )
186// }
187
188// fn cancel_reserve(
189// id: [u8; 16],
190// sponsor: <T as frame_system::Config>::AccountId,
191// ) -> Result<u128, DispatchError> {
192// Ok(
193// <Balances as NamedReservableCurrency<AccountId>>::unreserve_named(
194// &id,
195// &(sponsor.into()),
196// u128::MAX,
197// ),
198// )
199// }
200// }
142201
modifiedruntime/opal/Cargo.tomldiffbeforeafterboth
42 'pallet-inflation/runtime-benchmarks',42 'pallet-inflation/runtime-benchmarks',
43 'pallet-app-promotion/runtime-benchmarks',43 'pallet-app-promotion/runtime-benchmarks',
44 'pallet-unique-scheduler/runtime-benchmarks',44 'pallet-unique-scheduler/runtime-benchmarks',
45 'pallet-unique-scheduler-v2/runtime-benchmarks',
45 'pallet-xcm/runtime-benchmarks',46 'pallet-xcm/runtime-benchmarks',
46 'sp-runtime/runtime-benchmarks',47 'sp-runtime/runtime-benchmarks',
47 'xcm-builder/runtime-benchmarks',48 'xcm-builder/runtime-benchmarks',
140 'pallet-proxy-rmrk-equip/std',141 'pallet-proxy-rmrk-equip/std',
141 'pallet-unique/std',142 'pallet-unique/std',
142 'pallet-unique-scheduler/std',143 'pallet-unique-scheduler/std',
144 'pallet-unique-scheduler-v2/std',
143 'pallet-charge-transaction/std',145 'pallet-charge-transaction/std',
144 'up-data-structs/std',146 'up-data-structs/std',
145 'sp-api/std',147 'sp-api/std',
168 "orml-traits/std",170 "orml-traits/std",
169 "pallet-foreign-assets/std",171 "pallet-foreign-assets/std",
172
173 'pallet-test-utils?/std',
170]174]
171limit-testing = ['pallet-unique/limit-testing', 'up-data-structs/limit-testing']175limit-testing = ['pallet-unique/limit-testing', 'up-data-structs/limit-testing']
172opal-runtime = ['refungible', 'rmrk', 'app-promotion', 'foreign-assets']176opal-runtime = ['refungible', 'scheduler', 'rmrk', 'app-promotion', 'foreign-assets', 'pallet-test-utils']
173177
174refungible = []178refungible = []
175scheduler = []179scheduler = []
470pallet-proxy-rmrk-equip = { default-features = false, path = "../../pallets/proxy-rmrk-equip", package = "pallet-rmrk-equip" }474pallet-proxy-rmrk-equip = { default-features = false, path = "../../pallets/proxy-rmrk-equip", package = "pallet-rmrk-equip" }
471pallet-unique-scheduler = { path = '../../pallets/scheduler', default-features = false }475pallet-unique-scheduler = { path = '../../pallets/scheduler', default-features = false }
472pallet-charge-transaction = { git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = "polkadot-v0.9.30", package = "pallet-template-transaction-payment", default-features = false, version = "3.0.0" }476pallet-charge-transaction = { git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = "polkadot-v0.9.30", package = "pallet-template-transaction-payment", default-features = false, version = "3.0.0" }
477pallet-unique-scheduler-v2 = { path = '../../pallets/scheduler-v2', default-features = false }
473pallet-evm-migration = { path = '../../pallets/evm-migration', default-features = false }478pallet-evm-migration = { path = '../../pallets/evm-migration', default-features = false }
474pallet-evm-contract-helpers = { path = '../../pallets/evm-contract-helpers', default-features = false }479pallet-evm-contract-helpers = { path = '../../pallets/evm-contract-helpers', default-features = false }
475pallet-evm-transaction-payment = { path = '../../pallets/evm-transaction-payment', default-features = false }480pallet-evm-transaction-payment = { path = '../../pallets/evm-transaction-payment', default-features = false }
483up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = 'polkadot-v0.9.30' }488up-sponsorship = { default-features = false, git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = 'polkadot-v0.9.30' }
484pallet-foreign-assets = { default-features = false, path = "../../pallets/foreign-assets" }489pallet-foreign-assets = { default-features = false, path = "../../pallets/foreign-assets" }
490
491################################################################################
492# Test dependencies
493
494pallet-test-utils = { optional = true, default-features = false, path = "../../test-pallets/utils" }
485495
486################################################################################496################################################################################
487# Other Dependencies497# Other Dependencies
modifiedruntime/opal/src/lib.rsdiffbeforeafterboth
50 spec_name: create_runtime_str!(RUNTIME_NAME),50 spec_name: create_runtime_str!(RUNTIME_NAME),
51 impl_name: create_runtime_str!(RUNTIME_NAME),51 impl_name: create_runtime_str!(RUNTIME_NAME),
52 authoring_version: 1,52 authoring_version: 1,
53 spec_version: 930031,53 spec_version: 930032,
54 impl_version: 0,54 impl_version: 0,
55 apis: RUNTIME_API_VERSIONS,55 apis: RUNTIME_API_VERSIONS,
56 transaction_version: 2,56 transaction_version: 2,
modifiedruntime/quartz/src/lib.rsdiffbeforeafterboth
50 spec_name: create_runtime_str!(RUNTIME_NAME),50 spec_name: create_runtime_str!(RUNTIME_NAME),
51 impl_name: create_runtime_str!(RUNTIME_NAME),51 impl_name: create_runtime_str!(RUNTIME_NAME),
52 authoring_version: 1,52 authoring_version: 1,
53 spec_version: 930031,53 spec_version: 930032,
54 impl_version: 0,54 impl_version: 0,
55 apis: RUNTIME_API_VERSIONS,55 apis: RUNTIME_API_VERSIONS,
56 transaction_version: 2,56 transaction_version: 2,
modifiedruntime/unique/src/lib.rsdiffbeforeafterboth
50 spec_name: create_runtime_str!(RUNTIME_NAME),50 spec_name: create_runtime_str!(RUNTIME_NAME),
51 impl_name: create_runtime_str!(RUNTIME_NAME),51 impl_name: create_runtime_str!(RUNTIME_NAME),
52 authoring_version: 1,52 authoring_version: 1,
53 spec_version: 930031,53 spec_version: 930032,
54 impl_version: 0,54 impl_version: 0,
55 apis: RUNTIME_API_VERSIONS,55 apis: RUNTIME_API_VERSIONS,
56 transaction_version: 2,56 transaction_version: 2,
addedtest-pallets/utils/Cargo.lockdiffbeforeafterboth

no changes

addedtest-pallets/utils/Cargo.tomldiffbeforeafterboth

no changes

addedtest-pallets/utils/src/lib.rsdiffbeforeafterboth

no changes

modifiedtests/.vscode/settings.jsondiffbeforeafterboth
1{1{
2 "mocha.enabled": true,2 "mocha.enabled": true,
3 "mochaExplorer.files": "**/*.test.ts",3 "mochaExplorer.files": "**/*.test.ts",
4 "mochaExplorer.require": "ts-node/register"4 "mochaExplorer.require": "ts-node/register",
5 "eslint.format.enable": true,
6 "[javascript]": {
7 "editor.defaultFormatter": "dbaeumer.vscode-eslint"
8 },
9 "[typescript]": {
10 "editor.defaultFormatter": "dbaeumer.vscode-eslint"
11 }
5}12}
613
deletedtests/src/.outdated/eth/scheduling.test.tsdiffbeforeafterboth

no changes

deletedtests/src/.outdated/scheduler.test.tsdiffbeforeafterboth

no changes

modifiedtests/src/eth/allowlist.test.tsdiffbeforeafterboth
89 expect(await collectionEvm.methods.allowed(user).call({from: owner})).to.be.false;89 expect(await collectionEvm.methods.allowed(user).call({from: owner})).to.be.false;
90 });90 });
9191
92 // TODO: Temprorary off. Need refactor
93 // itEth('Collection allowlist can be added and removed by [sub] address', async ({helper}) => {92 //itEth('Collection allowlist can be added and removed by [cross] address', async ({helper}) => {
94 // const owner = await helper.eth.createAccountWithBalance(donor);93 // const owner = await helper.eth.createAccountWithBalance(donor);
95 // const user = donor;94 // const user = donor;
9695 //
97 // const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');96 // const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');
98 // const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);97 // const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
9998 // const userCross = helper.ethCrossAccount.fromKeyringPair(user);
99 //
100 // expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.false;100 // expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.false;
101 // await collectionEvm.methods.addToCollectionAllowListSubstrate(user.addressRaw).send({from: owner});101 // await collectionEvm.methods.addToCollectionAllowListCross(userCross).send({from: owner});
102 // expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.true;102 // expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.true;
103103 //
104 // await collectionEvm.methods.removeFromCollectionAllowListSubstrate(user.addressRaw).send({from: owner});104 // await collectionEvm.methods.removeFromCollectionAllowListCross(userCross).send({from: owner});
105 // expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.false;105 // expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.false;
106 // });106 //});
107107
108 itEth('Collection allowlist can not be add and remove [eth] address by not owner', async ({helper}) => {108 itEth('Collection allowlist can not be add and remove [eth] address by not owner', async ({helper}) => {
109 const owner = await helper.eth.createAccountWithBalance(donor);109 const owner = await helper.eth.createAccountWithBalance(donor);
123 expect(await collectionEvm.methods.allowed(user).call({from: owner})).to.be.true;122 expect(await collectionEvm.methods.allowed(user).call({from: owner})).to.be.true;
124 });123 });
125124
126 // TODO: Temprorary off. Need refactor
127 // itEth('Collection allowlist can not be add and remove [sub] address by not owner', async ({helper}) => {125 //itEth('Collection allowlist can not be add and remove [cross] address by not owner', async ({helper}) => {
128 // const owner = await helper.eth.createAccountWithBalance(donor);126 // const owner = await helper.eth.createAccountWithBalance(donor);
129 // const notOwner = await helper.eth.createAccountWithBalance(donor);127 // const notOwner = await helper.eth.createAccountWithBalance(donor);
130 // const user = donor;128 // const user = donor;
131129 //
132 // const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');130 // const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');
133 // const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);131 // const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
134132 //
135 // expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.false;133 // expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.false;
134 // const userCross = helper.ethCrossAccount.fromKeyringPair(user);
136 // await expect(collectionEvm.methods.addToCollectionAllowListSubstrate(user.addressRaw).call({from: notOwner})).to.be.rejectedWith('NoPermission');135 // await expect(collectionEvm.methods.addToCollectionAllowListCross(userCross).call({from: notOwner})).to.be.rejectedWith('NoPermission');
137 // expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.false;136 // expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.false;
138 // await collectionEvm.methods.addToCollectionAllowListSubstrate(user.addressRaw).send({from: owner});137 // await collectionEvm.methods.addToCollectionAllowListCross(userCross).send({from: owner});
139138 //
140 // expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.true;139 // expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.true;
141 // await expect(collectionEvm.methods.removeFromCollectionAllowListSubstrate(user.addressRaw).call({from: notOwner})).to.be.rejectedWith('NoPermission');140 // await expect(collectionEvm.methods.removeFromCollectionAllowListCross(userCross).call({from: notOwner})).to.be.rejectedWith('NoPermission');
142 // expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.true;141 // expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.true;
143 // });142 //});
144});143});
145144
modifiedtests/src/eth/api/CollectionHelpers.soldiffbeforeafterboth
15/// @dev inlined interface15/// @dev inlined interface
16interface CollectionHelpersEvents {16interface CollectionHelpersEvents {
17 event CollectionCreated(address indexed owner, address indexed collectionId);17 event CollectionCreated(address indexed owner, address indexed collectionId);
18 event CollectionDestroyed(address indexed collectionId);
18}19}
1920
20/// @title Contract, which allows users to operate with collections21/// @title Contract, which allows users to operate with collections
21/// @dev the ERC-165 identifier for this interface is 0x5891863122/// @dev the ERC-165 identifier for this interface is 0x7dea03b1
22interface CollectionHelpers is Dummy, ERC165, CollectionHelpersEvents {23interface CollectionHelpers is Dummy, ERC165, CollectionHelpersEvents {
23 /// Create an NFT collection24 /// Create an NFT collection
24 /// @param name Name of the collection25 /// @param name Name of the collection
50 string memory tokenPrefix51 string memory tokenPrefix
51 ) external payable returns (address);52 ) external payable returns (address);
53
54 /// @dev EVM selector for this function is: 0x7335b79f,
55 /// or in textual repr: createFTCollection(string,uint8,string,string)
56 function createFTCollection(
57 string memory name,
58 uint8 decimals,
59 string memory description,
60 string memory tokenPrefix
61 ) external payable returns (address);
5262
53 /// @dev EVM selector for this function is: 0x85624258,63 /// @dev EVM selector for this function is: 0x85624258,
54 /// or in textual repr: makeCollectionERC721MetadataCompatible(address,string)64 /// or in textual repr: makeCollectionERC721MetadataCompatible(address,string)
55 function makeCollectionERC721MetadataCompatible(address collection, string memory baseUri) external;65 function makeCollectionERC721MetadataCompatible(address collection, string memory baseUri) external;
66
67 /// @dev EVM selector for this function is: 0x564e321f,
68 /// or in textual repr: destroyCollection(address)
69 function destroyCollection(address collectionAddress) external;
5670
57 /// Check if a collection exists71 /// Check if a collection exists
58 /// @param collectionAddress Address of the collection in question72 /// @param collectionAddress Address of the collection in question
modifiedtests/src/eth/api/UniqueFungible.soldiffbeforeafterboth
13}13}
1414
15/// @title A contract that allows you to work with collections.15/// @title A contract that allows you to work with collections.
16/// @dev the ERC-165 identifier for this interface is 0x62e2229016/// @dev the ERC-165 identifier for this interface is 0xb3152af3
17interface Collection is Dummy, ERC165 {17interface Collection is Dummy, ERC165 {
18 /// Set collection property.18 /// Set collection property.
19 ///19 ///
23 /// or in textual repr: setCollectionProperty(string,bytes)23 /// or in textual repr: setCollectionProperty(string,bytes)
24 function setCollectionProperty(string memory key, bytes memory value) external;24 function setCollectionProperty(string memory key, bytes memory value) external;
25
26 /// Set collection properties.
27 ///
28 /// @param properties Vector of properties key/value pair.
29 /// @dev EVM selector for this function is: 0x50b26b2a,
30 /// or in textual repr: setCollectionProperties((string,bytes)[])
31 function setCollectionProperties(Tuple10[] memory properties) external;
2532
26 /// Delete collection property.33 /// Delete collection property.
27 ///34 ///
30 /// or in textual repr: deleteCollectionProperty(string)37 /// or in textual repr: deleteCollectionProperty(string)
31 function deleteCollectionProperty(string memory key) external;38 function deleteCollectionProperty(string memory key) external;
39
40 /// Delete collection properties.
41 ///
42 /// @param keys Properties keys.
43 /// @dev EVM selector for this function is: 0xee206ee3,
44 /// or in textual repr: deleteCollectionProperties(string[])
45 function deleteCollectionProperties(string[] memory keys) external;
3246
33 /// Get collection property.47 /// Get collection property.
34 ///48 ///
40 /// or in textual repr: collectionProperty(string)54 /// or in textual repr: collectionProperty(string)
41 function collectionProperty(string memory key) external view returns (bytes memory);55 function collectionProperty(string memory key) external view returns (bytes memory);
56
57 /// Get collection properties.
58 ///
59 /// @param keys Properties keys. Empty keys for all propertyes.
60 /// @return Vector of properties key/value pairs.
61 /// @dev EVM selector for this function is: 0x285fb8e6,
62 /// or in textual repr: collectionProperties(string[])
63 function collectionProperties(string[] memory keys) external view returns (Tuple10[] memory);
4264
43 /// Set the sponsor of the collection.65 /// Set the sponsor of the collection.
44 ///66 ///
49 /// or in textual repr: setCollectionSponsor(address)71 /// or in textual repr: setCollectionSponsor(address)
50 function setCollectionSponsor(address sponsor) external;72 function setCollectionSponsor(address sponsor) external;
73
74 /// Set the sponsor of the collection.
75 ///
76 /// @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.
77 ///
78 /// @param sponsor Cross account address of the sponsor from whose account funds will be debited for operations with the contract.
79 /// @dev EVM selector for this function is: 0x84a1d5a8,
80 /// or in textual repr: setCollectionSponsorCross((address,uint256))
81 function setCollectionSponsorCross(Tuple6 memory sponsor) external;
5182
52 /// Whether there is a pending sponsor.83 /// Whether there is a pending sponsor.
53 /// @dev EVM selector for this function is: 0x058ac185,84 /// @dev EVM selector for this function is: 0x058ac185,
103 /// or in textual repr: contractAddress()134 /// or in textual repr: contractAddress()
104 function contractAddress() external view returns (address);135 function contractAddress() external view returns (address);
136
137 /// Add collection admin.
138 /// @param newAdmin Cross account administrator address.
139 /// @dev EVM selector for this function is: 0x859aa7d6,
140 /// or in textual repr: addCollectionAdminCross((address,uint256))
141 function addCollectionAdminCross(Tuple6 memory newAdmin) external;
142
143 /// Remove collection admin.
144 /// @param admin Cross account administrator address.
145 /// @dev EVM selector for this function is: 0x6c0cd173,
146 /// or in textual repr: removeCollectionAdminCross((address,uint256))
147 function removeCollectionAdminCross(Tuple6 memory admin) external;
105148
106 /// Add collection admin.149 /// Add collection admin.
107 /// @param newAdmin Address of the added administrator.150 /// @param newAdmin Address of the added administrator.
153 /// or in textual repr: addToCollectionAllowList(address)196 /// or in textual repr: addToCollectionAllowList(address)
154 function addToCollectionAllowList(address user) external;197 function addToCollectionAllowList(address user) external;
198
199 /// Add user to allowed list.
200 ///
201 /// @param user User cross account address.
202 /// @dev EVM selector for this function is: 0xa0184a3a,
203 /// or in textual repr: addToCollectionAllowListCross((address,uint256))
204 function addToCollectionAllowListCross(Tuple6 memory user) external;
155205
156 /// Remove the user from the allowed list.206 /// Remove the user from the allowed list.
157 ///207 ///
160 /// or in textual repr: removeFromCollectionAllowList(address)210 /// or in textual repr: removeFromCollectionAllowList(address)
161 function removeFromCollectionAllowList(address user) external;211 function removeFromCollectionAllowList(address user) external;
212
213 /// Remove user from allowed list.
214 ///
215 /// @param user User cross account address.
216 /// @dev EVM selector for this function is: 0x09ba452a,
217 /// or in textual repr: removeFromCollectionAllowListCross((address,uint256))
218 function removeFromCollectionAllowListCross(Tuple6 memory user) external;
162219
163 /// Switch permission for minting.220 /// Switch permission for minting.
164 ///221 ///
175 /// or in textual repr: isOwnerOrAdmin(address)232 /// or in textual repr: isOwnerOrAdmin(address)
176 function isOwnerOrAdmin(address user) external view returns (bool);233 function isOwnerOrAdmin(address user) external view returns (bool);
234
235 /// Check that account is the owner or admin of the collection
236 ///
237 /// @param user User cross account to verify
238 /// @return "true" if account is the owner or admin
239 /// @dev EVM selector for this function is: 0x3e75a905,
240 /// or in textual repr: isOwnerOrAdminCross((address,uint256))
241 function isOwnerOrAdminCross(Tuple6 memory user) external view returns (bool);
177242
178 /// Returns collection type243 /// Returns collection type
179 ///244 ///
184249
185 /// Get collection owner.250 /// Get collection owner.
186 ///251 ///
187 /// @return Tuble with sponsor address and his substrate mirror.252 /// @return Tuple with sponsor address and his substrate mirror.
188 /// If address is canonical then substrate mirror is zero and vice versa.253 /// If address is canonical then substrate mirror is zero and vice versa.
189 /// @dev EVM selector for this function is: 0xdf727d3b,254 /// @dev EVM selector for this function is: 0xdf727d3b,
190 /// or in textual repr: collectionOwner()255 /// or in textual repr: collectionOwner()
198 /// or in textual repr: changeCollectionOwner(address)263 /// or in textual repr: changeCollectionOwner(address)
199 function changeCollectionOwner(address newOwner) external;264 function changeCollectionOwner(address newOwner) external;
265
266 /// Get collection administrators
267 ///
268 /// @return Vector of tuples with admins address and his substrate mirror.
269 /// If address is canonical then substrate mirror is zero and vice versa.
270 /// @dev EVM selector for this function is: 0x5813216b,
271 /// or in textual repr: collectionAdmins()
272 function collectionAdmins() external view returns (Tuple6[] memory);
273
274 /// Changes collection owner to another account
275 ///
276 /// @dev Owner can be changed only by current owner
277 /// @param newOwner new owner cross account
278 /// @dev EVM selector for this function is: 0xe5c9913f,
279 /// or in textual repr: setOwnerCross((address,uint256))
280 function setOwnerCross(Tuple6 memory newOwner) external;
200}281}
282
283/// @dev anonymous struct
284struct Tuple10 {
285 string field_0;
286 bytes field_1;
287}
201288
202/// @dev the ERC-165 identifier for this interface is 0x63034ac5289/// @dev the ERC-165 identifier for this interface is 0x032e5926
203interface ERC20UniqueExtensions is Dummy, ERC165 {290interface ERC20UniqueExtensions is Dummy, ERC165 {
291 /// @dev EVM selector for this function is: 0x0ecd0ab0,
292 /// or in textual repr: approveCross((address,uint256),uint256)
293 function approveCross(Tuple6 memory spender, uint256 amount) external returns (bool);
294
204 /// Burn tokens from account295 /// Burn tokens from account
205 /// @dev Function that burns an `amount` of the tokens of a given account,296 /// @dev Function that burns an `amount` of the tokens of a given account,
210 /// or in textual repr: burnFrom(address,uint256)301 /// or in textual repr: burnFrom(address,uint256)
211 function burnFrom(address from, uint256 amount) external returns (bool);302 function burnFrom(address from, uint256 amount) external returns (bool);
303
304 /// Burn tokens from account
305 /// @dev Function that burns an `amount` of the tokens of a given account,
306 /// deducting from the sender's allowance for said account.
307 /// @param from The account whose tokens will be burnt.
308 /// @param amount The amount that will be burnt.
309 /// @dev EVM selector for this function is: 0xbb2f5a58,
310 /// or in textual repr: burnFromCross((address,uint256),uint256)
311 function burnFromCross(Tuple6 memory from, uint256 amount) external returns (bool);
212312
213 /// Mint tokens for multiple accounts.313 /// Mint tokens for multiple accounts.
214 /// @param amounts array of pairs of account address and amount314 /// @param amounts array of pairs of account address and amount
215 /// @dev EVM selector for this function is: 0x1acf2d55,315 /// @dev EVM selector for this function is: 0x1acf2d55,
216 /// or in textual repr: mintBulk((address,uint256)[])316 /// or in textual repr: mintBulk((address,uint256)[])
217 function mintBulk(Tuple6[] memory amounts) external returns (bool);317 function mintBulk(Tuple6[] memory amounts) external returns (bool);
318
319 /// @dev EVM selector for this function is: 0xd5cf430b,
320 /// or in textual repr: transferFromCross((address,uint256),(address,uint256),uint256)
321 function transferFromCross(
322 Tuple6 memory from,
323 Tuple6 memory to,
324 uint256 amount
325 ) external returns (bool);
218}326}
219327
220/// @dev anonymous struct328/// @dev anonymous struct
modifiedtests/src/eth/api/UniqueNFT.soldiffbeforeafterboth
13}13}
1414
15/// @title A contract that allows to set and delete token properties and change token property permissions.15/// @title A contract that allows to set and delete token properties and change token property permissions.
16/// @dev the ERC-165 identifier for this interface is 0x4136937716/// @dev the ERC-165 identifier for this interface is 0x55dba919
17interface TokenProperties is Dummy, ERC165 {17interface TokenProperties is Dummy, ERC165 {
18 /// @notice Set permissions for token property.18 /// @notice Set permissions for token property.
19 /// @dev Throws error if `msg.sender` is not admin or owner of the collection.19 /// @dev Throws error if `msg.sender` is not admin or owner of the collection.
43 bytes memory value43 bytes memory value
44 ) external;44 ) external;
45
46 /// @notice Set token properties value.
47 /// @dev Throws error if `msg.sender` has no permission to edit the property.
48 /// @param tokenId ID of the token.
49 /// @param properties settable properties
50 /// @dev EVM selector for this function is: 0x14ed3a6e,
51 /// or in textual repr: setProperties(uint256,(string,bytes)[])
52 function setProperties(uint256 tokenId, Tuple19[] memory properties) external;
4553
46 /// @notice Delete token property value.54 /// @notice Delete token property value.
47 /// @dev Throws error if `msg.sender` has no permission to edit the property.55 /// @dev Throws error if `msg.sender` has no permission to edit the property.
62}70}
6371
64/// @title A contract that allows you to work with collections.72/// @title A contract that allows you to work with collections.
65/// @dev the ERC-165 identifier for this interface is 0x62e2229073/// @dev the ERC-165 identifier for this interface is 0xb3152af3
66interface Collection is Dummy, ERC165 {74interface Collection is Dummy, ERC165 {
67 /// Set collection property.75 /// Set collection property.
68 ///76 ///
72 /// or in textual repr: setCollectionProperty(string,bytes)80 /// or in textual repr: setCollectionProperty(string,bytes)
73 function setCollectionProperty(string memory key, bytes memory value) external;81 function setCollectionProperty(string memory key, bytes memory value) external;
82
83 /// Set collection properties.
84 ///
85 /// @param properties Vector of properties key/value pair.
86 /// @dev EVM selector for this function is: 0x50b26b2a,
87 /// or in textual repr: setCollectionProperties((string,bytes)[])
88 function setCollectionProperties(Tuple19[] memory properties) external;
7489
75 /// Delete collection property.90 /// Delete collection property.
76 ///91 ///
79 /// or in textual repr: deleteCollectionProperty(string)94 /// or in textual repr: deleteCollectionProperty(string)
80 function deleteCollectionProperty(string memory key) external;95 function deleteCollectionProperty(string memory key) external;
96
97 /// Delete collection properties.
98 ///
99 /// @param keys Properties keys.
100 /// @dev EVM selector for this function is: 0xee206ee3,
101 /// or in textual repr: deleteCollectionProperties(string[])
102 function deleteCollectionProperties(string[] memory keys) external;
81103
82 /// Get collection property.104 /// Get collection property.
83 ///105 ///
89 /// or in textual repr: collectionProperty(string)111 /// or in textual repr: collectionProperty(string)
90 function collectionProperty(string memory key) external view returns (bytes memory);112 function collectionProperty(string memory key) external view returns (bytes memory);
113
114 /// Get collection properties.
115 ///
116 /// @param keys Properties keys. Empty keys for all propertyes.
117 /// @return Vector of properties key/value pairs.
118 /// @dev EVM selector for this function is: 0x285fb8e6,
119 /// or in textual repr: collectionProperties(string[])
120 function collectionProperties(string[] memory keys) external view returns (Tuple19[] memory);
91121
92 /// Set the sponsor of the collection.122 /// Set the sponsor of the collection.
93 ///123 ///
98 /// or in textual repr: setCollectionSponsor(address)128 /// or in textual repr: setCollectionSponsor(address)
99 function setCollectionSponsor(address sponsor) external;129 function setCollectionSponsor(address sponsor) external;
130
131 /// Set the sponsor of the collection.
132 ///
133 /// @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.
134 ///
135 /// @param sponsor Cross account address of the sponsor from whose account funds will be debited for operations with the contract.
136 /// @dev EVM selector for this function is: 0x84a1d5a8,
137 /// or in textual repr: setCollectionSponsorCross((address,uint256))
138 function setCollectionSponsorCross(Tuple6 memory sponsor) external;
100139
101 /// Whether there is a pending sponsor.140 /// Whether there is a pending sponsor.
102 /// @dev EVM selector for this function is: 0x058ac185,141 /// @dev EVM selector for this function is: 0x058ac185,
120 /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.159 /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.
121 /// @dev EVM selector for this function is: 0x6ec0a9f1,160 /// @dev EVM selector for this function is: 0x6ec0a9f1,
122 /// or in textual repr: collectionSponsor()161 /// or in textual repr: collectionSponsor()
123 function collectionSponsor() external view returns (Tuple17 memory);162 function collectionSponsor() external view returns (Tuple6 memory);
124163
125 /// Set limits for the collection.164 /// Set limits for the collection.
126 /// @dev Throws error if limit not found.165 /// @dev Throws error if limit not found.
152 /// or in textual repr: contractAddress()191 /// or in textual repr: contractAddress()
153 function contractAddress() external view returns (address);192 function contractAddress() external view returns (address);
193
194 /// Add collection admin.
195 /// @param newAdmin Cross account administrator address.
196 /// @dev EVM selector for this function is: 0x859aa7d6,
197 /// or in textual repr: addCollectionAdminCross((address,uint256))
198 function addCollectionAdminCross(Tuple6 memory newAdmin) external;
199
200 /// Remove collection admin.
201 /// @param admin Cross account administrator address.
202 /// @dev EVM selector for this function is: 0x6c0cd173,
203 /// or in textual repr: removeCollectionAdminCross((address,uint256))
204 function removeCollectionAdminCross(Tuple6 memory admin) external;
154205
155 /// Add collection admin.206 /// Add collection admin.
156 /// @param newAdmin Address of the added administrator.207 /// @param newAdmin Address of the added administrator.
202 /// or in textual repr: addToCollectionAllowList(address)253 /// or in textual repr: addToCollectionAllowList(address)
203 function addToCollectionAllowList(address user) external;254 function addToCollectionAllowList(address user) external;
255
256 /// Add user to allowed list.
257 ///
258 /// @param user User cross account address.
259 /// @dev EVM selector for this function is: 0xa0184a3a,
260 /// or in textual repr: addToCollectionAllowListCross((address,uint256))
261 function addToCollectionAllowListCross(Tuple6 memory user) external;
204262
205 /// Remove the user from the allowed list.263 /// Remove the user from the allowed list.
206 ///264 ///
209 /// or in textual repr: removeFromCollectionAllowList(address)267 /// or in textual repr: removeFromCollectionAllowList(address)
210 function removeFromCollectionAllowList(address user) external;268 function removeFromCollectionAllowList(address user) external;
269
270 /// Remove user from allowed list.
271 ///
272 /// @param user User cross account address.
273 /// @dev EVM selector for this function is: 0x09ba452a,
274 /// or in textual repr: removeFromCollectionAllowListCross((address,uint256))
275 function removeFromCollectionAllowListCross(Tuple6 memory user) external;
211276
212 /// Switch permission for minting.277 /// Switch permission for minting.
213 ///278 ///
224 /// or in textual repr: isOwnerOrAdmin(address)289 /// or in textual repr: isOwnerOrAdmin(address)
225 function isOwnerOrAdmin(address user) external view returns (bool);290 function isOwnerOrAdmin(address user) external view returns (bool);
291
292 /// Check that account is the owner or admin of the collection
293 ///
294 /// @param user User cross account to verify
295 /// @return "true" if account is the owner or admin
296 /// @dev EVM selector for this function is: 0x3e75a905,
297 /// or in textual repr: isOwnerOrAdminCross((address,uint256))
298 function isOwnerOrAdminCross(Tuple6 memory user) external view returns (bool);
226299
227 /// Returns collection type300 /// Returns collection type
228 ///301 ///
233306
234 /// Get collection owner.307 /// Get collection owner.
235 ///308 ///
236 /// @return Tuble with sponsor address and his substrate mirror.309 /// @return Tuple with sponsor address and his substrate mirror.
237 /// If address is canonical then substrate mirror is zero and vice versa.310 /// If address is canonical then substrate mirror is zero and vice versa.
238 /// @dev EVM selector for this function is: 0xdf727d3b,311 /// @dev EVM selector for this function is: 0xdf727d3b,
239 /// or in textual repr: collectionOwner()312 /// or in textual repr: collectionOwner()
240 function collectionOwner() external view returns (Tuple17 memory);313 function collectionOwner() external view returns (Tuple6 memory);
241314
242 /// Changes collection owner to another account315 /// Changes collection owner to another account
243 ///316 ///
247 /// or in textual repr: changeCollectionOwner(address)320 /// or in textual repr: changeCollectionOwner(address)
248 function changeCollectionOwner(address newOwner) external;321 function changeCollectionOwner(address newOwner) external;
322
323 /// Get collection administrators
324 ///
325 /// @return Vector of tuples with admins address and his substrate mirror.
326 /// If address is canonical then substrate mirror is zero and vice versa.
327 /// @dev EVM selector for this function is: 0x5813216b,
328 /// or in textual repr: collectionAdmins()
329 function collectionAdmins() external view returns (Tuple6[] memory);
330
331 /// Changes collection owner to another account
332 ///
333 /// @dev Owner can be changed only by current owner
334 /// @param newOwner new owner cross account
335 /// @dev EVM selector for this function is: 0xe5c9913f,
336 /// or in textual repr: setOwnerCross((address,uint256))
337 function setOwnerCross(Tuple6 memory newOwner) external;
249}338}
250339
251/// @dev anonymous struct340/// @dev anonymous struct
252struct Tuple17 {341struct Tuple19 {
253 address field_0;342 string field_0;
254 uint256 field_1;343 bytes field_1;
255}344}
256345
257/// @title ERC-721 Non-Fungible Token Standard, optional metadata extension346/// @title ERC-721 Non-Fungible Token Standard, optional metadata extension
349}438}
350439
351/// @title Unique extensions for ERC721.440/// @title Unique extensions for ERC721.
352/// @dev the ERC-165 identifier for this interface is 0x4468500d441/// @dev the ERC-165 identifier for this interface is 0x244543ee
353interface ERC721UniqueExtensions is Dummy, ERC165 {442interface ERC721UniqueExtensions is Dummy, ERC165 {
354 /// @notice A descriptive name for a collection of NFTs in this contract443 /// @notice A descriptive name for a collection of NFTs in this contract
355 /// @dev EVM selector for this function is: 0x06fdde03,444 /// @dev EVM selector for this function is: 0x06fdde03,
361 /// or in textual repr: symbol()450 /// or in textual repr: symbol()
362 function symbol() external view returns (string memory);451 function symbol() external view returns (string memory);
452
453 /// @notice Set or reaffirm the approved address for an NFT
454 /// @dev The zero address indicates there is no approved address.
455 /// @dev Throws unless `msg.sender` is the current NFT owner, or an authorized
456 /// operator of the current owner.
457 /// @param approved The new substrate address approved NFT controller
458 /// @param tokenId The NFT to approve
459 /// @dev EVM selector for this function is: 0x0ecd0ab0,
460 /// or in textual repr: approveCross((address,uint256),uint256)
461 function approveCross(Tuple6 memory approved, uint256 tokenId) external;
363462
364 /// @notice Transfer ownership of an NFT463 /// @notice Transfer ownership of an NFT
365 /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`464 /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`
370 /// or in textual repr: transfer(address,uint256)469 /// or in textual repr: transfer(address,uint256)
371 function transfer(address to, uint256 tokenId) external;470 function transfer(address to, uint256 tokenId) external;
471
472 /// @notice Transfer ownership of an NFT from cross account address to cross account address
473 /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`
474 /// is the zero address. Throws if `tokenId` is not a valid NFT.
475 /// @param from Cross acccount address of current owner
476 /// @param to Cross acccount address of new owner
477 /// @param tokenId The NFT to transfer
478 /// @dev EVM selector for this function is: 0xd5cf430b,
479 /// or in textual repr: transferFromCross((address,uint256),(address,uint256),uint256)
480 function transferFromCross(
481 Tuple6 memory from,
482 Tuple6 memory to,
483 uint256 tokenId
484 ) external;
372485
373 /// @notice Burns a specific ERC721 token.486 /// @notice Burns a specific ERC721 token.
374 /// @dev Throws unless `msg.sender` is the current owner or an authorized487 /// @dev Throws unless `msg.sender` is the current owner or an authorized
380 /// or in textual repr: burnFrom(address,uint256)493 /// or in textual repr: burnFrom(address,uint256)
381 function burnFrom(address from, uint256 tokenId) external;494 function burnFrom(address from, uint256 tokenId) external;
495
496 /// @notice Burns a specific ERC721 token.
497 /// @dev Throws unless `msg.sender` is the current owner or an authorized
498 /// operator for this NFT. Throws if `from` is not the current owner. Throws
499 /// if `to` is the zero address. Throws if `tokenId` is not a valid NFT.
500 /// @param from The current owner of the NFT
501 /// @param tokenId The NFT to transfer
502 /// @dev EVM selector for this function is: 0xbb2f5a58,
503 /// or in textual repr: burnFromCross((address,uint256),uint256)
504 function burnFromCross(Tuple6 memory from, uint256 tokenId) external;
382505
383 /// @notice Returns next free NFT ID.506 /// @notice Returns next free NFT ID.
384 /// @dev EVM selector for this function is: 0x75794a3c,507 /// @dev EVM selector for this function is: 0x75794a3c,
400 // /// @param tokens array of pairs of token ID and token URI for minted tokens523 // /// @param tokens array of pairs of token ID and token URI for minted tokens
401 // /// @dev EVM selector for this function is: 0x36543006,524 // /// @dev EVM selector for this function is: 0x36543006,
402 // /// or in textual repr: mintBulkWithTokenURI(address,(uint256,string)[])525 // /// or in textual repr: mintBulkWithTokenURI(address,(uint256,string)[])
403 // function mintBulkWithTokenURI(address to, Tuple6[] memory tokens) external returns (bool);526 // function mintBulkWithTokenURI(address to, Tuple8[] memory tokens) external returns (bool);
404527
405}528}
406529
407/// @dev anonymous struct530/// @dev anonymous struct
408struct Tuple6 {531struct Tuple8 {
409 uint256 field_0;532 uint256 field_0;
410 string field_1;533 string field_1;
411}534}
535
536/// @dev anonymous struct
537struct Tuple6 {
538 address field_0;
539 uint256 field_1;
540}
412541
413/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension542/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
414/// @dev See https://eips.ethereum.org/EIPS/eip-721543/// @dev See https://eips.ethereum.org/EIPS/eip-721
modifiedtests/src/eth/api/UniqueRefungible.soldiffbeforeafterboth
13}13}
1414
15/// @title A contract that allows to set and delete token properties and change token property permissions.15/// @title A contract that allows to set and delete token properties and change token property permissions.
16/// @dev the ERC-165 identifier for this interface is 0x4136937716/// @dev the ERC-165 identifier for this interface is 0x55dba919
17interface TokenProperties is Dummy, ERC165 {17interface TokenProperties is Dummy, ERC165 {
18 /// @notice Set permissions for token property.18 /// @notice Set permissions for token property.
19 /// @dev Throws error if `msg.sender` is not admin or owner of the collection.19 /// @dev Throws error if `msg.sender` is not admin or owner of the collection.
43 bytes memory value43 bytes memory value
44 ) external;44 ) external;
45
46 /// @notice Set token properties value.
47 /// @dev Throws error if `msg.sender` has no permission to edit the property.
48 /// @param tokenId ID of the token.
49 /// @param properties settable properties
50 /// @dev EVM selector for this function is: 0x14ed3a6e,
51 /// or in textual repr: setProperties(uint256,(string,bytes)[])
52 function setProperties(uint256 tokenId, Tuple19[] memory properties) external;
4553
46 /// @notice Delete token property value.54 /// @notice Delete token property value.
47 /// @dev Throws error if `msg.sender` has no permission to edit the property.55 /// @dev Throws error if `msg.sender` has no permission to edit the property.
62}70}
6371
64/// @title A contract that allows you to work with collections.72/// @title A contract that allows you to work with collections.
65/// @dev the ERC-165 identifier for this interface is 0x62e2229073/// @dev the ERC-165 identifier for this interface is 0xb3152af3
66interface Collection is Dummy, ERC165 {74interface Collection is Dummy, ERC165 {
67 /// Set collection property.75 /// Set collection property.
68 ///76 ///
72 /// or in textual repr: setCollectionProperty(string,bytes)80 /// or in textual repr: setCollectionProperty(string,bytes)
73 function setCollectionProperty(string memory key, bytes memory value) external;81 function setCollectionProperty(string memory key, bytes memory value) external;
82
83 /// Set collection properties.
84 ///
85 /// @param properties Vector of properties key/value pair.
86 /// @dev EVM selector for this function is: 0x50b26b2a,
87 /// or in textual repr: setCollectionProperties((string,bytes)[])
88 function setCollectionProperties(Tuple19[] memory properties) external;
7489
75 /// Delete collection property.90 /// Delete collection property.
76 ///91 ///
79 /// or in textual repr: deleteCollectionProperty(string)94 /// or in textual repr: deleteCollectionProperty(string)
80 function deleteCollectionProperty(string memory key) external;95 function deleteCollectionProperty(string memory key) external;
96
97 /// Delete collection properties.
98 ///
99 /// @param keys Properties keys.
100 /// @dev EVM selector for this function is: 0xee206ee3,
101 /// or in textual repr: deleteCollectionProperties(string[])
102 function deleteCollectionProperties(string[] memory keys) external;
81103
82 /// Get collection property.104 /// Get collection property.
83 ///105 ///
89 /// or in textual repr: collectionProperty(string)111 /// or in textual repr: collectionProperty(string)
90 function collectionProperty(string memory key) external view returns (bytes memory);112 function collectionProperty(string memory key) external view returns (bytes memory);
113
114 /// Get collection properties.
115 ///
116 /// @param keys Properties keys. Empty keys for all propertyes.
117 /// @return Vector of properties key/value pairs.
118 /// @dev EVM selector for this function is: 0x285fb8e6,
119 /// or in textual repr: collectionProperties(string[])
120 function collectionProperties(string[] memory keys) external view returns (Tuple19[] memory);
91121
92 /// Set the sponsor of the collection.122 /// Set the sponsor of the collection.
93 ///123 ///
98 /// or in textual repr: setCollectionSponsor(address)128 /// or in textual repr: setCollectionSponsor(address)
99 function setCollectionSponsor(address sponsor) external;129 function setCollectionSponsor(address sponsor) external;
130
131 /// Set the sponsor of the collection.
132 ///
133 /// @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.
134 ///
135 /// @param sponsor Cross account address of the sponsor from whose account funds will be debited for operations with the contract.
136 /// @dev EVM selector for this function is: 0x84a1d5a8,
137 /// or in textual repr: setCollectionSponsorCross((address,uint256))
138 function setCollectionSponsorCross(Tuple6 memory sponsor) external;
100139
101 /// Whether there is a pending sponsor.140 /// Whether there is a pending sponsor.
102 /// @dev EVM selector for this function is: 0x058ac185,141 /// @dev EVM selector for this function is: 0x058ac185,
120 /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.159 /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.
121 /// @dev EVM selector for this function is: 0x6ec0a9f1,160 /// @dev EVM selector for this function is: 0x6ec0a9f1,
122 /// or in textual repr: collectionSponsor()161 /// or in textual repr: collectionSponsor()
123 function collectionSponsor() external view returns (Tuple17 memory);162 function collectionSponsor() external view returns (Tuple6 memory);
124163
125 /// Set limits for the collection.164 /// Set limits for the collection.
126 /// @dev Throws error if limit not found.165 /// @dev Throws error if limit not found.
152 /// or in textual repr: contractAddress()191 /// or in textual repr: contractAddress()
153 function contractAddress() external view returns (address);192 function contractAddress() external view returns (address);
193
194 /// Add collection admin.
195 /// @param newAdmin Cross account administrator address.
196 /// @dev EVM selector for this function is: 0x859aa7d6,
197 /// or in textual repr: addCollectionAdminCross((address,uint256))
198 function addCollectionAdminCross(Tuple6 memory newAdmin) external;
199
200 /// Remove collection admin.
201 /// @param admin Cross account administrator address.
202 /// @dev EVM selector for this function is: 0x6c0cd173,
203 /// or in textual repr: removeCollectionAdminCross((address,uint256))
204 function removeCollectionAdminCross(Tuple6 memory admin) external;
154205
155 /// Add collection admin.206 /// Add collection admin.
156 /// @param newAdmin Address of the added administrator.207 /// @param newAdmin Address of the added administrator.
202 /// or in textual repr: addToCollectionAllowList(address)253 /// or in textual repr: addToCollectionAllowList(address)
203 function addToCollectionAllowList(address user) external;254 function addToCollectionAllowList(address user) external;
255
256 /// Add user to allowed list.
257 ///
258 /// @param user User cross account address.
259 /// @dev EVM selector for this function is: 0xa0184a3a,
260 /// or in textual repr: addToCollectionAllowListCross((address,uint256))
261 function addToCollectionAllowListCross(Tuple6 memory user) external;
204262
205 /// Remove the user from the allowed list.263 /// Remove the user from the allowed list.
206 ///264 ///
209 /// or in textual repr: removeFromCollectionAllowList(address)267 /// or in textual repr: removeFromCollectionAllowList(address)
210 function removeFromCollectionAllowList(address user) external;268 function removeFromCollectionAllowList(address user) external;
269
270 /// Remove user from allowed list.
271 ///
272 /// @param user User cross account address.
273 /// @dev EVM selector for this function is: 0x09ba452a,
274 /// or in textual repr: removeFromCollectionAllowListCross((address,uint256))
275 function removeFromCollectionAllowListCross(Tuple6 memory user) external;
211276
212 /// Switch permission for minting.277 /// Switch permission for minting.
213 ///278 ///
224 /// or in textual repr: isOwnerOrAdmin(address)289 /// or in textual repr: isOwnerOrAdmin(address)
225 function isOwnerOrAdmin(address user) external view returns (bool);290 function isOwnerOrAdmin(address user) external view returns (bool);
291
292 /// Check that account is the owner or admin of the collection
293 ///
294 /// @param user User cross account to verify
295 /// @return "true" if account is the owner or admin
296 /// @dev EVM selector for this function is: 0x3e75a905,
297 /// or in textual repr: isOwnerOrAdminCross((address,uint256))
298 function isOwnerOrAdminCross(Tuple6 memory user) external view returns (bool);
226299
227 /// Returns collection type300 /// Returns collection type
228 ///301 ///
233306
234 /// Get collection owner.307 /// Get collection owner.
235 ///308 ///
236 /// @return Tuble with sponsor address and his substrate mirror.309 /// @return Tuple with sponsor address and his substrate mirror.
237 /// If address is canonical then substrate mirror is zero and vice versa.310 /// If address is canonical then substrate mirror is zero and vice versa.
238 /// @dev EVM selector for this function is: 0xdf727d3b,311 /// @dev EVM selector for this function is: 0xdf727d3b,
239 /// or in textual repr: collectionOwner()312 /// or in textual repr: collectionOwner()
240 function collectionOwner() external view returns (Tuple17 memory);313 function collectionOwner() external view returns (Tuple6 memory);
241314
242 /// Changes collection owner to another account315 /// Changes collection owner to another account
243 ///316 ///
247 /// or in textual repr: changeCollectionOwner(address)320 /// or in textual repr: changeCollectionOwner(address)
248 function changeCollectionOwner(address newOwner) external;321 function changeCollectionOwner(address newOwner) external;
322
323 /// Get collection administrators
324 ///
325 /// @return Vector of tuples with admins address and his substrate mirror.
326 /// If address is canonical then substrate mirror is zero and vice versa.
327 /// @dev EVM selector for this function is: 0x5813216b,
328 /// or in textual repr: collectionAdmins()
329 function collectionAdmins() external view returns (Tuple6[] memory);
330
331 /// Changes collection owner to another account
332 ///
333 /// @dev Owner can be changed only by current owner
334 /// @param newOwner new owner cross account
335 /// @dev EVM selector for this function is: 0xe5c9913f,
336 /// or in textual repr: setOwnerCross((address,uint256))
337 function setOwnerCross(Tuple6 memory newOwner) external;
249}338}
250339
251/// @dev anonymous struct340/// @dev anonymous struct
252struct Tuple17 {341struct Tuple19 {
253 address field_0;342 string field_0;
254 uint256 field_1;343 bytes field_1;
255}344}
256345
257/// @dev the ERC-165 identifier for this interface is 0x5b5e139f346/// @dev the ERC-165 identifier for this interface is 0x5b5e139f
347}436}
348437
349/// @title Unique extensions for ERC721.438/// @title Unique extensions for ERC721.
350/// @dev the ERC-165 identifier for this interface is 0xef1eaacb439/// @dev the ERC-165 identifier for this interface is 0x81feb398
351interface ERC721UniqueExtensions is Dummy, ERC165 {440interface ERC721UniqueExtensions is Dummy, ERC165 {
352 /// @notice A descriptive name for a collection of NFTs in this contract441 /// @notice A descriptive name for a collection of NFTs in this contract
353 /// @dev EVM selector for this function is: 0x06fdde03,442 /// @dev EVM selector for this function is: 0x06fdde03,
369 /// or in textual repr: transfer(address,uint256)458 /// or in textual repr: transfer(address,uint256)
370 function transfer(address to, uint256 tokenId) external;459 function transfer(address to, uint256 tokenId) external;
460
461 /// @notice Transfer ownership of an RFT
462 /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`
463 /// is the zero address. Throws if `tokenId` is not a valid RFT.
464 /// Throws if RFT pieces have multiple owners.
465 /// @param to The new owner
466 /// @param tokenId The RFT to transfer
467 /// @dev EVM selector for this function is: 0xd5cf430b,
468 /// or in textual repr: transferFromCross((address,uint256),(address,uint256),uint256)
469 function transferFromCross(
470 Tuple6 memory from,
471 Tuple6 memory to,
472 uint256 tokenId
473 ) external;
371474
372 /// @notice Burns a specific ERC721 token.475 /// @notice Burns a specific ERC721 token.
373 /// @dev Throws unless `msg.sender` is the current owner or an authorized476 /// @dev Throws unless `msg.sender` is the current owner or an authorized
380 /// or in textual repr: burnFrom(address,uint256)483 /// or in textual repr: burnFrom(address,uint256)
381 function burnFrom(address from, uint256 tokenId) external;484 function burnFrom(address from, uint256 tokenId) external;
485
486 /// @notice Burns a specific ERC721 token.
487 /// @dev Throws unless `msg.sender` is the current owner or an authorized
488 /// operator for this RFT. Throws if `from` is not the current owner. Throws
489 /// if `to` is the zero address. Throws if `tokenId` is not a valid RFT.
490 /// Throws if RFT pieces have multiple owners.
491 /// @param from The current owner of the RFT
492 /// @param tokenId The RFT to transfer
493 /// @dev EVM selector for this function is: 0xbb2f5a58,
494 /// or in textual repr: burnFromCross((address,uint256),uint256)
495 function burnFromCross(Tuple6 memory from, uint256 tokenId) external;
382496
383 /// @notice Returns next free RFT ID.497 /// @notice Returns next free RFT ID.
384 /// @dev EVM selector for this function is: 0x75794a3c,498 /// @dev EVM selector for this function is: 0x75794a3c,
401 // /// @param tokens array of pairs of token ID and token URI for minted tokens515 // /// @param tokens array of pairs of token ID and token URI for minted tokens
402 // /// @dev EVM selector for this function is: 0x36543006,516 // /// @dev EVM selector for this function is: 0x36543006,
403 // /// or in textual repr: mintBulkWithTokenURI(address,(uint256,string)[])517 // /// or in textual repr: mintBulkWithTokenURI(address,(uint256,string)[])
404 // function mintBulkWithTokenURI(address to, Tuple6[] memory tokens) external returns (bool);518 // function mintBulkWithTokenURI(address to, Tuple8[] memory tokens) external returns (bool);
405519
406 /// Returns EVM address for refungible token520 /// Returns EVM address for refungible token
407 ///521 ///
412}526}
413527
414/// @dev anonymous struct528/// @dev anonymous struct
415struct Tuple6 {529struct Tuple8 {
416 uint256 field_0;530 uint256 field_0;
417 string field_1;531 string field_1;
418}532}
533
534/// @dev anonymous struct
535struct Tuple6 {
536 address field_0;
537 uint256 field_1;
538}
419539
420/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension540/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
421/// @dev See https://eips.ethereum.org/EIPS/eip-721541/// @dev See https://eips.ethereum.org/EIPS/eip-721
modifiedtests/src/eth/base.test.tsdiffbeforeafterboth
116 await checkInterface(helper, '0x780e9d63', true, true);116 await checkInterface(helper, '0x780e9d63', true, true);
117 });117 });
118118
119 itEth('ERC721UniqueExtensions - 0x4468500d - support', async ({helper}) => {119 itEth('ERC721UniqueExtensions - 0x244543ee - support', async ({helper}) => {
120 await checkInterface(helper, '0x4468500d', true, true);120 await checkInterface(helper, '0x244543ee', true, true);
121 });121 });
122122
123 itEth('ERC721Burnable - 0x42966c68 - support', async ({helper}) => {123 itEth('ERC721Burnable - 0x42966c68 - support', async ({helper}) => {
modifiedtests/src/eth/collectionAdmin.test.tsdiffbeforeafterboth
49 .to.be.eq(newAdmin.toLocaleLowerCase());49 .to.be.eq(newAdmin.toLocaleLowerCase());
50 });50 });
5151
52 itEth.skip('Add substrate admin by owner', async ({helper}) => {52 itEth('Add cross account admin by owner', async ({helper, privateKey}) => {
53 const owner = await helper.eth.createAccountWithBalance(donor);53 const owner = await helper.eth.createAccountWithBalance(donor);
54
54 const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');55 const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');
55 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);56 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
5657
58 const newAdmin = await privateKey('//Bob');
57 const [newAdmin] = await helper.arrange.createAccounts([10n], donor);59 const newAdminCross = helper.ethCrossAccount.fromKeyringPair(newAdmin);
58 await collectionEvm.methods.addCollectionAdminSubstrate(newAdmin.addressRaw).send();60 await collectionEvm.methods.addCollectionAdminCross(newAdminCross).send();
5961
60 const adminList = await helper.callRpc('api.rpc.unique.adminlist', [collectionId]);62 const adminList = await helper.collection.getAdmins(collectionId);
61 expect(adminList[0].asSubstrate.toString().toLocaleLowerCase())63 expect(adminList).to.be.like([{Substrate: newAdmin.address}]);
62 .to.be.eq(newAdmin.address.toLocaleLowerCase());
63 });64 });
65
66 // itEth('Check adminlist', async ({helper, privateKey}) => {
67 // const owner = await helper.eth.createAccountWithBalance(donor);
68
69 // const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');
70 // const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
71
72 // const admin1 = helper.eth.createAccount();
73 // const admin2 = await privateKey('admin');
74 // await collectionEvm.methods.addCollectionAdmin(admin1).send();
75 // await collectionEvm.methods.addCollectionAdminCross(helper.ethCrossAccount.fromKeyringPair(admin2)).send();
76
77 // const adminListRpc = await helper.collection.getAdmins(collectionId);
78 // let adminListEth = await collectionEvm.methods.collectionAdmins().call();
79 // adminListEth = adminListEth.map((element: IEthCrossAccountId) => {
80 // return helper.address.convertCrossAccountFromEthCrossAcoount(element);
81 // });
82 // expect(adminListRpc).to.be.like(adminListEth);
83 // });
6484
65 itEth('Verify owner or admin', async ({helper}) => {85 itEth('Verify owner or admin', async ({helper}) => {
66 const owner = await helper.eth.createAccountWithBalance(donor);86 const owner = await helper.eth.createAccountWithBalance(donor);
73 expect(await collectionEvm.methods.isOwnerOrAdmin(newAdmin).call()).to.be.true;94 expect(await collectionEvm.methods.isOwnerOrAdmin(newAdmin).call()).to.be.true;
74 });95 });
7596
97 // itEth.skip('Check adminlist', async ({helper, privateKey}) => {
98 // const owner = await helper.eth.createAccountWithBalance(donor);
99
100 // const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');
101 // const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
102
103 // const admin1 = helper.eth.createAccount();
104 // const admin2 = await privateKey('admin');
105 // await collectionEvm.methods.addCollectionAdmin(admin1).send();
106 // await collectionEvm.methods.addCollectionAdminSubstrate(admin2.addressRaw).send();
107
108 // const adminListRpc = await helper.collection.getAdmins(collectionId);
109 // let adminListEth = await collectionEvm.methods.collectionAdmins().call();
110 // adminListEth = adminListEth.map((element: IEthCrossAccountId) => {
111 // return helper.address.convertCrossAccountFromEthCrossAcoount(element);
112 // });
113 // expect(adminListRpc).to.be.like(adminListEth);
114 // });
115
76 itEth('(!negative tests!) Add admin by ADMIN is not allowed', async ({helper}) => {116 itEth('(!negative tests!) Add admin by ADMIN is not allowed', async ({helper}) => {
77 const owner = await helper.eth.createAccountWithBalance(donor);117 const owner = await helper.eth.createAccountWithBalance(donor);
modifiedtests/src/eth/collectionHelpersAbi.jsondiffbeforeafterboth
18 "name": "CollectionCreated",18 "name": "CollectionCreated",
19 "type": "event"19 "type": "event"
20 },20 },
21 {
22 "anonymous": false,
23 "inputs": [
24 {
25 "indexed": true,
26 "internalType": "address",
27 "name": "collectionId",
28 "type": "address"
29 }
30 ],
31 "name": "CollectionDestroyed",
32 "type": "event"
33 },
21 {34 {
22 "inputs": [],35 "inputs": [],
23 "name": "collectionCreationFee",36 "name": "collectionCreationFee",
24 "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],37 "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
25 "stateMutability": "view",38 "stateMutability": "view",
26 "type": "function"39 "type": "function"
27 },40 },
41 {
42 "inputs": [
43 { "internalType": "string", "name": "name", "type": "string" },
44 { "internalType": "uint8", "name": "decimals", "type": "uint8" },
45 { "internalType": "string", "name": "description", "type": "string" },
46 { "internalType": "string", "name": "tokenPrefix", "type": "string" }
47 ],
48 "name": "createFTCollection",
49 "outputs": [{ "internalType": "address", "name": "", "type": "address" }],
50 "stateMutability": "payable",
51 "type": "function"
52 },
28 {53 {
29 "inputs": [54 "inputs": [
30 { "internalType": "string", "name": "name", "type": "string" },55 { "internalType": "string", "name": "name", "type": "string" },
47 "stateMutability": "payable",72 "stateMutability": "payable",
48 "type": "function"73 "type": "function"
49 },74 },
75 {
76 "inputs": [
77 {
78 "internalType": "address",
79 "name": "collectionAddress",
80 "type": "address"
81 }
82 ],
83 "name": "destroyCollection",
84 "outputs": [],
85 "stateMutability": "nonpayable",
86 "type": "function"
87 },
50 {88 {
51 "inputs": [89 "inputs": [
52 {90 {
modifiedtests/src/eth/collectionProperties.test.tsdiffbeforeafterboth
18import {Pallets} from '../util';18import {Pallets} from '../util';
19import {IProperty, ITokenPropertyPermission} from '../util/playgrounds/types';19import {IProperty, ITokenPropertyPermission} from '../util/playgrounds/types';
20import {IKeyringPair} from '@polkadot/types/types';20import {IKeyringPair} from '@polkadot/types/types';
21import {TCollectionMode} from '../util/playgrounds/types';
2122
22describe('EVM collection properties', () => {23describe('EVM collection properties', () => {
23 let donor: IKeyringPair;24 let donor: IKeyringPair;
162 });163 });
163});164});
165
166describe('EVM collection property', () => {
167 let donor: IKeyringPair;
168
169 before(async function() {
170 await usingEthPlaygrounds(async (_helper, privateKey) => {
171 donor = await privateKey({filename: __filename});
172 });
173 });
174
175 async function testSetReadProperties(helper: EthUniqueHelper, mode: TCollectionMode) {
176 const collection = await helper[mode].mintCollection(donor, {name: 'A', description: 'B', tokenPrefix: 'C'});
177
178 const sender = await helper.eth.createAccountWithBalance(donor, 100n);
179 await collection.addAdmin(donor, {Ethereum: sender});
180
181 const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);
182 const contract = helper.ethNativeContract.collection(collectionAddress, mode, sender);
183
184 const keys = ['key0', 'key1'];
185
186 const writeProperties = [
187 helper.ethProperty.property(keys[0], 'value0'),
188 helper.ethProperty.property(keys[1], 'value1'),
189 ];
190
191 await contract.methods.setCollectionProperties(writeProperties).send();
192 const readProperties = await contract.methods.collectionProperties([keys[0], keys[1]]).call();
193 expect(readProperties).to.be.like(writeProperties);
194 }
195
196 itEth('Set/read properties ft', async ({helper}) => {
197 await testSetReadProperties(helper, 'ft');
198 });
199 itEth.ifWithPallets('Set/read properties rft', [Pallets.ReFungible], async ({helper}) => {
200 await testSetReadProperties(helper, 'rft');
201 });
202 itEth('Set/read properties nft', async ({helper}) => {
203 await testSetReadProperties(helper, 'nft');
204 });
205
206 async function testDeleteProperties(helper: EthUniqueHelper, mode: TCollectionMode) {
207 const collection = await helper[mode].mintCollection(donor, {name: 'A', description: 'B', tokenPrefix: 'C'});
208
209 const sender = await helper.eth.createAccountWithBalance(donor, 100n);
210 await collection.addAdmin(donor, {Ethereum: sender});
211
212 const collectionAddress = helper.ethAddress.fromCollectionId(collection.collectionId);
213 const contract = helper.ethNativeContract.collection(collectionAddress, mode, sender);
214
215 const keys = ['key0', 'key1', 'key2', 'key3'];
216
217 {
218 const writeProperties = [
219 helper.ethProperty.property(keys[0], 'value0'),
220 helper.ethProperty.property(keys[1], 'value1'),
221 helper.ethProperty.property(keys[2], 'value2'),
222 helper.ethProperty.property(keys[3], 'value3'),
223 ];
224
225 await contract.methods.setCollectionProperties(writeProperties).send();
226 const readProperties = await contract.methods.collectionProperties([keys[0], keys[1], keys[2], keys[3]]).call();
227 expect(readProperties).to.be.like(writeProperties);
228 }
229
230 {
231 const expectProperties = [
232 helper.ethProperty.property(keys[0], 'value0'),
233 helper.ethProperty.property(keys[1], 'value1'),
234 ];
235
236 await contract.methods.deleteCollectionProperties([keys[2], keys[3]]).send();
237 const readProperties = await contract.methods.collectionProperties([]).call();
238 expect(readProperties).to.be.like(expectProperties);
239 }
240 }
241
242 itEth('Delete properties ft', async ({helper}) => {
243 await testDeleteProperties(helper, 'ft');
244 });
245 itEth.ifWithPallets('Delete properties rft', [Pallets.ReFungible], async ({helper}) => {
246 await testDeleteProperties(helper, 'rft');
247 });
248 itEth('Delete properties nft', async ({helper}) => {
249 await testDeleteProperties(helper, 'nft');
250 });
251
252});
164253
addedtests/src/eth/createFTCollection.test.tsdiffbeforeafterboth

no changes

modifiedtests/src/eth/createNFTCollection.test.tsdiffbeforeafterboth
35 const description = 'Some description';35 const description = 'Some description';
36 const prefix = 'token prefix';36 const prefix = 'token prefix';
3737
38 // todo:playgrounds this might fail when in async environment.
39 const collectionCountBefore = +(await helper.callRpc('api.rpc.unique.collectionStats')).created;
38 const {collectionId} = await helper.eth.createNFTCollection(owner, name, description, prefix);40 const {collectionId, collectionAddress, events} = await helper.eth.createNFTCollection(owner, name, description, prefix);
41
42 expect(events).to.be.deep.equal([
43 {
44 address: '0x6C4E9fE1AE37a41E93CEE429e8E1881aBdcbb54F',
45 event: 'CollectionCreated',
46 args: {
47 owner: owner,
48 collectionId: collectionAddress,
49 },
50 },
51 ]);
52
39 const data = (await helper.rft.getData(collectionId))!;53 const collectionCountAfter = +(await helper.callRpc('api.rpc.unique.collectionStats')).created;
54
40 const collection = helper.nft.getCollectionObject(collectionId);55 const collection = helper.nft.getCollectionObject(collectionId);
41 56 const data = (await collection.getData())!;
57
58 expect(collectionCountAfter - collectionCountBefore).to.be.eq(1);
59 expect(collectionId).to.be.eq(collectionCountAfter);
42 expect(data.name).to.be.eq(name);60 expect(data.name).to.be.eq(name);
43 expect(data.description).to.be.eq(description);61 expect(data.description).to.be.eq(description);
44 expect(data.raw.tokenPrefix).to.be.eq(prefix);62 expect(data.raw.tokenPrefix).to.be.eq(prefix);
57 const prefix = 'token prefix';75 const prefix = 'token prefix';
58 const baseUri = 'BaseURI';76 const baseUri = 'BaseURI';
5977
60 const {collectionId} = await helper.eth.createERC721MetadataCompatibleNFTCollection(owner, name, description, prefix, baseUri);78 const {collectionId, collectionAddress, events} = await helper.eth.createERC721MetadataCompatibleNFTCollection(owner, name, description, prefix, baseUri);
79
80 expect(events).to.be.deep.equal([
81 {
82 address: '0x6C4E9fE1AE37a41E93CEE429e8E1881aBdcbb54F',
83 event: 'CollectionCreated',
84 args: {
85 owner: owner,
86 collectionId: collectionAddress,
87 },
88 },
89 ]);
6190
62 const collection = helper.nft.getCollectionObject(collectionId);91 const collection = helper.nft.getCollectionObject(collectionId);
63 const data = (await collection.getData())!;92 const data = (await collection.getData())!;
260 .call()).to.be.rejectedWith('unknown boolean limit "badLimit"');289 .call()).to.be.rejectedWith('unknown boolean limit "badLimit"');
261 });290 });
291
292 itEth('destroyCollection', async ({helper}) => {
293 const owner = await helper.eth.createAccountWithBalance(donor);
294 const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'Limits', 'absolutely anything', 'OLF');
295 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);
296
297
298 const result = await collectionHelper.methods
299 .destroyCollection(collectionAddress)
300 .send({from: owner});
301
302 const events = helper.eth.normalizeEvents(result.events);
303
304 expect(events).to.be.deep.equal([
305 {
306 address: collectionHelper.options.address,
307 event: 'CollectionDestroyed',
308 args: {
309 collectionId: collectionAddress,
310 },
311 },
312 ]);
313
314 expect(await collectionHelper.methods
315 .isCollectionExist(collectionAddress)
316 .call()).to.be.false;
317 });
262});318});
263
modifiedtests/src/eth/createRFTCollection.test.tsdiffbeforeafterboth
264 .call()).to.be.rejectedWith('unknown boolean limit "badLimit"');264 .call()).to.be.rejectedWith('unknown boolean limit "badLimit"');
265 });265 });
266
267 itEth('destroyCollection', async ({helper}) => {
268 const owner = await helper.eth.createAccountWithBalance(donor);
269 const {collectionAddress} = await helper.eth.createRFTCollection(owner, 'Limits', 'absolutely anything', 'OLF');
270 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);
271
272 await expect(collectionHelper.methods
273 .destroyCollection(collectionAddress)
274 .send({from: owner})).to.be.fulfilled;
275
276 expect(await collectionHelper.methods
277 .isCollectionExist(collectionAddress)
278 .call()).to.be.false;
279 });
266});280});
267281
addedtests/src/eth/destroyCollection.test.tsdiffbeforeafterboth

no changes

modifiedtests/src/eth/fractionalizer/Fractionalizer.soldiffbeforeafterboth

no syntactic changes

modifiedtests/src/eth/fungible.test.tsdiffbeforeafterboth
148 }148 }
149 });149 });
150
151 itEth('Can perform burnFromCross()', async ({helper, privateKey}) => {
152 const alice = await privateKey('//Alice');
153 const sender = await helper.eth.createAccountWithBalance(alice, 100n);
154
155 const collection = await helper.ft.mintCollection(alice, {name: 'A', description: 'B', tokenPrefix: 'C'}, 0);
156
157 await collection.mint(alice, 200n, {Substrate: alice.address});
158 await collection.approveTokens(alice, {Ethereum: sender}, 100n);
159
160 const address = helper.ethAddress.fromCollectionId(collection.collectionId);
161 const contract = helper.ethNativeContract.collection(address, 'ft');
162
163 const fromBalanceBefore = await collection.getBalance({Substrate: alice.address});
164
165 const ownerCross = helper.ethCrossAccount.fromKeyringPair(alice);
166 const result = await contract.methods.burnFromCross(ownerCross, 49).send({from: sender});
167 const events = result.events;
168
169 expect(events).to.be.like({
170 Transfer: {
171 address: helper.ethAddress.fromCollectionId(collection.collectionId),
172 event: 'Transfer',
173 returnValues: {
174 from: helper.address.substrateToEth(alice.address),
175 to: '0x0000000000000000000000000000000000000000',
176 value: '49',
177 },
178 },
179 Approval: {
180 address: helper.ethAddress.fromCollectionId(collection.collectionId),
181 returnValues: {
182 owner: helper.address.substrateToEth(alice.address),
183 spender: sender,
184 value: '51',
185 },
186 event: 'Approval',
187 },
188 });
189
190 const fromBalanceAfter = await collection.getBalance({Substrate: alice.address});
191 expect(fromBalanceBefore - fromBalanceAfter).to.be.eq(49n);
192 });
150193
151 itEth('Can perform transferFrom()', async ({helper}) => {194 itEth('Can perform transferFrom()', async ({helper}) => {
152 const owner = await helper.eth.createAccountWithBalance(donor);195 const owner = await helper.eth.createAccountWithBalance(donor);
217 }260 }
218 });261 });
262
263 itEth('Can perform transferFromCross()', async ({helper, privateKey}) => {
264 const alice = await privateKey('//Alice');
265 const sender = await helper.eth.createAccountWithBalance(alice, 100n);
266
267 const collection = await helper.ft.mintCollection(alice, {name: 'A', description: 'B', tokenPrefix: 'C'}, 0);
268
269 const receiver = helper.eth.createAccount();
270
271 await collection.mint(alice, 200n, {Substrate: alice.address});
272 await collection.approveTokens(alice, {Ethereum: sender}, 100n);
273
274 const address = helper.ethAddress.fromCollectionId(collection.collectionId);
275 const contract = helper.ethNativeContract.collection(address, 'ft');
276
277 const from = helper.ethCrossAccount.fromKeyringPair(alice);
278 const to = helper.ethCrossAccount.fromAddress(receiver);
279
280 const fromBalanceBefore = await collection.getBalance({Substrate: alice.address});
281 const toBalanceBefore = await collection.getBalance({Ethereum: receiver});
282
283 const result = await contract.methods.transferFromCross(from, to, 51).send({from: sender});
284
285 expect(result.events).to.be.like({
286 Transfer: {
287 address,
288 event: 'Transfer',
289 returnValues: {
290 from: helper.address.substrateToEth(alice.address),
291 to: receiver,
292 value: '51',
293 },
294 },
295 Approval: {
296 address,
297 event: 'Approval',
298 returnValues: {
299 owner: helper.address.substrateToEth(alice.address),
300 spender: sender,
301 value: '49',
302 },
303 }});
304
305 const fromBalanceAfter = await collection.getBalance({Substrate: alice.address});
306 expect(fromBalanceBefore - fromBalanceAfter).to.be.eq(51n);
307 const toBalanceAfter = await collection.getBalance({Ethereum: receiver});
308 expect(toBalanceAfter - toBalanceBefore).to.be.eq(51n);
309 });
219});310});
220311
221describe('Fungible: Fees', () => {312describe('Fungible: Fees', () => {
363 expect(event.returnValues.value).to.be.equal('51');454 expect(event.returnValues.value).to.be.equal('51');
364 });455 });
456
457 itEth('Events emitted for transferFromCross()', async ({helper, privateKey}) => {
458 const alice = await privateKey('//Alice');
459 const sender = await helper.eth.createAccountWithBalance(alice, 100n);
460
461 const collection = await helper.ft.mintCollection(alice, {name: 'A', description: 'B', tokenPrefix: 'C'}, 0);
462
463 const receiver = helper.eth.createAccount();
464
465 await collection.mint(alice, 200n, {Substrate: alice.address});
466 await collection.approveTokens(alice, {Ethereum: sender}, 100n);
467
468 const address = helper.ethAddress.fromCollectionId(collection.collectionId);
469 const contract = helper.ethNativeContract.collection(address, 'ft');
470
471 const from = helper.ethCrossAccount.fromKeyringPair(alice);
472 const to = helper.ethCrossAccount.fromAddress(receiver);
473
474 const result = await contract.methods.transferFromCross(from, to, 51).send({from: sender});
475
476 expect(result.events).to.be.like({
477 Transfer: {
478 address,
479 event: 'Transfer',
480 returnValues: {
481 from: helper.address.substrateToEth(alice.address),
482 to: receiver,
483 value: '51',
484 },
485 },
486 Approval: {
487 address,
488 event: 'Approval',
489 returnValues: {
490 owner: helper.address.substrateToEth(alice.address),
491 spender: sender,
492 value: '49',
493 },
494 }});
495 });
365});496});
366497
modifiedtests/src/eth/fungibleAbi.jsondiffbeforeafterboth
58 "stateMutability": "nonpayable",58 "stateMutability": "nonpayable",
59 "type": "function"59 "type": "function"
60 },60 },
61 {
62 "inputs": [
63 {
64 "components": [
65 { "internalType": "address", "name": "field_0", "type": "address" },
66 { "internalType": "uint256", "name": "field_1", "type": "uint256" }
67 ],
68 "internalType": "struct Tuple6",
69 "name": "newAdmin",
70 "type": "tuple"
71 }
72 ],
73 "name": "addCollectionAdminCross",
74 "outputs": [],
75 "stateMutability": "nonpayable",
76 "type": "function"
77 },
61 {78 {
62 "inputs": [79 "inputs": [
63 { "internalType": "address", "name": "user", "type": "address" }80 { "internalType": "address", "name": "user", "type": "address" }
67 "stateMutability": "nonpayable",84 "stateMutability": "nonpayable",
68 "type": "function"85 "type": "function"
69 },86 },
87 {
88 "inputs": [
89 {
90 "components": [
91 { "internalType": "address", "name": "field_0", "type": "address" },
92 { "internalType": "uint256", "name": "field_1", "type": "uint256" }
93 ],
94 "internalType": "struct Tuple6",
95 "name": "user",
96 "type": "tuple"
97 }
98 ],
99 "name": "addToCollectionAllowListCross",
100 "outputs": [],
101 "stateMutability": "nonpayable",
102 "type": "function"
103 },
70 {104 {
71 "inputs": [105 "inputs": [
72 { "internalType": "address", "name": "owner", "type": "address" },106 { "internalType": "address", "name": "owner", "type": "address" },
96 "stateMutability": "nonpayable",130 "stateMutability": "nonpayable",
97 "type": "function"131 "type": "function"
98 },132 },
133 {
134 "inputs": [
135 {
136 "components": [
137 { "internalType": "address", "name": "field_0", "type": "address" },
138 { "internalType": "uint256", "name": "field_1", "type": "uint256" }
139 ],
140 "internalType": "struct Tuple6",
141 "name": "spender",
142 "type": "tuple"
143 },
144 { "internalType": "uint256", "name": "amount", "type": "uint256" }
145 ],
146 "name": "approveCross",
147 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
148 "stateMutability": "nonpayable",
149 "type": "function"
150 },
99 {151 {
100 "inputs": [152 "inputs": [
101 { "internalType": "address", "name": "owner", "type": "address" }153 { "internalType": "address", "name": "owner", "type": "address" }
115 "stateMutability": "nonpayable",167 "stateMutability": "nonpayable",
116 "type": "function"168 "type": "function"
117 },169 },
170 {
171 "inputs": [
172 {
173 "components": [
174 { "internalType": "address", "name": "field_0", "type": "address" },
175 { "internalType": "uint256", "name": "field_1", "type": "uint256" }
176 ],
177 "internalType": "struct Tuple6",
178 "name": "from",
179 "type": "tuple"
180 },
181 { "internalType": "uint256", "name": "amount", "type": "uint256" }
182 ],
183 "name": "burnFromCross",
184 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
185 "stateMutability": "nonpayable",
186 "type": "function"
187 },
118 {188 {
119 "inputs": [189 "inputs": [
120 { "internalType": "address", "name": "newOwner", "type": "address" }190 { "internalType": "address", "name": "newOwner", "type": "address" }
124 "stateMutability": "nonpayable",194 "stateMutability": "nonpayable",
125 "type": "function"195 "type": "function"
126 },196 },
197 {
198 "inputs": [],
199 "name": "collectionAdmins",
200 "outputs": [
201 {
202 "components": [
203 { "internalType": "address", "name": "field_0", "type": "address" },
204 { "internalType": "uint256", "name": "field_1", "type": "uint256" }
205 ],
206 "internalType": "struct Tuple6[]",
207 "name": "",
208 "type": "tuple[]"
209 }
210 ],
211 "stateMutability": "view",
212 "type": "function"
213 },
127 {214 {
128 "inputs": [],215 "inputs": [],
129 "name": "collectionOwner",216 "name": "collectionOwner",
141 "stateMutability": "view",228 "stateMutability": "view",
142 "type": "function"229 "type": "function"
143 },230 },
231 {
232 "inputs": [
233 { "internalType": "string[]", "name": "keys", "type": "string[]" }
234 ],
235 "name": "collectionProperties",
236 "outputs": [
237 {
238 "components": [
239 { "internalType": "string", "name": "field_0", "type": "string" },
240 { "internalType": "bytes", "name": "field_1", "type": "bytes" }
241 ],
242 "internalType": "struct Tuple10[]",
243 "name": "",
244 "type": "tuple[]"
245 }
246 ],
247 "stateMutability": "view",
248 "type": "function"
249 },
144 {250 {
145 "inputs": [{ "internalType": "string", "name": "key", "type": "string" }],251 "inputs": [{ "internalType": "string", "name": "key", "type": "string" }],
146 "name": "collectionProperty",252 "name": "collectionProperty",
186 "stateMutability": "view",292 "stateMutability": "view",
187 "type": "function"293 "type": "function"
188 },294 },
295 {
296 "inputs": [
297 { "internalType": "string[]", "name": "keys", "type": "string[]" }
298 ],
299 "name": "deleteCollectionProperties",
300 "outputs": [],
301 "stateMutability": "nonpayable",
302 "type": "function"
303 },
189 {304 {
190 "inputs": [{ "internalType": "string", "name": "key", "type": "string" }],305 "inputs": [{ "internalType": "string", "name": "key", "type": "string" }],
191 "name": "deleteCollectionProperty",306 "name": "deleteCollectionProperty",
209 "stateMutability": "view",324 "stateMutability": "view",
210 "type": "function"325 "type": "function"
211 },326 },
327 {
328 "inputs": [
329 {
330 "components": [
331 { "internalType": "address", "name": "field_0", "type": "address" },
332 { "internalType": "uint256", "name": "field_1", "type": "uint256" }
333 ],
334 "internalType": "struct Tuple6",
335 "name": "user",
336 "type": "tuple"
337 }
338 ],
339 "name": "isOwnerOrAdminCross",
340 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
341 "stateMutability": "view",
342 "type": "function"
343 },
212 {344 {
213 "inputs": [345 "inputs": [
214 { "internalType": "address", "name": "to", "type": "address" },346 { "internalType": "address", "name": "to", "type": "address" },
252 "stateMutability": "nonpayable",384 "stateMutability": "nonpayable",
253 "type": "function"385 "type": "function"
254 },386 },
387 {
388 "inputs": [
389 {
390 "components": [
391 { "internalType": "address", "name": "field_0", "type": "address" },
392 { "internalType": "uint256", "name": "field_1", "type": "uint256" }
393 ],
394 "internalType": "struct Tuple6",
395 "name": "admin",
396 "type": "tuple"
397 }
398 ],
399 "name": "removeCollectionAdminCross",
400 "outputs": [],
401 "stateMutability": "nonpayable",
402 "type": "function"
403 },
255 {404 {
256 "inputs": [],405 "inputs": [],
257 "name": "removeCollectionSponsor",406 "name": "removeCollectionSponsor",
268 "stateMutability": "nonpayable",417 "stateMutability": "nonpayable",
269 "type": "function"418 "type": "function"
270 },419 },
420 {
421 "inputs": [
422 {
423 "components": [
424 { "internalType": "address", "name": "field_0", "type": "address" },
425 { "internalType": "uint256", "name": "field_1", "type": "uint256" }
426 ],
427 "internalType": "struct Tuple6",
428 "name": "user",
429 "type": "tuple"
430 }
431 ],
432 "name": "removeFromCollectionAllowListCross",
433 "outputs": [],
434 "stateMutability": "nonpayable",
435 "type": "function"
436 },
271 {437 {
272 "inputs": [{ "internalType": "uint8", "name": "mode", "type": "uint8" }],438 "inputs": [{ "internalType": "uint8", "name": "mode", "type": "uint8" }],
273 "name": "setCollectionAccess",439 "name": "setCollectionAccess",
323 "stateMutability": "nonpayable",489 "stateMutability": "nonpayable",
324 "type": "function"490 "type": "function"
325 },491 },
492 {
493 "inputs": [
494 {
495 "components": [
496 { "internalType": "string", "name": "field_0", "type": "string" },
497 { "internalType": "bytes", "name": "field_1", "type": "bytes" }
498 ],
499 "internalType": "struct Tuple10[]",
500 "name": "properties",
501 "type": "tuple[]"
502 }
503 ],
504 "name": "setCollectionProperties",
505 "outputs": [],
506 "stateMutability": "nonpayable",
507 "type": "function"
508 },
326 {509 {
327 "inputs": [510 "inputs": [
328 { "internalType": "string", "name": "key", "type": "string" },511 { "internalType": "string", "name": "key", "type": "string" },
342 "stateMutability": "nonpayable",525 "stateMutability": "nonpayable",
343 "type": "function"526 "type": "function"
344 },527 },
528 {
529 "inputs": [
530 {
531 "components": [
532 { "internalType": "address", "name": "field_0", "type": "address" },
533 { "internalType": "uint256", "name": "field_1", "type": "uint256" }
534 ],
535 "internalType": "struct Tuple6",
536 "name": "sponsor",
537 "type": "tuple"
538 }
539 ],
540 "name": "setCollectionSponsorCross",
541 "outputs": [],
542 "stateMutability": "nonpayable",
543 "type": "function"
544 },
545 {
546 "inputs": [
547 {
548 "components": [
549 { "internalType": "address", "name": "field_0", "type": "address" },
550 { "internalType": "uint256", "name": "field_1", "type": "uint256" }
551 ],
552 "internalType": "struct Tuple6",
553 "name": "newOwner",
554 "type": "tuple"
555 }
556 ],
557 "name": "setOwnerCross",
558 "outputs": [],
559 "stateMutability": "nonpayable",
560 "type": "function"
561 },
345 {562 {
346 "inputs": [563 "inputs": [
347 { "internalType": "bytes4", "name": "interfaceID", "type": "bytes4" }564 { "internalType": "bytes4", "name": "interfaceID", "type": "bytes4" }
386 "stateMutability": "nonpayable",603 "stateMutability": "nonpayable",
387 "type": "function"604 "type": "function"
388 },605 },
606 {
607 "inputs": [
608 {
609 "components": [
610 { "internalType": "address", "name": "field_0", "type": "address" },
611 { "internalType": "uint256", "name": "field_1", "type": "uint256" }
612 ],
613 "internalType": "struct Tuple6",
614 "name": "from",
615 "type": "tuple"
616 },
617 {
618 "components": [
619 { "internalType": "address", "name": "field_0", "type": "address" },
620 { "internalType": "uint256", "name": "field_1", "type": "uint256" }
621 ],
622 "internalType": "struct Tuple6",
623 "name": "to",
624 "type": "tuple"
625 },
626 { "internalType": "uint256", "name": "amount", "type": "uint256" }
627 ],
628 "name": "transferFromCross",
629 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
630 "stateMutability": "nonpayable",
631 "type": "function"
632 },
389 {633 {
390 "inputs": [],634 "inputs": [],
391 "name": "uniqueCollectionType",635 "name": "uniqueCollectionType",
modifiedtests/src/eth/nonFungible.test.tsdiffbeforeafterboth
246 }246 }
247 });247 });
248
249 itEth('Can perform burnFromCross()', async ({helper, privateKey}) => {
250 const alice = await privateKey('//Alice');
251 const collection = await helper.nft.mintCollection(alice, {name: 'A', description: 'B', tokenPrefix: 'C'});
252
253 const owner = await privateKey('//Bob');
254 const spender = await helper.eth.createAccountWithBalance(alice, 100n);
255
256 const token = await collection.mintToken(alice, {Substrate: owner.address});
257
258 const address = helper.ethAddress.fromCollectionId(collection.collectionId);
259 const contract = helper.ethNativeContract.collection(address, 'nft');
260
261 {
262 await token.approve(owner, {Ethereum: spender});
263 const ownerCross = helper.ethCrossAccount.fromKeyringPair(owner);
264 const result = await contract.methods.burnFromCross(ownerCross, token.tokenId).send({from: spender});
265 const events = result.events.Transfer;
266
267 expect(events).to.be.like({
268 address,
269 event: 'Transfer',
270 returnValues: {
271 from: helper.address.substrateToEth(owner.address),
272 to: '0x0000000000000000000000000000000000000000',
273 tokenId: token.tokenId.toString(),
274 },
275 });
276 }
277 });
278
279 itEth('Can perform approveCross()', async ({helper, privateKey}) => {
280 const alice = await privateKey('//Alice');
281 const collection = await helper.nft.mintCollection(alice, {name: 'A', description: 'B', tokenPrefix: 'C'});
282
283 const owner = await helper.eth.createAccountWithBalance(alice, 100n);
284 const receiver = await privateKey('//Charlie');
285
286 const token = await collection.mintToken(alice, {Ethereum: owner});
287
288 const address = helper.ethAddress.fromCollectionId(collection.collectionId);
289 const contract = helper.ethNativeContract.collection(address, 'nft');
290
291 {
292 const recieverCross = helper.ethCrossAccount.fromKeyringPair(receiver);
293 const result = await contract.methods.approveCross(recieverCross, token.tokenId).send({from: owner});
294 const event = result.events.Approval;
295 expect(event).to.be.like({
296 address: helper.ethAddress.fromCollectionId(collection.collectionId),
297 event: 'Approval',
298 returnValues: {
299 owner,
300 approved: helper.address.substrateToEth(receiver.address),
301 tokenId: token.tokenId.toString(),
302 },
303 });
304 }
305 });
248306
249 itEth('Can perform transferFrom()', async ({helper}) => {307 itEth('Can perform transferFrom()', async ({helper}) => {
250 const owner = await helper.eth.createAccountWithBalance(donor);308 const owner = await helper.eth.createAccountWithBalance(donor);
351 expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal())));409 expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal())));
352 });410 });
411
412 itEth('Can perform transferFromCross()', async ({helper, privateKey}) => {
413 const alice = await privateKey('//Alice');
414 const collection = await helper.nft.mintCollection(alice, {name: 'A', description: 'B', tokenPrefix: 'C'});
415
416 const owner = await privateKey('//Bob');
417 const spender = await helper.eth.createAccountWithBalance(alice, 100n);
418 const receiver = await privateKey('//Charlie');
419
420 const token = await collection.mintToken(alice, {Substrate: owner.address});
421
422 const address = helper.ethAddress.fromCollectionId(collection.collectionId);
423 const contract = helper.ethNativeContract.collection(address, 'nft');
424
425 await token.approve(owner, {Ethereum: spender});
426
427 {
428 const ownerCross = helper.ethCrossAccount.fromKeyringPair(owner);
429 const recieverCross = helper.ethCrossAccount.fromKeyringPair(receiver);
430 const result = await contract.methods.transferFromCross(ownerCross, recieverCross, token.tokenId).send({from: spender});
431 const event = result.events.Transfer;
432 expect(event).to.be.like({
433 address: helper.ethAddress.fromCollectionId(collection.collectionId),
434 event: 'Transfer',
435 returnValues: {
436 from: helper.address.substrateToEth(owner.address),
437 to: helper.address.substrateToEth(receiver.address),
438 tokenId: token.tokenId.toString(),
439 },
440 });
441 }
442
443 expect(await token.getOwner()).to.be.like({Substrate: receiver.address});
444 });
353445
354 itEth('transfer() call fee is less than 0.2UNQ', async ({helper}) => {446 itEth('transfer() call fee is less than 0.2UNQ', async ({helper}) => {
355 const owner = await helper.eth.createAccountWithBalance(donor);447 const owner = await helper.eth.createAccountWithBalance(donor);
modifiedtests/src/eth/nonFungibleAbi.jsondiffbeforeafterboth
89 "stateMutability": "nonpayable",89 "stateMutability": "nonpayable",
90 "type": "function"90 "type": "function"
91 },91 },
92 {
93 "inputs": [
94 {
95 "components": [
96 { "internalType": "address", "name": "field_0", "type": "address" },
97 { "internalType": "uint256", "name": "field_1", "type": "uint256" }
98 ],
99 "internalType": "struct Tuple6",
100 "name": "newAdmin",
101 "type": "tuple"
102 }
103 ],
104 "name": "addCollectionAdminCross",
105 "outputs": [],
106 "stateMutability": "nonpayable",
107 "type": "function"
108 },
92 {109 {
93 "inputs": [110 "inputs": [
94 { "internalType": "address", "name": "user", "type": "address" }111 { "internalType": "address", "name": "user", "type": "address" }
98 "stateMutability": "nonpayable",115 "stateMutability": "nonpayable",
99 "type": "function"116 "type": "function"
100 },117 },
118 {
119 "inputs": [
120 {
121 "components": [
122 { "internalType": "address", "name": "field_0", "type": "address" },
123 { "internalType": "uint256", "name": "field_1", "type": "uint256" }
124 ],
125 "internalType": "struct Tuple6",
126 "name": "user",
127 "type": "tuple"
128 }
129 ],
130 "name": "addToCollectionAllowListCross",
131 "outputs": [],
132 "stateMutability": "nonpayable",
133 "type": "function"
134 },
101 {135 {
102 "inputs": [136 "inputs": [
103 { "internalType": "address", "name": "user", "type": "address" }137 { "internalType": "address", "name": "user", "type": "address" }
117 "stateMutability": "nonpayable",151 "stateMutability": "nonpayable",
118 "type": "function"152 "type": "function"
119 },153 },
154 {
155 "inputs": [
156 {
157 "components": [
158 { "internalType": "address", "name": "field_0", "type": "address" },
159 { "internalType": "uint256", "name": "field_1", "type": "uint256" }
160 ],
161 "internalType": "struct Tuple6",
162 "name": "approved",
163 "type": "tuple"
164 },
165 { "internalType": "uint256", "name": "tokenId", "type": "uint256" }
166 ],
167 "name": "approveCross",
168 "outputs": [],
169 "stateMutability": "nonpayable",
170 "type": "function"
171 },
120 {172 {
121 "inputs": [173 "inputs": [
122 { "internalType": "address", "name": "owner", "type": "address" }174 { "internalType": "address", "name": "owner", "type": "address" }
145 "stateMutability": "nonpayable",197 "stateMutability": "nonpayable",
146 "type": "function"198 "type": "function"
147 },199 },
200 {
201 "inputs": [
202 {
203 "components": [
204 { "internalType": "address", "name": "field_0", "type": "address" },
205 { "internalType": "uint256", "name": "field_1", "type": "uint256" }
206 ],
207 "internalType": "struct Tuple6",
208 "name": "from",
209 "type": "tuple"
210 },
211 { "internalType": "uint256", "name": "tokenId", "type": "uint256" }
212 ],
213 "name": "burnFromCross",
214 "outputs": [],
215 "stateMutability": "nonpayable",
216 "type": "function"
217 },
148 {218 {
149 "inputs": [219 "inputs": [
150 { "internalType": "address", "name": "newOwner", "type": "address" }220 { "internalType": "address", "name": "newOwner", "type": "address" }
154 "stateMutability": "nonpayable",224 "stateMutability": "nonpayable",
155 "type": "function"225 "type": "function"
156 },226 },
227 {
228 "inputs": [],
229 "name": "collectionAdmins",
230 "outputs": [
231 {
232 "components": [
233 { "internalType": "address", "name": "field_0", "type": "address" },
234 { "internalType": "uint256", "name": "field_1", "type": "uint256" }
235 ],
236 "internalType": "struct Tuple6[]",
237 "name": "",
238 "type": "tuple[]"
239 }
240 ],
241 "stateMutability": "view",
242 "type": "function"
243 },
157 {244 {
158 "inputs": [],245 "inputs": [],
159 "name": "collectionOwner",246 "name": "collectionOwner",
163 { "internalType": "address", "name": "field_0", "type": "address" },250 { "internalType": "address", "name": "field_0", "type": "address" },
164 { "internalType": "uint256", "name": "field_1", "type": "uint256" }251 { "internalType": "uint256", "name": "field_1", "type": "uint256" }
165 ],252 ],
166 "internalType": "struct Tuple17",253 "internalType": "struct Tuple6",
167 "name": "",254 "name": "",
168 "type": "tuple"255 "type": "tuple"
169 }256 }
170 ],257 ],
171 "stateMutability": "view",258 "stateMutability": "view",
172 "type": "function"259 "type": "function"
173 },260 },
261 {
262 "inputs": [
263 { "internalType": "string[]", "name": "keys", "type": "string[]" }
264 ],
265 "name": "collectionProperties",
266 "outputs": [
267 {
268 "components": [
269 { "internalType": "string", "name": "field_0", "type": "string" },
270 { "internalType": "bytes", "name": "field_1", "type": "bytes" }
271 ],
272 "internalType": "struct Tuple19[]",
273 "name": "",
274 "type": "tuple[]"
275 }
276 ],
277 "stateMutability": "view",
278 "type": "function"
279 },
174 {280 {
175 "inputs": [{ "internalType": "string", "name": "key", "type": "string" }],281 "inputs": [{ "internalType": "string", "name": "key", "type": "string" }],
176 "name": "collectionProperty",282 "name": "collectionProperty",
187 { "internalType": "address", "name": "field_0", "type": "address" },293 { "internalType": "address", "name": "field_0", "type": "address" },
188 { "internalType": "uint256", "name": "field_1", "type": "uint256" }294 { "internalType": "uint256", "name": "field_1", "type": "uint256" }
189 ],295 ],
190 "internalType": "struct Tuple17",296 "internalType": "struct Tuple6",
191 "name": "",297 "name": "",
192 "type": "tuple"298 "type": "tuple"
193 }299 }
209 "stateMutability": "view",315 "stateMutability": "view",
210 "type": "function"316 "type": "function"
211 },317 },
318 {
319 "inputs": [
320 { "internalType": "string[]", "name": "keys", "type": "string[]" }
321 ],
322 "name": "deleteCollectionProperties",
323 "outputs": [],
324 "stateMutability": "nonpayable",
325 "type": "function"
326 },
212 {327 {
213 "inputs": [{ "internalType": "string", "name": "key", "type": "string" }],328 "inputs": [{ "internalType": "string", "name": "key", "type": "string" }],
214 "name": "deleteCollectionProperty",329 "name": "deleteCollectionProperty",
268 "stateMutability": "view",383 "stateMutability": "view",
269 "type": "function"384 "type": "function"
270 },385 },
386 {
387 "inputs": [
388 {
389 "components": [
390 { "internalType": "address", "name": "field_0", "type": "address" },
391 { "internalType": "uint256", "name": "field_1", "type": "uint256" }
392 ],
393 "internalType": "struct Tuple6",
394 "name": "user",
395 "type": "tuple"
396 }
397 ],
398 "name": "isOwnerOrAdminCross",
399 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
400 "stateMutability": "view",
401 "type": "function"
402 },
271 {403 {
272 "inputs": [{ "internalType": "address", "name": "to", "type": "address" }],404 "inputs": [{ "internalType": "address", "name": "to", "type": "address" }],
273 "name": "mint",405 "name": "mint",
334 "stateMutability": "nonpayable",466 "stateMutability": "nonpayable",
335 "type": "function"467 "type": "function"
336 },468 },
469 {
470 "inputs": [
471 {
472 "components": [
473 { "internalType": "address", "name": "field_0", "type": "address" },
474 { "internalType": "uint256", "name": "field_1", "type": "uint256" }
475 ],
476 "internalType": "struct Tuple6",
477 "name": "admin",
478 "type": "tuple"
479 }
480 ],
481 "name": "removeCollectionAdminCross",
482 "outputs": [],
483 "stateMutability": "nonpayable",
484 "type": "function"
485 },
337 {486 {
338 "inputs": [],487 "inputs": [],
339 "name": "removeCollectionSponsor",488 "name": "removeCollectionSponsor",
350 "stateMutability": "nonpayable",499 "stateMutability": "nonpayable",
351 "type": "function"500 "type": "function"
352 },501 },
502 {
503 "inputs": [
504 {
505 "components": [
506 { "internalType": "address", "name": "field_0", "type": "address" },
507 { "internalType": "uint256", "name": "field_1", "type": "uint256" }
508 ],
509 "internalType": "struct Tuple6",
510 "name": "user",
511 "type": "tuple"
512 }
513 ],
514 "name": "removeFromCollectionAllowListCross",
515 "outputs": [],
516 "stateMutability": "nonpayable",
517 "type": "function"
518 },
353 {519 {
354 "inputs": [520 "inputs": [
355 { "internalType": "address", "name": "from", "type": "address" },521 { "internalType": "address", "name": "from", "type": "address" },
438 "stateMutability": "nonpayable",604 "stateMutability": "nonpayable",
439 "type": "function"605 "type": "function"
440 },606 },
607 {
608 "inputs": [
609 {
610 "components": [
611 { "internalType": "string", "name": "field_0", "type": "string" },
612 { "internalType": "bytes", "name": "field_1", "type": "bytes" }
613 ],
614 "internalType": "struct Tuple19[]",
615 "name": "properties",
616 "type": "tuple[]"
617 }
618 ],
619 "name": "setCollectionProperties",
620 "outputs": [],
621 "stateMutability": "nonpayable",
622 "type": "function"
623 },
441 {624 {
442 "inputs": [625 "inputs": [
443 { "internalType": "string", "name": "key", "type": "string" },626 { "internalType": "string", "name": "key", "type": "string" },
457 "stateMutability": "nonpayable",640 "stateMutability": "nonpayable",
458 "type": "function"641 "type": "function"
459 },642 },
643 {
644 "inputs": [
645 {
646 "components": [
647 { "internalType": "address", "name": "field_0", "type": "address" },
648 { "internalType": "uint256", "name": "field_1", "type": "uint256" }
649 ],
650 "internalType": "struct Tuple6",
651 "name": "sponsor",
652 "type": "tuple"
653 }
654 ],
655 "name": "setCollectionSponsorCross",
656 "outputs": [],
657 "stateMutability": "nonpayable",
658 "type": "function"
659 },
660 {
661 "inputs": [
662 {
663 "components": [
664 { "internalType": "address", "name": "field_0", "type": "address" },
665 { "internalType": "uint256", "name": "field_1", "type": "uint256" }
666 ],
667 "internalType": "struct Tuple6",
668 "name": "newOwner",
669 "type": "tuple"
670 }
671 ],
672 "name": "setOwnerCross",
673 "outputs": [],
674 "stateMutability": "nonpayable",
675 "type": "function"
676 },
677 {
678 "inputs": [
679 { "internalType": "uint256", "name": "tokenId", "type": "uint256" },
680 {
681 "components": [
682 { "internalType": "string", "name": "field_0", "type": "string" },
683 { "internalType": "bytes", "name": "field_1", "type": "bytes" }
684 ],
685 "internalType": "struct Tuple19[]",
686 "name": "properties",
687 "type": "tuple[]"
688 }
689 ],
690 "name": "setProperties",
691 "outputs": [],
692 "stateMutability": "nonpayable",
693 "type": "function"
694 },
460 {695 {
461 "inputs": [696 "inputs": [
462 { "internalType": "uint256", "name": "tokenId", "type": "uint256" },697 { "internalType": "uint256", "name": "tokenId", "type": "uint256" },
552 "stateMutability": "nonpayable",787 "stateMutability": "nonpayable",
553 "type": "function"788 "type": "function"
554 },789 },
790 {
791 "inputs": [
792 {
793 "components": [
794 { "internalType": "address", "name": "field_0", "type": "address" },
795 { "internalType": "uint256", "name": "field_1", "type": "uint256" }
796 ],
797 "internalType": "struct Tuple6",
798 "name": "from",
799 "type": "tuple"
800 },
801 {
802 "components": [
803 { "internalType": "address", "name": "field_0", "type": "address" },
804 { "internalType": "uint256", "name": "field_1", "type": "uint256" }
805 ],
806 "internalType": "struct Tuple6",
807 "name": "to",
808 "type": "tuple"
809 },
810 { "internalType": "uint256", "name": "tokenId", "type": "uint256" }
811 ],
812 "name": "transferFromCross",
813 "outputs": [],
814 "stateMutability": "nonpayable",
815 "type": "function"
816 },
555 {817 {
556 "inputs": [],818 "inputs": [],
557 "name": "uniqueCollectionType",819 "name": "uniqueCollectionType",
modifiedtests/src/eth/reFungible.test.tsdiffbeforeafterboth
227 }227 }
228 });228 });
229
230 itEth('Can perform burnFrom()', async ({helper, privateKey}) => {
231 const alice = await privateKey('//Alice');
232 const collection = await helper.rft.mintCollection(alice, {name: 'A', description: 'B', tokenPrefix: 'C'});
233
234 const owner = await helper.eth.createAccountWithBalance(alice, 100n);
235 const spender = await helper.eth.createAccountWithBalance(alice, 100n);
236
237 const token = await collection.mintToken(alice, 100n, {Ethereum: owner});
238
239 const address = helper.ethAddress.fromCollectionId(collection.collectionId);
240 const contract = helper.ethNativeContract.collection(address, 'rft');
241
242 const tokenAddress = helper.ethAddress.fromTokenId(collection.collectionId, token.tokenId);
243 const tokenContract = helper.ethNativeContract.rftToken(tokenAddress, owner);
244 await tokenContract.methods.repartition(15).send();
245 await tokenContract.methods.approve(spender, 15).send();
246
247 {
248 const result = await contract.methods.burnFrom(owner, token.tokenId).send({from: spender});
249 const event = result.events.Transfer;
250 expect(event).to.be.like({
251 address: helper.ethAddress.fromCollectionId(collection.collectionId),
252 event: 'Transfer',
253 returnValues: {
254 from: owner,
255 to: '0x0000000000000000000000000000000000000000',
256 tokenId: token.tokenId.toString(),
257 },
258 });
259 }
260
261 expect(await collection.getTokenBalance(token.tokenId, {Ethereum: owner})).to.be.eq(0n);
262 });
263
264 itEth('Can perform burnFromCross()', async ({helper, privateKey}) => {
265 const alice = await privateKey('//Alice');
266 const collection = await helper.rft.mintCollection(alice, {name: 'A', description: 'B', tokenPrefix: 'C'});
267
268 const owner = await privateKey('//Bob');
269 const spender = await helper.eth.createAccountWithBalance(alice, 100n);
270
271 const token = await collection.mintToken(alice, 100n, {Substrate: owner.address});
272
273 const address = helper.ethAddress.fromCollectionId(collection.collectionId);
274 const contract = helper.ethNativeContract.collection(address, 'rft');
275
276 await token.repartition(owner, 15n);
277 await token.approve(owner, {Ethereum: spender}, 15n);
278
279 {
280 const ownerCross = helper.ethCrossAccount.fromKeyringPair(owner);
281 const result = await contract.methods.burnFromCross(ownerCross, token.tokenId).send({from: spender});
282 const event = result.events.Transfer;
283 expect(event).to.be.like({
284 address: helper.ethAddress.fromCollectionId(collection.collectionId),
285 event: 'Transfer',
286 returnValues: {
287 from: helper.address.substrateToEth(owner.address),
288 to: '0x0000000000000000000000000000000000000000',
289 tokenId: token.tokenId.toString(),
290 },
291 });
292 }
293
294 expect(await collection.getTokenBalance(token.tokenId, {Substrate: owner.address})).to.be.eq(0n);
295 });
296
297 itEth('Can perform transferFromCross()', async ({helper, privateKey}) => {
298 const alice = await privateKey('//Alice');
299 const collection = await helper.rft.mintCollection(alice, {name: 'A', description: 'B', tokenPrefix: 'C'});
300
301 const owner = await privateKey('//Bob');
302 const spender = await helper.eth.createAccountWithBalance(alice, 100n);
303 const receiver = await privateKey('//Charlie');
304
305 const token = await collection.mintToken(alice, 100n, {Substrate: owner.address});
306
307 const address = helper.ethAddress.fromCollectionId(collection.collectionId);
308 const contract = helper.ethNativeContract.collection(address, 'rft');
309
310 await token.repartition(owner, 15n);
311 await token.approve(owner, {Ethereum: spender}, 15n);
312
313 {
314 const ownerCross = helper.ethCrossAccount.fromKeyringPair(owner);
315 const recieverCross = helper.ethCrossAccount.fromKeyringPair(receiver);
316 const result = await contract.methods.transferFromCross(ownerCross, recieverCross, token.tokenId).send({from: spender});
317 const event = result.events.Transfer;
318 expect(event).to.be.like({
319 address: helper.ethAddress.fromCollectionId(collection.collectionId),
320 event: 'Transfer',
321 returnValues: {
322 from: helper.address.substrateToEth(owner.address),
323 to: helper.address.substrateToEth(receiver.address),
324 tokenId: token.tokenId.toString(),
325 },
326 });
327 }
328
329 expect(await token.getTop10Owners()).to.be.like([{Substrate: receiver.address}]);
330 });
229331
230 itEth('Can perform transfer()', async ({helper}) => {332 itEth('Can perform transfer()', async ({helper}) => {
231 const caller = await helper.eth.createAccountWithBalance(donor);333 const caller = await helper.eth.createAccountWithBalance(donor);
modifiedtests/src/eth/reFungibleAbi.jsondiffbeforeafterboth
89 "stateMutability": "nonpayable",89 "stateMutability": "nonpayable",
90 "type": "function"90 "type": "function"
91 },91 },
92 {
93 "inputs": [
94 {
95 "components": [
96 { "internalType": "address", "name": "field_0", "type": "address" },
97 { "internalType": "uint256", "name": "field_1", "type": "uint256" }
98 ],
99 "internalType": "struct Tuple6",
100 "name": "newAdmin",
101 "type": "tuple"
102 }
103 ],
104 "name": "addCollectionAdminCross",
105 "outputs": [],
106 "stateMutability": "nonpayable",
107 "type": "function"
108 },
92 {109 {
93 "inputs": [110 "inputs": [
94 { "internalType": "address", "name": "user", "type": "address" }111 { "internalType": "address", "name": "user", "type": "address" }
98 "stateMutability": "nonpayable",115 "stateMutability": "nonpayable",
99 "type": "function"116 "type": "function"
100 },117 },
118 {
119 "inputs": [
120 {
121 "components": [
122 { "internalType": "address", "name": "field_0", "type": "address" },
123 { "internalType": "uint256", "name": "field_1", "type": "uint256" }
124 ],
125 "internalType": "struct Tuple6",
126 "name": "user",
127 "type": "tuple"
128 }
129 ],
130 "name": "addToCollectionAllowListCross",
131 "outputs": [],
132 "stateMutability": "nonpayable",
133 "type": "function"
134 },
101 {135 {
102 "inputs": [136 "inputs": [
103 { "internalType": "address", "name": "user", "type": "address" }137 { "internalType": "address", "name": "user", "type": "address" }
145 "stateMutability": "nonpayable",179 "stateMutability": "nonpayable",
146 "type": "function"180 "type": "function"
147 },181 },
182 {
183 "inputs": [
184 {
185 "components": [
186 { "internalType": "address", "name": "field_0", "type": "address" },
187 { "internalType": "uint256", "name": "field_1", "type": "uint256" }
188 ],
189 "internalType": "struct Tuple6",
190 "name": "from",
191 "type": "tuple"
192 },
193 { "internalType": "uint256", "name": "tokenId", "type": "uint256" }
194 ],
195 "name": "burnFromCross",
196 "outputs": [],
197 "stateMutability": "nonpayable",
198 "type": "function"
199 },
148 {200 {
149 "inputs": [201 "inputs": [
150 { "internalType": "address", "name": "newOwner", "type": "address" }202 { "internalType": "address", "name": "newOwner", "type": "address" }
154 "stateMutability": "nonpayable",206 "stateMutability": "nonpayable",
155 "type": "function"207 "type": "function"
156 },208 },
209 {
210 "inputs": [],
211 "name": "collectionAdmins",
212 "outputs": [
213 {
214 "components": [
215 { "internalType": "address", "name": "field_0", "type": "address" },
216 { "internalType": "uint256", "name": "field_1", "type": "uint256" }
217 ],
218 "internalType": "struct Tuple6[]",
219 "name": "",
220 "type": "tuple[]"
221 }
222 ],
223 "stateMutability": "view",
224 "type": "function"
225 },
157 {226 {
158 "inputs": [],227 "inputs": [],
159 "name": "collectionOwner",228 "name": "collectionOwner",
163 { "internalType": "address", "name": "field_0", "type": "address" },232 { "internalType": "address", "name": "field_0", "type": "address" },
164 { "internalType": "uint256", "name": "field_1", "type": "uint256" }233 { "internalType": "uint256", "name": "field_1", "type": "uint256" }
165 ],234 ],
166 "internalType": "struct Tuple17",235 "internalType": "struct Tuple6",
167 "name": "",236 "name": "",
168 "type": "tuple"237 "type": "tuple"
169 }238 }
170 ],239 ],
171 "stateMutability": "view",240 "stateMutability": "view",
172 "type": "function"241 "type": "function"
173 },242 },
243 {
244 "inputs": [
245 { "internalType": "string[]", "name": "keys", "type": "string[]" }
246 ],
247 "name": "collectionProperties",
248 "outputs": [
249 {
250 "components": [
251 { "internalType": "string", "name": "field_0", "type": "string" },
252 { "internalType": "bytes", "name": "field_1", "type": "bytes" }
253 ],
254 "internalType": "struct Tuple19[]",
255 "name": "",
256 "type": "tuple[]"
257 }
258 ],
259 "stateMutability": "view",
260 "type": "function"
261 },
174 {262 {
175 "inputs": [{ "internalType": "string", "name": "key", "type": "string" }],263 "inputs": [{ "internalType": "string", "name": "key", "type": "string" }],
176 "name": "collectionProperty",264 "name": "collectionProperty",
187 { "internalType": "address", "name": "field_0", "type": "address" },275 { "internalType": "address", "name": "field_0", "type": "address" },
188 { "internalType": "uint256", "name": "field_1", "type": "uint256" }276 { "internalType": "uint256", "name": "field_1", "type": "uint256" }
189 ],277 ],
190 "internalType": "struct Tuple17",278 "internalType": "struct Tuple6",
191 "name": "",279 "name": "",
192 "type": "tuple"280 "type": "tuple"
193 }281 }
209 "stateMutability": "view",297 "stateMutability": "view",
210 "type": "function"298 "type": "function"
211 },299 },
300 {
301 "inputs": [
302 { "internalType": "string[]", "name": "keys", "type": "string[]" }
303 ],
304 "name": "deleteCollectionProperties",
305 "outputs": [],
306 "stateMutability": "nonpayable",
307 "type": "function"
308 },
212 {309 {
213 "inputs": [{ "internalType": "string", "name": "key", "type": "string" }],310 "inputs": [{ "internalType": "string", "name": "key", "type": "string" }],
214 "name": "deleteCollectionProperty",311 "name": "deleteCollectionProperty",
268 "stateMutability": "view",365 "stateMutability": "view",
269 "type": "function"366 "type": "function"
270 },367 },
368 {
369 "inputs": [
370 {
371 "components": [
372 { "internalType": "address", "name": "field_0", "type": "address" },
373 { "internalType": "uint256", "name": "field_1", "type": "uint256" }
374 ],
375 "internalType": "struct Tuple6",
376 "name": "user",
377 "type": "tuple"
378 }
379 ],
380 "name": "isOwnerOrAdminCross",
381 "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }],
382 "stateMutability": "view",
383 "type": "function"
384 },
271 {385 {
272 "inputs": [{ "internalType": "address", "name": "to", "type": "address" }],386 "inputs": [{ "internalType": "address", "name": "to", "type": "address" }],
273 "name": "mint",387 "name": "mint",
334 "stateMutability": "nonpayable",448 "stateMutability": "nonpayable",
335 "type": "function"449 "type": "function"
336 },450 },
451 {
452 "inputs": [
453 {
454 "components": [
455 { "internalType": "address", "name": "field_0", "type": "address" },
456 { "internalType": "uint256", "name": "field_1", "type": "uint256" }
457 ],
458 "internalType": "struct Tuple6",
459 "name": "admin",
460 "type": "tuple"
461 }
462 ],
463 "name": "removeCollectionAdminCross",
464 "outputs": [],
465 "stateMutability": "nonpayable",
466 "type": "function"
467 },
337 {468 {
338 "inputs": [],469 "inputs": [],
339 "name": "removeCollectionSponsor",470 "name": "removeCollectionSponsor",
350 "stateMutability": "nonpayable",481 "stateMutability": "nonpayable",
351 "type": "function"482 "type": "function"
352 },483 },
484 {
485 "inputs": [
486 {
487 "components": [
488 { "internalType": "address", "name": "field_0", "type": "address" },
489 { "internalType": "uint256", "name": "field_1", "type": "uint256" }
490 ],
491 "internalType": "struct Tuple6",
492 "name": "user",
493 "type": "tuple"
494 }
495 ],
496 "name": "removeFromCollectionAllowListCross",
497 "outputs": [],
498 "stateMutability": "nonpayable",
499 "type": "function"
500 },
353 {501 {
354 "inputs": [502 "inputs": [
355 { "internalType": "address", "name": "from", "type": "address" },503 { "internalType": "address", "name": "from", "type": "address" },
438 "stateMutability": "nonpayable",586 "stateMutability": "nonpayable",
439 "type": "function"587 "type": "function"
440 },588 },
589 {
590 "inputs": [
591 {
592 "components": [
593 { "internalType": "string", "name": "field_0", "type": "string" },
594 { "internalType": "bytes", "name": "field_1", "type": "bytes" }
595 ],
596 "internalType": "struct Tuple19[]",
597 "name": "properties",
598 "type": "tuple[]"
599 }
600 ],
601 "name": "setCollectionProperties",
602 "outputs": [],
603 "stateMutability": "nonpayable",
604 "type": "function"
605 },
441 {606 {
442 "inputs": [607 "inputs": [
443 { "internalType": "string", "name": "key", "type": "string" },608 { "internalType": "string", "name": "key", "type": "string" },
457 "stateMutability": "nonpayable",622 "stateMutability": "nonpayable",
458 "type": "function"623 "type": "function"
459 },624 },
625 {
626 "inputs": [
627 {
628 "components": [
629 { "internalType": "address", "name": "field_0", "type": "address" },
630 { "internalType": "uint256", "name": "field_1", "type": "uint256" }
631 ],
632 "internalType": "struct Tuple6",
633 "name": "sponsor",
634 "type": "tuple"
635 }
636 ],
637 "name": "setCollectionSponsorCross",
638 "outputs": [],
639 "stateMutability": "nonpayable",
640 "type": "function"
641 },
642 {
643 "inputs": [
644 {
645 "components": [
646 { "internalType": "address", "name": "field_0", "type": "address" },
647 { "internalType": "uint256", "name": "field_1", "type": "uint256" }
648 ],
649 "internalType": "struct Tuple6",
650 "name": "newOwner",
651 "type": "tuple"
652 }
653 ],
654 "name": "setOwnerCross",
655 "outputs": [],
656 "stateMutability": "nonpayable",
657 "type": "function"
658 },
659 {
660 "inputs": [
661 { "internalType": "uint256", "name": "tokenId", "type": "uint256" },
662 {
663 "components": [
664 { "internalType": "string", "name": "field_0", "type": "string" },
665 { "internalType": "bytes", "name": "field_1", "type": "bytes" }
666 ],
667 "internalType": "struct Tuple19[]",
668 "name": "properties",
669 "type": "tuple[]"
670 }
671 ],
672 "name": "setProperties",
673 "outputs": [],
674 "stateMutability": "nonpayable",
675 "type": "function"
676 },
460 {677 {
461 "inputs": [678 "inputs": [
462 { "internalType": "uint256", "name": "tokenId", "type": "uint256" },679 { "internalType": "uint256", "name": "tokenId", "type": "uint256" },
561 "stateMutability": "nonpayable",778 "stateMutability": "nonpayable",
562 "type": "function"779 "type": "function"
563 },780 },
781 {
782 "inputs": [
783 {
784 "components": [
785 { "internalType": "address", "name": "field_0", "type": "address" },
786 { "internalType": "uint256", "name": "field_1", "type": "uint256" }
787 ],
788 "internalType": "struct Tuple6",
789 "name": "from",
790 "type": "tuple"
791 },
792 {
793 "components": [
794 { "internalType": "address", "name": "field_0", "type": "address" },
795 { "internalType": "uint256", "name": "field_1", "type": "uint256" }
796 ],
797 "internalType": "struct Tuple6",
798 "name": "to",
799 "type": "tuple"
800 },
801 { "internalType": "uint256", "name": "tokenId", "type": "uint256" }
802 ],
803 "name": "transferFromCross",
804 "outputs": [],
805 "stateMutability": "nonpayable",
806 "type": "function"
807 },
564 {808 {
565 "inputs": [],809 "inputs": [],
566 "name": "uniqueCollectionType",810 "name": "uniqueCollectionType",
addedtests/src/eth/scheduling.test.tsdiffbeforeafterboth

no changes

modifiedtests/src/eth/tokenProperties.test.tsdiffbeforeafterboth
1616
17import {itEth, usingEthPlaygrounds, expect} from './util';17import {itEth, usingEthPlaygrounds, expect} from './util';
18import {IKeyringPair} from '@polkadot/types/types';18import {IKeyringPair} from '@polkadot/types/types';
19import {ITokenPropertyPermission} from '../util/playgrounds/types';
20import {Pallets} from '../util';
1921
20describe('EVM token properties', () => {22describe('EVM token properties', () => {
21 let donor: IKeyringPair;23 let donor: IKeyringPair;
69 expect(value).to.equal('testValue');71 expect(value).to.equal('testValue');
70 });72 });
73
74 itEth('Can be multiple set for NFT ', async({helper}) => {
75 const caller = await helper.eth.createAccountWithBalance(donor);
76
77 const properties = Array(5).fill(0).map((_, i) => { return {field_0: `key_${i}`, field_1: Buffer.from(`value_${i}`)}; });
78 const permissions: ITokenPropertyPermission[] = properties.map(p => { return {key: p.field_0, permission: {tokenOwner: true,
79 collectionAdmin: true,
80 mutable: true}}; });
81
82 const collection = await helper.nft.mintCollection(alice, {
83 tokenPrefix: 'ethp',
84 tokenPropertyPermissions: permissions,
85 });
86
87 const token = await collection.mintToken(alice);
88
89 const valuesBefore = await token.getProperties(properties.map(p => p.field_0));
90 expect(valuesBefore).to.be.deep.equal([]);
91
92 await collection.addAdmin(alice, {Ethereum: caller});
93
94 const address = helper.ethAddress.fromCollectionId(collection.collectionId);
95 const contract = helper.ethNativeContract.collection(address, 'nft', caller);
96
97 await contract.methods.setProperties(token.tokenId, properties).send({from: caller});
98
99 const values = await token.getProperties(properties.map(p => p.field_0));
100 expect(values).to.be.deep.equal(properties.map(p => { return {key: p.field_0, value: p.field_1.toString()}; }));
101 });
102
103 itEth.ifWithPallets('Can be multiple set for RFT ', [Pallets.ReFungible], async({helper}) => {
104 const caller = await helper.eth.createAccountWithBalance(donor);
105
106 const properties = Array(5).fill(0).map((_, i) => { return {field_0: `key_${i}`, field_1: Buffer.from(`value_${i}`)}; });
107 const permissions: ITokenPropertyPermission[] = properties.map(p => { return {key: p.field_0, permission: {tokenOwner: true,
108 collectionAdmin: true,
109 mutable: true}}; });
110
111 const collection = await helper.rft.mintCollection(alice, {
112 tokenPrefix: 'ethp',
113 tokenPropertyPermissions: permissions,
114 });
115
116 const token = await collection.mintToken(alice);
117
118 const valuesBefore = await token.getProperties(properties.map(p => p.field_0));
119 expect(valuesBefore).to.be.deep.equal([]);
120
121 await collection.addAdmin(alice, {Ethereum: caller});
122
123 const address = helper.ethAddress.fromCollectionId(collection.collectionId);
124 const contract = helper.ethNativeContract.collection(address, 'rft', caller);
125
126 await contract.methods.setProperties(token.tokenId, properties).send({from: caller});
127
128 const values = await token.getProperties(properties.map(p => p.field_0));
129 expect(values).to.be.deep.equal(properties.map(p => { return {key: p.field_0, value: p.field_1.toString()}; }));
130 });
71131
72 itEth('Can be deleted', async({helper}) => {132 itEth('Can be deleted', async({helper}) => {
73 const caller = await helper.eth.createAccountWithBalance(donor);133 const caller = await helper.eth.createAccountWithBalance(donor);
modifiedtests/src/eth/util/playgrounds/types.tsdiffbeforeafterboth
13 event: string,13 event: string,
14 args: { [key: string]: string }14 args: { [key: string]: string }
15};15};
16export interface TEthCrossAccount {
17 readonly 0: string,
18 readonly 1: string | Uint8Array,
19 readonly field_0: string,
20 readonly field_1: string | Uint8Array,
21}
22
23export type EthProperty = string[];
1624
25
modifiedtests/src/eth/util/playgrounds/unique.dev.tsdiffbeforeafterboth
1818
19import {DevUniqueHelper} from '../../../util/playgrounds/unique.dev';19import {DevUniqueHelper} from '../../../util/playgrounds/unique.dev';
2020
21import {ContractImports, CompiledContract, NormalizedEvent} from './types';21import {ContractImports, CompiledContract, TEthCrossAccount, NormalizedEvent, EthProperty} from './types';
2222
23// Native contracts ABI23// Native contracts ABI
24import collectionHelpersAbi from '../../collectionHelpersAbi.json';24import collectionHelpersAbi from '../../collectionHelpersAbi.json';
28import refungibleTokenAbi from '../../reFungibleTokenAbi.json';28import refungibleTokenAbi from '../../reFungibleTokenAbi.json';
29import contractHelpersAbi from './../contractHelpersAbi.json';29import contractHelpersAbi from './../contractHelpersAbi.json';
30import {ICrossAccountId, TEthereumAccount} from '../../../util/playgrounds/types';30import {ICrossAccountId, TEthereumAccount} from '../../../util/playgrounds/types';
31import {TCollectionMode} from '../../../util/playgrounds/types';
3132
32class EthGroupBase {33class EthGroupBase {
33 helper: EthUniqueHelper;34 helper: EthUniqueHelper;
107 return new web3.eth.Contract(collectionHelpersAbi as any, '0x6c4e9fe1ae37a41e93cee429e8e1881abdcbb54f', {from: caller, gas: this.helper.eth.DEFAULT_GAS});108 return new web3.eth.Contract(collectionHelpersAbi as any, '0x6c4e9fe1ae37a41e93cee429e8e1881abdcbb54f', {from: caller, gas: this.helper.eth.DEFAULT_GAS});
108 }109 }
109110
110 collection(address: string, mode: 'nft' | 'rft' | 'ft', caller?: string): Contract {111 collection(address: string, mode: TCollectionMode, caller?: string): Contract {
111 const abi = {112 const abi = {
112 'nft': nonFungibleAbi,113 'nft': nonFungibleAbi,
113 'rft': refungibleAbi,114 'rft': refungibleAbi,
174 return await this.helper.callRpc('api.rpc.eth.call', [{from: signer, to: contractAddress, data: abi}]);175 return await this.helper.callRpc('api.rpc.eth.call', [{from: signer, to: contractAddress, data: abi}]);
175 }176 }
176177
177 async createNFTCollection(signer: string, name: string, description: string, tokenPrefix: string): Promise<{collectionId: number, collectionAddress: string}> {178 async createCollecion(functionName: string, signer: string, name: string, description: string, tokenPrefix: string): Promise<{ collectionId: number, collectionAddress: string, events: NormalizedEvent[] }> {
178 const collectionCreationPrice = this.helper.balance.getCollectionCreationPrice();179 const collectionCreationPrice = this.helper.balance.getCollectionCreationPrice();
179 const collectionHelper = this.helper.ethNativeContract.collectionHelpers(signer);180 const collectionHelper = this.helper.ethNativeContract.collectionHelpers(signer);
180181
181 const result = await collectionHelper.methods.createNFTCollection(name, description, tokenPrefix).send({value: Number(collectionCreationPrice)});182 const result = await collectionHelper.methods[functionName](name, description, tokenPrefix).send({value: Number(collectionCreationPrice)});
182183
183 const collectionAddress = this.helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);184 const collectionAddress = this.helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);
184 const collectionId = this.helper.ethAddress.extractCollectionId(collectionAddress);185 const collectionId = this.helper.ethAddress.extractCollectionId(collectionAddress);
186 const events = this.helper.eth.normalizeEvents(result.events);
185187
186 return {collectionId, collectionAddress};188 return {collectionId, collectionAddress, events};
187 }189 }
190
191 async createNFTCollection(signer: string, name: string, description: string, tokenPrefix: string): Promise<{ collectionId: number, collectionAddress: string, events: NormalizedEvent[] }> {
192 return this.createCollecion('createNFTCollection', signer, name, description, tokenPrefix);
193 }
188194
189 async createERC721MetadataCompatibleNFTCollection(signer: string, name: string, description: string, tokenPrefix: string, baseUri: string): Promise<{collectionId: number, collectionAddress: string}> {195 async createERC721MetadataCompatibleNFTCollection(signer: string, name: string, description: string, tokenPrefix: string, baseUri: string): Promise<{collectionId: number, collectionAddress: string, events: NormalizedEvent[] }> {
190 const collectionHelper = this.helper.ethNativeContract.collectionHelpers(signer);196 const collectionHelper = this.helper.ethNativeContract.collectionHelpers(signer);
191197
192 const {collectionId, collectionAddress} = await this.createNFTCollection(signer, name, description, tokenPrefix);198 const {collectionId, collectionAddress, events} = await this.createCollecion('createNFTCollection', signer, name, description, tokenPrefix);
193199
194 await collectionHelper.methods.makeCollectionERC721MetadataCompatible(collectionAddress, baseUri).send();200 await collectionHelper.methods.makeCollectionERC721MetadataCompatible(collectionAddress, baseUri).send();
195201
196 return {collectionId, collectionAddress};202 return {collectionId, collectionAddress, events};
197 }203 }
198204
199 async createRFTCollection(signer: string, name: string, description: string, tokenPrefix: string): Promise<{collectionId: number, collectionAddress: string}> {205 async createRFTCollection(signer: string, name: string, description: string, tokenPrefix: string): Promise<{collectionId: number, collectionAddress: string, events: NormalizedEvent[]}> {
206 return this.createCollecion('createRFTCollection', signer, name, description, tokenPrefix);
207 }
208
209 async createFungibleCollection(signer: string, name: string, decimals: number, description: string, tokenPrefix: string): Promise<{ collectionId: number, collectionAddress: string, events: NormalizedEvent[]}> {
200 const collectionCreationPrice = this.helper.balance.getCollectionCreationPrice();210 const collectionCreationPrice = this.helper.balance.getCollectionCreationPrice();
201 const collectionHelper = this.helper.ethNativeContract.collectionHelpers(signer);211 const collectionHelper = this.helper.ethNativeContract.collectionHelpers(signer);
202212
203 const result = await collectionHelper.methods.createRFTCollection(name, description, tokenPrefix).send({value: Number(collectionCreationPrice)});213 const result = await collectionHelper.methods.createFTCollection(name, decimals, description, tokenPrefix).send({value: Number(collectionCreationPrice)});
204
205 const collectionAddress = this.helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);214 const collectionAddress = this.helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);
206 const collectionId = this.helper.ethAddress.extractCollectionId(collectionAddress);215 const collectionId = this.helper.ethAddress.extractCollectionId(collectionAddress);
216
217 const events = this.helper.eth.normalizeEvents(result.events);
207218
208 return {collectionId, collectionAddress};219 return {collectionId, collectionAddress, events};
209 }220 }
210221
211 async createERC721MetadataCompatibleRFTCollection(signer: string, name: string, description: string, tokenPrefix: string, baseUri: string): Promise<{collectionId: number, collectionAddress: string}> {222 async createERC721MetadataCompatibleRFTCollection(signer: string, name: string, description: string, tokenPrefix: string, baseUri: string): Promise<{collectionId: number, collectionAddress: string, events: NormalizedEvent[] }> {
212 const collectionHelper = this.helper.ethNativeContract.collectionHelpers(signer);223 const collectionHelper = this.helper.ethNativeContract.collectionHelpers(signer);
213224
214 const {collectionId, collectionAddress} = await this.createRFTCollection(signer, name, description, tokenPrefix);225 const {collectionId, collectionAddress, events} = await this.createCollecion('createRFTCollection', signer, name, description, tokenPrefix);
215226
216 await collectionHelper.methods.makeCollectionERC721MetadataCompatible(collectionAddress, baseUri).send();227 await collectionHelper.methods.makeCollectionERC721MetadataCompatible(collectionAddress, baseUri).send();
217228
218 return {collectionId, collectionAddress};229 return {collectionId, collectionAddress, events};
219 }230 }
220231
221 async deployCollectorContract(signer: string): Promise<Contract> {232 async deployCollectorContract(signer: string): Promise<Contract> {
340 return '0x' + address.substring(address.length - 40);351 return '0x' + address.substring(address.length - 40);
341 }352 }
342}353}
343354export class EthPropertyGroup extends EthGroupBase {
355 property(key: string, value: string): EthProperty {
356 return [
357 key,
358 '0x'+Buffer.from(value).toString('hex'),
359 ];
360 }
361}
344export type EthUniqueHelperConstructor = new (...args: any[]) => EthUniqueHelper;362export type EthUniqueHelperConstructor = new (...args: any[]) => EthUniqueHelper;
363
364export class EthCrossAccountGroup extends EthGroupBase {
365 fromAddress(address: TEthereumAccount): TEthCrossAccount {
366 return {
367 0: address,
368 1: '0',
369 field_0: address,
370 field_1: '0',
371 };
372 }
373
374 fromKeyringPair(keyring: IKeyringPair): TEthCrossAccount {
375 return {
376 0: '0x0000000000000000000000000000000000000000',
377 1: keyring.addressRaw,
378 field_0: '0x0000000000000000000000000000000000000000',
379 field_1: keyring.addressRaw,
380 };
381 }
382}
345383
346export class EthUniqueHelper extends DevUniqueHelper {384export class EthUniqueHelper extends DevUniqueHelper {
347 web3: Web3 | null = null;385 web3: Web3 | null = null;
351 ethAddress: EthAddressGroup;389 ethAddress: EthAddressGroup;
352 ethNativeContract: NativeContractGroup;390 ethNativeContract: NativeContractGroup;
353 ethContract: ContractGroup;391 ethContract: ContractGroup;
392 ethCrossAccount: EthCrossAccountGroup;
393 ethProperty: EthPropertyGroup;
354394
355 constructor(logger: { log: (msg: any, level: any) => void, level: any }, options: {[key: string]: any} = {}) {395 constructor(logger: { log: (msg: any, level: any) => void, level: any }, options: {[key: string]: any} = {}) {
356 options.helperBase = options.helperBase ?? EthUniqueHelper;396 options.helperBase = options.helperBase ?? EthUniqueHelper;
357397
358 super(logger, options);398 super(logger, options);
359 this.eth = new EthGroup(this);399 this.eth = new EthGroup(this);
360 this.ethAddress = new EthAddressGroup(this);400 this.ethAddress = new EthAddressGroup(this);
401 this.ethCrossAccount = new EthCrossAccountGroup(this);
361 this.ethNativeContract = new NativeContractGroup(this);402 this.ethNativeContract = new NativeContractGroup(this);
362 this.ethContract = new ContractGroup(this);403 this.ethContract = new ContractGroup(this);
404 this.ethProperty = new EthPropertyGroup(this);
363 }405 }
364406
365 getWeb3(): Web3 {407 getWeb3(): Web3 {
modifiedtests/src/pallet-presence.test.tsdiffbeforeafterboth
62 const chain = await helper.callRpc('api.rpc.system.chain', []);62 const chain = await helper.callRpc('api.rpc.system.chain', []);
6363
64 const refungible = 'refungible';64 const refungible = 'refungible';
65 // const scheduler = 'scheduler';65 const scheduler = 'scheduler';
66 const foreignAssets = 'foreignassets';66 const foreignAssets = 'foreignassets';
67 const rmrkPallets = ['rmrkcore', 'rmrkequip'];67 const rmrkPallets = ['rmrkcore', 'rmrkequip'];
68 const appPromotion = 'apppromotion';68 const appPromotion = 'apppromotion';
69 const testUtils = 'testutils';
6970
70 if (chain.eq('OPAL by UNIQUE')) {71 if (chain.eq('OPAL by UNIQUE')) {
71 requiredPallets.push(72 requiredPallets.push(
72 refungible,73 refungible,
73 // scheduler,74 // scheduler,
74 foreignAssets,75 foreignAssets,
75 appPromotion,76 appPromotion,
77 testUtils,
78 scheduler,
76 ...rmrkPallets,79 ...rmrkPallets,
77 );80 );
78 } else if (chain.eq('QUARTZ by UNIQUE')) {81 } else if (chain.eq('QUARTZ by UNIQUE')) {
addedtests/src/scheduler.test.tsdiffbeforeafterboth

no changes

modifiedtests/src/util/index.tsdiffbeforeafterboth
95 NFT = 'nonfungible',95 NFT = 'nonfungible',
96 Scheduler = 'scheduler',96 Scheduler = 'scheduler',
97 AppPromotion = 'apppromotion',97 AppPromotion = 'apppromotion',
98 TestUtils = 'testutils',
98}99}
99100
100export function requirePalletsOrSkip(test: Context, helper: DevUniqueHelper, requiredPallets: string[]) {101export function requirePalletsOrSkip(test: Context, helper: DevUniqueHelper, requiredPallets: string[]) {
modifiedtests/src/util/playgrounds/types.tsdiffbeforeafterboth
70 ethereum?: TEthereumAccount;70 ethereum?: TEthereumAccount;
71}71}
72
73export interface IEthCrossAccountId {
74 0: TEthereumAccount;
75 1: TSubstrateAccount;
76 field_0: TEthereumAccount;
77 field_1: TSubstrateAccount;
78}
7279
73export interface ICollectionLimits {80export interface ICollectionLimits {
74 accountTokenOwnershipLimit?: number | null;81 accountTokenOwnershipLimit?: number | null;
217export type TRelayNetworks = 'rococo' | 'westend';224export type TRelayNetworks = 'rococo' | 'westend';
218export type TNetworks = TUniqueNetworks | TSiblingNetworkds | TRelayNetworks;225export type TNetworks = TUniqueNetworks | TSiblingNetworkds | TRelayNetworks;
219export type TSigner = IKeyringPair; // | 'string'226export type TSigner = IKeyringPair; // | 'string'
227export type TCollectionMode = 'nft' | 'rft' | 'ft';
220228
modifiedtests/src/util/playgrounds/unique.dev.tsdiffbeforeafterboth
8import * as defs from '../../interfaces/definitions';8import * as defs from '../../interfaces/definitions';
9import {IKeyringPair} from '@polkadot/types/types';9import {IKeyringPair} from '@polkadot/types/types';
10import {EventRecord} from '@polkadot/types/interfaces';10import {EventRecord} from '@polkadot/types/interfaces';
11import {ICrossAccountId} from './types';11import {ICrossAccountId, TSigner} from './types';
12import {FrameSystemEventRecord} from '@polkadot/types/lookup';12import {FrameSystemEventRecord} from '@polkadot/types/lookup';
13import {VoidFn} from '@polkadot/api/types';
14import {Pallets} from '..';
1315
14export class SilentLogger {16export class SilentLogger {
15 log(_msg: any, _level: any): void { }17 log(_msg: any, _level: any): void { }
63 arrange: ArrangeGroup;65 arrange: ArrangeGroup;
64 wait: WaitGroup;66 wait: WaitGroup;
65 admin: AdminGroup;67 admin: AdminGroup;
68 testUtils: TestUtilGroup;
6669
67 constructor(logger: { log: (msg: any, level: any) => void, level: any }, options: {[key: string]: any} = {}) {70 constructor(logger: { log: (msg: any, level: any) => void, level: any }, options: {[key: string]: any} = {}) {
68 options.helperBase = options.helperBase ?? DevUniqueHelper;71 options.helperBase = options.helperBase ?? DevUniqueHelper;
71 this.arrange = new ArrangeGroup(this);74 this.arrange = new ArrangeGroup(this);
72 this.wait = new WaitGroup(this);75 this.wait = new WaitGroup(this);
73 this.admin = new AdminGroup(this);76 this.admin = new AdminGroup(this);
77 this.testUtils = new TestUtilGroup(this);
74 }78 }
7579
76 async connect(wsEndpoint: string, _listeners?: any): Promise<void> {80 async connect(wsEndpoint: string, _listeners?: any): Promise<void> {
154class ArrangeGroup {158class ArrangeGroup {
155 helper: DevUniqueHelper;159 helper: DevUniqueHelper;
160
161 scheduledIdSlider = 0;
156162
157 constructor(helper: DevUniqueHelper) {163 constructor(helper: DevUniqueHelper) {
158 this.helper = helper;164 this.helper = helper;
298 return encodeAddress(address);304 return encodeAddress(address);
299 }305 }
306
307 async makeScheduledIds(num: number): Promise<string[]> {
308 await this.helper.wait.noScheduledTasks();
309
310 function makeId(slider: number) {
311 const scheduledIdSize = 64;
312 const hexId = slider.toString(16);
313 const prefixSize = scheduledIdSize - hexId.length;
314
315 const scheduledId = '0x' + '0'.repeat(prefixSize) + hexId;
316
317 return scheduledId;
318 }
319
320 const ids = [];
321 for (let i = 0; i < num; i++) {
322 ids.push(makeId(this.scheduledIdSlider));
323 this.scheduledIdSlider += 1;
324 }
325
326 return ids;
327 }
328
329 async makeScheduledId(): Promise<string> {
330 return (await this.makeScheduledIds(1))[0];
331 }
332
333 async captureEvents(eventSection: string, eventMethod: string): Promise<EventCapture> {
334 const capture = new EventCapture(this.helper, eventSection, eventMethod);
335 await capture.startCapture();
336
337 return capture;
338 }
300}339}
301340
302class MoonbeamAccountGroup {341class MoonbeamAccountGroup {
389 });428 });
390 }429 }
430
431 async noScheduledTasks() {
432 const api = this.helper.getApi();
433
434 // eslint-disable-next-line no-async-promise-executor
435 const promise = new Promise<void>(async resolve => {
436 const unsubscribe = await api.rpc.chain.subscribeNewHeads(async () => {
437 const areThereScheduledTasks = await api.query.scheduler.lookup.entries();
438
439 if(areThereScheduledTasks.length == 0) {
440 unsubscribe();
441 resolve();
442 }
443 });
444 });
445
446 return promise;
447 }
391448
392 event(maxBlocksToWait: number, eventSection: string, eventMethod: string) {449 async event(maxBlocksToWait: number, eventSection: string, eventMethod: string) {
393 // eslint-disable-next-line no-async-promise-executor450 // eslint-disable-next-line no-async-promise-executor
394 const promise = new Promise<EventRecord | null>(async (resolve) => {451 const promise = new Promise<EventRecord | null>(async (resolve) => {
395 const unsubscribe = await this.helper.getApi().rpc.chain.subscribeNewHeads(async header => {452 const unsubscribe = await this.helper.getApi().rpc.chain.subscribeNewHeads(async header => {
424 }480 }
425}481}
482
483class TestUtilGroup {
484 helper: DevUniqueHelper;
485
486 constructor(helper: DevUniqueHelper) {
487 this.helper = helper;
488 }
489
490 async enable() {
491 if (this.helper.fetchMissingPalletNames([Pallets.TestUtils]).length != 0) {
492 return;
493 }
494
495 const signer = this.helper.util.fromSeed('//Alice');
496 await this.helper.getSudo<DevUniqueHelper>().executeExtrinsic(signer, 'api.tx.testUtils.enable', [], true);
497 }
498
499 async setTestValue(signer: TSigner, testVal: number) {
500 await this.helper.executeExtrinsic(signer, 'api.tx.testUtils.setTestValue', [testVal], true);
501 }
502
503 async incTestValue(signer: TSigner) {
504 await this.helper.executeExtrinsic(signer, 'api.tx.testUtils.incTestValue', [], true);
505 }
506
507 async setTestValueAndRollback(signer: TSigner, testVal: number) {
508 await this.helper.executeExtrinsic(signer, 'api.tx.testUtils.setTestValueAndRollback', [testVal], true);
509 }
510
511 async testValue() {
512 return (await this.helper.callRpc('api.query.testUtils.testValue', [])).toNumber();
513 }
514
515 async justTakeFee(signer: TSigner) {
516 await this.helper.executeExtrinsic(signer, 'api.tx.testUtils.justTakeFee', [], true);
517 }
518
519 async selfCancelingInc(signer: TSigner, scheduledId: string, maxTestVal: number) {
520 await this.helper.executeExtrinsic(signer, 'api.tx.testUtils.selfCancelingInc', [scheduledId, maxTestVal], true);
521 }
522}
523
524class EventCapture {
525 helper: DevUniqueHelper;
526 eventSection: string;
527 eventMethod: string;
528 events: EventRecord[] = [];
529 unsubscribe: VoidFn | null = null;
530
531 constructor(
532 helper: DevUniqueHelper,
533 eventSection: string,
534 eventMethod: string,
535 ) {
536 this.helper = helper;
537 this.eventSection = eventSection;
538 this.eventMethod = eventMethod;
539 }
540
541 async startCapture() {
542 this.stopCapture();
543 this.unsubscribe = (await this.helper.getApi().query.system.events((eventRecords: FrameSystemEventRecord[]) => {
544 const newEvents = eventRecords.filter(r => {
545 return r.event.section == this.eventSection && r.event.method == this.eventMethod;
546 });
547
548 this.events.push(...newEvents);
549 })) as any;
550 }
551
552 stopCapture() {
553 if (this.unsubscribe !== null) {
554 this.unsubscribe();
555 }
556 }
557
558 extractCapturedEvents() {
559 return this.events;
560 }
561}
426562
427class AdminGroup {563class AdminGroup {
428 helper: UniqueHelper;564 helper: UniqueHelper;
modifiedtests/src/util/playgrounds/unique.tsdiffbeforeafterboth
9import {ApiInterfaceEvents, SignerOptions} from '@polkadot/api/types';9import {ApiInterfaceEvents, SignerOptions} from '@polkadot/api/types';
10import {encodeAddress, decodeAddress, keccakAsHex, evmToAddress, addressToEvm} from '@polkadot/util-crypto';10import {encodeAddress, decodeAddress, keccakAsHex, evmToAddress, addressToEvm} from '@polkadot/util-crypto';
11import {IKeyringPair} from '@polkadot/types/types';11import {IKeyringPair} from '@polkadot/types/types';
12import {IApiListeners, IBlock, IEvent, IChainProperties, ICollectionCreationOptions, ICollectionLimits, ICollectionPermissions, ICrossAccountId, ICrossAccountIdLower, ILogger, INestingPermissions, IProperty, IStakingInfo, ISchedulerOptions, ISubstrateBalance, IToken, ITokenPropertyPermission, ITransactionResult, IUniqueHelperLog, TApiAllowedListeners, TEthereumAccount, TSigner, TSubstrateAccount, IForeignAssetMetadata, TNetworks, MoonbeamAssetInfo, DemocracyStandardAccountVote, AcalaAssetMetadata} from './types';12import {
13 IApiListeners,
14 IBlock,
15 IEvent,
16 IChainProperties,
17 ICollectionCreationOptions,
18 ICollectionLimits,
19 ICollectionPermissions,
20 ICrossAccountId,
21 ICrossAccountIdLower,
22 ILogger,
23 INestingPermissions,
24 IProperty,
25 IStakingInfo,
26 ISchedulerOptions,
27 ISubstrateBalance,
28 IToken,
29 ITokenPropertyPermission,
30 ITransactionResult,
31 IUniqueHelperLog,
32 TApiAllowedListeners,
33 TEthereumAccount,
34 TSigner,
35 TSubstrateAccount,
36 TNetworks,
37 IForeignAssetMetadata,
38 AcalaAssetMetadata,
39 MoonbeamAssetInfo,
40 DemocracyStandardAccountVote,
41} from './types';
42import {RuntimeDispatchInfo} from '@polkadot/types/interfaces';
1343
14export class CrossAccountId implements ICrossAccountId {44export class CrossAccountId implements ICrossAccountId {
15 Substrate?: TSubstrateAccount;45 Substrate?: TSubstrateAccount;
532 });562 });
533 }563 }
564
565 async getPaymentInfo(signer: TSigner, tx: any, len: number | null) {
566 const api = this.getApi();
567 const signingInfo = await api.derive.tx.signingInfo(signer.address);
568
569 // We need to sign the tx because
570 // unsigned transactions does not have an inclusion fee
571 tx.sign(signer, {
572 blockHash: api.genesisHash,
573 genesisHash: api.genesisHash,
574 runtimeVersion: api.runtimeVersion,
575 nonce: signingInfo.nonce,
576 });
577
578 if (len === null) {
579 return (await this.callRpc('api.rpc.payment.queryInfo', [tx.toHex()])) as RuntimeDispatchInfo;
580 } else {
581 return (await api.call.transactionPaymentApi.queryInfo(tx, len)) as RuntimeDispatchInfo;
582 }
583 }
534584
535 constructApiCall(apiCall: string, params: any[]) {585 constructApiCall(apiCall: string, params: any[]) {
536 if(!apiCall.startsWith('api.')) throw Error(`Invalid api call: ${apiCall}`);586 if(!apiCall.startsWith('api.')) throw Error(`Invalid api call: ${apiCall}`);
904 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'CollectionAdminRemoved');954 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'unique', 'CollectionAdminRemoved');
905 }955 }
906956
907 /**957 /**
908 * Check if user is in allow list.958 * Check if user is in allow list.
909 * 959 *
910 * @param collectionId ID of collection960 * @param collectionId ID of collection
911 * @param user Account to check961 * @param user Account to check
912 * @example await getAdmins(1)962 * @example await getAdmins(1)
913 * @returns is user in allow list963 * @returns is user in allow list
914 */964 */
915 async allowed(collectionId: number, user: ICrossAccountId): Promise<boolean> {965 async allowed(collectionId: number, user: ICrossAccountId): Promise<boolean> {
916 return (await this.helper.callRpc('api.rpc.unique.allowed', [collectionId, user])).toJSON();966 return (await this.helper.callRpc('api.rpc.unique.allowed', [collectionId, user])).toJSON();
917 }967 }
1014 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'CollectionPropertySet');1064 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'CollectionPropertySet');
1015 }1065 }
10161066
1017 /**1067 /**
1018 * Get collection properties.1068 * Get collection properties.
1019 * 1069 *
1020 * @param collectionId ID of collection1070 * @param collectionId ID of collection
1021 * @param propertyKeys optionally filter the returned properties to only these keys1071 * @param propertyKeys optionally filter the returned properties to only these keys
1022 * @example getProperties(1219, ['location', 'date', 'time', 'isParadise']);1072 * @example getProperties(1219, ['location', 'date', 'time', 'isParadise']);
1023 * @returns array of key-value pairs1073 * @returns array of key-value pairs
1024 */1074 */
1025 async getProperties(collectionId: number, propertyKeys?: string[] | null): Promise<IProperty[]> {1075 async getProperties(collectionId: number, propertyKeys?: string[] | null): Promise<IProperty[]> {
1026 return (await this.helper.callRpc('api.rpc.unique.collectionProperties', [collectionId, propertyKeys])).toHuman();1076 return (await this.helper.callRpc('api.rpc.unique.collectionProperties', [collectionId, propertyKeys])).toHuman();
1027 }1077 }
1266 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'PropertyPermissionSet');1316 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'PropertyPermissionSet');
1267 }1317 }
12681318
1269 /**1319 /**
1270 * Get token property permissions.1320 * Get token property permissions.
1271 * 1321 *
1272 * @param collectionId ID of collection1322 * @param collectionId ID of collection
1273 * @param propertyKeys optionally filter the returned property permissions to only these keys1323 * @param propertyKeys optionally filter the returned property permissions to only these keys
1274 * @example getPropertyPermissions(1219, ['location', 'date', 'time', 'isParadise']);1324 * @example getPropertyPermissions(1219, ['location', 'date', 'time', 'isParadise']);
1275 * @returns array of key-permission pairs1325 * @returns array of key-permission pairs
1276 */1326 */
1277 async getPropertyPermissions(collectionId: number, propertyKeys: string[] | null = null): Promise<ITokenPropertyPermission[]> {1327 async getPropertyPermissions(collectionId: number, propertyKeys: string[] | null = null): Promise<ITokenPropertyPermission[]> {
1278 return (await this.helper.callRpc('api.rpc.unique.propertyPermissions', [collectionId, ...(propertyKeys === null ? [] : [propertyKeys])])).toHuman();1328 return (await this.helper.callRpc('api.rpc.unique.propertyPermissions', [collectionId, ...(propertyKeys === null ? [] : [propertyKeys])])).toHuman();
1279 }1329 }
1298 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'TokenPropertySet');1348 return this.helper.util.findCollectionInEvents(result.result.events, collectionId, 'common', 'TokenPropertySet');
1299 }1349 }
13001350
1301 /**1351 /**
1302 * Get properties, metadata assigned to a token.1352 * Get properties, metadata assigned to a token.
1303 * 1353 *
1304 * @param collectionId ID of collection1354 * @param collectionId ID of collection
1305 * @param tokenId ID of token1355 * @param tokenId ID of token
1306 * @param propertyKeys optionally filter the returned properties to only these keys1356 * @param propertyKeys optionally filter the returned properties to only these keys
1307 * @example getTokenProperties(1219, ['location', 'date', 'time', 'isParadise']);1357 * @example getTokenProperties(1219, ['location', 'date', 'time', 'isParadise']);
1308 * @returns array of key-value pairs1358 * @returns array of key-value pairs
1309 */1359 */
1310 async getTokenProperties(collectionId: number, tokenId: number, propertyKeys?: string[] | null): Promise<IProperty[]> {1360 async getTokenProperties(collectionId: number, tokenId: number, propertyKeys?: string[] | null): Promise<IProperty[]> {
1311 return (await this.helper.callRpc('api.rpc.unique.tokenProperties', [collectionId, tokenId, propertyKeys])).toHuman();1361 return (await this.helper.callRpc('api.rpc.unique.tokenProperties', [collectionId, tokenId, propertyKeys])).toHuman();
1312 }1362 }
2255 return this.subBalanceGroup.transferToSubstrate(signer, address, amount);2305 return this.subBalanceGroup.transferToSubstrate(signer, address, amount);
2256 }2306 }
2307
2308 async forceTransferToSubstrate(signer: TSigner, from: TSubstrateAccount, to: TSubstrateAccount, amount: bigint | string): Promise<boolean> {
2309 const result = await this.helper.executeExtrinsic(signer, 'api.tx.balances.forceTransfer', [from, to, amount], true);
2310
2311 let transfer = {from: null, to: null, amount: 0n} as any;
2312 result.result.events.forEach(({event: {data, method, section}}) => {
2313 if ((section === 'balances') && (method === 'Transfer')) {
2314 transfer = {
2315 from: this.helper.address.normalizeSubstrate(data[0]),
2316 to: this.helper.address.normalizeSubstrate(data[1]),
2317 amount: BigInt(data[2]),
2318 };
2319 }
2320 });
2321 let isSuccess = this.helper.address.normalizeSubstrate(from) === transfer.from;
2322 isSuccess = isSuccess && this.helper.address.normalizeSubstrate(to) === transfer.to;
2323 isSuccess = isSuccess && BigInt(amount) === transfer.amount;
2324 return isSuccess;
2325 }
2257}2326}
22582327
2259class AddressGroup extends HelperGroup<ChainHelperBase> {2328class AddressGroup extends HelperGroup<ChainHelperBase> {
2769 this.blocksNum,2838 this.blocksNum,
2770 this.options.periodic ? [this.options.periodic.period, this.options.periodic.repetitions] : null,2839 this.options.periodic ? [this.options.periodic.period, this.options.periodic.repetitions] : null,
2771 this.options.priority ?? null,2840 this.options.priority ?? null,
2772 {Value: scheduledTx},2841 scheduledTx,
2773 ],2842 ],
2774 expectSuccess,2843 expectSuccess,
2775 );2844 );